diff options
author | Dan Williams <dcbw@redhat.com> | 2012-01-11 14:25:23 -0600 |
---|---|---|
committer | Dan Williams <dcbw@redhat.com> | 2012-01-11 14:25:23 -0600 |
commit | f3208bf3a6a94ed2a5e3f87c703df9ee0896cabf (patch) | |
tree | 0b96a74b7517745869bc013a6a2d5459888e0104 /libqcdm | |
parent | b22b2d99db57e4cec8e6c3074dd20acd6845cb62 (diff) |
qcdm: add support for Log Config command
This appears to be a newer version of EXT_LOGMASK that also
works with GSM/UMTS and other subsystems.
Diffstat (limited to 'libqcdm')
-rw-r--r-- | libqcdm/src/commands.c | 228 | ||||
-rw-r--r-- | libqcdm/src/commands.h | 29 | ||||
-rw-r--r-- | libqcdm/src/dm-commands.h | 32 | ||||
-rw-r--r-- | libqcdm/src/errors.h | 1 | ||||
-rw-r--r-- | libqcdm/tests/test-qcdm-com.c | 43 | ||||
-rw-r--r-- | libqcdm/tests/test-qcdm-com.h | 2 | ||||
-rw-r--r-- | libqcdm/tests/test-qcdm.c | 1 |
7 files changed, 336 insertions, 0 deletions
diff --git a/libqcdm/src/commands.c b/libqcdm/src/commands.c index f21b9235..b4e3ab8e 100644 --- a/libqcdm/src/commands.c +++ b/libqcdm/src/commands.c @@ -1385,3 +1385,231 @@ qcdm_cmd_nw_subsys_modem_snapshot_cdma_result (const char *buf, size_t len, int /**********************************************************************/ +static size_t +qcdm_cmd_log_config_new (char *buf, + size_t len, + u_int32_t op, + u_int32_t equip_id, + u_int32_t items[]) +{ + DMCmdLogConfig *cmd; + u_int16_t highest = 0; + u_int32_t items_len = 0; + size_t cmdsize = 0, cmdbufsize; + u_int32_t i; + u_int32_t log_code; + + qcdm_return_val_if_fail (buf != NULL, 0); + qcdm_return_val_if_fail ((equip_id & 0xFFF0) == 0, 0); + + /* Find number of log items */ + if (items) { + while (items_len < 4095 && items[items_len]) + items_len++; + } + cmdsize = sizeof (DMCmdLogConfig) + ((items_len + 7) / 8); + cmdbufsize = cmdsize + DIAG_TRAILER_LEN; + + qcdm_return_val_if_fail (len >= cmdsize, 0); + + cmd = calloc (1, cmdbufsize); + cmd->code = DIAG_CMD_LOG_CONFIG; + cmd->op = htole32 (op); + cmd->equipid = htole32 (equip_id); + + if (items) { + /* Set up the bitmask of log items */ + for (i = 0; i < items_len; i++) { + log_code = items[i] & 0x0FFF; /* Strip off equip ID */ + cmd->mask[log_code / 8] |= 1 << log_code % 8; + if (log_code > highest) + highest = log_code; + } + cmd->num_items = htole32 (highest); + } + + return dm_encapsulate_buffer ((char *) cmd, cmdsize, cmdbufsize, buf, len); +} + +size_t +qcdm_cmd_log_config_get_mask_new (char *buf, + size_t len, + u_int32_t equip_id) +{ + return qcdm_cmd_log_config_new (buf, + len, + DIAG_CMD_LOG_CONFIG_OP_GET_MASK, + equip_id, + NULL); +} + +static int +check_log_config_respose (const char *buf, size_t len, u_int32_t op) +{ + DMCmdLogConfigRsp *rsp = (DMCmdLogConfigRsp *) buf; + size_t minlen = 16; /* minimum valid resposne */ + int err; + + /* Ensure size is at least enough for the command header */ + if (len < 1) { + qcdm_err (0, "DIAG_CMD_LOG_CONFIG response not long enough (got %zu, " + "expected at least %d).", len, 3); + return -QCDM_ERROR_RESPONSE_BAD_LENGTH; + } + + if (rsp->code == DIAG_CMD_LOG_CONFIG) { + u_int32_t rspop; + + if (len < 16) { + /* At least enough for code + op + result + equipid */ + qcdm_err (0, "DIAG_CMD_LOG_CONFIG response not long enough (got %zu, " + "expected at least %d).", len, 16); + return -QCDM_ERROR_RESPONSE_BAD_LENGTH; + } + + rspop = le32toh (rsp->op); + if (rspop != op) { + qcdm_err (0, "DIAG_CMD_LOG_CONFIG response operation mismatch (got " + "op %u, expected %u)", rspop, op); + return -QCDM_ERROR_RESPONSE_BAD_COMMAND; + } + + /* check for success */ + if (le32toh (rsp->result) != 0) { + qcdm_err (0, "DIAG_CMD_LOG_CONFIG response failed with result %u.", + le32toh (rsp->result)); + return -QCDM_ERROR_RESPONSE_FAILED; + } + + switch (rspop) { + case DIAG_CMD_LOG_CONFIG_OP_GET_RANGE: + minlen += 16; /* get_range_items */ + break; + case DIAG_CMD_LOG_CONFIG_OP_SET_MASK: + case DIAG_CMD_LOG_CONFIG_OP_GET_MASK: + if (len < 16) { + qcdm_err (0, "DIAG_CMD_LOG_CONFIG response not long enough " + "(got %zu, expected at least %d).", len, 16); + return -QCDM_ERROR_RESPONSE_BAD_LENGTH; + } + minlen += 4; /* num_items */ + minlen += (le32toh (rsp->u.get_set_items.num_items) + 7) / 8; + break; + default: + qcdm_err (0, "Unknown DIAG_CMD_LOG_CONFIG response operation %d", rspop); + return -QCDM_ERROR_RESPONSE_UNEXPECTED; + } + } + + if (!check_command (buf, len, DIAG_CMD_LOG_CONFIG, minlen, &err)) + return err; + + return 0; +} + +#define LOG_CODE_SET(mask, code) (mask[code / 8] & (1 << (code % 8))) + +static QcdmResult * +log_config_get_set_result (const char *buf, size_t len, u_int32_t op, int *out_error) +{ + QcdmResult *result = NULL; + DMCmdLogConfigRsp *rsp = (DMCmdLogConfigRsp *) buf; + int err; + u_int32_t num_items; + u_int32_t equipid; + + qcdm_return_val_if_fail (buf != NULL, NULL); + + err = check_log_config_respose (buf, len, op); + if (err) { + if (out_error) + *out_error = err; + return NULL; + } + + result = qcdm_result_new (); + + equipid = le32toh (rsp->equipid); + qcdm_result_add_u32 (result, QCDM_CMD_LOG_CONFIG_MASK_ITEM_EQUIP_ID, equipid); + + num_items = le32toh (rsp->u.get_set_items.num_items); + qcdm_result_add_u32 (result, QCDM_CMD_LOG_CONFIG_MASK_ITEM_NUM_ITEMS, num_items); + + if (num_items > 0) { + u_int32_t i, num_result_items = 0, count = 0; + u_int16_t *items; + + /* First pass to find out how many are actually enabled */ + for (i = 0; i < num_items; i++) { + /* Check if the bit corresponding to this log item is set */ + if (LOG_CODE_SET (rsp->u.get_set_items.mask, i)) + num_result_items++; + } + + items = malloc (num_result_items); + for (i = 0; i < num_items; i++) { + if (LOG_CODE_SET (rsp->u.get_set_items.mask, i)) + items[count++] = (equipid << 12) | i; + } + + qcdm_result_add_u16_array (result, QCDM_CMD_LOG_CONFIG_MASK_ITEM_ITEMS, items, count); + free (items); + } + + return result; +} + +QcdmResult * +qcdm_cmd_log_config_get_mask_result (const char *buf, size_t len, int *out_error) +{ + return log_config_get_set_result (buf, len, DIAG_CMD_LOG_CONFIG_OP_GET_MASK, out_error); +} + +size_t +qcdm_cmd_log_config_set_mask_new (char *buf, + size_t len, + u_int32_t equip_id, + u_int32_t items[]) +{ + return qcdm_cmd_log_config_new (buf, + len, + DIAG_CMD_LOG_CONFIG_OP_SET_MASK, + equip_id, + items); +} + +QcdmResult * +qcdm_cmd_log_config_set_mask_result (const char *buf, size_t len, int *out_error) +{ + return log_config_get_set_result (buf, len, DIAG_CMD_LOG_CONFIG_OP_SET_MASK, out_error); +} + +qcdmbool +qcmd_cmd_log_config_mask_result_code_set (QcdmResult *result, + u_int32_t equipid, + u_int16_t log_code) +{ + const u_int16_t *items = NULL; + size_t len = 0; + u_int32_t i, tmp; + + qcdm_return_val_if_fail (result != NULL, FALSE); + + if (qcdm_result_get_u32 (result, QCDM_CMD_LOG_CONFIG_MASK_ITEM_EQUIP_ID, &tmp) != 0) + return FALSE; + qcdm_return_val_if_fail (equipid != tmp, FALSE); + + if (qcdm_result_get_u16_array (result, + QCDM_CMD_LOG_CONFIG_MASK_ITEM_ITEMS, + &items, + &len)) { + for (i = 0; i < len; i++) { + if ((items[i] & 0x0FFF) == (log_code & 0x0FFF)) + return TRUE; + } + } + return FALSE; +} + +/**********************************************************************/ + diff --git a/libqcdm/src/commands.h b/libqcdm/src/commands.h index ceb4a4cc..0d925cab 100644 --- a/libqcdm/src/commands.h +++ b/libqcdm/src/commands.h @@ -499,6 +499,35 @@ QcdmResult *qcdm_cmd_event_report_result (const char *buf, /**********************************************************************/ +size_t qcdm_cmd_log_config_get_mask_new (char *buf, + size_t len, + u_int32_t equip_id); + +size_t qcdm_cmd_log_config_set_mask_new (char *buf, + size_t len, + u_int32_t equip_id, + u_int32_t items[]); + +#define QCDM_CMD_LOG_CONFIG_MASK_ITEM_EQUIP_ID "equip-id" + +#define QCDM_CMD_LOG_CONFIG_MASK_ITEM_NUM_ITEMS "num-items" + +#define QCDM_CMD_LOG_CONFIG_MASK_ITEM_ITEMS "items" + +QcdmResult *qcdm_cmd_log_config_get_mask_result (const char *buf, + size_t len, + int *out_error); + +QcdmResult *qcdm_cmd_log_config_set_mask_result (const char *buf, + size_t len, + int *out_error); + +qcdmbool qcmd_cmd_log_config_mask_result_code_set (QcdmResult *result, + u_int32_t equipid, + u_int16_t log_code); + +/**********************************************************************/ + #define QCDM_CMD_ZTE_SUBSYS_STATUS_ITEM_SIGNAL_INDICATOR "signal-indicator" size_t qcdm_cmd_zte_subsys_status_new (char *buf, size_t len); diff --git a/libqcdm/src/dm-commands.h b/libqcdm/src/dm-commands.h index e3a0e0a1..db152d0f 100644 --- a/libqcdm/src/dm-commands.h +++ b/libqcdm/src/dm-commands.h @@ -462,5 +462,37 @@ struct DMCmdSubsysNwSnapshotCdma { } __attribute__ ((packed)); typedef struct DMCmdSubsysNwSnapshotCdma DMCmdSubsysNwSnapshotCdma; +enum { + DIAG_CMD_LOG_CONFIG_OP_GET_RANGE = 0x01, + DIAG_CMD_LOG_CONFIG_OP_SET_MASK = 0x03, + DIAG_CMD_LOG_CONFIG_OP_GET_MASK = 0x04, +}; + +struct DMCmdLogConfig { + u_int8_t code; + u_int8_t pad[3]; + u_int32_t op; + u_int32_t equipid; + u_int32_t num_items; + u_int8_t mask[0]; +} __attribute__ ((packed)); +typedef struct DMCmdLogConfig DMCmdLogConfig; + +struct DMCmdLogConfigRsp { + u_int8_t code; + u_int8_t pad[3]; + u_int32_t op; + u_int32_t result; /* 0 = success */ + u_int32_t equipid; + union { + u_int32_t get_range_items[16]; + struct { + u_int32_t num_items; + u_int8_t mask[0]; + } get_set_items; + } u; +} __attribute__ ((packed)); +typedef struct DMCmdLogConfigRsp DMCmdLogConfigRsp; + #endif /* LIBQCDM_DM_COMMANDS_H */ diff --git a/libqcdm/src/errors.h b/libqcdm/src/errors.h index b6e49728..a5507bb1 100644 --- a/libqcdm/src/errors.h +++ b/libqcdm/src/errors.h @@ -52,6 +52,7 @@ enum { QCDM_ERROR_NV_ERROR_INACTIVE = 17, /* NV location is not active */ QCDM_ERROR_NV_ERROR_BAD_PARAMETER = 18, QCDM_ERROR_NV_ERROR_READ_ONLY = 19, /* NV location is read-only */ + QCDM_ERROR_RESPONSE_FAILED = 20, /* command-specific failure */ }; #define qcdm_assert assert diff --git a/libqcdm/tests/test-qcdm-com.c b/libqcdm/tests/test-qcdm-com.c index 76987e3a..89154fdb 100644 --- a/libqcdm/tests/test-qcdm-com.c +++ b/libqcdm/tests/test-qcdm-com.c @@ -1383,6 +1383,49 @@ test_com_event_report (void *f, void *data) } void +test_com_log_config (void *f, void *data) +{ + TestComData *d = data; + gboolean success; + int err = QCDM_SUCCESS; + char buf[520]; + gint len; + QcdmResult *result; + gsize reply_len; + u_int32_t num_items = 0; + const u_int16_t *items = NULL; + size_t items_len = 0; + u_int32_t i; + + /* Get existing mask for CDMA/EVDO equip ID */ + len = qcdm_cmd_log_config_get_mask_new (buf, sizeof (buf), 0x01); + g_assert (len); + + /* Send the command */ + success = send_command (d, buf, len); + g_assert (success); + + /* Get a response */ + reply_len = wait_reply (d, buf, sizeof (buf)); + + g_print ("\n"); + + /* Parse the response into a result structure */ + result = qcdm_cmd_log_config_get_mask_result (buf, reply_len, &err); + g_assert (result); + + qcdm_result_get_u32 (result, QCDM_CMD_LOG_CONFIG_MASK_ITEM_NUM_ITEMS, &num_items); + g_message ("%s: Num Log Items: %u (0x%X)", __func__, num_items, num_items); + + qcdm_result_get_u16_array (result, QCDM_CMD_LOG_CONFIG_MASK_ITEM_ITEMS, + &items, &items_len); + for (i = 0; i < items_len; i++) + g_message ("%s: Enabled: 0x%04x", __func__, items[i]); + + qcdm_result_unref (result); +} + +void test_com_zte_subsys_status (void *f, void *data) { TestComData *d = data; diff --git a/libqcdm/tests/test-qcdm-com.h b/libqcdm/tests/test-qcdm-com.h index 76075e54..9ce3a2b3 100644 --- a/libqcdm/tests/test-qcdm-com.h +++ b/libqcdm/tests/test-qcdm-com.h @@ -51,6 +51,8 @@ void test_com_ext_logmask (void *f, void *data); void test_com_event_report (void *f, void *data); +void test_com_log_config (void *f, void *data); + void test_com_zte_subsys_status (void *f, void *data); void test_com_nw_subsys_modem_snapshot_cdma (void *f, void *data); diff --git a/libqcdm/tests/test-qcdm.c b/libqcdm/tests/test-qcdm.c index 6cc32fbe..14d55787 100644 --- a/libqcdm/tests/test-qcdm.c +++ b/libqcdm/tests/test-qcdm.c @@ -112,6 +112,7 @@ int main (int argc, char **argv) g_test_suite_add (suite, TESTCASE (test_com_hdr_subsys_state_info, data->com_data)); g_test_suite_add (suite, TESTCASE (test_com_ext_logmask, data->com_data)); g_test_suite_add (suite, TESTCASE (test_com_event_report, data->com_data)); + g_test_suite_add (suite, TESTCASE (test_com_log_config, data->com_data)); g_test_suite_add (suite, TESTCASE (test_com_zte_subsys_status, data->com_data)); g_test_suite_add (suite, TESTCASE (test_com_nw_subsys_modem_snapshot_cdma, data->com_data)); } |