From a8ac4bb2dffe2dfe8030ad9f34ec10a4f9684d54 Mon Sep 17 00:00:00 2001 From: "Andreas.Eversberg" Date: Sun, 24 Oct 2010 14:12:58 +0000 Subject: [PATCH] Introducing "gsmmap" to convert SYSTEM INFORMATION log into a KML map --- src/Makefile | 15 +- src/host/gsmmap/.gitignore | 35 ++ src/host/gsmmap/Makefile.am | 18 + src/host/gsmmap/configure.ac | 25 ++ src/host/gsmmap/geo.c | 47 +++ src/host/gsmmap/geo.h | 12 + src/host/gsmmap/git-version-gen | 151 ++++++++ src/host/gsmmap/gsmmap.c | 646 ++++++++++++++++++++++++++++++++ src/host/gsmmap/locate.c | 182 +++++++++ src/host/gsmmap/locate.h | 8 + src/host/gsmmap/log.c | 377 +++++++++++++++++++ src/host/gsmmap/log.h | 80 ++++ 12 files changed, 1595 insertions(+), 1 deletion(-) create mode 100644 src/host/gsmmap/.gitignore create mode 100644 src/host/gsmmap/Makefile.am create mode 100644 src/host/gsmmap/configure.ac create mode 100644 src/host/gsmmap/geo.c create mode 100644 src/host/gsmmap/geo.h create mode 100755 src/host/gsmmap/git-version-gen create mode 100644 src/host/gsmmap/gsmmap.c create mode 100644 src/host/gsmmap/locate.c create mode 100644 src/host/gsmmap/locate.h create mode 100644 src/host/gsmmap/log.c create mode 100644 src/host/gsmmap/log.h diff --git a/src/Makefile b/src/Makefile index 6d16b7d6c..c8caff083 100644 --- a/src/Makefile +++ b/src/Makefile @@ -12,7 +12,7 @@ OSMOCORE_CONFIGURE_ENV= LIBOSMOCORE_LIBS=$(TOPDIR)/shared/libosmocore/build-host LIBOSMOCORE_CFLAGS=-I$(TOPDIR)/shared/libosmocore/include \ LIBOSMOVTY_CFLAGS=-I$(TOPDIR)/shared/libosmocore/include -all: libosmocore-host libosmocore-target layer23 osmocon firmware +all: libosmocore-host libosmocore-target layer23 osmocon gsmmap firmware libosmocore-host: shared/libosmocore/build-host/src/.libs/libosmocore.la @@ -57,6 +57,19 @@ host/osmocon/osmocon: host/osmocon/Makefile libosmocore-host make -C host/osmocon +.PHONY: gsmmap +gsmmap: host/gsmmap/gsmmap + +host/gsmmap/configure: host/gsmmap/configure.ac + cd host/gsmmap && autoreconf -i + +host/gsmmap/Makefile: host/gsmmap/configure + cd host/gsmmap && $(OSMOCORE_CONFIGURE_ENV) ./configure + +host/gsmmap/gsmmap: host/gsmmap/Makefile libosmocore-host + make -C host/gsmmap + + .PHONY: layer23 layer23: host/layer23/layer23 diff --git a/src/host/gsmmap/.gitignore b/src/host/gsmmap/.gitignore new file mode 100644 index 000000000..661fd133d --- /dev/null +++ b/src/host/gsmmap/.gitignore @@ -0,0 +1,35 @@ +# autoreconf by-products +*.in + +aclocal.m4 +autom4te.cache/ +configure +depcomp +install-sh +missing + +# configure by-products +.deps/ +Makefile + +config.status +version.h + +# build by-products +*.o + +gsmmap + +# various +.version +.tarball-version + +# IDA file +*.id* +*.nam +*.til + +# Other test files +*.dump +*.bin +*.log diff --git a/src/host/gsmmap/Makefile.am b/src/host/gsmmap/Makefile.am new file mode 100644 index 000000000..d866d02e4 --- /dev/null +++ b/src/host/gsmmap/Makefile.am @@ -0,0 +1,18 @@ +AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6 + +# versioning magic +BUILT_SOURCES = $(top_srcdir)/.version +$(top_srcdir)/.version: + echo $(VERSION) > $@-t && mv $@-t $@ +dist-hook: + echo $(VERSION) > $(distdir)/.tarball-version + +INCLUDES = $(all_includes) -I$(top_srcdir)/include +AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) + +sbin_PROGRAMS = gsmmap + +INCLUDES += -I../layer23/include -DHOST_BUILD +gsmmap_SOURCES = gsmmap.c geo.c locate.c log.c ../layer23/src/common/sysinfo.c ../layer23/src/common/networks.c +gsmmap_LDADD = $(LIBOSMOCORE_LIBS) -lm + diff --git a/src/host/gsmmap/configure.ac b/src/host/gsmmap/configure.ac new file mode 100644 index 000000000..45a00e2ee --- /dev/null +++ b/src/host/gsmmap/configure.ac @@ -0,0 +1,25 @@ +dnl Process this file with autoconf to produce a configure script +AC_INIT([gsmmap], + m4_esyscmd([./git-version-gen .tarball-version]), + [baseband-devel@lists.osmocom.org]) + +AM_INIT_AUTOMAKE([dist-bzip2]) + +dnl kernel style compile messages +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +dnl checks for programs +AC_PROG_MAKE_SET +AC_PROG_CC +AC_PROG_INSTALL + +dnl checks for libraries +PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore) + +dnl checks for header files +AC_HEADER_STDC + +dnl Checks for typedefs, structures and compiler characteristics + +AC_OUTPUT( + Makefile) diff --git a/src/host/gsmmap/geo.c b/src/host/gsmmap/geo.c new file mode 100644 index 000000000..3fb9b7a28 --- /dev/null +++ b/src/host/gsmmap/geo.c @@ -0,0 +1,47 @@ +#include +#include + +void geo2space(double *x, double *y, double *z, double lon, double lat) +{ + *z = sin(lat / 180.0 * PI) * POLE_RADIUS; + *x = sin(lon / 180.0 * PI) * cos(lat / 180.0 * PI) * EQUATOR_RADIUS; + *y = -cos(lon / 180.0 * PI) * cos(lat / 180.0 * PI) * EQUATOR_RADIUS; +} + +void space2geo(double *lon, double *lat, double x, double y, double z) +{ + double r; + + /* bring geoid to 1m radius */ + z = z / POLE_RADIUS; + x = x / EQUATOR_RADIUS; + y = y / EQUATOR_RADIUS; + + /* normalize */ + r = sqrt(x * x + y * y + z * z); + z = z / r; + x = x / r; + y = y / r; + + *lat = asin(z) / PI * 180; + *lon = atan2(x, -y) / PI * 180; +} + +double distinspace(double x1, double y1, double z1, double x2, double y2, + double z2) +{ + double x = x1 - x2; + double y = y1 - y2; + double z = z1 - z2; + + return sqrt(x * x + y * y + z * z); +} + +double distonplane(double x1, double y1, double x2, double y2) +{ + double x = x1 - x2; + double y = y1 - y2; + + return sqrt(x * x + y * y); +} + diff --git a/src/host/gsmmap/geo.h b/src/host/gsmmap/geo.h new file mode 100644 index 000000000..25e26cbac --- /dev/null +++ b/src/host/gsmmap/geo.h @@ -0,0 +1,12 @@ +/* WGS 84 */ +#define EQUATOR_RADIUS 6378137.0 +#define POLE_RADIUS 6356752.314 + +#define PI 3.1415926536 + +void geo2space(double *x, double *y, double *z, double lat, double lon); +void space2geo(double *lat, double *lon, double x, double y, double z); +double distinspace(double x1, double y1, double z1, double x2, double y2, + double z2); +double distonplane(double x1, double y1, double x2, double y2); + diff --git a/src/host/gsmmap/git-version-gen b/src/host/gsmmap/git-version-gen new file mode 100755 index 000000000..652fac680 --- /dev/null +++ b/src/host/gsmmap/git-version-gen @@ -0,0 +1,151 @@ +#!/bin/sh +# Print a version string. +scriptversion=2010-01-28.01 + +# Copyright (C) 2007-2010 Free Software Foundation, Inc. +# +# 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 3 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, see . + +# This script is derived from GIT-VERSION-GEN from GIT: http://git.or.cz/. +# It may be run two ways: +# - from a git repository in which the "git describe" command below +# produces useful output (thus requiring at least one signed tag) +# - from a non-git-repo directory containing a .tarball-version file, which +# presumes this script is invoked like "./git-version-gen .tarball-version". + +# In order to use intra-version strings in your project, you will need two +# separate generated version string files: +# +# .tarball-version - present only in a distribution tarball, and not in +# a checked-out repository. Created with contents that were learned at +# the last time autoconf was run, and used by git-version-gen. Must not +# be present in either $(srcdir) or $(builddir) for git-version-gen to +# give accurate answers during normal development with a checked out tree, +# but must be present in a tarball when there is no version control system. +# Therefore, it cannot be used in any dependencies. GNUmakefile has +# hooks to force a reconfigure at distribution time to get the value +# correct, without penalizing normal development with extra reconfigures. +# +# .version - present in a checked-out repository and in a distribution +# tarball. Usable in dependencies, particularly for files that don't +# want to depend on config.h but do want to track version changes. +# Delete this file prior to any autoconf run where you want to rebuild +# files to pick up a version string change; and leave it stale to +# minimize rebuild time after unrelated changes to configure sources. +# +# It is probably wise to add these two files to .gitignore, so that you +# don't accidentally commit either generated file. +# +# Use the following line in your configure.ac, so that $(VERSION) will +# automatically be up-to-date each time configure is run (and note that +# since configure.ac no longer includes a version string, Makefile rules +# should not depend on configure.ac for version updates). +# +# AC_INIT([GNU project], +# m4_esyscmd([build-aux/git-version-gen .tarball-version]), +# [bug-project@example]) +# +# Then use the following lines in your Makefile.am, so that .version +# will be present for dependencies, and so that .tarball-version will +# exist in distribution tarballs. +# +# BUILT_SOURCES = $(top_srcdir)/.version +# $(top_srcdir)/.version: +# echo $(VERSION) > $@-t && mv $@-t $@ +# dist-hook: +# echo $(VERSION) > $(distdir)/.tarball-version + +case $# in + 1) ;; + *) echo 1>&2 "Usage: $0 \$srcdir/.tarball-version"; exit 1;; +esac + +tarball_version_file=$1 +nl=' +' + +# First see if there is a tarball-only version file. +# then try "git describe", then default. +if test -f $tarball_version_file +then + v=`cat $tarball_version_file` || exit 1 + case $v in + *$nl*) v= ;; # reject multi-line output + [0-9]*) ;; + *) v= ;; + esac + test -z "$v" \ + && echo "$0: WARNING: $tarball_version_file seems to be damaged" 1>&2 +fi + +if test -n "$v" +then + : # use $v +elif + v=`git describe --abbrev=4 --match='osmocon_v*' HEAD 2>/dev/null \ + || git describe --abbrev=4 HEAD 2>/dev/null` \ + && case $v in + osmocon_[0-9]*) ;; + osmocon_v[0-9]*) ;; + *) (exit 1) ;; + esac +then + # Is this a new git that lists number of commits since the last + # tag or the previous older version that did not? + # Newer: v6.10-77-g0f8faeb + # Older: v6.10-g0f8faeb + case $v in + *-*-*) : git describe is okay three part flavor ;; + *-*) + : git describe is older two part flavor + # Recreate the number of commits and rewrite such that the + # result is the same as if we were using the newer version + # of git describe. + vtag=`echo "$v" | sed 's/-.*//'` + numcommits=`git rev-list "$vtag"..HEAD | wc -l` + v=`echo "$v" | sed "s/\(.*\)-\(.*\)/\1-$numcommits-\2/"`; + ;; + esac + + # Change the first '-' to a '.', so version-comparing tools work properly. + # Remove the "g" in git describe's output string, to save a byte. + v=`echo "$v" | sed 's/-/./;s/\(.*\)-g/\1-/;s/^osmocon_//'`; +else + v="UNKNOWN" +fi + +v=`echo "$v" |sed 's/^v//'` + +# Don't declare a version "dirty" merely because a time stamp has changed. +git status > /dev/null 2>&1 + +dirty=`sh -c 'git diff-index --name-only HEAD' 2>/dev/null` || dirty= +case "$dirty" in + '') ;; + *) # Append the suffix only if there isn't one already. + case $v in + *-dirty) ;; + *) v="$v-dirty" ;; + esac ;; +esac + +# Omit the trailing newline, so that m4_esyscmd can use the result directly. +echo "$v" | tr -d '\012' + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/src/host/gsmmap/gsmmap.c b/src/host/gsmmap/gsmmap.c new file mode 100644 index 000000000..01f3670c0 --- /dev/null +++ b/src/host/gsmmap/gsmmap.c @@ -0,0 +1,646 @@ +/* Conversion of logged cells to KML file */ + +/* (C) 2010 by Andreas Eversberg + * + * All Rights Reserved + * + * 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. + * + */ +#warning todo bsic +#include +#include +#include +#include +#include +#include + +#define GSM_TA_M 553.85 +#define PI 3.1415926536 + +#include +#include + +#include "log.h" +#include "geo.h" +#include "locate.h" + +/* + * structure of power and cell infos + */ + +struct power power; +struct sysinfo sysinfo; +static struct node_power *node_power_first = NULL; +static struct node_power **node_power_last_p = &node_power_first; +struct node_mcc *node_mcc_first = NULL; +int log_lines = 0, log_debug = 0; + + +static void nomem(void) +{ + fprintf(stderr, "No mem!\n"); + exit(-ENOMEM); +} + +static void add_power() +{ + struct node_power *node_power; + +// printf("New Power\n"); + /* append or insert to list */ + node_power = calloc(1, sizeof(struct node_power)); + if (!node_power) + nomem(); + *node_power_last_p = node_power; + node_power_last_p = &node_power->next; + memcpy(&node_power->power, &power, sizeof(power)); +} + +static void add_sysinfo() +{ + struct gsm48_sysinfo s; + struct node_mcc *mcc; + struct node_mnc *mnc; + struct node_lac *lac; + struct node_cell *cell; + struct node_meas *meas; + + memset(&s, 0, sizeof(s)); + + /* decode sysinfo */ + if (sysinfo.si1[2]) + gsm48_decode_sysinfo1(&s, + (struct gsm48_system_information_type_1 *) sysinfo.si1, + 23); + if (sysinfo.si2[2]) + gsm48_decode_sysinfo2(&s, + (struct gsm48_system_information_type_2 *) sysinfo.si2, + 23); + if (sysinfo.si2bis[2]) + gsm48_decode_sysinfo2bis(&s, + (struct gsm48_system_information_type_2bis *) + sysinfo.si2bis, + 23); + if (sysinfo.si2ter[2]) + gsm48_decode_sysinfo2ter(&s, + (struct gsm48_system_information_type_2ter *) + sysinfo.si2ter, + 23); + if (sysinfo.si3[2]) + gsm48_decode_sysinfo3(&s, + (struct gsm48_system_information_type_3 *) sysinfo.si3, + 23); + if (sysinfo.si4[2]) + gsm48_decode_sysinfo4(&s, + (struct gsm48_system_information_type_4 *) sysinfo.si4, + 23); + + mcc = get_node_mcc(s.mcc); + if (!mcc) + nomem(); + mnc = get_node_mnc(mcc, s.mnc); + if (!mnc) + nomem(); + lac = get_node_lac(mnc, s.lac); + if (!lac) + nomem(); + cell = get_node_cell(lac, s.cell_id); + if (!cell) + nomem(); + meas = add_node_meas(cell); + if (!meas) + nomem(); + if (!cell->content) { + cell->content = 1; + memcpy(&cell->sysinfo, &sysinfo, sizeof(sysinfo)); + memcpy(&cell->s, &s, sizeof(s)); + } else { + if (memcmp(&cell->sysinfo.si1, sysinfo.si1, + sizeof(sysinfo.si1))) { +new_sysinfo: + fprintf(stderr, "FIXME: the cell changed sysinfo\n"); + return; + } + if (memcmp(&cell->sysinfo.si2, sysinfo.si2, + sizeof(sysinfo.si2))) + goto new_sysinfo; + if (memcmp(&cell->sysinfo.si2bis, sysinfo.si2bis, + sizeof(sysinfo.si2bis))) + goto new_sysinfo; + if (memcmp(&cell->sysinfo.si2ter, sysinfo.si2ter, + sizeof(sysinfo.si2ter))) + goto new_sysinfo; + if (memcmp(&cell->sysinfo.si3, sysinfo.si3, + sizeof(sysinfo.si3))) + goto new_sysinfo; + if (memcmp(&cell->sysinfo.si4, sysinfo.si4, + sizeof(sysinfo.si4))) + goto new_sysinfo; + } +} + +void kml_header(FILE *outfp, char *name) +{ + /* XML header */ + fprintf(outfp, "\n"); + + /* KML open tag */ + fprintf(outfp, "\n"); + + /* document open tag */ + fprintf(outfp, "\n"); + + /* pushpin */ + fprintf(outfp, "\t\n"); + fprintf(outfp, "\t\n"); + fprintf(outfp, "\t\n"); + fprintf(outfp, "\t\t\n"); + fprintf(outfp, "\t\t\tnormal\n"); + fprintf(outfp, "\t\t\t#sn_placemark_red_pushpin" + "\n"); + fprintf(outfp, "\t\t\n"); + fprintf(outfp, "\t\t\n"); + fprintf(outfp, "\t\t\thighlight\n"); + fprintf(outfp, "\t\t\t#sh_placemark_red_pushpin_highlight" + "\n"); + fprintf(outfp, "\t\t\n"); + fprintf(outfp, "\t\n"); + + fprintf(outfp, "\t\n"); + fprintf(outfp, "\t\n"); + fprintf(outfp, "\t\n"); + fprintf(outfp, "\t\t\n"); + fprintf(outfp, "\t\t\tnormal\n"); + fprintf(outfp, "\t\t\t#sn_placemark_grn_pushpin" + "\n"); + fprintf(outfp, "\t\t\n"); + fprintf(outfp, "\t\t\n"); + fprintf(outfp, "\t\t\thighlight\n"); + fprintf(outfp, "\t\t\t#sh_placemark_grn_pushpin_highlight" + "\n"); + fprintf(outfp, "\t\t\n"); + fprintf(outfp, "\t\n"); + + /* circle */ + fprintf(outfp, "\t\n"); + fprintf(outfp, "\t\n"); + fprintf(outfp, "\t\n"); + fprintf(outfp, "\t\t\n"); + fprintf(outfp, "\t\t\tnormal\n"); + fprintf(outfp, "\t\t\t#sn_placemark_circle\n"); + fprintf(outfp, "\t\t\n"); + fprintf(outfp, "\t\t\n"); + fprintf(outfp, "\t\t\thighlight\n"); + fprintf(outfp, "\t\t\t#sh_placemark_circle_highlight" + "\n"); + fprintf(outfp, "\t\t\n"); + fprintf(outfp, "\t\n"); +} + +void kml_footer(FILE *outfp) +{ + /* document close tag */ + fprintf(outfp, "\n"); + + /* KML close tag */ + fprintf(outfp, "\n"); + +} + +void kml_meas(FILE *outfp, struct node_meas *meas, int n, uint16_t mcc, + uint16_t mnc, uint16_t lac, uint16_t cellid) +{ + struct tm *tm = localtime(&meas->gmt); + + fprintf(outfp, "\t\t\t\t\t\n"); + fprintf(outfp, "\t\t\t\t\t\t%d: %d\n", n, meas->rxlev); + fprintf(outfp, "\t\t\t\t\t\t\n"); + fprintf(outfp, "MCC=%s MNC=%s\nLAC=%04x CELL-ID=%04x\n(%s %s)\n", + gsm_print_mcc(mcc), gsm_print_mnc(mnc), lac, cellid, + gsm_get_mcc(mcc), gsm_get_mnc(mcc, mnc)); + fprintf(outfp, "\n%s", asctime(tm)); + fprintf(outfp, "RX-LEV %d dBm\n", meas->rxlev); + if (meas->ta_valid) + fprintf(outfp, "TA=%d (%d-%d meter)\n", meas->ta, + (int)(GSM_TA_M * meas->ta), + (int)(GSM_TA_M * (meas->ta + 1))); + fprintf(outfp, "\t\t\t\t\t\t\n"); + fprintf(outfp, "\t\t\t\t\t\t\n"); + fprintf(outfp, "\t\t\t\t\t\t\t%.8f\n", + meas->longitude); + fprintf(outfp, "\t\t\t\t\t\t\t%.8f\n", + meas->latitude); + fprintf(outfp, "\t\t\t\t\t\t\t0\n"); + fprintf(outfp, "\t\t\t\t\t\t\t0\n"); + fprintf(outfp, "\t\t\t\t\t\t\trelativeToGround" + "\n"); + fprintf(outfp, "\t\t\t\t\t\t\trelativeToSeaFloor" + "\n"); + fprintf(outfp, "\t\t\t\t\t\t\n"); + fprintf(outfp, "\t\t\t\t\t\t#msn_placemark_circle" + "\n"); + fprintf(outfp, "\t\t\t\t\t\t\n"); + fprintf(outfp, "\t\t\t\t\t\t\t%.8f,%.8f\n", + meas->longitude, meas->latitude); + fprintf(outfp, "\t\t\t\t\t\t\n"); + fprintf(outfp, "\t\t\t\t\t\n"); +} + +static void print_si(void *priv, const char *fmt, ...) +{ + char buffer[1000]; + FILE *outfp = (FILE *)priv; + va_list args; + + va_start(args, fmt); + vsnprintf(buffer, sizeof(buffer) - 1, fmt, args); + buffer[sizeof(buffer) - 1] = '\0'; + va_end(args); + + if (buffer[0]) + fprintf(outfp, "%s", buffer); +} + +double debug_long, debug_lat, debug_x_scale; +FILE *debug_fp; + +void kml_cell(FILE *outfp, struct node_cell *cell) +{ + struct node_meas *meas; + double x, y, z, sum_x = 0, sum_y = 0, sum_z = 0, longitude, latitude; + int n, known = 0; + + meas = cell->meas; + n = 0; + while (meas) { + if (meas->gps_valid && meas->ta_valid) { + geo2space(&x, &y, &z, meas->longitude, meas->latitude); + sum_x += x; + sum_y += y; + sum_z += z; + n++; + } + meas = meas->next; + } + if (!n) + return; + if (n < 3) { + x = sum_x / n; + y = sum_y / n; + z = sum_z / n; + space2geo(&longitude, &latitude, x, y, z); + } else { + struct probe *probe_first = NULL, *probe, + **probe_last_p = &probe_first; + double x_scale; + + /* translate to flat surface */ + meas = cell->meas; + x_scale = 1.0 / cos(meas->latitude / 180.0 * PI); + longitude = meas->longitude; + latitude = meas->latitude; + debug_x_scale = x_scale; + debug_long = longitude; + debug_lat = latitude; + debug_fp = outfp; + while (meas) { + if (meas->gps_valid && meas->ta_valid) { + probe = calloc(1, sizeof(struct probe)); + if (!probe) + nomem(); + probe->x = (meas->longitude - longitude) / + x_scale; + if (x < -180) + x += 360; + else if (x > 180) + x -= 360; + probe->y = meas->latitude - latitude; + probe->dist = GSM_TA_M * (0.5 + + (double)meas->ta) / + (EQUATOR_RADIUS * PI / 180.0); + *probe_last_p = probe; + probe_last_p = &probe->next; + } + meas = meas->next; + } + + /* locate */ + locate_cell(probe_first, &x, &y); + + /* translate from flat surface */ + longitude += x * x_scale; + if (longitude < 0) + longitude += 360; + else if (longitude >= 360) + longitude -= 360; + latitude += y; + + /* remove probes */ + while (probe_first) { + probe = probe_first; + probe_first = probe->next; + free(probe); + } + + known = 1; + } + + if (!known) + return; + + fprintf(outfp, "\t\t\t\t\t\n"); + fprintf(outfp, "\t\t\t\t\t\tMCC=%s MNC=%s\nLAC=%04x " + "CELL-ID=%04x\n(%s %s)\n", gsm_print_mcc(cell->s.mcc), + gsm_print_mnc(cell->s.mnc), cell->s.lac, cell->s.cell_id, + gsm_get_mcc(cell->s.mcc), + gsm_get_mnc(cell->s.mcc, cell->s.mnc)); + fprintf(outfp, "\t\t\t\t\t\t\n"); + gsm48_sysinfo_dump(&cell->s, cell->sysinfo.arfcn, print_si, outfp); + fprintf(outfp, "\t\t\t\t\t\t\n"); + fprintf(outfp, "\t\t\t\t\t\t\n"); + fprintf(outfp, "\t\t\t\t\t\t\t%.8f\n", + longitude); + fprintf(outfp, "\t\t\t\t\t\t\t%.8f\n", latitude); + fprintf(outfp, "\t\t\t\t\t\t\t0\n"); + fprintf(outfp, "\t\t\t\t\t\t\t0\n"); + fprintf(outfp, "\t\t\t\t\t\t\trelativeToGround" + "\n"); + fprintf(outfp, "\t\t\t\t\t\t\trelativeToSeaFloor" + "\n"); + fprintf(outfp, "\t\t\t\t\t\t\n"); + if (known) + fprintf(outfp, "\t\t\t\t\t\t#msn_placemark_grn_" + "pushpin\n"); + else + fprintf(outfp, "\t\t\t\t\t\t#msn_placemark_red_" + "pushpin\n"); + fprintf(outfp, "\t\t\t\t\t\t\n"); + fprintf(outfp, "\t\t\t\t\t\t\t%.8f,%.8f\n", + longitude, latitude); + fprintf(outfp, "\t\t\t\t\t\t\n"); + fprintf(outfp, "\t\t\t\t\t\n"); + + if (!log_lines) + return; + + fprintf(outfp, "\t\n"); + fprintf(outfp, "\t\tLines\n"); + fprintf(outfp, "\t\t0\n"); + fprintf(outfp, "\t\t0\n"); + + geo2space(&x, &y, &z, longitude, latitude); + meas = cell->meas; + n = 0; + while (meas) { + if (meas->gps_valid) { + double mx, my, mz, dist; + + geo2space(&mx, &my, &mz, meas->longitude, + meas->latitude); + dist = distinspace(x, y, z, mx, my, mz); + fprintf(outfp, "\t\t\n"); + fprintf(outfp, "\t\t\tRange\n"); + fprintf(outfp, "\t\t\t\n"); + fprintf(outfp, "Distance: %d\n", (int)dist); + fprintf(outfp, "TA=%d (%d-%d meter)\n", meas->ta, + (int)(GSM_TA_M * meas->ta), + (int)(GSM_TA_M * (meas->ta + 1))); + fprintf(outfp, "\t\t\t\n"); + fprintf(outfp, "\t\t\t0\n"); + fprintf(outfp, "\t\t\t\n"); + fprintf(outfp, "\t\t\t\t1\n"); + fprintf(outfp, "\t\t\t\t\n"); + fprintf(outfp, "%.8f,%.8f\n", longitude, latitude); + fprintf(outfp, "%.8f,%.8f\n", meas->longitude, + meas->latitude); + fprintf(outfp, "\t\t\t\t\n"); + fprintf(outfp, "\t\t\t\n"); + fprintf(outfp, "\t\t\n"); + } + meas = meas->next; + } + fprintf(outfp, "\t\n"); +} + +int main(int argc, char *argv[]) +{ + FILE *infp, *outfp; + int type, n, i; + char *p; + struct node_mcc *mcc; + struct node_mnc *mnc; + struct node_lac *lac; + struct node_cell *cell; + struct node_meas *meas; + + if (argc <= 2) { +usage: + fprintf(stderr, "Usage: %s " + "[lines] [debug]\n", argv[0]); + fprintf(stderr, "lines: Add lines between cell and " + "Measurement point\n"); + fprintf(stderr, "debug: Add debugging of location algorithm.\n" + ); + return 0; + } + + for (i = 3; i < argc; i++) { + if (!strcmp(argv[i], "lines")) + log_lines = 1; + else if (!strcmp(argv[i], "debug")) + log_debug = 1; + else goto usage; + } + + infp = fopen(argv[1], "r"); + if (!infp) { + fprintf(stderr, "Failed to open '%s' for reading\n", argv[1]); + return -EIO; + } + + while ((type = read_log(infp))) { + switch (type) { + case LOG_TYPE_SYSINFO: + add_sysinfo(); + break; + case LOG_TYPE_POWER: + add_power(); + break; + } + } + + fclose(infp); + + if (!strcmp(argv[2], "-")) + outfp = stdout; + else + outfp = fopen(argv[2], "w"); + if (!outfp) { + fprintf(stderr, "Failed to open '%s' for writing\n", argv[2]); + return -EIO; + } + + /* document name */ + p = argv[2]; + while (strchr(p, '/')) + p = strchr(p, '/') + 1; + + kml_header(outfp, p); + mcc = node_mcc_first; + while (mcc) { + printf("MCC: %02x\n", mcc->mcc); + /* folder open */ + fprintf(outfp, "\t\n"); + fprintf(outfp, "\t\tMCC %s (%s)\n", + gsm_print_mcc(mcc->mcc), gsm_get_mcc(mcc->mcc)); + fprintf(outfp, "\t\t0\n"); + mnc = mcc->mnc; + while (mnc) { + printf(" MNC: %02x\n", mnc->mnc); + /* folder open */ + fprintf(outfp, "\t\t\n"); + fprintf(outfp, "\t\t\tMNC %s (%s)\n", + gsm_print_mnc(mnc->mnc), gsm_get_mnc(mcc->mcc, mnc->mnc)); + fprintf(outfp, "\t\t\t0\n"); + lac = mnc->lac; + while (lac) { + printf(" LAC: %04x\n", lac->lac); + /* folder open */ + fprintf(outfp, "\t\t\t\n"); + fprintf(outfp, "\t\t\t\tLAC %04x\n", lac->lac); + fprintf(outfp, "\t\t\t\t0\n"); + cell = lac->cell; + while (cell) { + printf(" CELL: %04x\n", cell->cellid); + fprintf(outfp, "\t\t\t\t\n"); + fprintf(outfp, "\t\t\t\t\tCELL-ID %04x\n", cell->cellid); + fprintf(outfp, "\t\t\t\t\t0\n"); + meas = cell->meas; + n = 0; + while (meas) { + if (meas->ta_valid) + printf(" TA: %d\n", meas->ta); + if (meas->gps_valid) + kml_meas(outfp, meas, ++n, mcc->mcc, mnc->mnc, + lac->lac, cell->cellid); + meas = meas->next; + } + kml_cell(outfp, cell); + /* folder close */ + fprintf(outfp, "\t\t\t\t\n"); + cell = cell->next; + } + /* folder close */ + fprintf(outfp, "\t\t\t\n"); + lac = lac->next; + } + /* folder close */ + fprintf(outfp, "\t\t\n"); + mnc = mnc->next; + } + /* folder close */ + fprintf(outfp, "\t\n"); + mcc = mcc->next; + } +#if 0 + FIXME: power + /* folder open */ + fprintf(outfp, "\t\n"); + fprintf(outfp, "\t\tPower\n"); + fprintf(outfp, "\t\t0\n"); + power = node_power_first; + n = 0; + while (power) { + /* folder open */ + fprintf(outfp, "\t\t\n"); + fprintf(outfp, "\t\t\tPower %d\n", ++n); + fprintf(outfp, "\t\t\t0\n"); + /* folder close */ + fprintf(outfp, "\t\t\n"); + power = power->next; + } + /* folder close */ + fprintf(outfp, "\t\n"); +#endif + kml_footer(outfp); + + fclose(outfp); + + return 0; +} diff --git a/src/host/gsmmap/locate.c b/src/host/gsmmap/locate.c new file mode 100644 index 000000000..ed0ac9312 --- /dev/null +++ b/src/host/gsmmap/locate.c @@ -0,0 +1,182 @@ +/* Algorithm to locate a destination by distance measurement: + */ + +#include +#include +#include + +#include "geo.h" +#include "locate.h" + +#define CIRCLE_PROBE 30.0 +#define FINETUNE_RADIUS 5.0 + +extern double debug_long, debug_lat, debug_x_scale; +extern FILE *debug_fp; +extern int log_debug; + +static double finetune_x[6], finetune_y[6], finetune_dist[6]; + +int locate_cell(struct probe *probe_first, double *min_x, double *min_y) +{ + struct probe *probe, *min_probe; + int i, test_steps, optimized; + double min_dist, dist, x, y, rad, temp; + double circle_probe, finetune_radius; + + /* convert meters into degrees */ + circle_probe = CIRCLE_PROBE / (EQUATOR_RADIUS * PI / 180.0); + finetune_radius = FINETUNE_RADIUS / (EQUATOR_RADIUS * PI / 180.0); + + if (log_debug) { + fprintf(debug_fp, "\n"); + fprintf(debug_fp, "\tDebug Locator\n"); + fprintf(debug_fp, "\t0\n"); + fprintf(debug_fp, "\t0\n"); + } + + /* get probe of minimum distance */ + min_probe = NULL; + probe = probe_first; + min_dist = 42; + i = 0; + while (probe) { + if (log_debug) { + fprintf(debug_fp, "\t\n"); + fprintf(debug_fp, "\t\tMEAS\n"); + fprintf(debug_fp, "\t\t0\n"); + fprintf(debug_fp, "\t\t\n"); + fprintf(debug_fp, "\t\t\t1\n"); + fprintf(debug_fp, "\t\t\t\n"); + rad = 2.0 * 3.1415927 / 35; + for (i = 0; i < 35; i++) { + x = probe->x + probe->dist * sin(rad * i); + y = probe->y + probe->dist * cos(rad * i); + fprintf(debug_fp, "%.8f,%.8f\n", debug_long + + x * debug_x_scale, debug_lat + y); + } + fprintf(debug_fp, "\t\t\t\n"); + fprintf(debug_fp, "\t\t\n"); + fprintf(debug_fp, "\t\n"); + } + + if (!min_probe || probe->dist < min_dist) { + min_probe = probe; + min_dist = probe->dist; + } + probe = probe->next; + i++; + } + + if (i < 3) { + fprintf(stderr, "Need at least 3 points\n"); + return -EINVAL; + } + + /* calculate the number of steps to search for destination point */ + test_steps = 2.0 * 3.1415927 * min_probe->dist / circle_probe; + rad = 2.0 * 3.1415927 / test_steps; + + if (log_debug) { + fprintf(debug_fp, "\t\n"); + fprintf(debug_fp, "\t\tSmallest MEAS\n"); + fprintf(debug_fp, "\t\t0\n"); + fprintf(debug_fp, "\t\t\n"); + fprintf(debug_fp, "\t\t\t1\n"); + fprintf(debug_fp, "\t\t\t\n"); + } + + /* search on a circle for the location of the lowest distance + * to the radius with the greatest distance */ + min_dist = 42; + *min_x = *min_y = 42; + for (i = 0; i < test_steps; i++) { + x = min_probe->x + min_probe->dist * sin(rad * i); + y = min_probe->y + min_probe->dist * cos(rad * i); + if (log_debug) + fprintf(debug_fp, "%.8f,%.8f\n", debug_long + + x * debug_x_scale, debug_lat + y); + /* look for greatest distance */ + dist = 0; + probe = probe_first; + while (probe) { + if (probe != min_probe) { + /* distance to the radius */ + temp = distonplane(probe->x, probe->y, x, y); + temp -= probe->dist; + if (temp < 0) + temp = -temp; + if (temp > dist) + dist = temp; + } + probe = probe->next; + } + if (i == 0 || dist < min_dist) { + min_dist = dist; + *min_x = x; + *min_y = y; + } + } + + if (log_debug) { + fprintf(debug_fp, "\t\t\t\n"); + fprintf(debug_fp, "\t\t\n"); + fprintf(debug_fp, "\t\n"); + + fprintf(debug_fp, "\t\n"); + fprintf(debug_fp, "\t\tFinetune\n"); + fprintf(debug_fp, "\t\t0\n"); + fprintf(debug_fp, "\t\t\n"); + fprintf(debug_fp, "\t\t\t1\n"); + fprintf(debug_fp, "\t\t\t\n"); + } + + min_dist = 9999999999.0; +tune_again: + if (log_debug) + fprintf(debug_fp, "%.8f,%.8f\n", debug_long + + *min_x * debug_x_scale, debug_lat + *min_y); + + /* finetune the point */ + rad = 2.0 * 3.1415927 / 6; + for (i = 0; i < 6; i++) { + x = *min_x + finetune_radius * sin(rad * i); + y = *min_y + finetune_radius * cos(rad * i); + /* search for the point with the lowest sum of distances */ + dist = 0; + probe = probe_first; + while (probe) { + /* distance to the radius */ + temp = distonplane(probe->x, probe->y, x, y); + temp -= probe->dist; + if (temp < 0) + temp = -temp; + dist += temp; + probe = probe->next; + } + finetune_dist[i] = dist; + finetune_x[i] = x; + finetune_y[i] = y; + } + + optimized = 0; + for (i = 0; i < 6; i++) { + if (finetune_dist[i] < min_dist) { + min_dist = finetune_dist[i]; + *min_x = finetune_x[i]; + *min_y = finetune_y[i]; + optimized = 1; + } + } + if (optimized) + goto tune_again; + + if (log_debug) { + fprintf(debug_fp, "\t\t\t\n"); + fprintf(debug_fp, "\t\t\n"); + fprintf(debug_fp, "\t\n"); + fprintf(debug_fp, "\n"); + } + + return 0; +} diff --git a/src/host/gsmmap/locate.h b/src/host/gsmmap/locate.h new file mode 100644 index 000000000..26133452d --- /dev/null +++ b/src/host/gsmmap/locate.h @@ -0,0 +1,8 @@ + +struct probe { + struct probe *next; + double x, y, dist; +}; + +int locate_cell(struct probe *probe_first, double *min_x, double *min_y); + diff --git a/src/host/gsmmap/log.c b/src/host/gsmmap/log.c new file mode 100644 index 000000000..c2db801e3 --- /dev/null +++ b/src/host/gsmmap/log.c @@ -0,0 +1,377 @@ +/* Conversion of logged cells to KML file */ + +/* (C) 2010 by Andreas Eversberg + * + * All Rights Reserved + * + * 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. + * + */ + +#include +#include + +#include + +#include "log.h" + +extern struct power power; +extern struct sysinfo sysinfo; +extern struct node_power *node_power_first; +extern struct node_power **node_power_last_p; +extern struct node_mcc *node_mcc_first; + +struct node_mcc *get_node_mcc(uint16_t mcc) +{ + struct node_mcc *node_mcc; + struct node_mcc **node_mcc_p = &node_mcc_first; + +//printf("add mcc %d\n", mcc); + while (*node_mcc_p) { + /* found in list */ + if ((*node_mcc_p)->mcc == mcc) + return *node_mcc_p; + /* insert into list */ + if ((*node_mcc_p)->mcc > mcc) + break; + node_mcc_p = &((*node_mcc_p)->next); + } + +//printf("new mcc %d\n", mcc); + /* append or insert to list */ + node_mcc = calloc(1, sizeof(struct node_mcc)); + if (!node_mcc) + return NULL; + node_mcc->mcc = mcc; + node_mcc->next = *node_mcc_p; + *node_mcc_p = node_mcc; + return node_mcc; +} + +struct node_mnc *get_node_mnc(struct node_mcc *mcc, uint16_t mnc) +{ + struct node_mnc *node_mnc; + struct node_mnc **node_mnc_p = &mcc->mnc; + + while (*node_mnc_p) { + /* found in list */ + if ((*node_mnc_p)->mnc == mnc) + return *node_mnc_p; + /* insert into list */ + if ((*node_mnc_p)->mnc > mnc) + break; + node_mnc_p = &((*node_mnc_p)->next); + } + + /* append or insert to list */ + node_mnc = calloc(1, sizeof(struct node_mnc)); + if (!node_mnc) + return NULL; + node_mnc->mnc = mnc; + node_mnc->next = *node_mnc_p; + *node_mnc_p = node_mnc; + return node_mnc; +} + +struct node_lac *get_node_lac(struct node_mnc *mnc, uint16_t lac) +{ + struct node_lac *node_lac; + struct node_lac **node_lac_p = &mnc->lac; + + while (*node_lac_p) { + /* found in list */ + if ((*node_lac_p)->lac == lac) + return *node_lac_p; + /* insert into list */ + if ((*node_lac_p)->lac > lac) + break; + node_lac_p = &((*node_lac_p)->next); + } + + /* append or insert to list */ + node_lac = calloc(1, sizeof(struct node_lac)); + if (!node_lac) + return NULL; + node_lac->lac = lac; + node_lac->next = *node_lac_p; + *node_lac_p = node_lac; + return node_lac; +} + +struct node_cell *get_node_cell(struct node_lac *lac, uint16_t cellid) +{ + struct node_cell *node_cell; + struct node_cell **node_cell_p = &lac->cell; + + while (*node_cell_p) { + /* found in list */ + if ((*node_cell_p)->cellid == cellid) + return *node_cell_p; + /* insert into list */ + if ((*node_cell_p)->cellid > cellid) + break; + node_cell_p = &((*node_cell_p)->next); + } + + /* append or insert to list */ + node_cell = calloc(1, sizeof(struct node_cell)); + if (!node_cell) + return NULL; + node_cell->meas_last_p = &node_cell->meas; + node_cell->cellid = cellid; + node_cell->next = *node_cell_p; + *node_cell_p = node_cell; + return node_cell; +} + +struct node_meas *add_node_meas(struct node_cell *cell) +{ + struct node_meas *node_meas; + + /* append to list */ + node_meas = calloc(1, sizeof(struct node_meas)); + if (!node_meas) + return NULL; + node_meas->gmt = sysinfo.gmt; + node_meas->rxlev = sysinfo.rxlev; + if (sysinfo.ta_valid) { + node_meas->ta_valid = 1; + node_meas->ta = sysinfo.ta; + } + if (sysinfo.gps_valid) { + node_meas->gps_valid = 1; + node_meas->longitude = sysinfo.longitude; + node_meas->latitude = sysinfo.latitude; + } + *cell->meas_last_p = node_meas; + cell->meas_last_p = &node_meas->next; + return node_meas; +} + +/* read "," */ +static void read_log_bsic(char *buffer) +{ + char *p; + uint8_t bsic; + + /* skip first spaces */ + while (*buffer == ' ') + buffer++; + + /* read ncc */ + p = buffer; + while (*p > ' ' && *p != ',') + p++; + if (*p == '\0') + return; /* no value */ + *p++ = '\0'; + bsic = atoi(buffer) << 3; + buffer = p; + + /* read latitude */ + bsic |= atoi(buffer); + + sysinfo.bsic = bsic; +} + +/* read " " */ +static void read_log_pos(char *buffer, double *longitude, double *latitude, + uint8_t *valid) +{ + char *p; + + /* skip first spaces */ + while (*buffer == ' ') + buffer++; + + /* read longitude */ + p = buffer; + while (*p > ' ') + p++; + if (*p == '\0') + return; /* no value after longitude */ + *p++ = '\0'; + *longitude = atof(buffer); + buffer = p; + + /* skip second spaces */ + while (*buffer == ' ') + buffer++; + + /* read latitude */ + *latitude = atof(buffer); + + *valid = 1; +} + +/* read " ...." */ +static void read_log_power(char *buffer) +{ + char *p; + int arfcn; + + /* skip first spaces */ + while (*buffer == ' ') + buffer++; + + /* read arfcn */ + p = buffer; + while (*p > ' ') + p++; + if (*p == '\0') + return; /* no value after arfcn */ + *p++ = '\0'; + arfcn = atoi(buffer); + buffer = p; + + while (*buffer) { + /* wrong arfcn */ + if (arfcn < 0 || arfcn > 1023) + break; + /* skip spaces */ + while (*buffer == ' ') + buffer++; + /* get value */ + p = buffer; + while (*p > ' ') + p++; + /* last value */ + if (*p == '\0') { + power.rxlev[arfcn] = atoi(buffer); + break; + } + *p++ = '\0'; + power.rxlev[arfcn] = atoi(buffer); + arfcn++; + buffer = p; + } +} + +/* read "xx xx xx xx xx...." */ +static void read_log_si(char *buffer, uint8_t *data) +{ + uint8_t si[23]; + int i; + +// printf("%s ", buffer); + for (i = 0; i < 23; i++) { + while (*buffer == ' ') + buffer++; + if (*buffer >= '0' && *buffer <= '9') + si[i] = (*buffer - '0') << 4; + else if (*buffer >= 'a' && *buffer <= 'f') + si[i] = (*buffer - 'a' + 10) << 4; + else if (*buffer >= 'A' && *buffer <= 'F') + si[i] = (*buffer - 'A' + 10) << 4; + else + break; + buffer++; + if (*buffer >= '0' && *buffer <= '9') + si[i] += *buffer - '0'; + else if (*buffer >= 'a' && *buffer <= 'f') + si[i] += *buffer - 'a' + 10; + else if (*buffer >= 'A' && *buffer <= 'F') + si[i] += *buffer - 'A' + 10; + else + break; + buffer++; +// printf("%02x ", si[i]); + } +// printf("\n"); + + if (i == 23) + memcpy(data, si, 23); +} + +/* read next record from log file */ +int read_log(FILE *infp) +{ + static int type = LOG_TYPE_NONE, ret; + char buffer[256]; + + memset(&sysinfo, 0, sizeof(sysinfo)); + memset(&power, 0, sizeof(power)); + memset(&power.rxlev, -128, sizeof(power.rxlev)); + + if (feof(infp)) + return LOG_TYPE_NONE; + + while (fgets(buffer, sizeof(buffer), infp)) { + buffer[sizeof(buffer) - 1] = 0; + if (buffer[0]) + buffer[strlen(buffer) - 1] = '\0'; + if (buffer[0] == '[') { + if (!strcmp(buffer, "[sysinfo]")) { + ret = type; + type = LOG_TYPE_SYSINFO; + if (ret != LOG_TYPE_NONE) + return ret; + } else + if (!strcmp(buffer, "[power]")) { + ret = type; + type = LOG_TYPE_POWER; + if (ret != LOG_TYPE_NONE) + return ret; + } else { + type = LOG_TYPE_NONE; + } + continue; + } + switch (type) { + case LOG_TYPE_SYSINFO: + if (!strncmp(buffer, "arfcn ", 6)) + sysinfo.arfcn = atoi(buffer + 6); + else if (!strncmp(buffer, "si1 ", 4)) + read_log_si(buffer + 4, sysinfo.si1); + else if (!strncmp(buffer, "si2 ", 4)) + read_log_si(buffer + 4, sysinfo.si2); + else if (!strncmp(buffer, "si2bis ", 7)) + read_log_si(buffer + 7, sysinfo.si2bis); + else if (!strncmp(buffer, "si2ter ", 7)) + read_log_si(buffer + 7, sysinfo.si2ter); + else if (!strncmp(buffer, "si3 ", 4)) + read_log_si(buffer + 4, sysinfo.si3); + else if (!strncmp(buffer, "si4 ", 4)) + read_log_si(buffer + 4, sysinfo.si4); + else if (!strncmp(buffer, "time ", 5)) + sysinfo.gmt = strtoul(buffer + 5, NULL, 0); + else if (!strncmp(buffer, "position ", 9)) + read_log_pos(buffer + 9, &sysinfo.longitude, + &sysinfo.latitude, &sysinfo.gps_valid); + else if (!strncmp(buffer, "rxlev ", 5)) + sysinfo.rxlev = + strtoul(buffer + 5, NULL, 0); + else if (!strncmp(buffer, "bsic ", 5)) + read_log_bsic(buffer + 5); + else if (!strncmp(buffer, "ta ", 3)) { + sysinfo.ta_valid = 1; + sysinfo.ta = atoi(buffer + 3); + } + break; + case LOG_TYPE_POWER: + if (!strncmp(buffer, "arfcn ", 6)) + read_log_power(buffer + 6); + else if (!strncmp(buffer, "time ", 5)) + power.gmt = strtoul(buffer + 5, NULL, 0); + else if (!strncmp(buffer, "position ", 9)) + read_log_pos(buffer + 9, &power.longitude, + &power.latitude, &sysinfo.gps_valid); + break; + } + } + + return type; +} + diff --git a/src/host/gsmmap/log.h b/src/host/gsmmap/log.h new file mode 100644 index 000000000..d1520101f --- /dev/null +++ b/src/host/gsmmap/log.h @@ -0,0 +1,80 @@ + +enum { + LOG_TYPE_NONE = 0, + LOG_TYPE_SYSINFO, + LOG_TYPE_POWER, +}; + +struct power { + uint8_t gps_valid; + double longitude, latitude; + time_t gmt; + int8_t rxlev[1024]; +}; + +struct node_power { + struct node_power *next; + struct power power; +}; + +struct node_mcc { + struct node_mcc *next; + uint16_t mcc; + struct node_mnc *mnc; +}; + +struct node_mnc { + struct node_mnc *next; + uint16_t mnc; + struct node_lac *lac; +}; + +struct node_lac { + struct node_lac *next; + uint16_t lac; + struct node_cell *cell; +}; + +struct sysinfo { + uint16_t arfcn; + int8_t rxlev; + uint8_t bsic; + uint8_t gps_valid; + double longitude, latitude; + time_t gmt; + uint8_t si1[23]; + uint8_t si2[23]; + uint8_t si2bis[23]; + uint8_t si2ter[23]; + uint8_t si3[23]; + uint8_t si4[23]; + uint8_t ta_valid; + uint8_t ta; +}; + +struct node_cell { + struct node_cell *next; + uint16_t cellid; + uint8_t content; /* indicates, if sysinfo is already applied */ + struct node_meas *meas, **meas_last_p; + struct sysinfo sysinfo; + struct gsm48_sysinfo s; +}; + +struct node_meas { + struct node_meas *next; + time_t gmt; + int8_t rxlev; + uint8_t gps_valid; + double longitude, latitude; + uint8_t ta_valid; + uint8_t ta; +}; + +struct node_mcc *get_node_mcc(uint16_t mcc); +struct node_mnc *get_node_mnc(struct node_mcc *mcc, uint16_t mnc); +struct node_lac *get_node_lac(struct node_mnc *mnc, uint16_t lac); +struct node_cell *get_node_cell(struct node_lac *lac, uint16_t cellid); +struct node_meas *add_node_meas(struct node_cell *cell); +int read_log(FILE *infp); +