aboutsummaryrefslogtreecommitdiffstats
path: root/src/diag_event.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/diag_event.c')
-rw-r--r--src/diag_event.c159
1 files changed, 159 insertions, 0 deletions
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 <laforge@gnumonks.org>
+ *
+ * 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 <string.h>
+#include <stdint.h>
+#include <osmocom/core/msgb.h>
+
+#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));
+}