diff options
Diffstat (limited to 'src/diag_event.c')
-rw-r--r-- | src/diag_event.c | 159 |
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)); +} |