Add python tools that (partially) parse the QXDM database
This commit is contained in:
parent
7c5858ec43
commit
cef7ef60d0
|
@ -0,0 +1,38 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Code to parse the ASCII Database files of QXDM
|
||||||
|
# (C) 2017 by Harald Welte <laforge@gnumonks.org>
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along
|
||||||
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
from optparse import OptionParser
|
||||||
|
from qxdm_db import QxdmDb
|
||||||
|
|
||||||
|
parser = OptionParser()
|
||||||
|
parser.add_option("-d", "--database-dir", dest="db_dir",
|
||||||
|
help="QXDM Database directory to use")
|
||||||
|
|
||||||
|
(options, args) = parser.parse_args()
|
||||||
|
|
||||||
|
if not options.db_dir:
|
||||||
|
print "You have to specify the database directory"
|
||||||
|
exit(2)
|
||||||
|
|
||||||
|
db = QxdmDb(options.db_dir)
|
||||||
|
|
||||||
|
db.export_valstr_events()
|
||||||
|
db.export_valstr_event_descs()
|
||||||
|
db.export_valstr_logitems()
|
||||||
|
db.export_valstr_msgs()
|
|
@ -0,0 +1,160 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Code to parse the ASCII Database files of QXDM
|
||||||
|
# (C) 2017 by Harald Welte <laforge@gnumonks.org>
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along
|
||||||
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
import csv
|
||||||
|
|
||||||
|
def export_value_str(name, vals, flavor='osmocom'):
|
||||||
|
if flavor == 'osmocom':
|
||||||
|
print("const struct value_string %s[] = {" % name);
|
||||||
|
elif flavor == 'wireshark':
|
||||||
|
print("const value_string %s[] = {" % name);
|
||||||
|
for v in sorted(vals.iterkeys(), key=int):
|
||||||
|
print("\t{ %d, \"%s\" }," % (int(v), vals[v]));
|
||||||
|
print("\t{ 0, NULL }")
|
||||||
|
print("};");
|
||||||
|
|
||||||
|
class QxdmDb(object):
|
||||||
|
file_fields = {
|
||||||
|
'Enum': ['id', 'name', 'entries_id', 'unknown'],
|
||||||
|
'EnumEntry': ['enum_id', 'value', 'name', 'unknown'],
|
||||||
|
'EventID': ['value', 'name', 'category_id', 'description_id'],
|
||||||
|
'EventCategory': ['value', 'name', 'unknown', 'unknown2'],
|
||||||
|
'Struct': ['id', 'index', 'unknown', 'field_id', 'unknown2', 'unknown3', 'unknown4'],
|
||||||
|
'Field': ['id', 'name', 'bits', 'unknown1', 'unknown2',
|
||||||
|
'unknown3', 'unknown4', 'unknown5'],
|
||||||
|
'Description': ['id', 'text'],
|
||||||
|
'LogItem': ['id', 'name', 'category_id', 'unknown'],
|
||||||
|
'LogCategory': ['id', 'name', 'unknown', 'parent_id'],
|
||||||
|
'MessageLevel': ['id', 'level', 'name', 'category_id'],
|
||||||
|
'MessageCategory': ['id', 'name', 'unknown', 'parent_id'],
|
||||||
|
}
|
||||||
|
_csvdicts= {}
|
||||||
|
|
||||||
|
descs = {}
|
||||||
|
enums = {}
|
||||||
|
events = {}
|
||||||
|
event_cats = {}
|
||||||
|
logitems = {}
|
||||||
|
log_cats = {}
|
||||||
|
msgs = {}
|
||||||
|
msg_cats = {}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def read_into_dict(fname, fieldnames=None):
|
||||||
|
csvfile = open(fname, 'rb')
|
||||||
|
r = csv.DictReader(csvfile, fieldnames=fieldnames, delimiter='^')
|
||||||
|
return r
|
||||||
|
|
||||||
|
def gen_descs(self):
|
||||||
|
for d in self._csvdicts['Description']:
|
||||||
|
self.descs[int(d['id'], base=0)] = d['text']
|
||||||
|
|
||||||
|
def gen_enums(self):
|
||||||
|
for e in self._csvdicts['Enum']:
|
||||||
|
self.enums[int(e['id'], base=0)] = {'name': e['name'], 'entries': {}}
|
||||||
|
for ee in self._csvdicts['EnumEntry']:
|
||||||
|
self.enums[int(ee['enum_id'], base=0)]['entries'][int(ee['value'],base=0)] = ee['name']
|
||||||
|
|
||||||
|
def gen_events(self):
|
||||||
|
for c in self._csvdicts['EventCategory']:
|
||||||
|
self.event_cats[int(c['value'],base=0)] = {'name': c['name'], 'events': []}
|
||||||
|
|
||||||
|
for e in self._csvdicts['EventID']:
|
||||||
|
val_int = int(e['value'], base=0)
|
||||||
|
self.events[val_int] = {'name': e['name']}
|
||||||
|
if e['description_id'] != '-1':
|
||||||
|
self.events[val_int]['description'] = self.descs[int(e['description_id'], base=0)]
|
||||||
|
cats = e['category_id'].split(',')
|
||||||
|
for c in cats:
|
||||||
|
cat_int = int(c, base=0)
|
||||||
|
if cat_int in self.event_cats:
|
||||||
|
self.event_cats[cat_int]['events'].append(self.events[val_int])
|
||||||
|
|
||||||
|
def gen_logitems(self):
|
||||||
|
for c in self._csvdicts['LogCategory']:
|
||||||
|
self.log_cats[int(c['id'],base=0)] = {'name': c['name'], 'items': []}
|
||||||
|
|
||||||
|
for l in self._csvdicts['LogItem']:
|
||||||
|
val_int = int(l['id'], base=0)
|
||||||
|
self.logitems[val_int] = {'name': l['name']}
|
||||||
|
|
||||||
|
cats = l['category_id'].split(',')
|
||||||
|
for c in cats:
|
||||||
|
cat_int = int(c, base=0)
|
||||||
|
if cat_int in self.log_cats:
|
||||||
|
self.log_cats[cat_int]['items'].append(self.logitems[val_int])
|
||||||
|
|
||||||
|
def gen_msglevels(self):
|
||||||
|
def strip_suffix(s):
|
||||||
|
slash = s.rfind('/')
|
||||||
|
if slash == -1:
|
||||||
|
return s
|
||||||
|
else:
|
||||||
|
return s[:slash]
|
||||||
|
for c in self._csvdicts['MessageCategory']:
|
||||||
|
self.msg_cats[int(c['id'],base=0)] = {'name': c['name'], 'msgs': []}
|
||||||
|
|
||||||
|
for l in self._csvdicts['MessageLevel']:
|
||||||
|
val_int = int(l['id'], base=0)
|
||||||
|
level_int = int(l['level'], base=0)
|
||||||
|
if not val_int in self.msgs:
|
||||||
|
self.msgs[val_int] = {'levels':{}, 'name': strip_suffix(l['name'])}
|
||||||
|
self.msgs[val_int]['levels'][level_int] = {'name': l['name']}
|
||||||
|
|
||||||
|
cats = l['category_id'].split(',')
|
||||||
|
for c in cats:
|
||||||
|
cat_int = int(c, base=0)
|
||||||
|
if cat_int in self.msg_cats:
|
||||||
|
self.msg_cats[cat_int]['msgs'].append(self.msgs[val_int]['levels'][level_int])
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self, dir_to_db):
|
||||||
|
for f in self.file_fields:
|
||||||
|
fname = '%s/%s.txt' % (dir_to_db, f)
|
||||||
|
self._csvdicts[f] = self.read_into_dict(fname, self.file_fields[f])
|
||||||
|
self.gen_descs()
|
||||||
|
self.gen_enums()
|
||||||
|
self.gen_events()
|
||||||
|
self.gen_logitems()
|
||||||
|
self.gen_msglevels()
|
||||||
|
|
||||||
|
def export_valstr_events(self):
|
||||||
|
def f(v):
|
||||||
|
return v['name']
|
||||||
|
vals = dict(zip(self.events, map(f, self.events.values())))
|
||||||
|
export_value_str('diag_event_vals', vals)
|
||||||
|
|
||||||
|
def export_valstr_event_descs(self):
|
||||||
|
vals = {}
|
||||||
|
for e in self.events:
|
||||||
|
if 'description' in self.events[e]:
|
||||||
|
vals[e] = self.events[e]['description']
|
||||||
|
export_value_str('diag_event_descs', vals)
|
||||||
|
|
||||||
|
def export_valstr_logitems(self):
|
||||||
|
def f(v):
|
||||||
|
return v['name']
|
||||||
|
vals = dict(zip(self.logitems, map(f, self.logitems.values())))
|
||||||
|
export_value_str('diag_log_item_vals', vals)
|
||||||
|
|
||||||
|
def export_valstr_msgs(self):
|
||||||
|
def f(v):
|
||||||
|
return v['name']
|
||||||
|
vals = dict(zip(self.msgs, map(f, self.msgs.values())))
|
||||||
|
export_value_str('diag_msg_vals', vals)
|
Loading…
Reference in New Issue