Fix RCS ID.
[metze/wireshark/wip.git] / epan / dissectors / packet-ar_drone.c
1 /* packet-ar_drone.c
2  * Routines for AR ar_drone protocol packet disassembly
3  * By Paul Hoisington <hoisingtonp@bit-sys.com>,
4  * Tom Hildesheim <hildesheimt@bit-sys.com>,
5  * and Claire Brantley <brantleyc@bit-sys.com>
6  * Copyright 2012 BIT Systems
7  *
8  * $Id$
9  *
10  * Wireshark - Network traffic analyzer
11  * By Gerald Combs <gerald@wireshark.org>
12  * Copyright 1998 Gerald Combs
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27  */
28
29 #include "config.h"
30
31 #include <glib.h>
32
33 #include <epan/packet.h>
34 #include <epan/prefs.h>
35
36 static guint ar_drone_port = 0;
37
38 /* ************************************************ */
39 /* Begin static variable declaration/initialization */
40 /* ************************************************ */
41
42 /* ar_drone Protocol */
43 static int proto_ar_drone = -1;
44
45 /* Headers */
46 static int hf_command = -1;
47 static int hf_PCMD_id = -1;
48 static int hf_PCMD_flag = -1;
49 static int hf_PCMD_roll = -1;
50 static int hf_PCMD_pitch = -1;
51 static int hf_PCMD_gaz = -1;
52 static int hf_PCMD_yaw = -1;
53 static int hf_REF_id = -1;
54 static int hf_REF_ctrl = -1;
55 static int hf_FTRIM_seq = -1;
56 static int hf_CONFIG_seq = -1;
57 static int hf_CONFIG_name = -1;
58 static int hf_CONFIG_val = -1;
59 static int hf_CONFIG_ID_seq = -1;
60 static int hf_CONFIG_ID_session = -1;
61 static int hf_CONFIG_ID_user = -1;
62 static int hf_CONFIG_ID_app = -1;
63 static int hf_COMWDG = -1;
64 static int hf_LED_seq = -1;
65 static int hf_LED_anim = -1;
66 static int hf_LED_freq = -1;
67 static int hf_LED_sec = -1;
68 static int hf_ANIM_seq = -1;
69 static int hf_ANIM_anim = -1;
70 static int hf_ANIM_sec = -1;
71 static int hf_CTRL_seq = -1;
72 static int hf_CTRL_mode = -1;
73 static int hf_CTRL_fsize = -1;
74
75 /**Subtrees */
76 static gint ett_FTRIM = -1;
77 static gint ett_ar_drone = -1;
78 static gint ett_PCMD = -1;
79 static gint ett_REF = -1;
80 static gint ett_CONFIG = -1;
81 static gint ett_CONFIG_ID = -1;
82 static gint ett_COMWDG = -1;
83 static gint ett_LED = -1;
84 static gint ett_ANIM = -1;
85 static gint ett_CTRL = -1;
86
87 /* Value String */
88 static const value_string REF_types_vs[] = {
89     { 0x38323038, "FLYING MODE" },
90     { 0x37393532, "EMERGENCY LANDING" },
91     { 0x37363936, "LANDING MODE" },
92     { 0, NULL },
93 };
94 static const value_string PCMD_flag_vs[] = {
95     { 0x30 , "DO NOT ALLOW ROLL/PITCH" },
96     { 0x31 , "ALLOW ROLL/PITCH" },
97     { 0 , NULL },
98 };
99
100 static const string_string CTRL_mode_vs[] = {
101     { "4" , " (CFG_GET_CONTROL_MODE)" },
102     { "5" , " (ACK_CONTROL_MODE)" },
103     { "6" , " (CUSTOM_CFG_GET_CONTROL_MODE)" },
104     { 0, NULL },
105 };
106
107 /* ********************************************** */
108 /* End static variable declaration/initialization */
109 /* ********************************************** */
110 static int
111 dissect_ar_drone(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
112 {
113     gint offset, length,
114          master_offset = 0;
115     proto_item *ti, *sub_item;
116     proto_tree *ar_tree, *sub_tree;
117     char* command;
118
119     if (!tvb_bytes_exist(tvb, 0, 3))
120         return 0;
121
122     /* Make sure the packet we're dissecting is a ar_drone packet */
123     if(strcmp(tvb_get_ephemeral_string(tvb,0,3),"AT*"))
124         return 0;
125
126     col_set_str(pinfo->cinfo, COL_PROTOCOL, "ar_drone");
127     col_set_str(pinfo->cinfo, COL_INFO,"AR Drone Packet");
128
129     /* Initialize ar_drone Packet tree with subtrees */
130     ti = proto_tree_add_item(tree, proto_ar_drone, tvb, 0, -1, ENC_NA);
131     ar_tree = proto_item_add_subtree(ti, ett_ar_drone);
132
133     while(tvb_reported_length_remaining(tvb, master_offset) > 3)
134     {
135         /* Get a string to compare our command strings (aka "AT*PCMD", etc.) to */
136         offset = tvb_find_guint8(tvb, master_offset, -1, '=');
137         if (offset < master_offset)
138             return master_offset;
139
140         command = tvb_get_ephemeral_string(tvb, master_offset, offset-master_offset);
141         sub_item = proto_tree_add_string(ar_tree, hf_command, tvb, master_offset, -1, 
142                         tvb_get_ephemeral_string(tvb, master_offset+3, offset-master_offset-3));
143
144
145         if(!strncmp(command,"AT*PCMD",7))
146         { 
147             /** Parse according the PCMD layout: */
148             guint8 PCMD_byte;
149             char *PCMD_str;
150
151             sub_tree = proto_item_add_subtree(sub_item, ett_PCMD);
152
153             offset = master_offset + 8;
154
155             /* Add PCMD ID */
156             length = tvb_find_guint8(tvb, offset, -1, ',') - offset;
157             proto_tree_add_item(sub_tree, hf_PCMD_id, tvb, offset, length, ENC_ASCII|ENC_NA);
158             offset += (length + 1);
159
160             /* Add PCMD Flag */
161             length = tvb_find_guint8(tvb, offset, -1, ',') - offset;
162             proto_tree_add_item(sub_tree, hf_PCMD_flag, tvb, offset, length, ENC_ASCII|ENC_NA);
163             offset += (length + 1);
164
165             /* Add PCMD Roll */
166             length = tvb_find_guint8(tvb, offset, -1, ',') - offset;
167             ti = proto_tree_add_item(sub_tree, hf_PCMD_roll, tvb, offset, length, ENC_ASCII|ENC_NA);
168
169             PCMD_byte = tvb_get_guint8(tvb, offset);
170             if (PCMD_byte == 0x30) 
171             {
172                 PCMD_str = " (NO CHANGE)";
173             }
174             else if(PCMD_byte == 0x2d)
175             {
176                 PCMD_byte = tvb_get_guint8(tvb, offset + 1);
177                 if(PCMD_byte == 0x30) 
178                 {
179                     PCMD_str = " (NO CHANGE)";
180                 } 
181                 else 
182                 {
183                     PCMD_str = " (ROLL LEFT)";
184                 }
185             }
186             else
187             {
188                 PCMD_str = " (ROLL RIGHT)";
189             }
190             proto_item_append_string(ti, PCMD_str);
191             offset += (length + 1);
192
193             /* Add PCMD Pitch */
194             length = tvb_find_guint8(tvb, offset, -1, ',') - offset;
195             ti = proto_tree_add_item(sub_tree, hf_PCMD_pitch, tvb, offset, length, ENC_ASCII|ENC_NA);
196
197             PCMD_byte = tvb_get_guint8(tvb, offset);
198             if (PCMD_byte == 0x30) 
199             {
200                 PCMD_str = " (NO CHANGE)";
201             }
202             else if(PCMD_byte == 0x2d)
203             {
204                 PCMD_byte = tvb_get_guint8(tvb, offset + 1);
205                 if(PCMD_byte == 0x30) 
206                 {
207                     PCMD_str = " (NO CHANGE)";
208                 } 
209                 else 
210                 {
211                     PCMD_str = " (PITCH FORWARD)";
212                 }
213             }
214             else
215             {
216                 PCMD_str = " (PITCH BACKWARD)";
217             }
218             proto_item_append_string(ti, PCMD_str);
219             offset += (length + 1);
220
221             /* Add PCMD Gaz */
222             length = tvb_find_guint8(tvb, offset, -1, ',') - offset;
223             ti = proto_tree_add_item(sub_tree, hf_PCMD_gaz, tvb, offset, length, ENC_ASCII|ENC_NA);
224
225             PCMD_byte = tvb_get_guint8(tvb, offset);
226             if (PCMD_byte == 0x30) 
227             {
228                 PCMD_str = " (NO CHANGE)";
229             }
230             else if(PCMD_byte == 0x2d)
231             {
232                 PCMD_byte = tvb_get_guint8(tvb, offset + 1);
233                 if(PCMD_byte == 0x30) 
234                 {
235                     PCMD_str = " (NO CHANGE)";
236                 } 
237                 else 
238                 {
239                     PCMD_str = " (DECREASE VERT SPEED)";
240                 }
241             }
242             else
243             {
244                 PCMD_str = " (INCREASE VERT SPEED)";
245             }
246             proto_item_append_string(ti, PCMD_str);
247             offset += (length + 1);
248
249             /* Add PCMD Yaw */
250             length = tvb_find_guint8(tvb, offset, -1, 0x0d) - offset;
251             ti = proto_tree_add_item(sub_tree, hf_PCMD_yaw, tvb, offset, length, ENC_ASCII|ENC_NA);
252
253             PCMD_byte = tvb_get_guint8(tvb, offset);
254             if (PCMD_byte == 0x30) 
255             {
256                 PCMD_str = " (NO CHANGE)";
257             }
258             else if(PCMD_byte == 0x2d)
259             {
260                 PCMD_byte = tvb_get_guint8(tvb, offset + 1);
261                 if(PCMD_byte == 0x30) 
262                 {
263                     PCMD_str = " (NO CHANGE)";
264                 } 
265                 else 
266                 {
267                     PCMD_str = " (ROTATE LEFT)";
268                 }
269             }
270             else
271             {
272                 PCMD_str = " (ROTATE RIGHT)";
273             }
274             proto_item_append_string(ti, PCMD_str);
275             offset += (length + 1);
276         } 
277         else if(!strncmp(command, "AT*REF",6))
278         {
279             /** Parse according to the REF layout: */
280             sub_tree = proto_item_add_subtree(sub_item, ett_REF);
281
282             offset = master_offset + 7;
283
284             /* Add REF ID */
285             length = tvb_find_guint8(tvb, offset, -1, ',') - offset;
286             proto_tree_add_item(sub_tree, hf_REF_id, tvb, offset, length, ENC_ASCII|ENC_NA);
287             offset += (length + 1);
288
289             /* Add REF ctrl */
290             length = tvb_find_guint8(tvb, offset, -1, 0x0d) - offset;
291             proto_tree_add_item(sub_tree, hf_REF_ctrl, tvb, offset, length, ENC_ASCII|ENC_NA);
292             offset += (length + 1);
293
294         } else if(!strncmp(command, "AT*CONFIG_IDS", 13))
295         {
296             /** Parse according to the CONFIG_ID layout:  */
297             sub_tree = proto_item_add_subtree(sub_item, ett_CONFIG_ID);
298
299             offset = master_offset + 14;
300
301             /* Add Sequence Number */
302             length = tvb_find_guint8(tvb, offset, -1, ',') - offset;
303             proto_tree_add_item(sub_tree, hf_CONFIG_ID_seq, tvb, offset, length, ENC_ASCII|ENC_NA);
304             offset += (length + 1);
305
306             /* Add Session ID */
307             length = tvb_find_guint8(tvb, offset, -1, ',') - offset;
308             proto_tree_add_item(sub_tree, hf_CONFIG_ID_session, tvb, offset, length, ENC_ASCII|ENC_NA);
309             offset += (length + 1);
310
311             /* Add User ID */
312             length = tvb_find_guint8(tvb, offset, -1, ',') - offset;
313             proto_tree_add_item(sub_tree, hf_CONFIG_ID_user, tvb, offset, length, ENC_ASCII|ENC_NA);
314             offset += (length + 1);
315
316             /* Add Application ID */
317             length = tvb_find_guint8(tvb, offset, -1, 0x0d) - offset;
318             proto_tree_add_item(sub_tree, hf_CONFIG_ID_app, tvb, offset, length, ENC_ASCII|ENC_NA);
319             offset += (length + 1);
320
321         } else if(!strncmp(command, "AT*ANIM", 7))
322         {
323             /** Parse according to the ANIM layout: */
324             sub_tree = proto_item_add_subtree(sub_item, ett_ANIM);
325
326             offset = master_offset + 8;
327
328             /* Add sequence */
329             length = tvb_find_guint8(tvb, offset, -1, ',') - offset;
330             proto_tree_add_item(sub_tree, hf_ANIM_seq, tvb, offset, length, ENC_ASCII|ENC_NA);
331             offset += (length + 1);
332
333             /* Add Animation */
334             length = tvb_find_guint8(tvb, offset, -1, ',') - offset;
335             proto_tree_add_item(sub_tree, hf_ANIM_anim, tvb, offset, length, ENC_ASCII|ENC_NA);
336             offset += (length + 1);
337
338             /* Add animation time(sec) */
339             length = tvb_find_guint8(tvb, offset, -1, 0x0d) - offset;
340             proto_tree_add_item(sub_tree, hf_ANIM_sec, tvb, offset, length, ENC_ASCII|ENC_NA);
341             offset += (length + 1);
342
343         } else if(!strncmp(command, "AT*FTRIM", 8))
344         {
345             /** Parse according to the FTRIM layout: */
346             sub_tree = proto_item_add_subtree(sub_item, ett_FTRIM);
347
348             offset = master_offset + 9;
349
350             /* Add sequence number */
351             length = tvb_find_guint8(tvb, offset, -1, 0x0d) - offset;
352             ti = proto_tree_add_text(sub_tree, tvb, master_offset, length, "(Sets the reference for the horizontal plane)");
353             proto_tree_add_item(sub_tree, hf_FTRIM_seq, tvb, offset, length, ENC_ASCII|ENC_NA);
354             offset += (length + 1);\
355         } else if(!strncmp(command, "AT*CONFIG", 9))
356         {
357             /** Parse according to the CONFIG layout: */
358             sub_tree = proto_item_add_subtree(sub_item, ett_CONFIG);
359
360             offset = master_offset + 10;
361
362             /* Add sequence */
363             length = tvb_find_guint8(tvb, offset, -1, ',') - offset;
364             proto_tree_add_item(sub_tree, hf_CONFIG_seq, tvb, offset, length, ENC_ASCII|ENC_NA);
365             offset += (length + 1);
366
367             /* Add Name */
368             length = tvb_find_guint8(tvb, offset, -1, ',') - offset;
369             proto_tree_add_item(sub_tree, hf_CONFIG_name, tvb, offset, length, ENC_ASCII|ENC_NA);
370             offset += (length + 1);
371
372             /* Add Value */
373             length = tvb_find_guint8(tvb, offset, -1, 0x0d) - offset;
374             proto_tree_add_item(sub_tree, hf_CONFIG_val, tvb, offset, length, ENC_ASCII|ENC_NA);
375             offset += (length + 1);
376
377         } else if(!strncmp(command, "AT*LED", 6))
378         {
379             /** Parse according to the LED layout: */
380             sub_tree = proto_item_add_subtree(sub_item, ett_LED);
381
382             offset = master_offset + 7;
383
384             /* Add sequence */
385             length = tvb_find_guint8(tvb, offset, -1, ',') - offset;
386             proto_tree_add_item(sub_tree, hf_LED_seq, tvb, offset, length, ENC_ASCII|ENC_NA);
387             offset += (length + 1);
388
389             /* Add animation to play */
390             length = tvb_find_guint8(tvb, offset, -1, ',') - offset;
391             proto_tree_add_item(sub_tree, hf_LED_anim, tvb, offset, length, ENC_ASCII|ENC_NA);
392             offset += (length + 1);
393
394             /* Add frequency */
395             length = tvb_find_guint8(tvb, offset, -1, ',') - offset;
396             proto_tree_add_item(sub_tree, hf_LED_freq, tvb, offset, length, ENC_ASCII|ENC_NA);
397             offset += (length + 1);
398
399             /* Add Time to play in sec  */
400             length = tvb_find_guint8(tvb, offset, -1, 0x0d) - offset;
401             proto_tree_add_item(sub_tree, hf_LED_sec, tvb, offset, length, ENC_ASCII|ENC_NA);
402             offset += (length + 1);
403
404         }else if(!strncmp(command, "AT*COMWDG", 9))
405         {
406             /** Parse according to the COMWDG layout: */
407             sub_tree = proto_item_add_subtree(sub_item, ett_COMWDG);
408
409             offset = master_offset + 10;
410
411             /* Add sequence number */
412             length = tvb_find_guint8(tvb, offset, -1, 0x0d) - offset;
413             proto_tree_add_item(sub_tree, hf_COMWDG, tvb, offset, length, ENC_ASCII|ENC_NA);
414             offset += (length + 1);
415
416         }else if(!strncmp(command, "AT*CTRL", 7))
417         {
418             /** Parse according to the CTRL layout: */
419             sub_tree = proto_item_add_subtree(sub_item, ett_CTRL);
420
421             offset = master_offset + 8;
422
423             /* Add sequence */
424             length = tvb_find_guint8(tvb, offset, -1, ',') - offset;
425             proto_tree_add_item(sub_tree, hf_CTRL_seq, tvb, offset, length, ENC_ASCII|ENC_NA);
426             offset += (length + 1);
427
428             /* Add Mode */
429             length = tvb_find_guint8(tvb, offset, -1, ',') - offset;
430             ti = proto_tree_add_item(sub_tree, hf_CTRL_mode, tvb, offset, length, ENC_ASCII|ENC_NA);
431             proto_item_append_text(ti, "%s", 
432                     str_to_str(tvb_get_ephemeral_string(tvb, offset, length), CTRL_mode_vs, " (Unknown Mode)"));
433             offset += (length + 1);
434
435             /* Add File Size */
436             length = tvb_find_guint8(tvb, offset, -1, 0x0d) - offset;
437             proto_tree_add_item(sub_tree, hf_CTRL_fsize, tvb, offset, length, ENC_ASCII|ENC_NA);
438             offset += (length + 1);
439         } 
440         else
441         {
442             /* Unknown command, just abort */
443             return master_offset;
444         }
445
446         proto_item_set_len(sub_item, offset-master_offset);
447         master_offset = offset;
448     }
449
450     return master_offset;
451 }
452
453 void
454 proto_register_ar_drone(void)
455 {
456     /* Setup protocol header array */
457     static hf_register_info hf[] = {
458     { &hf_command,
459         { "Command", "ar_drone.command",
460         FT_STRING, BASE_NONE,
461         NULL, 0x0,
462         NULL, HFILL }
463     },
464     { &hf_PCMD_id,
465         { "Sequence Number", "ar_drone.pcmd.id",
466         FT_STRING, BASE_NONE,
467         NULL, 0x0,
468         "Progressive Command ID", HFILL }
469     },
470     { &hf_PCMD_flag,
471         { "Flag", "ar_drone.pcmd.flag",
472         FT_STRING, BASE_NONE,
473         NULL/*VALS(PCMD_flag_vs)*/, 0x0,
474         "Progressive Command Flag", HFILL }
475     },
476     { &hf_PCMD_roll,
477         { "Roll", "ar_drone.pcmd.roll",
478         FT_STRING, BASE_NONE,
479         NULL, 0x0,
480         "Progressive Command Roll", HFILL }
481     },
482     { &hf_PCMD_pitch,
483         { "Pitch", "ar_drone.pcmd.pitch",
484         FT_STRING, BASE_NONE,
485         NULL, 0x0,
486         "Progressive Command Pitch", HFILL }
487     },
488     { &hf_PCMD_gaz,
489         { "Gaz", "ar_drone.pcmd.gaz",
490         FT_STRING, BASE_NONE,
491         NULL, 0x0,
492         "Progressive Command Gaz", HFILL }
493         },
494     { &hf_PCMD_yaw,
495         { "Yaw", "ar_drone.pcmd.yaw",
496         FT_STRING, BASE_NONE,
497         NULL, 0x0,
498         "Progressive Command Yaw", HFILL }
499         },
500     { &hf_REF_id,
501         { "Sequence Number", "ar_drone.ref.id",
502         FT_STRING, BASE_NONE,
503         NULL, 0x0,
504         "Reference ID", HFILL }
505     },
506     { &hf_REF_ctrl,
507         { "Control Command", "ar_drone.ref.ctrl",
508         FT_STRING, BASE_NONE,
509         NULL/*VALS(REF_types_vs)*/, 0x0,
510         NULL, HFILL }
511     },
512     { &hf_FTRIM_seq,
513         { "Sequence Number", "ar_drone.ftrim.seq",
514         FT_STRING, BASE_NONE,
515         NULL, 0x0,
516         "Flap Trim / Horizontal Plane Reference", HFILL }
517     },
518     { &hf_CONFIG_ID_seq,
519         { "Sequence Number", "ar_drone.configids.seq",
520         FT_STRING, BASE_NONE,
521         NULL, 0x0,
522         "Configuration ID sequence number", HFILL }
523     },
524     { &hf_CONFIG_ID_session,
525         { "Current Session ID", "ar_drone.configids.session",
526         FT_STRING, BASE_NONE,
527         NULL, 0x0,
528         "Configuration ID current session ID", HFILL }
529     },
530     { &hf_CONFIG_ID_user,
531         { "Current User ID", "ar_drone.configids.user",
532         FT_STRING, BASE_NONE,
533         NULL, 0x0,
534         "Configuration ID current user ID", HFILL }
535     },
536     { &hf_CONFIG_ID_app,
537         { "Current Application ID", "ar_drone.configids.app",
538         FT_STRING, BASE_NONE,
539         NULL, 0x0,
540         "Configuration ID current application ID", HFILL }
541     },
542     { &hf_COMWDG,
543         { "Command WatchDog Request", "ar_drone.comwdg",
544         FT_STRING, BASE_NONE,
545         NULL, 0x0,
546         "Command WatchDog Reset request", HFILL }
547     },
548     { &hf_CONFIG_seq,
549         { "Sequence Number", "ar_drone.config.seq",
550         FT_STRING, BASE_NONE,
551         NULL, 0x0,
552         "Configuration Seq Num", HFILL }
553     },
554     { &hf_CONFIG_name,
555         { "Option Name", "ar_drone.config.name",
556         FT_STRING, BASE_NONE,
557         NULL, 0x0,
558         NULL, HFILL }
559     },
560     { &hf_CONFIG_val,
561         { "Option Parameter", "ar_drone.config.val",
562         FT_STRING, BASE_NONE,
563         NULL, 0x0,
564         NULL, HFILL }
565     },
566     { &hf_LED_seq,
567         { "Sequence Number", "ar_drone.led.seq",
568         FT_STRING, BASE_NONE,
569         NULL, 0x0,
570         "LED Sequence Number", HFILL }
571     },
572     { &hf_LED_anim,
573         { "Selected Animation", "ar_drone.led.anim",
574         FT_STRING, BASE_NONE,
575         NULL, 0x0,
576         "Selected LED Animation", HFILL }
577     },
578     { &hf_LED_freq,
579         { "Animation Frequency", "ar_drone.led.freq",
580         FT_STRING, BASE_NONE,
581         NULL, 0x0,
582         "LED Animation Frequency", HFILL }
583     },
584     { &hf_LED_sec,
585         { "LED Animation Length (Seconds)", "ar_drone.led.sec",
586         FT_STRING, BASE_NONE,
587         NULL, 0x0,
588         "LED Anim Length", HFILL }
589     },
590     { &hf_ANIM_seq,
591         { "Animation Sequence Number", "ar_drone.anim.seq",
592         FT_STRING, BASE_NONE,
593         NULL, 0x0,
594         "Movment(Animation) Sequence #", HFILL }
595     },
596     { &hf_ANIM_anim,
597         { "Selected Animation Number", "ar_drone.anim.num",
598         FT_STRING, BASE_NONE,
599         NULL, 0x0,
600         "Movment(Animation) to Play", HFILL }
601     },
602     { &hf_ANIM_sec,
603         { "Animation Duration (seconds)", "ar_drone.anim.sec",
604         FT_STRING, BASE_NONE,
605         NULL, 0x0,
606         "Movment(Animation) Time in Seconds", HFILL }
607     },
608     { &hf_CTRL_seq,
609         { "Sequence Number", "ar_drone.ctrl.seq",
610         FT_STRING, BASE_NONE,
611         NULL, 0x0,
612         NULL, HFILL }
613     },
614     { &hf_CTRL_mode,
615         { "Control Mode", "ar_drone.ctrl.mode",
616         FT_STRING, BASE_NONE,
617         NULL, 0x0,
618         NULL, HFILL }
619     },
620     { &hf_CTRL_fsize,
621         { "Firmware Update File Size (0 for no update)", "ar_drone.ctrl.filesize",
622         FT_STRING, BASE_NONE,
623         NULL, 0x0,
624         NULL, HFILL }
625     }
626     };
627
628     /* Setup protocol subtree array */
629     static gint *ett[] = {
630     &ett_ar_drone,
631     &ett_PCMD,
632     &ett_REF,
633     &ett_FTRIM,
634     &ett_CONFIG,
635     &ett_CONFIG_ID,
636     &ett_COMWDG,
637     &ett_LED,
638     &ett_ANIM,
639     &ett_CTRL
640     };
641
642     module_t *drone_module;
643
644
645     /* Setup protocol info */
646     proto_ar_drone = proto_register_protocol (
647         "AR Drone Packet", /* name       */
648         "ar drone",      /* short name */
649         "ar_drone"       /* abbrev     */
650     );
651
652     proto_register_field_array(proto_ar_drone, hf, array_length(hf));
653     proto_register_subtree_array(ett, array_length(ett));
654
655     drone_module = prefs_register_protocol(proto_ar_drone, NULL);
656
657     prefs_register_uint_preference(drone_module, "udp.port",
658                                    "AR Drone UDP Port",
659                                    "AR Drone UDP port",
660                                    10,
661                                    &ar_drone_port);
662
663 }
664
665 void
666 proto_reg_handoff_ar_drone(void)
667 {
668     static dissector_handle_t ar_drone_handle;
669     static guint old_port = 0;
670     static gboolean initialized = FALSE;
671
672     if (initialized == FALSE) {
673         ar_drone_handle = new_create_dissector_handle(dissect_ar_drone, proto_ar_drone);
674
675         heur_dissector_add("udp", dissect_ar_drone, proto_ar_drone);
676
677         initialized = TRUE;
678     }
679
680     /* Register UDP port for dissection */
681     if(old_port != 0 && old_port != ar_drone_port){
682     dissector_delete_uint("udp.port", old_port, ar_drone_handle);
683     }
684
685     if(ar_drone_port != 0 && old_port != ar_drone_port) {
686         dissector_add_uint("udp.port", ar_drone_port, ar_drone_handle);
687     }
688
689     old_port = ar_drone_port;
690 }
691 /*
692  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
693  *
694  * Local variables:
695  * c-basic-offset: 4
696  * tab-width: 4
697  * indent-tabs-mode: nil
698  * End:
699  *
700  * vi: set shiftwidth=4 tabstop=4 expandtab:
701  * :indentSize=4:tabSize=4:noTabs=true:
702  */