root/juggler/branches/2.2/modules/gadgeteer/tools/ethereal/packet-birdnet.c

Revision 12765, 61.0 kB (checked in by patrickh, 5 years ago)

Initial revision

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /* packet-birdnet.c
2  * Routines for BIRDNET protocol dissection
3  * Copyright 2001, 2003 Patrick Hartling <patrick@vrac.iastate.edu>
4  *
5  * packet-birdnet.c,v 1.3 2003/06/13 14:23:38 patrick Exp
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@unicom.net>
9  * Copyright 1998 Gerald Combs
10  *
11  * Copied from README.developer
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36 #include <glib.h>
37
38 #ifdef HAVE_SYS_TYPES_H
39 # include <sys/types.h>
40 #endif
41
42 #ifdef HAVE_NETINET_IN_H
43 # include <netinet/in.h>
44 #endif
45
46 #ifdef NEED_SNPRINTF_H
47 # include "snprintf.h"
48 #endif
49
50 #include <epan/packet.h>
51 #include "packet-birdnet.h"
52
53 /* Initialize the protocol and registered fields */
54 static int proto_birdnet = -1;
55 static int hf_birdnet_seq = -1;
56 static int hf_birdnet_int = -1;
57 /* static int hf_birdnet_time = -1; */
58 static int hf_birdnet_time[4] = { -1, -1, -1, -1 };
59 static int hf_birdnet_type = -1;
60 static int hf_birdnet_xtype = -1;
61 static int hf_birdnet_proto = -1;
62 static int hf_birdnet_error_code = -1;
63 static int hf_birdnet_error_code_ext = -1;
64 static int hf_birdnet_num_bytes = -1;
65
66 static int hf_birdnet_data_sys_all                 = -1;
67 static int hf_birdnet_data_sys_all_running         = -1;
68 static int hf_birdnet_data_sys_all_error           = -1;
69 static int hf_birdnet_data_sys_all_fbb_error       = -1;
70 static int hf_birdnet_data_sys_all_local_error     = -1;
71 static int hf_birdnet_data_sys_all_local_power     = -1;
72 static int hf_birdnet_data_sys_all_master          = -1;
73 static int hf_birdnet_data_sys_all_crtsync_type    = -1;
74 static int hf_birdnet_data_sys_all_crtsync         = -1;
75 static int hf_birdnet_data_sys_error               = -1;
76 static int hf_birdnet_data_sys_flock_num           = -1;
77 static int hf_birdnet_data_sys_server_num          = -1;
78 static int hf_birdnet_data_sys_transmitter_num     = -1;
79 static int hf_birdnet_data_sys_measurement_rate[6] = { -1, -1, -1, -1, -1, -1 };
80 static int hf_birdnet_data_sys_chassis_num         = -1;
81 static int hf_birdnet_data_sys_chassis_devs        = -1;
82 static int hf_birdnet_data_sys_first_addr          = -1;
83 static int hf_birdnet_data_sys_software_rev[2]     = { -1, -1 };
84 static int hf_birdnet_data_sys_fbb_device          = -1;
85 static int hf_birdnet_data_sys_fbb_device_accessible = -1;
86 static int hf_birdnet_data_sys_fbb_device_running    = -1;
87 static int hf_birdnet_data_sys_fbb_device_sensor     = -1;
88 static int hf_birdnet_data_sys_fbb_device_erc        = -1;
89 static int hf_birdnet_data_sys_fbb_device_ert3       = -1;
90 static int hf_birdnet_data_sys_fbb_device_ert2       = -1;
91 static int hf_birdnet_data_sys_fbb_device_ert1       = -1;
92 static int hf_birdnet_data_sys_fbb_device_ert0       = -1;
93
94 static int hf_birdnet_data_bird_status                     = -1;
95 static int hf_birdnet_data_bird_status_error               = -1;
96 static int hf_birdnet_data_bird_status_running             = -1;
97 static int hf_birdnet_data_bird_status_reserved1           = -1;
98 static int hf_birdnet_data_bird_status_reserved2           = -1;
99 static int hf_birdnet_data_bird_status_buttons_present     = -1;
100 static int hf_birdnet_data_bird_status_sensor_present      = -1;
101 static int hf_birdnet_data_bird_status_transmitter_present = -1;
102 static int hf_birdnet_data_bird_status_transmitter_running = -1;
103 static int hf_birdnet_data_bird_id                         = -1;
104 static int hf_birdnet_data_bird_software_rev[2]            = { -1, -1 };
105 static int hf_birdnet_data_bird_error_code                 = -1;
106 static int hf_birdnet_data_bird_setup                      = -1;
107 static int hf_birdnet_data_bird_setup_sudden               = -1;
108 static int hf_birdnet_data_bird_setup_xyz_ref              = -1;
109 static int hf_birdnet_data_bird_setup_button_data          = -1;
110 static int hf_birdnet_data_bird_setup_ac_narrow            = -1;
111 static int hf_birdnet_data_bird_setup_ac_wide              = -1;
112 static int hf_birdnet_data_bird_setup_dc                   = -1;
113 static int hf_birdnet_data_bird_data_format                = -1;
114 static int hf_birdnet_data_bird_report_rate                = -1;
115 static int hf_birdnet_data_bird_scaling                    = -1;
116 /* static int hf_birdnet_data_bird_scaling_sys_code           = -1; */
117 /* static int hf_birdnet_data_bird_scaling_fs_meas            = -1; */
118 static int hf_birdnet_data_bird_hemisphere                 = -1;
119 static int hf_birdnet_data_bird_fbb_address                = -1;
120 static int hf_birdnet_data_bird_transmitter_type           = -1;
121 static int hf_birdnet_data_bird_transmitter_type_ert       = -1;
122 static int hf_birdnet_data_bird_transmitter_type_srt       = -1;
123 static int hf_birdnet_data_bird_transmitter_type_pcbird    = -1;
124 static int hf_birdnet_data_bird_transmitter_type_active    = -1;
125 static int hf_birdnet_data_bird_transmitter_type_selected  = -1;
126 static int hf_birdnet_data_bird_transmitter_type_number    = -1;
127 static int hf_birdnet_data_bird_spare1                     = -1;
128 static int hf_birdnet_data_bird_spare2                     = -1;
129
130 /* Initialize the subtree pointers */
131 static gint ett_birdnet_header                = -1;
132 static gint ett_birdnet_data                  = -1;
133 static gint ett_birdnet_data_sys_status       = -1;
134 static gint ett_birdnet_data_sys_xmtr_info    = -1;
135 static gint ett_birdnet_data_sys_flock        = -1;
136 static gint ett_birdnet_data_bird             = -1;
137 static gint ett_birdnet_data_bird_status      = -1;
138 static gint ett_birdnet_data_bird_setup       = -1;
139 static gint ett_birdnet_data_bird_data_format = -1;
140 static gint ett_birdnet_data_bird_scaling     = -1;
141 static gint ett_birdnet_data_bird_xmtr_type   = -1;
142
143 static const guint32 UDP_PORT_BIRDNET = 5000;
144 static const guint32 TCP_PORT_BIRDNET = 6000;
145
146 /*
147 static const unsigned char MSG_WAKE_UP        = 10;
148 static const unsigned char RSP_WAKE_UP        = 20;
149 static const unsigned char MSG_SHUT_DOWN      = 11;
150 static const unsigned char RSP_SHUT_DOWN      = 21;
151 static const unsigned char MSG_GET_STATUS     = 101;
152 static const unsigned char MSG_SEND_SETUP     = 102;
153 static const unsigned char MSG_SINGLE_SHOT    = 103;
154 static const unsigned char MSG_RUN_CONTINUOUS = 104;
155 static const unsigned char MSG_STOP_DATA      = 105;
156 static const unsigned char RSP_GET_STATUS     = 201;
157 static const unsigned char RSP_SEND_SETUP     = 202;
158 static const unsigned char RSP_RUN_CONTINUOUS = 204;
159 static const unsigned char RSP_STOP_DATA      = 205;
160 static const unsigned char DATA_PACKET_MULTI  = 210;
161 static const unsigned char RSP_ILLEGAL        = 40;
162 static const unsigned char RSP_UNKNOWN        = 50;
163 static const unsigned char MSG_SYNC_SEQUENCE  = 30;
164 static const unsigned char RSP_SYNC_SEQUENCE  = 31;
165 */
166 #define MSG_WAKE_UP 10
167 #define RSP_WAKE_UP 20
168 #define MSG_SHUT_DOWN 11
169 #define RSP_SHUT_DOWN 21
170 #define MSG_GET_STATUS 101
171 #define MSG_SEND_SETUP 102
172 #define MSG_SINGLE_SHOT 103
173 #define MSG_RUN_CONTINUOUS 104
174 #define MSG_STOP_DATA 105
175 #define RSP_GET_STATUS 201
176 #define RSP_SEND_SETUP 202
177 #define RSP_RUN_CONTINUOUS 204
178 #define RSP_STOP_DATA 205
179 #define DATA_PACKET_MULTI 210
180 #define RSP_ILLEGAL 40
181 #define RSP_UNKNOWN 50
182 #define MSG_SYNC_SEQUENCE 30
183 #define RSP_SYNC_SEQUENCE 31
184
185 static const unsigned char BN_SEQUENCE       = 0;
186 static const unsigned char BN_INTERVAL       = 2;
187 static const unsigned char BN_TIME           = 4;
188 static const unsigned char BN_TYPE           = 8;
189 static const unsigned char BN_XTYPE          = 9;
190 static const unsigned char BN_PROTOCOL       = 10;
191 static const unsigned char BN_ERROR_CODE     = 11;
192 static const unsigned char BN_ERROR_CODE_EXT = 12;
193 static const unsigned char BN_NUM_BYTES      = 14;
194
195 static const unsigned char BN_DATA_SYS_ALL             = 0;
196 static const unsigned char BN_DATA_SYS_ERROR           = 1;
197 static const unsigned char BN_DATA_SYS_FLOCK_NUM       = 2;
198 static const unsigned char BN_DATA_SYS_SERVER_NUM      = 3;
199 static const unsigned char BN_DATA_SYS_TRANSMITTER_NUM = 4;
200 static const unsigned char BN_DATA_SYS_MEAS_RATE       = 5;
201 static const unsigned char BN_DATA_SYS_CHASSIS_NUM     = 11;
202 static const unsigned char BN_DATA_SYS_CHASSIS_DEVS    = 12;
203 static const unsigned char BN_DATA_SYS_FIRST_ADDR      = 13;
204 static const unsigned char BN_DATA_SYS_SOFTWARE_REV    = 14;
205
206 static const unsigned char BN_DATA_BIRD_STATUS       = 0;
207 static const unsigned char BN_DATA_BIRD_ID           = 1;
208 static const unsigned char BN_DATA_BIRD_SOFTWARE_REV = 2;
209 static const unsigned char BN_DATA_BIRD_ERROR_CODE   = 4;
210 static const unsigned char BN_DATA_BIRD_SETUP        = 5;
211 static const unsigned char BN_DATA_BIRD_DATA_FORMAT  = 6;
212 static const unsigned char BN_DATA_BIRD_REPORT_RATE  = 7;
213 static const unsigned char BN_DATA_BIRD_SCALING      = 8;
214 static const unsigned char BN_DATA_BIRD_HEMISPHERE   = 10;
215 static const unsigned char BN_DATA_BIRD_FBB_ADDRESS  = 11;
216 static const unsigned char BN_DATA_BIRD_XMTR_TYPE    = 12;
217 static const unsigned char BN_DATA_BIRD_SPARE1       = 13;
218 static const unsigned char BN_DATA_BIRD_SPARE2       = 14;
219
220 /*
221 static const unsigned char BN_SYSTEM_RUNNING      = 0x80;
222 static const unsigned char BN_SYSTEM_ERROR        = 0x40;
223 static const unsigned char BN_SYSTEM_FBB_ERROR    = 0x20;
224 static const unsigned char BN_SYSTEM_LOCAL_ERROR  = 0x10;
225 static const unsigned char BN_SYSTEM_LOCAL_POWER  = 0x08;
226 static const unsigned char BN_SYSTEM_MASTER       = 0x04;
227 static const unsigned char BN_SYSTEM_CRTSYNC_TYPE = 0x02;
228 static const unsigned char BN_SYSTEM_CRTSYNC      = 0x01;
229 */
230
231 #define BN_SYSTEM_RUNNING      0x80
232 #define BN_SYSTEM_ERROR        0x40
233 #define BN_SYSTEM_FBB_ERROR    0x20
234 #define BN_SYSTEM_LOCAL_ERROR  0x10
235 #define BN_SYSTEM_LOCAL_POWER  0x08
236 #define BN_SYSTEM_MASTER       0x04
237 #define BN_SYSTEM_CRTSYNC_TYPE 0x02
238 #define BN_SYSTEM_CRTSYNC      0x01
239
240 /*
241 static const unsigned char FBB_ACCESS  = 0x80;
242 static const unsigned char FBB_RUNNING = 0x40;
243 static const unsigned char FBB_SENSOR  = 0x20;
244 static const unsigned char FBB_ERC     = 0x10;
245 static const unsigned char FBB_ERT3    = 0x08;
246 static const unsigned char FBB_ERT2    = 0x04;
247 static const unsigned char FBB_ERT1    = 0x02;
248 static const unsigned char FBB_ERT0    = 0x01;
249 */
250
251 #define FBB_ACCESS  0x80
252 #define FBB_RUNNING 0x40
253 #define FBB_SENSOR  0x20
254 #define FBB_ERC     0x10
255 #define FBB_ERT3    0x08
256 #define FBB_ERT2    0x04
257 #define FBB_ERT1    0x02
258 #define FBB_ERT0    0x01
259
260 /*
261 static const unsigned char BN_BIRD_ERROR               = 0x80;
262 static const unsigned char BN_BIRD_RUNNING             = 0x40;
263 static const unsigned char BN_BIRD_RESERVED1           = 0x20;
264 static const unsigned char BN_BIRD_RESERVED2           = 0x10;
265 static const unsigned char BN_BIRD_BUTTONS_PRESENT     = 0x08;
266 static const unsigned char BN_BIRD_SENSOR_PRESENT      = 0x04;
267 static const unsigned char BN_BIRD_TRANSMITTER_PRESENT = 0x02;
268 static const unsigned char BN_BIRD_TRANSMITTER_RUNNING = 0x01;
269 */
270
271 #define BN_BIRD_ERROR                0x80
272 #define BN_BIRD_RUNNING              0x40
273 #define BN_BIRD_RESERVED1            0x20
274 #define BN_BIRD_RESERVED2            0x10
275 #define BN_BIRD_BUTTONS_PRESENT      0x08
276 #define BN_BIRD_SENSOR_PRESENT       0x04
277 #define BN_BIRD_TRANSMITTER_PRESENT  0x02
278 #define BN_BIRD_TRANSMITTER_RUNNING  0x01
279
280 #define BN_BIRD_SETUP_SUDDEN      0x20
281 #define BN_BIRD_SETUP_XYZ_REF     0x10
282 #define BN_BIRD_SETUP_BUTTON_DATA 0x08
283 #define BN_BIRD_SETUP_AC_NARROW   0x04
284 #define BN_BIRD_SETUP_AC_WIDE     0x02
285 #define BN_BIRD_SETUP_DC          0x01
286
287 #define BN_BIRD_XMTR_TYPE_ERT      0x80
288 #define BN_BIRD_XMTR_TYPE_SRT      0x40
289 #define BN_BIRD_XMTR_TYPE_PCBIRD   0x20
290 #define BN_BIRD_XMTR_TYPE_ACTIVE   0x10
291 #define BN_BIRD_XMTR_TYPE_SELECTED 0x0c
292 #define BN_BIRD_XMTR_TYPE_NUMBER   0x03
293
294
295 static char*
296 getTypeString (const unsigned char type) {
297     static char ret_str[40];
298
299     memset(ret_str, '\0', sizeof(ret_str));
300
301     switch (type) {
302       case MSG_WAKE_UP:
303         strcpy(ret_str, "Server wakeup request");
304         break;
305       case RSP_WAKE_UP:
306         strcpy(ret_str, "Server wakeup resposne");
307         break;
308       case MSG_SHUT_DOWN:
309         strcpy(ret_str, "Server shutdown request");
310         break;
311       case RSP_SHUT_DOWN:
312         strcpy(ret_str, "Shutdown request response");
313         break;
314       case MSG_GET_STATUS:
315         strcpy(ret_str, "Device status reqeust");
316         break;
317       case RSP_GET_STATUS:
318         strcpy(ret_str, "Device status response");
319         break;
320       case MSG_SEND_SETUP:
321         strcpy(ret_str, "Device configuration request");
322         break;
323       case RSP_SEND_SETUP:
324         strcpy(ret_str, "Device configuration response");
325         break;
326       case MSG_SINGLE_SHOT:
327         strcpy(ret_str, "Single-shot request");
328         break;
329       case MSG_RUN_CONTINUOUS:
330         strcpy(ret_str, "Continuous data request");
331         break;
332       case RSP_RUN_CONTINUOUS:
333         strcpy(ret_str, "Continuous data response");
334         break;
335       case MSG_STOP_DATA:
336         strcpy(ret_str, "Data stop request");
337         break;
338       case RSP_STOP_DATA:
339         strcpy(ret_str, "Data stop response");
340         break;
341       case DATA_PACKET_MULTI:
342         strcpy(ret_str, "Data packet multi");
343         break;
344       case RSP_ILLEGAL:
345         strcpy(ret_str, "Response to illegal command");
346         break;
347       case RSP_UNKNOWN:
348         strcpy(ret_str, "Response to unknown command");
349         break;
350       case MSG_SYNC_SEQUENCE:
351         strcpy(ret_str, "Sync sequence request");
352         break;
353       case RSP_SYNC_SEQUENCE:
354         strcpy(ret_str, "Sync sequence response");
355         break;
356       default:
357         strcpy(ret_str, "Unknown packet type!");
358         break;
359     }
360
361     return ret_str;
362 }
363
364 static char*
365 getErrorCode (const unsigned char error_code) {
366     static char code_str[80];
367
368     memset(code_str, '\0', sizeof(code_str));
369
370     switch (error_code) {
371       case 1:
372         strcpy(code_str, "Single packet missing");
373         break;
374       case 2:
375         strcpy(code_str, "Two or more packets missing");
376         break;
377       case 3:
378         strcpy(code_str, "Many, many packets missing");
379         break;
380       case 4:
381         strcpy(code_str, "Packet sequence number repeated");
382         break;
383       case 6:
384         strcpy(code_str, "Unexpected packet type received");
385         break;
386       case 7:
387         strcpy(code_str, "Packet contents could not be determined");
388         break;
389       case 8:
390         strcpy(code_str, "Status requested for non-existant FBB device");
391         break;
392       case 9:
393         strcpy(code_str, "Illegal setup data sent");
394         break;
395       case 100:
396         strcpy(code_str, "System not ready");
397         break;
398     }
399
400     return code_str;
401 }
402
403 static double
404 convertMeasurementRateToDouble (const unsigned char rate[6]) {
405     int i;
406     double data_rate;
407     char data_rate_a[7];
408
409     /*
410      * Copy the bytes in status_info->measurementRate into data_rate_a.  I
411      * know this is probably being overly cautious, but getting the byte
412      * ordering right is important.
413      */
414     for ( i = 0; i < 6; i++ ) {
415         data_rate_a[i] = rate[i];
416     }
417
418     /* Terminate the measurement rate string. */
419     data_rate_a[6] = '\0';
420
421     /*
422      * This conversion is described in the measurementRate row of the
423      * General System Status table on page 121 of the MotionStar Operation and
424      * Installation Guide.
425      */
426     data_rate = atof(data_rate_a) / 1000.0;
427
428     return data_rate;
429 }
430
431 static void
432 dissect_birdnet_data_sys_status (tvbuff_t* tvb, struct SYSTEM_STATUS* status,
433                                  double* rate)
434 {
435     int i;
436
437     status->all          = tvb_get_guint8(tvb, BN_DATA_SYS_ALL);
438     status->error        = tvb_get_guint8(tvb, BN_DATA_SYS_ERROR);
439     status->flockNumber  = tvb_get_guint8(tvb, BN_DATA_SYS_FLOCK_NUM);
440     status->serverNumber = tvb_get_guint8(tvb, BN_DATA_SYS_SERVER_NUM);
441
442     status->transmitterNumber =
443         tvb_get_guint8(tvb, BN_DATA_SYS_TRANSMITTER_NUM);
444
445     for ( i = 0; i < 6; i++ ) {
446         status->measurementRate[i] =
447             tvb_get_guint8(tvb, BN_DATA_SYS_MEAS_RATE + i);
448     }
449
450     status->chassisNumber  = tvb_get_guint8(tvb, BN_DATA_SYS_CHASSIS_NUM);
451     status->chassisDevices = tvb_get_guint8(tvb, BN_DATA_SYS_CHASSIS_DEVS);
452     status->firstAddress   = tvb_get_guint8(tvb, BN_DATA_SYS_FIRST_ADDR);
453
454     status->softwareRevision[0] = tvb_get_guint8(tvb, BN_DATA_SYS_SOFTWARE_REV);
455     status->softwareRevision[1] = tvb_get_guint8(tvb, BN_DATA_SYS_SOFTWARE_REV + 1);
456
457     *rate = convertMeasurementRateToDouble(status->measurementRate);
458 }
459
460 static void
461 populate_tree_data_sys_status (tvbuff_t* tvb, proto_tree* tree,
462                                const struct SYSTEM_STATUS* status,
463                                const double rate)
464 {
465     unsigned char erc_num, xmtr_num;
466     proto_item* tf;
467     proto_tree *status_tree, *xmtr_tree;
468
469     tf = proto_tree_add_uint(tree, hf_birdnet_data_sys_all, tvb,
470                              BN_DATA_SYS_ALL, sizeof(status->all),
471                              status->all);
472
473     status_tree = proto_item_add_subtree(tf, ett_birdnet_data_sys_status);
474     proto_tree_add_boolean(status_tree, hf_birdnet_data_sys_all_running, tvb,
475                            BN_DATA_SYS_ALL, 1, status->all);
476     proto_tree_add_boolean(status_tree, hf_birdnet_data_sys_all_error, tvb,
477                            BN_DATA_SYS_ALL, 1, status->all);
478     proto_tree_add_boolean(status_tree, hf_birdnet_data_sys_all_fbb_error, tvb,
479                            BN_DATA_SYS_ALL, 1, status->all);
480     proto_tree_add_boolean(status_tree, hf_birdnet_data_sys_all_local_error,
481                            tvb, BN_DATA_SYS_ALL, 1, status->all);
482     proto_tree_add_boolean(status_tree, hf_birdnet_data_sys_all_local_power,
483                            tvb, BN_DATA_SYS_ALL, 1, status->all);
484     proto_tree_add_boolean(status_tree, hf_birdnet_data_sys_all_master, tvb,
485                            BN_DATA_SYS_ALL, 1, status->all);
486     proto_tree_add_boolean(status_tree, hf_birdnet_data_sys_all_crtsync_type,
487                            tvb, BN_DATA_SYS_ALL, 1, status->all);
488     proto_tree_add_boolean(status_tree, hf_birdnet_data_sys_all_crtsync, tvb,
489                            BN_DATA_SYS_ALL, 1, status->all);
490
491     proto_tree_add_uint(tree, hf_birdnet_data_sys_error, tvb,
492                         BN_DATA_SYS_ERROR, sizeof(status->error),
493                         status->error);
494     proto_tree_add_uint(tree, hf_birdnet_data_sys_flock_num, tvb,
495                         BN_DATA_SYS_FLOCK_NUM, sizeof(status->flockNumber),
496                         status->flockNumber);
497     proto_tree_add_uint(tree, hf_birdnet_data_sys_server_num, tvb,
498                         BN_DATA_SYS_SERVER_NUM, sizeof(status->serverNumber),
499                         status->serverNumber);
500
501     tf = proto_tree_add_uint(tree, hf_birdnet_data_sys_transmitter_num, tvb,
502                              BN_DATA_SYS_TRANSMITTER_NUM,
503                              sizeof(status->transmitterNumber),
504                              status->transmitterNumber);
505
506     erc_num  = status->transmitterNumber >> 4;
507     xmtr_num = status->transmitterNumber & 0x03;
508
509     xmtr_tree = proto_item_add_subtree(tf, ett_birdnet_data_sys_xmtr_info);
510
511     proto_tree_add_uint_format(xmtr_tree, hf_birdnet_data_sys_transmitter_num,
512                                tvb, BN_DATA_SYS_TRANSMITTER_NUM,
513                                sizeof(status->transmitterNumber),
514                                status->transmitterNumber,
515                                "FBB Address of ERC: %u",
516                                (unsigned int) erc_num);
517     proto_tree_add_uint_format(xmtr_tree, hf_birdnet_data_sys_transmitter_num,
518                                tvb, BN_DATA_SYS_TRANSMITTER_NUM,
519                                sizeof(status->transmitterNumber),
520                                status->transmitterNumber,
521                                "Transmitter number within ERC: %u",
522                                (unsigned int) xmtr_num);
523
524     proto_tree_add_uint_format(tree, hf_birdnet_data_sys_measurement_rate[0],
525                                tvb, BN_DATA_SYS_MEAS_RATE, sizeof(guint8),
526                                hf_birdnet_data_sys_measurement_rate[0],
527                                "Measurement rate: %f", rate);
528
529     proto_tree_add_uint(tree, hf_birdnet_data_sys_chassis_num, tvb,
530                         BN_DATA_SYS_CHASSIS_NUM, sizeof(status->chassisNumber),
531                         status->chassisNumber);
532     proto_tree_add_uint(tree, hf_birdnet_data_sys_chassis_devs, tvb,
533                         BN_DATA_SYS_CHASSIS_DEVS,
534                         sizeof(status->chassisDevices),
535                         status->chassisDevices);
536     proto_tree_add_uint(tree, hf_birdnet_data_sys_first_addr, tvb,
537                         BN_DATA_SYS_FIRST_ADDR, sizeof(status->firstAddress),
538                         status->firstAddress);
539
540     proto_tree_add_uint_format(tree, hf_birdnet_data_sys_software_rev[0], tvb,
541                                BN_DATA_SYS_SOFTWARE_REV, sizeof(guint8),
542                                status->softwareRevision[0],
543                                "Server software revision: %d.%d",
544                                (unsigned int) status->softwareRevision[0],
545                                (unsigned int) status->softwareRevision[1]);
546 }
547
548 static void
549 process_fbb_device (tvbuff_t* tvb, proto_tree* tree, const unsigned int id,
550                     const guint offset, const unsigned short num_bytes)
551 {
552     proto_item* tf;
553     proto_tree* flock_tree;
554     guint8 fbb_device;
555
556     fbb_device = tvb_get_guint8(tvb, offset);
557
558     tf = proto_tree_add_text(tree, tvb, offset, num_bytes, "Flock #%u: 0x%02x",
559                              id, (unsigned int) fbb_device);
560
561     flock_tree = proto_item_add_subtree(tf, ett_birdnet_data_sys_flock);
562
563     proto_tree_add_boolean(flock_tree,
564                            hf_birdnet_data_sys_fbb_device_accessible, tvb,
565                            offset, 1, fbb_device);
566     proto_tree_add_boolean(flock_tree, hf_birdnet_data_sys_fbb_device_running,
567                            tvb, offset, 1, fbb_device);
568     proto_tree_add_boolean(flock_tree, hf_birdnet_data_sys_fbb_device_sensor,
569                            tvb, offset, 1, fbb_device);
570     proto_tree_add_boolean(flock_tree, hf_birdnet_data_sys_fbb_device_erc,
571                            tvb, offset, 1, fbb_device);
572
573     if ( fbb_device & FBB_ERC ) {
574         proto_tree_add_boolean(flock_tree, hf_birdnet_data_sys_fbb_device_ert3,
575                                tvb, offset, 1, fbb_device);
576         proto_tree_add_boolean(flock_tree, hf_birdnet_data_sys_fbb_device_ert2,
577                                tvb, offset, 1, fbb_device);
578         proto_tree_add_boolean(flock_tree, hf_birdnet_data_sys_fbb_device_ert1,
579                                tvb, offset, 1, fbb_device);
580         proto_tree_add_boolean(flock_tree, hf_birdnet_data_sys_fbb_device_ert0,
581                                tvb, offset, 1, fbb_device);
582     }
583 }
584
585 static void
586 dissect_birdnet_data_bird_status (tvbuff_t* tvb,
587                                   struct BIRD_STATUS* status)
588 {
589     status->status.status         = tvb_get_guint8(tvb, BN_DATA_BIRD_STATUS);
590     status->status.id             = tvb_get_guint8(tvb, BN_DATA_BIRD_ID);
591     status->status.softwareRev[0] = tvb_get_guint8(tvb, BN_DATA_BIRD_SOFTWARE_REV);
592     status->status.softwareRev[1] = tvb_get_guint8(tvb, BN_DATA_BIRD_SOFTWARE_REV + 1);
593     status->status.errorCode      = tvb_get_guint8(tvb, BN_DATA_BIRD_ERROR_CODE);
594     status->status.setup          = tvb_get_guint8(tvb, BN_DATA_BIRD_SETUP);
595     status->status.dataFormat     = tvb_get_guint8(tvb, BN_DATA_BIRD_DATA_FORMAT);
596     status->status.reportRate     = tvb_get_guint8(tvb, BN_DATA_BIRD_REPORT_RATE);
597     status->status.scaling[0]     = tvb_get_guint8(tvb, BN_DATA_BIRD_SCALING);
598     status->status.scaling[1]     = tvb_get_guint8(tvb, BN_DATA_BIRD_SCALING + 1);
599     status->status.hemisphere     = tvb_get_guint8(tvb, BN_DATA_BIRD_HEMISPHERE);
600     status->status.FBBaddress     = tvb_get_guint8(tvb, BN_DATA_BIRD_FBB_ADDRESS);
601     status->status.spare1         = tvb_get_guint8(tvb, BN_DATA_BIRD_SPARE1);
602     status->status.spare2[0]      = tvb_get_guint8(tvb, BN_DATA_BIRD_SPARE2);
603     status->status.spare2[1]      = tvb_get_guint8(tvb, BN_DATA_BIRD_SPARE2 + 1);
604 }
605
606 static char*
607 get_id_string (const unsigned char id) {
608     static char ret_str[11];
609
610     switch (id) {
611       case 1:
612         strcpy(ret_str, "6DFOB     ");
613         break;
614       case 2:
615         strcpy(ret_str, "6DERC     ");
616         break;
617       case 3:
618         strcpy(ret_str, "6DBOF     ");
619         break;
620       case 4:
621         strcpy(ret_str, "PCBIRD    ");
622         break;
623       case 5:
624         strcpy(ret_str, "SPACEPAD  ");
625         break;
626       case 6:
627         strcpy(ret_str, "MOTIONSTAR");
628         break;
629       case 7:
630         strcpy(ret_str, "WIRELESS  ");
631         break;
632       case 255:
633         strcpy(ret_str, "UNKNOWN");
634         break;
635     }
636
637     return ret_str;
638 }
639
640 static char*
641 getFormatCode (const unsigned char code) {
642     static char code_str[20];
643
644     memset(code_str, '\0', sizeof(code_str));
645
646     switch (code) {
647       case 0:
648         strcpy(code_str, "No data");
649         break;
650       case 1:
651         strcpy(code_str, "POSITION");
652         break;
653       case 2:
654         strcpy(code_str, "ANGLES");
655         break;
656       case 3:
657         strcpy(code_str, "MATRIX");
658         break;
659       case 4:
660         strcpy(code_str, "POSITION/ANGLES");
661         break;
662       case 5:
663         strcpy(code_str, "POSITION/MATRIX");
664         break;
665       case 6:
666         strcpy(code_str, "<invalid>");
667         break;
668       case 7:
669         strcpy(code_str, "QUATERNION");
670         break;
671       case 8:
672         strcpy(code_str, "POSITION/QUATERNION");
673         break;
674       default:
675         strcpy(code_str, "<invalid>");
676         break;
677     }
678
679     return code_str;
680 }
681
682 static char*
683 getHemisphereString (const unsigned char hemi) {
684     static char hemi_str[7];
685
686     memset(hemi_str, '\0', sizeof(hemi_str));
687
688     switch (hemi) {
689       case 0:
690         strcpy(hemi_str, "FRONT");
691         break;
692       case 1:
693         strcpy(hemi_str, "REAR");
694         break;
695       case 2:
696         strcpy(hemi_str, "UPPER");
697         break;
698       case 3:
699         strcpy(hemi_str, "LOWER");
700         break;
701       case 4:
702         strcpy(hemi_str, "LEFT");
703         break;
704       case 5:
705         strcpy(hemi_str, "RIGHT");
706         break;
707     }
708
709     return hemi_str;
710 }
711
712 static void
713 populate_tree_data_bird_status (tvbuff_t* tvb, proto_tree* tree,
714                                 const struct BIRD_STATUS* status)
715 {
716     proto_item* tf;
717     proto_tree *status_tree, *setup_tree, *format_tree, *scaling_tree;
718     proto_tree* xmtr_tree;
719     unsigned char data_size, data_code;
720     guint16 sys_code;
721
722     tf = proto_tree_add_uint(tree, hf_birdnet_data_bird_status, tvb,
723                              BN_DATA_BIRD_STATUS, sizeof(status->status),
724                              status->status.status);
725
726     status_tree = proto_item_add_subtree(tf, ett_birdnet_data_bird_status);
727     proto_tree_add_boolean(status_tree, hf