/* Cesar project {{{ * * Copyright (C) 2008 Spidcom * * <<>> * * }}} */ /** * \file cp/src/trace.c * \brief Define CP trace events. * \ingroup cp */ #include "common/std.h" #include #include #include "cp/inc/context.h" #include "cp/fsm/inc/tables.h" #include "cp/msg/inc/allowed_mme.h" #include "ce/tx/mme.h" #include "mac/common/tonemap.h" /** * Table to associate an MME error code and its string translation. */ const char *cp_trace_ce_tx_mme_error_code_table[] = { "CE_TX_MME_OK", "CE_TX_MME_BROADCAST", "CE_TX_MME_UNKNOWN_STA", "CE_TX_MME_HEADER", "CE_TX_MME_TMI_LIST", "CE_TX_MME_DEFAULT_TMI_DISABLED", "CE_TX_MME_DEFAULT_TMI", "CE_TX_MME_INTERVAL", "CE_TX_MME_NEW_TMI", "CE_TX_MME_NEW_TMI_DISABLED", "CE_TX_MME_BAD_TM", "CE_TX_MME_NEW_TMI_ROBO", "CE_TX_MME_TOO_SHORT", "CE_TX_MME_OLD_TMI", "CE_TX_MME_OLD_TMI_NOT_FOUND", "UNKNOWN", }; /** * Table to associate an MME dispatch error code and its string translation. */ const char *cp_trace_rx_mme_error_code_table[] = { "OK", "NOT_HANDLED", "PHY_NOT_ALLOWED", "H1_NOT_ALLOWED", "STA_STATUS_NOK", "SPC_OUI_NOT_SPIDCOM", "BAD_ENCRYPTION", "UNKNOWN" }; /** * Format a FSM state. * \see trace_format_t. */ static int cp_trace_format_fsm_state (char *text, uint text_size, int data) { const char *state_name; if (data < 0 || data >= CP_FSM_STATE_NB) state_name = "UNKNOWN"; else state_name = cp_fsm_state_names_table[data]; uint state_name_len = strlen (state_name); if (state_name_len > text_size) return -1; else { memcpy (text, state_name, state_name_len); return state_name_len; } } /** * Format a FSM event. * \see trace_format_t. */ static int cp_trace_format_fsm_event (char *text, uint text_size, int data) { const char *event_name; if (data < 0 || data >= CP_FSM_EVENT_TYPE_NB) event_name = "UNKNOWN"; else event_name = cp_fsm_event_names_table[data]; uint event_name_len = strlen (event_name); if (event_name_len > text_size) return -1; else { memcpy (text, event_name, event_name_len); return event_name_len; } } /** * Format an MMType. * \see trace_format_t. */ static int cp_trace_format_mmtype (char *text, uint text_size, int data) { const char *mmtype_name = "UNKNOWN"; /* Try to find the MMType. */ uint i; mmtype_t mmtype = data; DICHOTOMY_SEARCH (0, cp_msg_mme_allowed_count, i, mmtype <= cp_msg_mme_allowed[i].mmtype); /* If found. */ if ((i < cp_msg_mme_allowed_count) && (mmtype == cp_msg_mme_allowed[i].mmtype)) mmtype_name = cp_msg_mme_allowed[i].mmtype_name; /* Copy if we can. */ uint mmtype_name_len = strlen (mmtype_name); if (mmtype_name_len > text_size) return -1; else { memcpy (text, mmtype_name, mmtype_name_len); return mmtype_name_len; } } /** * Copy an error into trace buffer. * \param error_name the error to trace. * \return error_name length on success, -1 otherwise. */ static int cp_trace_format_copy_error (char *text, uint text_size, const char *error_name) { /* Copy if we can. */ uint error_name_len = strlen (error_name); if (error_name_len > text_size) return -1; else { memcpy (text, error_name, error_name_len); return error_name_len; } } /** * Format an error of CE MME. * \see trace_format_t. */ static int cp_trace_format_ce_mme_error (char *text, uint text_size, int data) { const char *error_name; /* Handle unknown error. */ if (data > CE_TX_MME_NB || data < 0) data = CE_TX_MME_NB; /* Sanity check. */ dbg_assert (COUNT (cp_trace_ce_tx_mme_error_code_table) == CE_TX_MME_NB + 1); dbg_assert ((uint) data <= COUNT (cp_trace_ce_tx_mme_error_code_table)); /* Get error message. */ error_name = cp_trace_ce_tx_mme_error_code_table[data]; return cp_trace_format_copy_error (text, text_size, error_name); } /** * Format list of TMIs enabled. * \see trace_format_t. */ static int cp_trace_format_tm_enabled_list (char *text, uint text_size, int data) { #define STRING_LEN 255 char tmi_enabled_list[STRING_LEN] = ""; static const char sep_empty[] = ""; static const char sep[] = ", "; const char *s = sep_empty; uint i; for (i = TONEMAP_INDEX_NEGOTIATED_FIRST; i < TONEMAP_INDEX_NB; i++) { /* Tone map index enabled? */ if (data & (1 << i)) { /* Build 'separator and tmi' string. */ char tmp[STRING_LEN]; snprintf (tmp, STRING_LEN, "%s%i", s, i); /* Add it to main string. */ strcat (tmi_enabled_list, tmp); /* Update separator. */ s = sep; } } return cp_trace_format_copy_error (text, text_size, tmi_enabled_list); #undef STRING_LEN } /** * Format an dispatch error of cp_msg_dispatch. * \see trace_format_t */ static int cp_trace_format_msg_dispatch_error (char *text, uint text_size, int data) { const char *error_name; /* Sanity check. */ dbg_assert ((uint) data <= COUNT (cp_trace_rx_mme_error_code_table)); /* Get error message. */ error_name = cp_trace_rx_mme_error_code_table[data]; return cp_trace_format_copy_error (text, text_size, error_name); } void cp_trace_common_init (cp_t *ctx, trace_namespace_t *ns, const trace_event_id_t *event_ids, const uint event_ids_nb) { dbg_assert (ctx); dbg_assert (ns); dbg_assert (event_ids); trace_namespace_init (ns, event_ids, event_ids_nb); trace_namespace_register_format (ns, 'S', cp_trace_format_fsm_state); trace_namespace_register_format (ns, 'E', cp_trace_format_fsm_event); trace_namespace_register_format (ns, 'M', cp_trace_format_mmtype); trace_namespace_register_format (ns, 'Z', cp_trace_format_ce_mme_error); trace_namespace_register_format (ns, 'T', cp_trace_format_tm_enabled_list); trace_namespace_register_format (ns, 'Y', cp_trace_format_msg_dispatch_error); trace_buffer_add (&ctx->trace, "cp", 8, 1, false, ns); trace_buffer_add (&ctx->trace_verbose, "cp-verbose", 8, 8, true, ns); } void cp_trace_uninit (cp_t *ctx) { dbg_assert (ctx); trace_buffer_remove (&ctx->trace_verbose); trace_buffer_remove (&ctx->trace); }