diff options
Diffstat (limited to 'src/host/gsmmap/log.c')
-rw-r--r-- | src/host/gsmmap/log.c | 377 |
1 files changed, 377 insertions, 0 deletions
diff --git a/src/host/gsmmap/log.c b/src/host/gsmmap/log.c new file mode 100644 index 00000000..c2db801e --- /dev/null +++ b/src/host/gsmmap/log.c @@ -0,0 +1,377 @@ +/* Conversion of logged cells to KML file */ + +/* (C) 2010 by Andreas Eversberg <jolly@eversberg.eu> + * + * 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 <stdio.h> +#include <stdlib.h> + +#include <osmocom/bb/common/osmocom_data.h> + +#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 "<ncc>,<bcc>" */ +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 "<longitude> <latitude>" */ +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 "<arfcn> <value> <next value> ...." */ +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; +} + |