From faea754d39248d76cdd1806414f8a8c171b2049b Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 24 Dec 2016 01:21:03 +0100 Subject: [PATCH] re-structure the LOG dispatcher we now have a nice structure for dispatching log messages to various handlers, each self-contained. As an added benefit, we remove the need to manually enable all the various log codes, as we simply auto-generate the default config from all the message types we support. Furthermore, we reduce computational complexity by avoiding linear iteration over the array of registered log handlers. --- src/Makefile | 4 +- src/config.c | 58 --------- src/config.h | 8 -- src/diag_log.c | 143 ++++++++++++++++++++++ src/diag_log.h | 24 ++++ src/diag_log_gprs.c | 177 +++++++++++++++++++++++++++ src/diag_log_gsm.c | 33 ++++++ src/diag_log_qmi.c | 85 +++++++++++++ src/diag_log_umts.c | 25 ++++ src/log_codes_gsm.h | 2 + src/qmi_decode.c | 29 ----- src/qmi_decode.h | 4 - src/qxdm-log.c | 283 +------------------------------------------- 13 files changed, 498 insertions(+), 377 deletions(-) delete mode 100644 src/config.c delete mode 100644 src/config.h create mode 100644 src/diag_log.c create mode 100644 src/diag_log.h create mode 100644 src/diag_log_gprs.c create mode 100644 src/diag_log_gsm.c create mode 100644 src/diag_log_qmi.c create mode 100644 src/diag_log_umts.c delete mode 100644 src/qmi_decode.c delete mode 100644 src/qmi_decode.h diff --git a/src/Makefile b/src/Makefile index a88d001..e81eb5c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2,7 +2,9 @@ CPPFLAGS ?= -g -O0 -Wall `pkg-config --cflags qmi-glib` LIBS ?= -losmocore `pkg-config --libs qmi-glib` all: qxdm-log -qxdm-log: diagchar_hdlc.o diag_io.o qxdm-log.o config.o gprs_rlc.o gprs_mac.o diag_gsm.o protocol.o qmi_decode.o +MODS_LOG = gprs_rlc.o gprs_mac.o diag_gsm.o diag_log.o diag_log_gsm.o diag_log_gprs.o diag_log_umts.o diag_log_qmi.o + +qxdm-log: diagchar_hdlc.o diag_io.o qxdm-log.o protocol.o $(MODS_LOG) $(CC) $(CPPFLAGS) -o $@ $^ $(LIBS) clean: diff --git a/src/config.c b/src/config.c deleted file mode 100644 index 4ccb4d7..0000000 --- a/src/config.c +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include - -#include "diagcmd.h" -#include "protocol.h" - -enum log_config_op { - LOG_CONFIG_DISABLE_OP = 0, - LOG_CONFIG_RETRIEVE_ID_RANGES_OP = 1, - LOG_CONFIG_RETRIEVE_VALID_MASK_OP = 2, - LOG_CONFIG_SET_MASK_OP = 3, - LOG_CONFIG_GET_LOGMASK_OP = 4, -}; - -struct diag_log_config_req_hdr { - uint8_t msg_type; - uint8_t pad[3]; - uint32_t operation; -} __attribute((packed)); - -struct diag_log_config_set_mask { - struct diag_log_config_req_hdr hdr; - uint32_t equip_id; - uint32_t last_item; - uint8_t data[0]; -} __attribute((packed)); - -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"); - struct diag_log_config_set_mask *dlcsm; - - msg->l2h = msgb_put(msg, sizeof(*dlcsm)); - dlcsm = (struct diag_log_config_set_mask *) msg->l2h; - dlcsm->hdr.msg_type = DIAG_LOG_CONFIG_F; - dlcsm->hdr.operation = LOG_CONFIG_SET_MASK_OP; - dlcsm->equip_id = equip_id; - dlcsm->last_item = last_item; - msg->l3h = msgb_put(msg, dlcsm->last_item/8); - - return msg; -} - -int log_config_set_mask_bit(struct msgb *msg, uint32_t bit_in) -{ - struct diag_log_config_set_mask *dlcsm; - dlcsm = (struct diag_log_config_set_mask *) msg->l2h; - uint8_t *mask = msg->l3h; - unsigned int byte = bit_in / 8; - unsigned int bit = bit_in % 8; - - if (byte > dlcsm->last_item/8) - return -1; - - mask[byte] |= (1 << bit); - - return 0; -} diff --git a/src/config.h b/src/config.h deleted file mode 100644 index 39bf4ad..0000000 --- a/src/config.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include - -struct msgb; - -struct msgb *gen_log_config_set_mask(uint32_t equip_id, uint32_t last_item); -int log_config_set_mask_bit(struct msgb *msg, uint32_t bit_in); diff --git a/src/diag_log.c b/src/diag_log.c new file mode 100644 index 0000000..1bb3a72 --- /dev/null +++ b/src/diag_log.c @@ -0,0 +1,143 @@ +#include +#include +#include +#include + +#include "diag_log.h" +#include "protocol.h" +#include "diagcmd.h" + +/*********************************************************************** + * LOG Configuration / Protocol + ***********************************************************************/ + +enum log_config_op { + LOG_CONFIG_DISABLE_OP = 0, + LOG_CONFIG_RETRIEVE_ID_RANGES_OP = 1, + LOG_CONFIG_RETRIEVE_VALID_MASK_OP = 2, + LOG_CONFIG_SET_MASK_OP = 3, + LOG_CONFIG_GET_LOGMASK_OP = 4, +}; + +struct diag_log_config_req_hdr { + uint8_t msg_type; + uint8_t pad[3]; + uint32_t operation; +} __attribute((packed)); + +struct diag_log_config_set_mask { + struct diag_log_config_req_hdr hdr; + uint32_t equip_id; + uint32_t last_item; + uint8_t data[0]; +} __attribute((packed)); + +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"); + struct diag_log_config_set_mask *dlcsm; + + msg->l2h = msgb_put(msg, sizeof(*dlcsm)); + dlcsm = (struct diag_log_config_set_mask *) msg->l2h; + dlcsm->hdr.msg_type = DIAG_LOG_CONFIG_F; + dlcsm->hdr.operation = LOG_CONFIG_SET_MASK_OP; + dlcsm->equip_id = equip_id; + dlcsm->last_item = last_item; + msg->l3h = msgb_put(msg, dlcsm->last_item/8); + + return msg; +} + +int log_config_set_mask_bit(struct msgb *msg, uint32_t bit_in) +{ + struct diag_log_config_set_mask *dlcsm; + dlcsm = (struct diag_log_config_set_mask *) msg->l2h; + uint8_t *mask = msg->l3h; + unsigned int byte = bit_in / 8; + unsigned int bit = bit_in % 8; + + if (byte > dlcsm->last_item/8) + return -1; + + mask[byte] |= (1 << bit); + + return 0; +} + + +/*********************************************************************** + * LOG Dispatch + ***********************************************************************/ + +/* not particularly memory efficient, but welll, only 500kB on 64bit */ +static diag_log_handler *log_handlers[0xffff]; + +/* called by individual modules to register their own decoders */ +void diag_log_reg_dispatch(const struct diag_log_dispatch_tbl *tbl, unsigned int size) +{ + unsigned int i; + for (i = 0; i < size; i++) { + printf("Registering dispatch for 0x%04x\n", tbl[i].code); + log_handlers[tbl[i].code] = tbl[i].handler; + } +} + +void diag_log_enable_all_supported_family(struct diag_instance *di, uint8_t family) +{ + struct msgb *msg; + unsigned int i, size; + unsigned int family_base = (family & 0xf) << 12; + unsigned int max = 0; + + for (i = family_base; i < family_base + 0x1000; i++) { + if (log_handlers[i]) { + if (max < i) + max = i; + } + } + + if (!max) + return; + + size = max - family_base; + printf("family %u: allocating log mask of size %u\n", family, size); + msg = gen_log_config_set_mask(family, size); + for (i = family_base; i < family_base + 0x1000; i++) { + if (log_handlers[i]) + log_config_set_mask_bit(msg, i-family_base); + } + + diag_transmit_msgb(di, msg); + diag_read(di); +} + +void diag_log_enable_all_supported(struct diag_instance *di) +{ + unsigned int i; + + for (i = 0; i < 0xF; i++) { + diag_log_enable_all_supported_family(di, i); + } +} + +void diag_log_handle(struct diag_instance *di, struct msgb *msg) +{ + struct diag_log_hdr *dlh; + struct log_hdr *lh; + + dlh = (struct diag_log_hdr *) msg->data; + /* FIXME: verify length */ + msg->l3h = msgb_pull(msg, sizeof(*dlh)); + + lh = (struct log_hdr *) msg->l3h; + /* FIXME: verify length */ + msgb_pull(msg, sizeof(*lh)); + + printf("LOG(0x%04x|%u|%u): ", lh->code, + diag_ts_to_epoch(lh->ts), diag_ts_to_fn(lh->ts)); + + if (log_handlers[lh->code]) + log_handlers[lh->code](lh, msg); + else + printf("%s\n", osmo_hexdump(lh->data, lh->len)); +} diff --git a/src/diag_log.h b/src/diag_log.h new file mode 100644 index 0000000..785549e --- /dev/null +++ b/src/diag_log.h @@ -0,0 +1,24 @@ +#pragma once + +#include "diag_io.h" +#include "protocol.h" + +typedef void diag_log_handler(struct log_hdr *lh, struct msgb *msg); + +struct diag_log_dispatch_tbl { + uint16_t code; + diag_log_handler *handler; +}; + +/* called by input whenever a LOG message is registered */ +void diag_log_handle(struct diag_instance *di, struct msgb *msg); + +/* called by individual modules to register their own decoders */ +void diag_log_reg_dispatch(const struct diag_log_dispatch_tbl *tbl, unsigned int size); + +void diag_log_enable_all_supported_family(struct diag_instance *di, uint8_t family); +void diag_log_enable_all_supported(struct diag_instance *di); + +/* functions for log configuration */ +struct msgb *gen_log_config_set_mask(uint32_t equip_id, uint32_t last_item); +int log_config_set_mask_bit(struct msgb *msg, uint32_t bit_in); diff --git a/src/diag_log_gprs.c b/src/diag_log_gprs.c new file mode 100644 index 0000000..f267600 --- /dev/null +++ b/src/diag_log_gprs.c @@ -0,0 +1,177 @@ +#include + +#include "diag_log.h" +#include "diag_gsm.h" +#include "gprs_rlc.h" +#include "gprs_mac.h" +#include "log_codes_gsm.h" + + +static void handle_grr_state_msg(struct log_hdr *lh, struct msgb *msg) +{ + struct diag_gprs_grr_state *rrs = (struct diag_gprs_grr_state *) msgb_data(msg); + + printf("GRR-STATE { active=%u, state=%s }\n", rrs->active_state, + get_value_string(diag_gprs_grr_st_vals, rrs->grr_state)); +} + +static void handle_rlc_ul_abnrml_rls(struct log_hdr *lh, struct msgb *msg) +{ + struct gprs_rlc_ul_abnrml_rls_counts *arc; + arc = (struct gprs_rlc_ul_abnrml_rls_counts *) msgb_data(msg); + + printf("RLC-UL-ABNRML-RLS-COUNTS { access_reject_cnt=%u, arc_retry_cnt=%u, arc_wo_retry_cnt=%u, arc_sys_info_cnt=%u }", + arc->access_reject_cnt, arc->arc_retry_cnt, arc->arc_wo_retry_cnt, arc->arc_sys_info_cnt); +} + +static void handle_mac_sign_msg(struct log_hdr *lh, struct msgb *msg) +{ + struct gprs_mac_signalling_msg *msm; + msm = (struct gprs_mac_signalling_msg *) msgb_data(msg); + printf("MAC-SIGN-MSG { chan_type=%s, msg_type=%s, msg=%s }\n", + get_value_string(gprs_mac_chan_type_vals, msm->chan_type), + get_value_string(gprs_mac_msg_type_vals, msm->msg_type), + osmo_hexdump(msm->msg, msm->msg_len)); +} + +static void handle_llc_me_info(struct log_hdr *lh, struct msgb *msg) +{ + struct diag_gprs_llme_info *gli; + gli = (struct diag_gprs_llme_info *) msgb_data(msg); + printf("LLC-ME-INFO { state=%s, xid_version=%u, tlli_new=0x%08x, tlli_old=0x%08x, gea=%u, key=%s }\n", + get_value_string(diag_gprs_llme_st_vals, gli->state), gli->xid_version, + gli->tlli_new, gli->tlli_old, gli->enc_alg, + osmo_hexdump_nospc(gli->enc_key, sizeof(gli->enc_key))); +} + +static void handle_llc_pdu_stats(struct log_hdr *lh, struct msgb *msg) +{ + struct diag_gprs_llc_stats *gls; + gls = (struct diag_gprs_llc_stats *) msgb_data(msg); + printf("LLC-PDU-STATS-ACK { sap=%u, l3pdu_tx=%u, octet_tx=%u, octet_retrans=%u, l3pdu_rx=%u, octet_rx=%u }\n", + gls->sapi, gls->ack_l3pdu_tx, gls->ack_octet_tx, gls->ack_l3pdu_retrans, gls->ack_l3pdu_rx, gls->ack_octet_rx); + printf("LLC-PDU-STATS-UNACK { sapi=%u, l3pdu_tx=%u, octet_tx=%u, l3pdu_rx=%u, octet_rx=%u }\n", + gls->sapi, gls->unack_l3pdu_tx, gls->unack_octet_tx, gls->unack_l3pdu_rx, gls->unack_octet_rx); + printf("LLC-PDU-STATS-LLPDU { tx=%u, rx=%u, fcs_err=%u, frm_rej=%u, tlli_err=%u, addr_err=%u, short_err=%u }\n", + gls->llpdu_tx, gls->llpdu_rx, gls->llpdu_fcs_err, gls->llpdu_frm_rej, gls->llpdu_tlli_err, gls->llpdu_addr_err, gls->llpdu_short_err); +} + +static void handle_mac_state(struct log_hdr *lh, struct msgb *msg) +{ + struct gprs_mac_state_change *msc; + msc = (struct gprs_mac_state_change *) msgb_data(msg); + const char *name = ""; + + switch (msc->mac_mode) { + case NULL_MODE: + name = get_value_string(gprs_mac_null_substate_vals, msc->mac_null_fsm_state); + break; + case IDLE_MODE: + name = get_value_string(gprs_mac_idle_substate_vals, msc->mac_idle_fsm_state); + break; + case TRANSFER_MODE: + name = get_value_string(gprs_mac_transfer_substate_vals, msc->mac_transfer_fsm_state); + break; + } + + printf("MAC-STATE { mode=%s, state=%s }\n", + get_value_string(gprs_mac_mode_vals, msc->mac_mode), name); +} + +static void handle_mac_dl_tbf_est(struct log_hdr *lh, struct msgb *msg) +{ + struct gprs_mac_dl_tbf_est *dte; + dte = (struct gprs_mac_dl_tbf_est *) msgb_data(msg); + + printf("MAC-DL-TBF-EST { tfi=%u, rlc_mode=%u, dl_ts_bmap=0x%x, is_egprs=%u, egprs_win_size=%u, egprs_link_qual_mode=%u, bep_period2=%u }\n", + dte->dl_tfi, dte->rlc_mode, dte->dl_ts_bmap, dte->is_egprs_tbf, dte->egprs_win_size, dte->egprs_link_qual_mode, dte->bep_period2); +} + +static void handle_mac_ul_tbf_est(struct log_hdr *lh, struct msgb *msg) +{ + struct gprs_mac_ul_tbf_est *ute; + ute = (struct gprs_mac_ul_tbf_est *) msgb_data(msg); + + printf("MAC-UL-TBF-EST { tbf_req_cause=%u, acc_granted=%u, radio_prio=%u, peak_tput=%u, ul_tfi=%u, rlc_mode=%u, ul_ts_bmap=0x%x, is_egprs=%u, egprs_win_size=%u, resegment=%u, bep_period2=%u }\n", + ute->tbf_req_cause, ute->acc_granted, ute->radio_prio, ute->peak_tput, ute->ul_tfi, ute->rlc_mode, ute->ul_ts_bmap, ute->is_egprs_tbf, ute->egprs_win_size, ute->resegment, ute->bep_period2); +} + +static void handle_mac_dl_tbf_rel(struct log_hdr *lh, struct msgb *msg) +{ + struct gprs_mac_tbf_release *tr; + tr = (struct gprs_mac_tbf_release *) msgb_data(msg); + + printf("MAC-DL-TBF-REL { tfi=%u, fail_cause=%u }\n", tr->tfi, tr->fail_cause); +} + +static void handle_mac_ul_tbf_rel(struct log_hdr *lh, struct msgb *msg) +{ + struct gprs_mac_tbf_release *tr; + tr = (struct gprs_mac_tbf_release *) msgb_data(msg); + + printf("MAC-DL-TBF-REL { tfi=%u, fail_cause=%u }\n", tr->tfi, tr->fail_cause); +} + +static void handle_rlc_ul_evt_cnt(struct log_hdr *lh, struct msgb *msg) +{ + struct gprs_rlc_ul_event_counts *uec; + uec = (struct gprs_rlc_ul_event_counts *) msgb_data(msg); + + printf("RLC-UL-EVT-CNT { llc_event_cnt=%u, mac_event_cnt=%u, pl1_event_cnt=%u, tmr_event_cnt=%u }\n", + uec->llc_event_cnt, uec->mac_event_cnt, uec->pl1_event_cnt, uec->tmr_event_cnt); +} + +static void handle_rlc_ul_stats(struct log_hdr *lh, struct msgb *msg) +{ + struct gprs_rlc_ul_stats *uls; + uls = (struct gprs_rlc_ul_stats *) msgb_data(msg); + + printf("RLC-UL-STATS { state=%s(%s), FIXME... }\n", + get_value_string(gprs_rlc_ul_state_vals, uls->rlc_ul_state), + get_value_string(gprs_rlc_ul_substate_vals, uls->rlc_ul_substate)); +} + +static void handle_rlc_dl_stats(struct log_hdr *lh, struct msgb *msg) +{ + struct gprs_rlc_dl_stats *dls; + dls = (struct gprs_rlc_dl_stats *) msgb_data(msg); + + printf("RLC-DL-STATS { state=%s, FIXME... }\n", + get_value_string(gprs_rlc_dl_state_vals, dls->rlc_dl_state)); +} + +static void handle_rlc_rel(struct log_hdr *lh, struct msgb *msg) +{ + struct gprs_rlc_release_ind *rli; + rli = (struct gprs_rlc_release_ind *) msgb_data(msg); + char ud = 'D'; + + if (lh->code == LOG_GPRS_RLC_UL_RELEASE_IND_C) + ud ='U'; + + printf("RLC-%cL-RELEASE { tfi=%u, cause=%u }\n", ud, rli->tfi, rli->cause); +} + + +static const struct diag_log_dispatch_tbl log_tbl[] = { + { GSM(LOG_GPRS_LLC_ME_INFO_C), handle_llc_me_info }, + { GSM(LOG_GPRS_LLC_PDU_STATS_C), handle_llc_pdu_stats }, + { GSM(LOG_GPRS_GRR_STATE_C), handle_grr_state_msg }, + { GSM(LOG_GPRS_RLC_UL_ABNRML_RLS_COUNTS_C), handle_rlc_ul_abnrml_rls }, + { GSM(LOG_GPRS_RLC_UL_EVENT_COUNTS_C), handle_rlc_ul_evt_cnt }, + { GSM(LOG_GPRS_RLC_UL_RELEASE_IND_C), handle_rlc_rel }, + { GSM(LOG_GPRS_RLC_DL_RELEASE_IND_C), handle_rlc_rel }, + { GSM(LOG_GPRS_MAC_SIGNALLING_MESSAGE_C), handle_mac_sign_msg }, + { GSM(LOG_GPRS_MAC_STATE_C), handle_mac_state }, + { GSM(LOG_GPRS_MAC_DL_TBF_ESTABLISH_C), handle_mac_dl_tbf_est }, + { GSM(LOG_GPRS_MAC_UL_TBF_ESTABLISH_C), handle_mac_ul_tbf_est }, + { GSM(LOG_GPRS_MAC_DL_TBF_RELEASE_C), handle_mac_dl_tbf_rel }, + { GSM(LOG_GPRS_MAC_UL_TBF_RELEASE_C), handle_mac_ul_tbf_rel }, + { GSM(LOG_GPRS_RLC_UL_STATS_C), handle_rlc_ul_stats }, + { GSM(LOG_GPRS_RLC_DL_STATS_C), handle_rlc_dl_stats }, +}; + +static __attribute__((constructor)) void on_dso_load_gprs(void) +{ + diag_log_reg_dispatch(log_tbl, ARRAY_SIZE(log_tbl)); +} diff --git a/src/diag_log_gsm.c b/src/diag_log_gsm.c new file mode 100644 index 0000000..791d6c6 --- /dev/null +++ b/src/diag_log_gsm.c @@ -0,0 +1,33 @@ +#include + +#include "diag_log.h" +#include "diag_gsm.h" +#include "log_codes_gsm.h" + + +static void handle_rr_sig_msg(struct log_hdr *lh, struct msgb *msg) +{ + struct diag_gsm_rr_msg *rm = (struct diag_gsm_rr_msg *) msgb_data(msg); + + printf("RR: %02x %02x %u: %s\n", rm->chan_type, rm->msg_type, + rm->length, osmo_hexdump(msgb_data(msg), rm->length)); +} + +static void handle_rr_state_msg(struct log_hdr *lh, struct msgb *msg) +{ + struct diag_gsm_rr_state *rrs = (struct diag_gsm_rr_state *) msgb_data(msg); + printf("RR-STATE { state=%s, substate=%u, status=%u, mode=%u }\n", + get_value_string(diag_gsm_rr_st_vals, rrs->state) + , rrs->substate, rrs->status, rrs->mode); + +} + +static const struct diag_log_dispatch_tbl log_tbl[] = { + { GSM(LOG_GSM_RR_SIGNALING_MESSAGE_C), handle_rr_sig_msg }, + { GSM(LOG_GSM_RR_STATE_C), handle_rr_state_msg }, +}; + +static __attribute__((constructor)) void on_dso_load_gsm(void) +{ + diag_log_reg_dispatch(log_tbl, ARRAY_SIZE(log_tbl)); +} diff --git a/src/diag_log_qmi.c b/src/diag_log_qmi.c new file mode 100644 index 0000000..b6f7eb5 --- /dev/null +++ b/src/diag_log_qmi.c @@ -0,0 +1,85 @@ +#include +#include + +#include + +#include "diag_log.h" +#include "log_codes_qmi.h" + +/* A small wrapper around libqmi-glib to give us a human-readable string + * representation of QMI messages that we receive from DIAG */ +static int dump_qmi_msg(const uint8_t *data, unsigned int len) +{ + GByteArray *buffer; + GError *error = NULL; + QmiMessage *message; + gchar *printable; + + buffer = g_byte_array_sized_new(len); + g_byte_array_append(buffer, data, len); + + message = qmi_message_new_from_raw(buffer, &error); + if (!message) { + fprintf(stderr, "qmi_message_new_from_raw() returned NULL\n"); + return -1; + } + + printable = qmi_message_get_printable(message, "QMI "); + fputs(printable, stdout); + g_free(printable); + + return 0; +} + +static void handle_qmi_msg(struct log_hdr *lh, struct msgb *msg) +{ + dump_qmi_msg(lh->data, lh->len); +} + +#define CORE(x) (0x1000 + x) + +/* Tx and Rx might be switched */ +#define LOG_QMI_PORT_RX(i) CORE(LOG_QMI_RESERVED_CODES_BASE_C+(i*2)) +#define LOG_QMI_PORT_TX(i) CORE(LOG_QMI_RESERVED_CODES_BASE_C+(i*2)+1) + +static const struct diag_log_dispatch_tbl log_tbl[] = { + { CORE(LOG_QMI_CALL_FLOW_C), handle_qmi_msg }, + { CORE(LOG_QMI_SUPPORTED_INTERFACES_C), handle_qmi_msg }, + { LOG_QMI_PORT_RX(0), handle_qmi_msg }, + { LOG_QMI_PORT_RX(1), handle_qmi_msg }, + { LOG_QMI_PORT_RX(2), handle_qmi_msg }, + { LOG_QMI_PORT_RX(3), handle_qmi_msg }, + { LOG_QMI_PORT_RX(4), handle_qmi_msg }, + { LOG_QMI_PORT_RX(5), handle_qmi_msg }, + { LOG_QMI_PORT_RX(6), handle_qmi_msg }, + { LOG_QMI_PORT_RX(7), handle_qmi_msg }, + { LOG_QMI_PORT_RX(8), handle_qmi_msg }, + { LOG_QMI_PORT_RX(9), handle_qmi_msg }, + { LOG_QMI_PORT_RX(10), handle_qmi_msg }, + { LOG_QMI_PORT_RX(11), handle_qmi_msg }, + { LOG_QMI_PORT_RX(12), handle_qmi_msg }, + { LOG_QMI_PORT_RX(13), handle_qmi_msg }, + { LOG_QMI_PORT_RX(14), handle_qmi_msg }, + { LOG_QMI_PORT_RX(15), handle_qmi_msg }, + { LOG_QMI_PORT_TX(0), handle_qmi_msg }, + { LOG_QMI_PORT_TX(1), handle_qmi_msg }, + { LOG_QMI_PORT_TX(2), handle_qmi_msg }, + { LOG_QMI_PORT_TX(3), handle_qmi_msg }, + { LOG_QMI_PORT_TX(4), handle_qmi_msg }, + { LOG_QMI_PORT_TX(5), handle_qmi_msg }, + { LOG_QMI_PORT_TX(6), handle_qmi_msg }, + { LOG_QMI_PORT_TX(7), handle_qmi_msg }, + { LOG_QMI_PORT_TX(8), handle_qmi_msg }, + { LOG_QMI_PORT_TX(9), handle_qmi_msg }, + { LOG_QMI_PORT_TX(10), handle_qmi_msg }, + { LOG_QMI_PORT_TX(11), handle_qmi_msg }, + { LOG_QMI_PORT_TX(12), handle_qmi_msg }, + { LOG_QMI_PORT_TX(13), handle_qmi_msg }, + { LOG_QMI_PORT_TX(14), handle_qmi_msg }, + { LOG_QMI_PORT_TX(15), handle_qmi_msg }, +}; + +static __attribute__((constructor)) void on_dso_load_qmi(void) +{ + diag_log_reg_dispatch(log_tbl, ARRAY_SIZE(log_tbl)); +} diff --git a/src/diag_log_umts.c b/src/diag_log_umts.c new file mode 100644 index 0000000..c0303b4 --- /dev/null +++ b/src/diag_log_umts.c @@ -0,0 +1,25 @@ +#include + +#include "diag_log.h" +#include "diag_wcdma.h" +#include "log_codes_wcdma.h" + +static void handle_rrc_sig_msg(struct log_hdr *lh, struct msgb *msg) +{ + struct diag_umts_rrc_msg *rrm = (struct diag_umts_rrc_msg *) msgb_data(msg); + + printf("RRC: %u %u %u: %s\n", rrm->chan_type, rrm->rb_id, rrm->length, + osmo_hexdump(msgb_data(msg), rrm->length)); +} + +#define UMTS(x) (0x4000 + x) + + +static const struct diag_log_dispatch_tbl log_tbl[] = { + { UMTS(LOG_WCDMA_SIGNALING_MSG_C), handle_rrc_sig_msg }, +}; + +static __attribute__((constructor)) void on_dso_load_umts(void) +{ + diag_log_reg_dispatch(log_tbl, ARRAY_SIZE(log_tbl)); +} diff --git a/src/log_codes_gsm.h b/src/log_codes_gsm.h index 457e046..aba64ab 100644 --- a/src/log_codes_gsm.h +++ b/src/log_codes_gsm.h @@ -1,5 +1,7 @@ #pragma once +#define GSM(x) (0x5000 + x) + enum diag_log_code_gsm { LOG_GSM_POWER_SCAN_C = 0x64, LOG_GSM_FCCH_DECODE_C = 0x65, diff --git a/src/qmi_decode.c b/src/qmi_decode.c deleted file mode 100644 index dec48a4..0000000 --- a/src/qmi_decode.c +++ /dev/null @@ -1,29 +0,0 @@ -#include -#include - -#include - -/* A small wrapper around libqmi-glib to give us a human-readable string - * representation of QMI messages that we receive from DIAG */ -int dump_qmi_msg(const uint8_t *data, unsigned int len) -{ - GByteArray *buffer; - GError *error = NULL; - QmiMessage *message; - gchar *printable; - - buffer = g_byte_array_sized_new(len); - g_byte_array_append(buffer, data, len); - - message = qmi_message_new_from_raw(buffer, &error); - if (!message) { - fprintf(stderr, "qmi_message_new_from_raw() returned NULL\n"); - return -1; - } - - printable = qmi_message_get_printable(message, "QMI "); - fputs(printable, stdout); - g_free(printable); - - return 0; -} diff --git a/src/qmi_decode.h b/src/qmi_decode.h deleted file mode 100644 index 0e4ac6a..0000000 --- a/src/qmi_decode.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -#include - -int dump_qmi_msg(const uint8_t *data, unsigned int len); diff --git a/src/qxdm-log.c b/src/qxdm-log.c index 9aa6a81..14f494a 100644 --- a/src/qxdm-log.c +++ b/src/qxdm-log.c @@ -16,16 +16,8 @@ #include "diag_io.h" #include "protocol.h" -#include "config.h" +#include "diag_log.h" #include "diagcmd.h" -#include "diag_gsm.h" -#include "log_codes_gsm.h" -#include "log_codes_wcdma.h" -#include "log_codes_qmi.h" -#include "diag_wcdma.h" -#include "gprs_rlc.h" -#include "gprs_mac.h" -#include "qmi_decode.h" /* handler for EXT MSG */ static int diag_rx_ext_msg_f(const uint8_t *data, const size_t len) @@ -66,248 +58,13 @@ static int diag_rx_ext_msg_f(const uint8_t *data, const size_t len) return 0; } -static void handle_rr_sig_msg(struct log_hdr *lh, struct msgb *msg) -{ - struct diag_gsm_rr_msg *rm = (struct diag_gsm_rr_msg *) msgb_data(msg); - - printf("RR: %02x %02x %u: %s\n", rm->chan_type, rm->msg_type, - rm->length, osmo_hexdump(msgb_data(msg), rm->length)); -} - -static void handle_rr_state_msg(struct log_hdr *lh, struct msgb *msg) -{ - struct diag_gsm_rr_state *rrs = (struct diag_gsm_rr_state *) msgb_data(msg); - printf("RR-STATE { state=%s, substate=%u, status=%u, mode=%u }\n", - get_value_string(diag_gsm_rr_st_vals, rrs->state) - , rrs->substate, rrs->status, rrs->mode); - -} - -static void handle_grr_state_msg(struct log_hdr *lh, struct msgb *msg) -{ - struct diag_gprs_grr_state *rrs = (struct diag_gprs_grr_state *) msgb_data(msg); - - printf("GRR-STATE { active=%u, state=%s }\n", rrs->active_state, - get_value_string(diag_gprs_grr_st_vals, rrs->grr_state)); -} - -static void handle_rrc_sig_msg(struct log_hdr *lh, struct msgb *msg) -{ - struct diag_umts_rrc_msg *rrm = (struct diag_umts_rrc_msg *) msgb_data(msg); - - printf("RRC: %u %u %u: %s\n", rrm->chan_type, rrm->rb_id, rrm->length, - osmo_hexdump(msgb_data(msg), rrm->length)); -} - -static void handle_rlc_ul_abnrml_rls(struct log_hdr *lh, struct msgb *msg) -{ - struct gprs_rlc_ul_abnrml_rls_counts *arc; - arc = (struct gprs_rlc_ul_abnrml_rls_counts *) msgb_data(msg); - - printf("RLC-UL-ABNRML-RLS-COUNTS { access_reject_cnt=%u, arc_retry_cnt=%u, arc_wo_retry_cnt=%u, arc_sys_info_cnt=%u }", - arc->access_reject_cnt, arc->arc_retry_cnt, arc->arc_wo_retry_cnt, arc->arc_sys_info_cnt); -} - -static void handle_mac_sign_msg(struct log_hdr *lh, struct msgb *msg) -{ - struct gprs_mac_signalling_msg *msm; - msm = (struct gprs_mac_signalling_msg *) msgb_data(msg); - printf("MAC-SIGN-MSG { chan_type=%s, msg_type=%s, msg=%s }\n", - get_value_string(gprs_mac_chan_type_vals, msm->chan_type), - get_value_string(gprs_mac_msg_type_vals, msm->msg_type), - osmo_hexdump(msm->msg, msm->msg_len)); -} - -static void handle_llc_me_info(struct log_hdr *lh, struct msgb *msg) -{ - struct diag_gprs_llme_info *gli; - gli = (struct diag_gprs_llme_info *) msgb_data(msg); - printf("LLC-ME-INFO { state=%s, xid_version=%u, tlli_new=0x%08x, tlli_old=0x%08x, gea=%u, key=%s }\n", - get_value_string(diag_gprs_llme_st_vals, gli->state), gli->xid_version, - gli->tlli_new, gli->tlli_old, gli->enc_alg, - osmo_hexdump_nospc(gli->enc_key, sizeof(gli->enc_key))); -} - -static void handle_llc_pdu_stats(struct log_hdr *lh, struct msgb *msg) -{ - struct diag_gprs_llc_stats *gls; - gls = (struct diag_gprs_llc_stats *) msgb_data(msg); - printf("LLC-PDU-STATS-ACK { sap=%u, l3pdu_tx=%u, octet_tx=%u, octet_retrans=%u, l3pdu_rx=%u, octet_rx=%u }\n", - gls->sapi, gls->ack_l3pdu_tx, gls->ack_octet_tx, gls->ack_l3pdu_retrans, gls->ack_l3pdu_rx, gls->ack_octet_rx); - printf("LLC-PDU-STATS-UNACK { sapi=%u, l3pdu_tx=%u, octet_tx=%u, l3pdu_rx=%u, octet_rx=%u }\n", - gls->sapi, gls->unack_l3pdu_tx, gls->unack_octet_tx, gls->unack_l3pdu_rx, gls->unack_octet_rx); - printf("LLC-PDU-STATS-LLPDU { tx=%u, rx=%u, fcs_err=%u, frm_rej=%u, tlli_err=%u, addr_err=%u, short_err=%u }\n", - gls->llpdu_tx, gls->llpdu_rx, gls->llpdu_fcs_err, gls->llpdu_frm_rej, gls->llpdu_tlli_err, gls->llpdu_addr_err, gls->llpdu_short_err); -} - -static void handle_mac_state(struct log_hdr *lh, struct msgb *msg) -{ - struct gprs_mac_state_change *msc; - msc = (struct gprs_mac_state_change *) msgb_data(msg); - const char *name = ""; - - switch (msc->mac_mode) { - case NULL_MODE: - name = get_value_string(gprs_mac_null_substate_vals, msc->mac_null_fsm_state); - break; - case IDLE_MODE: - name = get_value_string(gprs_mac_idle_substate_vals, msc->mac_idle_fsm_state); - break; - case TRANSFER_MODE: - name = get_value_string(gprs_mac_transfer_substate_vals, msc->mac_transfer_fsm_state); - break; - } - - printf("MAC-STATE { mode=%s, state=%s }\n", - get_value_string(gprs_mac_mode_vals, msc->mac_mode), name); -} - -static void handle_mac_dl_tbf_est(struct log_hdr *lh, struct msgb *msg) -{ - struct gprs_mac_dl_tbf_est *dte; - dte = (struct gprs_mac_dl_tbf_est *) msgb_data(msg); - - printf("MAC-DL-TBF-EST { tfi=%u, rlc_mode=%u, dl_ts_bmap=0x%x, is_egprs=%u, egprs_win_size=%u, egprs_link_qual_mode=%u, bep_period2=%u }\n", - dte->dl_tfi, dte->rlc_mode, dte->dl_ts_bmap, dte->is_egprs_tbf, dte->egprs_win_size, dte->egprs_link_qual_mode, dte->bep_period2); -} - -static void handle_mac_ul_tbf_est(struct log_hdr *lh, struct msgb *msg) -{ - struct gprs_mac_ul_tbf_est *ute; - ute = (struct gprs_mac_ul_tbf_est *) msgb_data(msg); - - printf("MAC-UL-TBF-EST { tbf_req_cause=%u, acc_granted=%u, radio_prio=%u, peak_tput=%u, ul_tfi=%u, rlc_mode=%u, ul_ts_bmap=0x%x, is_egprs=%u, egprs_win_size=%u, resegment=%u, bep_period2=%u }\n", - ute->tbf_req_cause, ute->acc_granted, ute->radio_prio, ute->peak_tput, ute->ul_tfi, ute->rlc_mode, ute->ul_ts_bmap, ute->is_egprs_tbf, ute->egprs_win_size, ute->resegment, ute->bep_period2); -} - -static void handle_mac_dl_tbf_rel(struct log_hdr *lh, struct msgb *msg) -{ - struct gprs_mac_tbf_release *tr; - tr = (struct gprs_mac_tbf_release *) msgb_data(msg); - - printf("MAC-DL-TBF-REL { tfi=%u, fail_cause=%u }\n", tr->tfi, tr->fail_cause); -} - -static void handle_mac_ul_tbf_rel(struct log_hdr *lh, struct msgb *msg) -{ - struct gprs_mac_tbf_release *tr; - tr = (struct gprs_mac_tbf_release *) msgb_data(msg); - - printf("MAC-DL-TBF-REL { tfi=%u, fail_cause=%u }\n", tr->tfi, tr->fail_cause); -} - -static void handle_rlc_ul_evt_cnt(struct log_hdr *lh, struct msgb *msg) -{ - struct gprs_rlc_ul_event_counts *uec; - uec = (struct gprs_rlc_ul_event_counts *) msgb_data(msg); - - printf("RLC-UL-EVT-CNT { llc_event_cnt=%u, mac_event_cnt=%u, pl1_event_cnt=%u, tmr_event_cnt=%u }\n", - uec->llc_event_cnt, uec->mac_event_cnt, uec->pl1_event_cnt, uec->tmr_event_cnt); -} - -static void handle_rlc_ul_stats(struct log_hdr *lh, struct msgb *msg) -{ - struct gprs_rlc_ul_stats *uls; - uls = (struct gprs_rlc_ul_stats *) msgb_data(msg); - - printf("RLC-UL-STATS { state=%s(%s), FIXME... }\n", - get_value_string(gprs_rlc_ul_state_vals, uls->rlc_ul_state), - get_value_string(gprs_rlc_ul_substate_vals, uls->rlc_ul_substate)); -} - -static void handle_rlc_dl_stats(struct log_hdr *lh, struct msgb *msg) -{ - struct gprs_rlc_dl_stats *dls; - dls = (struct gprs_rlc_dl_stats *) msgb_data(msg); - - printf("RLC-DL-STATS { state=%s, FIXME... }\n", - get_value_string(gprs_rlc_dl_state_vals, dls->rlc_dl_state)); -} - -static void handle_rlc_rel(struct log_hdr *lh, struct msgb *msg) -{ - struct gprs_rlc_release_ind *rli; - rli = (struct gprs_rlc_release_ind *) msgb_data(msg); - char ud = 'D'; - - if (lh->code == LOG_GPRS_RLC_UL_RELEASE_IND_C) - ud ='U'; - - printf("RLC-%cL-RELEASE { tfi=%u, cause=%u }\n", ud, rli->tfi, rli->cause); -} - - - -struct log_dispatch_tbl { - uint16_t code; - void (*handler)(struct log_hdr *lh, struct msgb *msg); -}; - -#define GSM(x) (0x5000 + x) -#define UMTS(x) (0x4000 + x) - -static const struct log_dispatch_tbl log_tbl[] = { - { GSM(LOG_GSM_RR_SIGNALING_MESSAGE_C), handle_rr_sig_msg }, - { GSM(LOG_GSM_RR_STATE_C), handle_rr_state_msg }, - { GSM(LOG_GPRS_LLC_ME_INFO_C), handle_llc_me_info }, - { GSM(LOG_GPRS_LLC_PDU_STATS_C), handle_llc_pdu_stats }, - { GSM(LOG_GPRS_GRR_STATE_C), handle_grr_state_msg }, - { GSM(LOG_GPRS_RLC_UL_ABNRML_RLS_COUNTS_C), handle_rlc_ul_abnrml_rls }, - { GSM(LOG_GPRS_RLC_UL_EVENT_COUNTS_C), handle_rlc_ul_evt_cnt }, - { GSM(LOG_GPRS_RLC_UL_RELEASE_IND_C), handle_rlc_rel }, - { GSM(LOG_GPRS_RLC_DL_RELEASE_IND_C), handle_rlc_rel }, - { GSM(LOG_GPRS_MAC_SIGNALLING_MESSAGE_C), handle_mac_sign_msg }, - { GSM(LOG_GPRS_MAC_STATE_C), handle_mac_state }, - { GSM(LOG_GPRS_MAC_DL_TBF_ESTABLISH_C), handle_mac_dl_tbf_est }, - { GSM(LOG_GPRS_MAC_UL_TBF_ESTABLISH_C), handle_mac_ul_tbf_est }, - { GSM(LOG_GPRS_MAC_DL_TBF_RELEASE_C), handle_mac_dl_tbf_rel }, - { GSM(LOG_GPRS_MAC_UL_TBF_RELEASE_C), handle_mac_ul_tbf_rel }, - { GSM(LOG_GPRS_RLC_UL_STATS_C), handle_rlc_ul_stats }, - { GSM(LOG_GPRS_RLC_DL_STATS_C), handle_rlc_dl_stats }, - { UMTS(LOG_WCDMA_SIGNALING_MSG_C), handle_rrc_sig_msg }, -}; - -static void diag_log_handle(struct msgb *msg) -{ - struct diag_log_hdr *dlh; - struct log_hdr *lh; - int i; - - dlh = (struct diag_log_hdr *) msg->data; - /* FIXME: verify length */ - msg->l3h = msgb_pull(msg, sizeof(*dlh)); - - lh = (struct log_hdr *) msg->l3h; - /* FIXME: verify length */ - msgb_pull(msg, sizeof(*lh)); - - printf("LOG(0x%04x|%u|%u): ", lh->code, - diag_ts_to_epoch(lh->ts), diag_ts_to_fn(lh->ts)); - - for (i = 0; i < ARRAY_SIZE(log_tbl); i++) { - if (log_tbl[i].code == lh->code) { - log_tbl[i].handler(lh, msg); - return; - } - } - - printf("%s\n", osmo_hexdump(lh->data, lh->len)); - - uint8_t subsys = lh->code >> 12; - - if (subsys == 0x01 && - ((lh->code & 0xfff) >= LOG_QMI_RESERVED_CODES_BASE_C) && - ((lh->code & 0xfff) <= LOG_QMI_LAST_C)) - dump_qmi_msg(lh->data, lh->len); -} - /*********/ static void diag_process_msg(struct diag_instance *di, struct msgb *msg) { switch (msg->l2h[0]) { case DIAG_LOG_F: - diag_log_handle(msg); + diag_log_handle(di, msg); break; case DIAG_EXT_MSG_F: diag_rx_ext_msg_f(msgb_data(msg), msgb_length(msg)); @@ -361,6 +118,7 @@ static void do_configure(struct diag_instance *di) diag_transmit_buf(di, extended_report_cfg, sizeof(extended_report_cfg)); diag_read(di); +#if 0 printf("GSM\n"); struct msgb *msg = gen_log_config_set_mask(5, 1064); #if 0 @@ -369,38 +127,20 @@ static void do_configure(struct diag_instance *di) #endif log_config_set_mask_bit(msg, LOG_GSM_RR_CONTROL_CHANNEL_PARAMS_C); - log_config_set_mask_bit(msg, LOG_GSM_RR_SIGNALING_MESSAGE_C); - log_config_set_mask_bit(msg, LOG_GSM_RR_STATE_C); - log_config_set_mask_bit(msg, LOG_GPRS_GRR_STATE_C); - - log_config_set_mask_bit(msg, LOG_GPRS_RLC_UL_ABNRML_RLS_COUNTS_C); - log_config_set_mask_bit(msg, LOG_GPRS_RLC_UL_EVENT_COUNTS_C); - log_config_set_mask_bit(msg, LOG_GPRS_RLC_UL_STATS_C); - log_config_set_mask_bit(msg, LOG_GPRS_RLC_DL_STATS_C); log_config_set_mask_bit(msg, LOG_GPRS_RLC_UL_ACKNACK_PARAMS_VER2_C); log_config_set_mask_bit(msg, LOG_GPRS_RLC_DL_ACKNACK_PARAMS_VER2_C); - log_config_set_mask_bit(msg, LOG_GPRS_RLC_UL_RELEASE_IND_C); - log_config_set_mask_bit(msg, LOG_GPRS_RLC_DL_RELEASE_IND_C); log_config_set_mask_bit(msg, LOG_EGPRS_RLC_DL_HEADER_C); log_config_set_mask_bit(msg, LOG_EGPRS_RLC_UL_HEADER_C); - log_config_set_mask_bit(msg, LOG_GPRS_LLC_ME_INFO_C); - log_config_set_mask_bit(msg, LOG_GPRS_LLC_PDU_STATS_C); log_config_set_mask_bit(msg, LOG_GPRS_LLC_PERIODIC_STATS_C); log_config_set_mask_bit(msg, LOG_GPRS_SNDCP_UL_TCP_HDR_C); log_config_set_mask_bit(msg, LOG_GPRS_SNDCP_DL_TCP_HDR_C); log_config_set_mask_bit(msg, 546); log_config_set_mask_bit(msg, 547); - log_config_set_mask_bit(msg, LOG_GPRS_MAC_STATE_C); - log_config_set_mask_bit(msg, LOG_GPRS_MAC_SIGNALLING_MESSAGE_C); - log_config_set_mask_bit(msg, LOG_GPRS_MAC_UL_TBF_ESTABLISH_C); - log_config_set_mask_bit(msg, LOG_GPRS_MAC_DL_TBF_ESTABLISH_C); log_config_set_mask_bit(msg, LOG_EGPRS_MAC_UL_ACKNACK_C); log_config_set_mask_bit(msg, LOG_EGPRS_MAC_DL_ACKNACK_C); - log_config_set_mask_bit(msg, LOG_GPRS_MAC_UL_TBF_RELEASE_C); - log_config_set_mask_bit(msg, LOG_GPRS_MAC_DL_TBF_RELEASE_C); diag_transmit_msgb(di, msg); diag_read(di); @@ -416,23 +156,12 @@ static void do_configure(struct diag_instance *di) log_config_set_mask_bit(msg, 0x127); log_config_set_mask_bit(msg, 0x128); log_config_set_mask_bit(msg, 0x129); - log_config_set_mask_bit(msg, LOG_WCDMA_SIGNALING_MSG_C); - - diag_transmit_msgb(di, msg); - diag_read(di); - - - printf("Core\n"); - msg = gen_log_config_set_mask(1, 1064); - log_config_set_mask_bit(msg, LOG_QMI_CALL_FLOW_C); - log_config_set_mask_bit(msg, LOG_QMI_SUPPORTED_INTERFACES_C); - for (int i = 0; i < 16*2; i++) - log_config_set_mask_bit(msg, LOG_QMI_RESERVED_CODES_BASE_C+i); - for (int i = LOG_QMI_RESERVED_CODES_BASE_C; i < LOG_QMI_LAST_C; i++) - log_config_set_mask_bit(msg, i); diag_transmit_msgb(di, msg); diag_read(di); +#else + diag_log_enable_all_supported(di); +#endif } int main(int argc, char **argv)