blob: 48741f4610c26053fba0c107a05b5a33095dbd76 [file] [log] [blame]
Harald Weltedbb0f5a2016-10-18 23:51:54 +02001#include <stdio.h>
Harald Welte74d1e342016-10-19 00:06:22 +02002#include <time.h>
Harald Weltef4032322016-10-19 00:23:10 +02003#include <unistd.h>
Harald Welte74d1e342016-10-19 00:06:22 +02004
Harald Weltedbb0f5a2016-10-18 23:51:54 +02005#include <sys/time.h>
6
7#include <osmocom/core/signal.h>
8#include <osmocom/core/logging.h>
9#include <osmocom/core/application.h>
Harald Welte525af182016-10-19 00:38:46 +020010#include <osmocom/abis/subchan_demux.h>
Harald Weltedbb0f5a2016-10-18 23:51:54 +020011
12#include "storage.h"
13#include "recorder.h"
14
15struct e1_recorder g_recorder;
16
Harald Weltef4032322016-10-19 00:23:10 +020017enum mode {
18 MODE_PRINT,
19 MODE_BIN,
20};
21
22static enum mode g_mode = MODE_PRINT;
23static int g_filter_line = -1;
24static int g_filter_slot = -1;
Harald Welte525af182016-10-19 00:38:46 +020025static int g_filter_subslot = -1;
26static struct osmo_e1cap_pkthdr *g_last_pkthdr;
Harald Weltef4032322016-10-19 00:23:10 +020027
Harald Welte74d1e342016-10-19 00:06:22 +020028static char *timeval2str(struct timeval *tv)
29{
30 time_t nowtime;
31 struct tm *nowtm;
32 char tmbuf[64];
33 static char buf[64];
34
35 nowtime = tv->tv_sec;
36 nowtm = localtime(&nowtime);
37 strftime(tmbuf, sizeof tmbuf, "%Y-%m-%d %H:%M:%S", nowtm);
38 snprintf(buf, sizeof buf, "%s.%06ld", tmbuf, tv->tv_usec);
39 return buf;
40}
41
Harald Welte525af182016-10-19 00:38:46 +020042static void handle_data(struct osmo_e1cap_pkthdr *pkt, const uint8_t *data, int len)
43{
44 switch (g_mode) {
45 case MODE_PRINT:
46 printf("%s %02u/%02u %u (%u): %s\n",
47 timeval2str(&pkt->ts),
48 pkt->line_nr, pkt->ts_nr, pkt->capture_mode,
49 pkt->len,
50 osmo_hexdump_nospc(data, len));
51 break;
52 case MODE_BIN:
53 write(1, data, len);
54 break;
55 }
56}
57
58static int subch_demux_out_cb(struct subch_demux *dmx, int ch, uint8_t *data,
59 int len, void *c)
60{
61 OSMO_ASSERT(ch == g_filter_subslot);
62 handle_data(g_last_pkthdr, data, len);
63
64 return 0;
65}
66
Harald Weltef4032322016-10-19 00:23:10 +020067static int handle_options(int argc, char **argv)
68{
69 int opt;
70
Harald Welte525af182016-10-19 00:38:46 +020071 while ((opt = getopt(argc, argv, "l:s:bu:")) != -1) {
Harald Weltef4032322016-10-19 00:23:10 +020072 switch (opt) {
Harald Welte525af182016-10-19 00:38:46 +020073 case 'l': /* Filter on E1 Line Number */
Harald Weltef4032322016-10-19 00:23:10 +020074 g_filter_line = atoi(optarg);
75 break;
Harald Welte525af182016-10-19 00:38:46 +020076 case 's': /* Filter on E1 Slot Number */
Harald Weltef4032322016-10-19 00:23:10 +020077 g_filter_slot = atoi(optarg);
78 break;
Harald Welte525af182016-10-19 00:38:46 +020079 case 'b': /* Raw binary output mode (for piping) */
Harald Weltef4032322016-10-19 00:23:10 +020080 g_mode = MODE_BIN;
81 break;
Harald Welte525af182016-10-19 00:38:46 +020082 case 'u': /* 16k Sub-channel demux + filter */
83 g_filter_subslot = atoi(optarg);
84 if (g_filter_subslot < 0 || g_filter_subslot > 3)
85 exit(2);
86 break;
Harald Weltef4032322016-10-19 00:23:10 +020087 default:
88 fprintf(stderr, "Unknown option '%c'\n", opt);
89 exit(EXIT_FAILURE);
90 break;
91 }
92 }
93
94 return 0;
95}
96
Harald Weltedbb0f5a2016-10-18 23:51:54 +020097int main(int argc, char **argv)
98{
99 struct osmo_e1cap_file *f;
100 struct osmo_e1cap_pkthdr *pkt;
Harald Weltef4032322016-10-19 00:23:10 +0200101 unsigned long num_pkt = 0;
Harald Welte525af182016-10-19 00:38:46 +0200102 struct subch_demux smux;
Harald Weltedbb0f5a2016-10-18 23:51:54 +0200103
104 printf("sizeof(timeval) = %zu\n", sizeof(struct timeval));
105 printf("sizeof(osmo_e1cap_pkthdr) = %zu\n", sizeof(*pkt));
106
Harald Weltef4032322016-10-19 00:23:10 +0200107 handle_options(argc, argv);
Harald Weltedbb0f5a2016-10-18 23:51:54 +0200108
Harald Weltef4032322016-10-19 00:23:10 +0200109 if (optind >= argc) {
110 fprintf(stderr, "Missing input file name\n");
111 exit(2);
112 }
113
114 f = osmo_e1cap_open(NULL, argv[optind++]);
115 if (!f) {
116 fprintf(stderr, "Unable to open input file\n");
Harald Weltedbb0f5a2016-10-18 23:51:54 +0200117 exit(1);
Harald Weltef4032322016-10-19 00:23:10 +0200118 }
Harald Weltedbb0f5a2016-10-18 23:51:54 +0200119
Harald Welte525af182016-10-19 00:38:46 +0200120 if (g_filter_subslot >= 0) {
121 smux.out_cb = subch_demux_out_cb;
122 subch_demux_init(&smux);
123 subch_demux_activate(&smux, g_filter_subslot);
124 }
125
Harald Weltedbb0f5a2016-10-18 23:51:54 +0200126 while ((pkt = osmo_e1cap_read_next(f))) {
Harald Weltef4032322016-10-19 00:23:10 +0200127 num_pkt++;
Harald Welte525af182016-10-19 00:38:46 +0200128 g_last_pkthdr = pkt;
Harald Weltef4032322016-10-19 00:23:10 +0200129
130 if (g_filter_line >= 0 && pkt->line_nr != g_filter_line)
131 continue;
132 if (g_filter_slot >= 0 && pkt->ts_nr != g_filter_slot)
133 continue;
134
Harald Welte525af182016-10-19 00:38:46 +0200135 if (g_filter_subslot >= 0) {
136 subch_demux_in(&smux, pkt->data, pkt->len);
137 continue;
Harald Weltef4032322016-10-19 00:23:10 +0200138 }
Harald Welte525af182016-10-19 00:38:46 +0200139
140 handle_data(pkt, pkt->data, pkt->len);
141
Harald Weltedbb0f5a2016-10-18 23:51:54 +0200142 talloc_free(pkt);
143 }
Harald Weltef4032322016-10-19 00:23:10 +0200144
145 fprintf(stderr, "Processed a total of %lu packets\n", num_pkt);
Harald Weltedbb0f5a2016-10-18 23:51:54 +0200146}