summaryrefslogtreecommitdiff
path: root/libqcdm
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2012-01-11 14:25:23 -0600
committerDan Williams <dcbw@redhat.com>2012-01-11 14:25:23 -0600
commitf3208bf3a6a94ed2a5e3f87c703df9ee0896cabf (patch)
tree0b96a74b7517745869bc013a6a2d5459888e0104 /libqcdm
parentb22b2d99db57e4cec8e6c3074dd20acd6845cb62 (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.c228
-rw-r--r--libqcdm/src/commands.h29
-rw-r--r--libqcdm/src/dm-commands.h32
-rw-r--r--libqcdm/src/errors.h1
-rw-r--r--libqcdm/tests/test-qcdm-com.c43
-rw-r--r--libqcdm/tests/test-qcdm-com.h2
-rw-r--r--libqcdm/tests/test-qcdm.c1
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));
}