From 3710dcc1eb1a634d72ca216a7e2bcfd986e7671e Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 21 Jan 2017 23:53:15 +0100 Subject: [PATCH] Add support for DIAG EVENT reporting --- src/Makefile | 2 +- src/diag_event.c | 159 ++++++++++++++++++++++++++++++++++++++++++ src/diag_io.h | 9 +++ src/diag_log.c | 8 --- src/osmo-qcdiag-log.c | 2 +- 5 files changed, 170 insertions(+), 10 deletions(-) create mode 100644 src/diag_event.c diff --git a/src/Makefile b/src/Makefile index 9a95505..3591ece 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2,7 +2,7 @@ CPPFLAGS ?= -g -O0 -Wall `pkg-config --cflags libosmocore` `pkg-config --cflags LIBS ?= `pkg-config --libs libosmocore` `pkg-config --libs qmi-glib` all: osmo-qcdiag-log -MODS_LOG = gprs_l1.c gprs_rlc.o gprs_mac.o diag_gsm.o diag_log.o diag_log_gsm.o diag_log_gprs.o diag_log_wcdma.o diag_log_umts.o diag_log_qmi.o diag_dpl.o diag_log_simcard.o +MODS_LOG = gprs_l1.c gprs_rlc.o gprs_mac.o diag_gsm.o diag_log.o diag_log_gsm.o diag_log_gprs.o diag_log_wcdma.o diag_log_umts.o diag_log_qmi.o diag_dpl.o diag_log_simcard.o diag_event.o osmo-qcdiag-log: diagchar_hdlc.o diag_io.o osmo-qcdiag-log.o diag_msg.o protocol.o diag_cmd.o $(MODS_LOG) $(CC) $(CPPFLAGS) -o $@ $^ $(LIBS) diff --git a/src/diag_event.c b/src/diag_event.c new file mode 100644 index 0000000..7acbe8d --- /dev/null +++ b/src/diag_event.c @@ -0,0 +1,159 @@ +/* + * (C) 2013-2016 by Harald Welte + * + * 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 + +#include "diag_cmd.h" +#include "protocol/protocol.h" +#include "protocol/diagcmd.h" + +/*********************************************************************** + * EVENT Configuration / Protocol + ***********************************************************************/ + +struct diag_event_mask_set_req { + uint8_t cmd_code; + uint8_t pad[3]; + uint8_t mask[0]; +} __attribute__((packed)); + +struct diag_event_cfg_req { + uint8_t cmd_code; + uint8_t enable; +} __attribute__((packed)); + +static struct msgb *gen_event_set_mask(uint32_t last_item) +{ + struct msgb *msg = msgb_alloc(DIAG_MAX_REQ_SIZE, "Diag Event Cfg"); + struct diag_event_mask_set_req *demsr; + + msg->l2h = msgb_put(msg, sizeof(*demsr)); + demsr = (struct diag_event_mask_set_req *) msg->l2h; + demsr->cmd_code = DIAG_EVENT_MASK_SET_F; + msg->l3h = msgb_put(msg, bytes_rqd_for_bit(last_item)); + + return msg; +} + +int diag_event_set_bit(struct msgb *msg, uint32_t bit_in) +{ + struct diag_event_mask_set_req *demsr; + demsr = (struct diag_event_mask_set_req *) msg->l2h; + uint8_t *mask = demsr->mask; + unsigned int byte = bit_in / 8; + unsigned int bit = bit_in % 8; + + if (mask + byte > msg->tail) { + fprintf(stderr, "bit %u is outside event mask!\n", bit_in); + return -1; + } + + mask[byte] |= (1 << bit); + + return 0; +} + +struct diag_event_id { + uint16_t id:12, + _pad:1, + payload_len:2, /* 0x2000, 0x4000 */ + ts_trunc:1; /* 0x8000 */ +} __attribute__ ((packed)); + +struct diag_event_report_event { + struct diag_event_id event_id; + uint64_t timestamp; + uint8_t payload[0]; +} __attribute__ ((packed)); + +struct diag_event_report_event_trunc { + struct diag_event_id event_id; + uint16_t timestamp_trunc; + uint8_t payload[0]; +} __attribute__ ((packed)); + +struct diag_event_report { + uint8_t cmd_code; + uint16_t len; + struct diag_event_report_event events[0]; +} __attribute__ ((packed)); + +static void diag_rx_event_report_f(struct diag_instance *di, struct msgb *msg) +{ + struct diag_event_report *erep = (struct diag_event_report *) msgb_l2(msg); + uint16_t erep_len = osmo_load16le(&erep->len); + uint8_t *cur; + + //printf("EVENT (erep_len=%u): %s\n", erep_len, msgb_hexdump(msg)); + + for (cur = (uint8_t *)erep->events; cur < (uint8_t *)erep->events + erep_len;) { + uint16_t _eid = osmo_load16le(cur); + struct diag_event_id *event_id = (struct diag_event_id *)&_eid; + + if (event_id->ts_trunc) { + struct diag_event_report_event_trunc *ret; + ret = (struct diag_event_report_event_trunc *) cur; + cur += sizeof(*ret); + printf("EVENT-TRUNC(0x%04x|FIXME)", event_id->id); + } else { + struct diag_event_report_event *re; + re = (struct diag_event_report_event *) cur; + cur += sizeof(*re); + uint64_t ts = osmo_load64le(&re->timestamp); + + printf("EVENT(0x%04x|%u|%u)", event_id->id, + diag_ts_to_epoch(ts), diag_ts_to_fn(ts)); + } + switch (event_id->payload_len) { + case 0: + printf("\n"); + break; + case 1: + printf(": 0x%02x\n", cur[0]); + cur += 1; + break; + case 2: + printf(": 0x%02x, 0x%02x\n", cur[0], cur[1]); + cur += 2; + break; + case 3: + printf(": %s\n", osmo_hexdump(cur+1, *cur)); + cur += *cur + 1; + break; + } + } + +#if 0 + for (i = 0; (i+1)*sizeof(struct diag_event_report_event) <= erep_len; i++) { + struct diag_event_report_event *evt = &erep->events[i]; + uint16_t event_id = osmo_load16le(&evt->event_id); + } +#endif +} + +static const struct diag_cmd_dispatch_tbl cmd_tbl[] = { + { DIAG_EVENT_REPORT_F, diag_rx_event_report_f }, +}; + +static __attribute__((constructor)) void on_dso_load_event(void) +{ + diag_cmd_reg_dispatch(cmd_tbl, ARRAY_SIZE(cmd_tbl)); +} diff --git a/src/diag_io.h b/src/diag_io.h index d3fd64e..6e3cd1e 100644 --- a/src/diag_io.h +++ b/src/diag_io.h @@ -29,3 +29,12 @@ struct msgb *diag_subsys_transceive_msg(struct diag_instance *di, struct msgb *t void diag_transceive_msg_ign(struct diag_instance *di, struct msgb *tx); struct msgb *diag_transceive_buf(struct diag_instance *di, const uint8_t *data, size_t data_len); void diag_transceive_buf_ign(struct diag_instance *di, const uint8_t *data, size_t data_len); + +/* FIXME: this should be in libosmocore */ +static inline unsigned int bytes_rqd_for_bit(unsigned int bit) +{ + if (bit % 8) + return bit/8 + 1; + else + return bit/8; +} diff --git a/src/diag_log.c b/src/diag_log.c index 9140bf3..5a9a580 100644 --- a/src/diag_log.c +++ b/src/diag_log.c @@ -50,14 +50,6 @@ struct diag_log_config_set_mask { uint8_t data[0]; } __attribute((packed)); -static inline unsigned int bytes_rqd_for_bit(unsigned int bit) -{ - if (bit % 8) - return bit/8 + 1; - else - return bit/8; -} - struct msgb *gen_log_config_set_mask(uint32_t equip_id, uint32_t last_item) { struct msgb *msg = msgb_alloc(DIAG_MAX_REQ_SIZE, "Diag Tx"); diff --git a/src/osmo-qcdiag-log.c b/src/osmo-qcdiag-log.c index 5d8461d..0f9e0a4 100644 --- a/src/osmo-qcdiag-log.c +++ b/src/osmo-qcdiag-log.c @@ -60,7 +60,7 @@ static void do_configure(struct diag_instance *di) /* response: 3d 67 a8 81 d4 46 6d d9 00 */ /* enable|disable the event report */ -#if 0 +#if 1 diag_transceive_buf_ign(di, enable_evt_report, sizeof(enable_evt_report)); #else diag_transceive_buf_ign(di, disable_evt_report, sizeof(disable_evt_report));