2 ******************************************************************************
4 * @file uavobjectgeneratorflight.cpp
5 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
6 * @brief produce flight code for uavobjects
8 * @see The GNU Public License (GPL) Version 3
10 *****************************************************************************/
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * You should have received a copy of the GNU General Public License along
23 * with this program; if not, write to the Free Software Foundation, Inc.,
24 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include "uavobjectgeneratorwireshark.h"
31 bool UAVObjectGeneratorWireshark::generate(UAVObjectParser
*parser
, QString templatepath
, QString outputpath
)
33 fieldTypeStrHf
<< "FT_INT8" << "FT_INT16" << "FT_INT32" << "FT_UINT8"
34 << "FT_UINT16" << "FT_UINT32" << "FT_FLOAT" << "FT_UINT8";
35 fieldTypeStrGlib
<< "gint8" << "gint16" << "gint32" << "guint8"
36 << "guint16" << "guint32" << "gfloat" << "guint8";
38 wiresharkCodePath
= QDir(templatepath
+ QString("ground/gcs/src/plugins/uavobjects/wireshark"));
40 wiresharkOutputPath
= QDir(outputpath
);
41 wiresharkOutputPath
.mkpath(wiresharkOutputPath
.absolutePath());
43 wiresharkCodeTemplate
= readFile(wiresharkCodePath
.absoluteFilePath("op-uavobjects/packet-op-uavobjects.c.template"));
44 wiresharkMakeTemplate
= readFile(wiresharkCodePath
.absoluteFilePath("op-uavobjects/Makefile.common.template"));
46 if (wiresharkCodeTemplate
.isNull() || wiresharkMakeTemplate
.isNull()) {
47 cerr
<< "Error: Could not open wireshark template files." << endl
;
51 /* Copy static files for wireshark plugins root directory into output directory */
52 QStringList topstaticfiles
;
53 topstaticfiles
<< "Custom.m4" << "Custom.make" << "Custom.nmake";
54 for (int i
= 0; i
< topstaticfiles
.length(); ++i
) {
55 QFile::copy(wiresharkCodePath
.absoluteFilePath(topstaticfiles
[i
]),
56 wiresharkOutputPath
.absoluteFilePath(topstaticfiles
[i
]));
59 /* Copy static files for op-uavtalk dissector into output directory */
60 QDir uavtalkOutputPath
= QDir(outputpath
+ QString("wireshark/op-uavtalk"));
61 uavtalkOutputPath
.mkpath(uavtalkOutputPath
.absolutePath());
62 QStringList uavtalkstaticfiles
;
63 uavtalkstaticfiles
<< "AUTHORS" << "COPYING" << "ChangeLog";
64 uavtalkstaticfiles
<< "CMakeLists.txt" << "Makefile.nmake";
65 uavtalkstaticfiles
<< "Makefile.am" << "moduleinfo.h" << "moduleinfo.nmake";
66 uavtalkstaticfiles
<< "plugin.rc.in";
67 uavtalkstaticfiles
<< "Makefile.common" << "packet-op-uavtalk.c";
68 for (int i
= 0; i
< uavtalkstaticfiles
.length(); ++i
) {
69 QFile::copy(wiresharkCodePath
.absoluteFilePath("op-uavtalk/" + uavtalkstaticfiles
[i
]),
70 uavtalkOutputPath
.absoluteFilePath(uavtalkstaticfiles
[i
]));
73 /* Copy static files for op-uavobjects dissector into output directory */
74 QDir uavobjectsOutputPath
= QDir(outputpath
+ QString("wireshark/op-uavobjects"));
75 uavobjectsOutputPath
.mkpath(uavobjectsOutputPath
.absolutePath());
76 QStringList uavostaticfiles
;
77 uavostaticfiles
<< "AUTHORS" << "COPYING" << "ChangeLog";
78 uavostaticfiles
<< "CMakeLists.txt" << "Makefile.nmake";
79 uavostaticfiles
<< "Makefile.am" << "moduleinfo.h" << "moduleinfo.nmake";
80 uavostaticfiles
<< "plugin.rc.in";
81 for (int i
= 0; i
< uavostaticfiles
.length(); ++i
) {
82 QFile::copy(wiresharkCodePath
.absoluteFilePath("op-uavobjects/" + uavostaticfiles
[i
]),
83 uavobjectsOutputPath
.absoluteFilePath(uavostaticfiles
[i
]));
86 /* Generate the per-object files from the templates, and keep track of the list of generated filenames */
88 for (int objidx
= 0; objidx
< parser
->getNumObjects(); ++objidx
) {
89 ObjectInfo
*info
= parser
->getObjectByIndex(objidx
);
90 process_object(info
, uavobjectsOutputPath
);
91 objFileNames
.append(" packet-op-uavobjects-" + info
->namelc
+ ".c");
94 /* Write the uavobject dissector's Makefile.common */
95 wiresharkMakeTemplate
.replace(QString("$(UAVOBJFILENAMES)"), objFileNames
);
96 bool res
= writeFileIfDifferent(uavobjectsOutputPath
.absolutePath() + "/Makefile.common",
97 wiresharkMakeTemplate
);
99 cout
<< "Error: Could not write wireshark Makefile" << endl
;
108 * Generate the Flight object files
110 bool UAVObjectGeneratorWireshark::process_object(ObjectInfo
*info
, QDir outputpath
)
116 // Prepare output strings
117 QString outCode
= wiresharkCodeTemplate
;
119 // Replace common tags
120 replaceCommonTags(outCode
, info
);
122 // Replace the $(SUBTREES) and $(SUBTREESTATICS) tags
124 QString subtreestatics
;
125 subtreestatics
.append(QString("static gint ett_uavo = -1;\r\n"));
126 subtrees
.append(QString("&ett_uavo,\r\n"));
127 for (int n
= 0; n
< info
->fields
.length(); ++n
) {
128 if (info
->fields
[n
]->numElements
> 1) {
129 /* Reserve a subtree for each array */
130 subtreestatics
.append(QString("static gint ett_%1_%2 = -1;\r\n")
132 .arg(info
->fields
[n
]->name
));
133 subtrees
.append(QString("&ett_%1_%2,\r\n")
135 .arg(info
->fields
[n
]->name
));
138 outCode
.replace(QString("$(SUBTREES)"), subtrees
);
139 outCode
.replace(QString("$(SUBTREESTATICS)"), subtreestatics
);
141 // Replace the $(FIELDHANDLES) tag
144 for (int n
= 0; n
< info
->fields
.length(); ++n
) {
145 fields
.append(QString("static int hf_op_uavobjects_%1_%2 = -1;\r\n")
147 .arg(info
->fields
[n
]->name
));
148 if (info
->fields
[n
]->numElements
> 1) {
149 QStringList elemNames
= info
->fields
[n
]->elementNames
;
150 for (int m
= 0; m
< elemNames
.length(); ++m
) {
151 fields
.append(QString("static int hf_op_uavobjects_%1_%2_%3 = -1;\r\n")
153 .arg(info
->fields
[n
]->name
)
158 outCode
.replace(QString("$(FIELDHANDLES)"), fields
);
160 // Replace the $(ENUMFIELDNAMES) tag
162 for (int n
= 0; n
< info
->fields
.length(); ++n
) {
163 // Only for enum types
164 if (info
->fields
[n
]->type
== FIELDTYPE_ENUM
) {
165 enums
.append(QString("/* Field %1 information */\r\n").arg(info
->fields
[n
]->name
));
166 enums
.append(QString("/* Enumeration options for field %1 */\r\n").arg(info
->fields
[n
]->name
));
167 enums
.append(QString("static const value_string uavobjects_%1_%2[]= {\r\n")
169 .arg(info
->fields
[n
]->name
));
170 // Go through each option
171 QStringList options
= info
->fields
[n
]->options
;
172 for (int m
= 0; m
< options
.length(); ++m
) {
173 enums
.append(QString("\t{ %1, \"%2\" },\r\n")
175 .arg(options
[m
].replace(QRegExp(ENUM_SPECIAL_CHARS
), "")));
177 enums
.append(QString("\t{ 0, NULL }\r\n"));
178 enums
.append(QString("};\r\n"));
181 outCode
.replace(QString("$(ENUMFIELDNAMES)"), enums
);
183 // Replace the $(POPULATETREE) tag
185 for (int n
= 0; n
< info
->fields
.length(); ++n
) {
186 if (info
->fields
[n
]->numElements
== 1) {
187 treefields
.append(QString(" ptvcursor_add(cursor, hf_op_uavobjects_%1_%2, sizeof(%3), ENC_LITTLE_ENDIAN);\r\n")
189 .arg(info
->fields
[n
]->name
)
190 .arg(fieldTypeStrGlib
[info
->fields
[n
]->type
]));
192 treefields
.append(QString(" {\r\n"));
193 treefields
.append(QString(" proto_item * it = NULL;\r\n"));
194 treefields
.append(QString(" it = ptvcursor_add_no_advance(cursor, hf_op_uavobjects_%1_%2, 1, ENC_NA);\r\n")
196 .arg(info
->fields
[n
]->name
));
197 treefields
.append(QString(" ptvcursor_push_subtree(cursor, it, ett_%1_%2);\r\n")
199 .arg(info
->fields
[n
]->name
));
200 /* Populate each array element into the table */
201 QStringList elemNames
= info
->fields
[n
]->elementNames
;
202 for (int m
= 0; m
< elemNames
.length(); ++m
) {
203 treefields
.append(QString(" ptvcursor_add(cursor, hf_op_uavobjects_%1_%2_%3, sizeof(%4), ENC_LITTLE_ENDIAN);\r\n")
205 .arg(info
->fields
[n
]->name
)
207 .arg(fieldTypeStrGlib
[info
->fields
[n
]->type
]));
209 treefields
.append(QString(" ptvcursor_pop_subtree(cursor);\r\n"));
210 treefields
.append(QString(" }\r\n"));
213 outCode
.replace(QString("$(POPULATETREE)"), treefields
);
215 // Replace the $(HEADERFIELDS) tag
216 QString headerfields
;
217 headerfields
.append(QString(" static hf_register_info hf[] = {\r\n"));
218 for (int n
= 0; n
< info
->fields
.length(); ++n
) {
219 // For non-array fields
220 if (info
->fields
[n
]->numElements
== 1) {
221 headerfields
.append(QString("\t { &hf_op_uavobjects_%1_%2,\r\n")
223 .arg(info
->fields
[n
]->name
));
224 headerfields
.append(QString("\t { \"%1\", \"%2.%3\", %4,\r\n")
225 .arg(info
->fields
[n
]->name
)
227 .arg(info
->fields
[n
]->name
)
228 .arg(fieldTypeStrHf
[info
->fields
[n
]->type
]));
229 if (info
->fields
[n
]->type
== FIELDTYPE_ENUM
) {
230 headerfields
.append(QString("\t BASE_DEC, VALS(uavobjects_%1_%2), 0x0, NULL, HFILL \r\n")
232 .arg(info
->fields
[n
]->name
));
233 } else if (info
->fields
[n
]->type
== FIELDTYPE_FLOAT32
) {
234 headerfields
.append(QString("\t BASE_NONE, NULL, 0x0, NULL, HFILL \r\n"));
236 headerfields
.append(QString("\t BASE_DEC, NULL, 0x0, NULL, HFILL\r\n"));
238 headerfields
.append(QString("\t },\r\n"));
239 headerfields
.append(QString("\t },\r\n"));
241 headerfields
.append(QString("\t { &hf_op_uavobjects_%1_%2,\r\n")
243 .arg(info
->fields
[n
]->name
));
244 headerfields
.append(QString("\t { \"%1\", \"%2.%3\", FT_NONE,\r\n")
245 .arg(info
->fields
[n
]->name
)
247 .arg(info
->fields
[n
]->name
));
248 headerfields
.append(QString("\t BASE_NONE, NULL, 0x0, NULL, HFILL\r\n"));
249 headerfields
.append(QString("\t },\r\n"));
250 headerfields
.append(QString("\t },\r\n"));
252 QStringList elemNames
= info
->fields
[n
]->elementNames
;
253 for (int m
= 0; m
< elemNames
.length(); ++m
) {
254 headerfields
.append(QString("\t { &hf_op_uavobjects_%1_%2_%3,\r\n")
256 .arg(info
->fields
[n
]->name
)
258 headerfields
.append(QString("\t { \"%1\", \"%2.%3.%4\", %5,\r\n")
261 .arg(info
->fields
[n
]->name
)
263 .arg(fieldTypeStrHf
[info
->fields
[n
]->type
]));
264 if (info
->fields
[n
]->type
== FIELDTYPE_ENUM
) {
265 headerfields
.append(QString("\t BASE_DEC, VALS(uavobjects_%1_%2), 0x0, NULL, HFILL \r\n")
267 .arg(info
->fields
[n
]->name
));
268 } else if (info
->fields
[n
]->type
== FIELDTYPE_FLOAT32
) {
269 headerfields
.append(QString("\t BASE_NONE, NULL, 0x0, NULL, HFILL \r\n"));
271 headerfields
.append(QString("\t BASE_DEC, NULL, 0x0, NULL, HFILL\r\n"));
273 headerfields
.append(QString("\t },\r\n"));
274 headerfields
.append(QString("\t },\r\n"));
278 headerfields
.append(QString(" };\r\n"));
279 outCode
.replace(QString("$(HEADERFIELDS)"), headerfields
);
281 // Write the flight code
282 bool res
= writeFileIfDifferent(outputpath
.absolutePath() + "/packet-op-uavobjects-" + info
->namelc
+ ".c", outCode
);
284 cout
<< "Error: Could not write wireshark code files" << endl
;