osmocom-bb/src/host/gprsdecode/main.c

197 lines
4.1 KiB
C

/*
* (C) 2017-2018 by sysmocom - s.f.m.c. GmbH, Author: Max <msuraev@sysmocom.de>
* (C) 2018 by Vadim Yanitskiy <axilirator@gmail.com>
* (C) 2011-2012 by Luca Melette <luca@srlabs.de>
*
* All Rights Reserved
*
* SPDX-License-Identifier: GPL-2.0+
*
* 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.
*
*/
#include <stdio.h>
#include <errno.h>
#include <getopt.h>
#include <signal.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <arpa/inet.h>
#include <osmocom/core/signal.h>
#include <osmocom/core/select.h>
#include <osmocom/core/application.h>
#include <osmocom/gsm/rsl.h>
#include <osmocom/gsm/gsm_utils.h>
#include <osmocom/gsm/protocol/gsm_04_08.h>
#include "l1ctl_proto.h"
#include "gsmtap.h"
#include "gprs.h"
static struct {
char *capture_file;
char *gsmtap_ip;
bool verbose;
bool quit;
} app_data;
static void burst_handle(struct l1ctl_burst_ind *bi)
{
uint8_t type, subch, ts;
uint32_t fn;
fn = ntohl(bi->frame_nr);
rsl_dec_chan_nr(bi->chan_nr, &type, &subch, &ts);
switch (type) {
case RSL_CHAN_Bm_ACCHs:
/* FIXME: what is (fn % 13) != 12? */
/* TODO: use the multiframe layout here */
if ((ts > 0) && ((fn % 13) != 12))
process_pdch(bi, app_data.verbose);
break;
default:
/* We are only interested in GPRS messages */
break;
}
}
static void print_help(const char *app)
{
printf(" Some help...\n\n");
printf(" Usage: %s [OPTIONS]\n\n", app);
printf(" -h --help this text\n");
printf(" -c --capture The capture file to decode\n");
printf(" -i --gsmtap-ip The destination IP used for GSMTAP\n");
printf(" -v --verbose Increase the verbosity level\n");
}
static int handle_options(int argc, char **argv)
{
/* Init defaults */
app_data.capture_file = NULL;
app_data.gsmtap_ip = NULL;
app_data.verbose = false;
app_data.quit = false;
/* Parse options */
while (1) {
int option_index = 0, c;
static struct option long_options[] = {
{"help", 0, 0, 'h'},
{"verbose", 0, 0, 'v'},
{"capture", 1, 0, 'c'},
{"gsmtap-ip", 1, 0, 'i'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "c:i:vh",
long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'h':
print_help(argv[0]);
return 1;
case 'c':
app_data.capture_file = optarg;
break;
case 'i':
app_data.gsmtap_ip = optarg;
break;
case 'v':
app_data.verbose = true;
break;
default:
break;
}
}
/* Make sure we have the capture file path */
if (!app_data.capture_file) {
print_help(argv[0]);
printf("\nPlease specify the capture file\n");
return -1;
}
return 0;
}
static void signal_handler(int signal)
{
fprintf(stderr, "signal %d received\n", signal);
switch (signal) {
case SIGINT:
app_data.quit = true;
break;
default:
break;
}
}
int main(int argc, char **argv)
{
struct l1ctl_burst_ind bi;
FILE *burst_fd;
int rc;
/* Setup signal handlers */
signal(SIGINT, &signal_handler);
osmo_init_ignore_signals();
/* Parse options */
rc = handle_options(argc, argv);
if (rc)
return EXIT_FAILURE;
/* Attempt to open the capture for reading */
burst_fd = fopen(app_data.capture_file, "rb");
if (!burst_fd) {
printf("Cannot open capture file '%s': %s\n",
app_data.capture_file, strerror(errno));
return EXIT_FAILURE;
}
/* Init GSMTAP sink if required */
if (app_data.gsmtap_ip != NULL)
gsmtap_init(app_data.gsmtap_ip);
/* Application main loop */
while (!app_data.quit) {
/* The end of capture file */
if (feof(burst_fd))
break;
/* Read a single burst */
rc = fread(&bi, sizeof(bi), 1, burst_fd);
if (!rc)
break;
/* Filter or handle burst */
burst_handle(&bi);
osmo_select_main(1);
}
/* Close the capture file */
fclose(burst_fd);
return 0;
}