Merged in f5soh/librepilot/update_credits (pull request #529)
[librepilot.git] / ground / uavobjgenerator / generators / wireshark / uavobjectgeneratorwireshark.cpp
blob7c5bf86b5dd73f19bfe1a29eacb29df8258e3e85
1 /**
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
20 * for more details.
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"
29 using namespace std;
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;
48 return false;
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 */
87 QString objFileNames;
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);
98 if (!res) {
99 cout << "Error: Could not write wireshark Makefile" << endl;
100 return false;
103 return true;
108 * Generate the Flight object files
110 bool UAVObjectGeneratorWireshark::process_object(ObjectInfo *info, QDir outputpath)
112 if (info == NULL) {
113 return false;
116 // Prepare output strings
117 QString outCode = wiresharkCodeTemplate;
119 // Replace common tags
120 replaceCommonTags(outCode, info);
122 // Replace the $(SUBTREES) and $(SUBTREESTATICS) tags
123 QString subtrees;
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")
131 .arg(info->namelc)
132 .arg(info->fields[n]->name));
133 subtrees.append(QString("&ett_%1_%2,\r\n")
134 .arg(info->namelc)
135 .arg(info->fields[n]->name));
138 outCode.replace(QString("$(SUBTREES)"), subtrees);
139 outCode.replace(QString("$(SUBTREESTATICS)"), subtreestatics);
141 // Replace the $(FIELDHANDLES) tag
142 QString type;
143 QString fields;
144 for (int n = 0; n < info->fields.length(); ++n) {
145 fields.append(QString("static int hf_op_uavobjects_%1_%2 = -1;\r\n")
146 .arg(info->namelc)
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")
152 .arg(info->namelc)
153 .arg(info->fields[n]->name)
154 .arg(elemNames[m]));
158 outCode.replace(QString("$(FIELDHANDLES)"), fields);
160 // Replace the $(ENUMFIELDNAMES) tag
161 QString enums;
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")
168 .arg(info->namelc)
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")
174 .arg(m)
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
184 QString treefields;
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")
188 .arg(info->namelc)
189 .arg(info->fields[n]->name)
190 .arg(fieldTypeStrGlib[info->fields[n]->type]));
191 } else {
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")
195 .arg(info->namelc)
196 .arg(info->fields[n]->name));
197 treefields.append(QString(" ptvcursor_push_subtree(cursor, it, ett_%1_%2);\r\n")
198 .arg(info->namelc)
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")
204 .arg(info->namelc)
205 .arg(info->fields[n]->name)
206 .arg(elemNames[m])
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")
222 .arg(info->namelc)
223 .arg(info->fields[n]->name));
224 headerfields.append(QString("\t { \"%1\", \"%2.%3\", %4,\r\n")
225 .arg(info->fields[n]->name)
226 .arg(info->namelc)
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")
231 .arg(info->namelc)
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"));
235 } else {
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"));
240 } else {
241 headerfields.append(QString("\t { &hf_op_uavobjects_%1_%2,\r\n")
242 .arg(info->namelc)
243 .arg(info->fields[n]->name));
244 headerfields.append(QString("\t { \"%1\", \"%2.%3\", FT_NONE,\r\n")
245 .arg(info->fields[n]->name)
246 .arg(info->namelc)
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")
255 .arg(info->namelc)
256 .arg(info->fields[n]->name)
257 .arg(elemNames[m]));
258 headerfields.append(QString("\t { \"%1\", \"%2.%3.%4\", %5,\r\n")
259 .arg(elemNames[m])
260 .arg(info->namelc)
261 .arg(info->fields[n]->name)
262 .arg(elemNames[m])
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")
266 .arg(info->namelc)
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"));
270 } else {
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);
283 if (!res) {
284 cout << "Error: Could not write wireshark code files" << endl;
285 return false;
288 return true;