aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2010-03-30 00:32:05 -0700
committerDan Williams <dcbw@redhat.com>2010-03-30 00:32:27 -0700
commit0ae176c63c8686cd3a86b7933be5ae3546782475 (patch)
tree33486efe86bf3469fbff80283621423c0b37dd6e
parentcff40ac4724780e73f47af4f17cba952ab1ed680 (diff)
qcdm: add Pilot Set retrieval for signal strength calculations
Determined from various sources including RTManager and "Technical Introduction to CDMA" (Course RF100 Chapter 7).
-rw-r--r--libqcdm/src/commands.c122
-rw-r--r--libqcdm/src/commands.h28
-rw-r--r--libqcdm/src/dm-commands.h16
-rw-r--r--libqcdm/tests/test-qcdm-com.c54
-rw-r--r--libqcdm/tests/test-qcdm-com.h2
-rw-r--r--libqcdm/tests/test-qcdm.c1
6 files changed, 223 insertions, 0 deletions
diff --git a/libqcdm/src/commands.c b/libqcdm/src/commands.c
index 156cf14c..6bdaff06 100644
--- a/libqcdm/src/commands.c
+++ b/libqcdm/src/commands.c
@@ -366,6 +366,128 @@ qcdm_cmd_sw_version_result (const char *buf, gsize len, GError **error)
/**********************************************************************/
gsize
+qcdm_cmd_pilot_sets_new (char *buf, gsize len, GError **error)
+{
+ char cmdbuf[3];
+ DMCmdHeader *cmd = (DMCmdHeader *) &cmdbuf[0];
+
+ g_return_val_if_fail (buf != NULL, 0);
+ g_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
+
+ memset (cmd, 0, sizeof (*cmd));
+ cmd->code = DIAG_CMD_PILOT_SETS;
+
+ return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
+}
+
+#define PILOT_SETS_CMD_ACTIVE_SET "active-set"
+#define PILOT_SETS_CMD_CANDIDATE_SET "candidate-set"
+#define PILOT_SETS_CMD_NEIGHBOR_SET "neighbor-set"
+
+static const char *
+set_num_to_str (guint32 num)
+{
+ if (num == QCDM_CMD_PILOT_SETS_TYPE_ACTIVE)
+ return PILOT_SETS_CMD_ACTIVE_SET;
+ if (num == QCDM_CMD_PILOT_SETS_TYPE_CANDIDATE)
+ return PILOT_SETS_CMD_CANDIDATE_SET;
+ if (num == QCDM_CMD_PILOT_SETS_TYPE_NEIGHBOR)
+ return PILOT_SETS_CMD_NEIGHBOR_SET;
+ return NULL;
+}
+
+QCDMResult *
+qcdm_cmd_pilot_sets_result (const char *buf, gsize len, GError **error)
+{
+ QCDMResult *result = NULL;
+ DMCmdPilotSetsRsp *rsp = (DMCmdPilotSetsRsp *) buf;
+ GByteArray *array;
+ gsize sets_len;
+
+ g_return_val_if_fail (buf != NULL, NULL);
+
+ if (!check_command (buf, len, DIAG_CMD_PILOT_SETS, sizeof (DMCmdPilotSetsRsp), error))
+ return NULL;
+
+ result = qcdm_result_new ();
+
+ sets_len = rsp->active_count * sizeof (DMCmdPilotSetsSet);
+ if (sets_len > 0) {
+ array = g_byte_array_sized_new (sets_len);
+ g_byte_array_append (array, (const guint8 *) &rsp->sets[0], sets_len);
+ qcdm_result_add_boxed (result, PILOT_SETS_CMD_ACTIVE_SET, G_TYPE_BYTE_ARRAY, array);
+ }
+
+ sets_len = rsp->candidate_count * sizeof (DMCmdPilotSetsSet);
+ if (sets_len > 0) {
+ array = g_byte_array_sized_new (sets_len);
+ g_byte_array_append (array, (const guint8 *) &rsp->sets[rsp->active_count], sets_len);
+ qcdm_result_add_boxed (result, PILOT_SETS_CMD_CANDIDATE_SET, G_TYPE_BYTE_ARRAY, array);
+ }
+
+ sets_len = rsp->neighbor_count * sizeof (DMCmdPilotSetsSet);
+ if (sets_len > 0) {
+ array = g_byte_array_sized_new (sets_len);
+ g_byte_array_append (array, (const guint8 *) &rsp->sets[rsp->active_count + rsp->candidate_count], sets_len);
+ qcdm_result_add_boxed (result, PILOT_SETS_CMD_NEIGHBOR_SET, G_TYPE_BYTE_ARRAY, array);
+ }
+
+ return result;
+}
+
+gboolean
+qcdm_cmd_pilot_sets_result_get_num (QCDMResult *result,
+ guint32 set_type,
+ guint32 *out_num)
+{
+ const char *set_name;
+ GByteArray *array = NULL;
+
+ g_return_val_if_fail (result != NULL, FALSE);
+
+ set_name = set_num_to_str (set_type);
+ g_return_val_if_fail (set_name != NULL, FALSE);
+
+ if (!qcdm_result_get_boxed (result, set_name, (gpointer) &array))
+ return FALSE;
+
+ *out_num = array->len / sizeof (DMCmdPilotSetsSet);
+ return TRUE;
+}
+
+gboolean
+qcdm_cmd_pilot_sets_result_get_pilot (QCDMResult *result,
+ guint32 set_type,
+ guint32 num,
+ guint32 *out_pn_offset,
+ guint32 *out_ecio,
+ float *out_db)
+{
+ const char *set_name;
+ GByteArray *array = NULL;
+ DMCmdPilotSetsSet *set;
+
+ g_return_val_if_fail (result != NULL, FALSE);
+
+ set_name = set_num_to_str (set_type);
+ g_return_val_if_fail (set_name != NULL, FALSE);
+
+ if (!qcdm_result_get_boxed (result, set_name, (gpointer) &array))
+ return FALSE;
+
+ g_return_val_if_fail (num < array->len / sizeof (DMCmdPilotSetsSet), FALSE);
+
+ set = (DMCmdPilotSetsSet *) &array->data[num * sizeof (DMCmdPilotSetsSet)];
+ *out_pn_offset = set->pn_offset;
+ *out_ecio = set->ecio;
+ /* EC/IO is in units of -0.5 dB per the specs */
+ *out_db = (float) set->ecio * -0.5;
+ return TRUE;
+}
+
+/**********************************************************************/
+
+gsize
qcdm_cmd_nv_get_mdn_new (char *buf, gsize len, guint8 profile, GError **error)
{
char cmdbuf[sizeof (DMCmdNVReadWrite) + 2];
diff --git a/libqcdm/src/commands.h b/libqcdm/src/commands.h
index 0878fe33..38aec359 100644
--- a/libqcdm/src/commands.h
+++ b/libqcdm/src/commands.h
@@ -110,6 +110,34 @@ QCDMResult *qcdm_cmd_sw_version_result (const char *buf,
/**********************************************************************/
+enum {
+ QCDM_CMD_PILOT_SETS_TYPE_UNKNOWN = 0,
+ QCDM_CMD_PILOT_SETS_TYPE_ACTIVE = 1,
+ QCDM_CMD_PILOT_SETS_TYPE_CANDIDATE = 2,
+ QCDM_CMD_PILOT_SETS_TYPE_NEIGHBOR = 3,
+};
+
+gsize qcdm_cmd_pilot_sets_new (char *buf,
+ gsize len,
+ GError **error);
+
+QCDMResult *qcdm_cmd_pilot_sets_result (const char *buf,
+ gsize len,
+ GError **error);
+
+gboolean qcdm_cmd_pilot_sets_result_get_num (QCDMResult *result,
+ guint32 set_type,
+ guint32 *out_num);
+
+gboolean qcdm_cmd_pilot_sets_result_get_pilot (QCDMResult *result,
+ guint32 set_type,
+ guint32 num,
+ guint32 *out_pn_offset,
+ guint32 *out_ecio,
+ float *out_db);
+
+/**********************************************************************/
+
#define QCDM_CMD_NV_GET_MDN_ITEM_PROFILE "profile"
#define QCDM_CMD_NV_GET_MDN_ITEM_MDN "mdn"
diff --git a/libqcdm/src/dm-commands.h b/libqcdm/src/dm-commands.h
index 35245281..0777104c 100644
--- a/libqcdm/src/dm-commands.h
+++ b/libqcdm/src/dm-commands.h
@@ -279,5 +279,21 @@ struct DMCmdSubsysZteStatusRsp {
} __attribute__ ((packed));
typedef struct DMCmdSubsysZteStatusRsp DMCmdSubsysZteStatusRsp;
+struct DMCmdPilotSetsSet {
+ guint16 pn_offset;
+ guint16 ecio;
+} __attribute__ ((packed));
+typedef struct DMCmdPilotSetsSet DMCmdPilotSetsSet;
+
+struct DMCmdPilotSetsRsp {
+ guint8 code;
+ guint16 pilot_inc;
+ guint8 active_count;
+ guint8 candidate_count;
+ guint8 neighbor_count;
+ DMCmdPilotSetsSet sets[52];
+} __attribute__ ((packed));
+typedef struct DMCmdPilotSetsRsp DMCmdPilotSetsRsp;
+
#endif /* LIBQCDM_DM_COMMANDS_H */
diff --git a/libqcdm/tests/test-qcdm-com.c b/libqcdm/tests/test-qcdm-com.c
index c9fe7296..1327f33e 100644
--- a/libqcdm/tests/test-qcdm-com.c
+++ b/libqcdm/tests/test-qcdm-com.c
@@ -599,6 +599,60 @@ test_com_sw_version (void *f, void *data)
}
void
+test_com_pilot_sets (void *f, void *data)
+{
+ TestComData *d = data;
+ gboolean success;
+ GError *error = NULL;
+ char buf[256];
+ gint len;
+ QCDMResult *result;
+ gsize reply_len;
+ guint32 num, i;
+
+ len = qcdm_cmd_pilot_sets_new (buf, sizeof (buf), NULL);
+ g_assert (len == 4);
+
+ /* Send the command */
+ success = send_command (d, buf, len);
+ g_assert (success);
+
+ /* Get a response */
+ reply_len = wait_reply (d, buf, sizeof (buf));
+
+ /* Parse the response into a result structure */
+ result = qcdm_cmd_pilot_sets_result (buf, reply_len, &error);
+ g_assert (result);
+
+ num = 0;
+ qcdm_cmd_pilot_sets_result_get_num (result, QCDM_CMD_PILOT_SETS_TYPE_ACTIVE, &num);
+ g_message ("%s: Active Pilots: %d", __func__, num);
+ for (i = 0; i < num; i++) {
+ guint32 pn_offset = 0, ecio = 0;
+ float db = 0;
+
+ qcdm_cmd_pilot_sets_result_get_pilot (result,
+ QCDM_CMD_PILOT_SETS_TYPE_ACTIVE,
+ i,
+ &pn_offset,
+ &ecio,
+ &db);
+ g_message (" %d: PN offset %d", i, pn_offset);
+ g_message (" EC/IO %d (%.1f dB)", ecio, db);
+ }
+
+ num = 0;
+ qcdm_cmd_pilot_sets_result_get_num (result, QCDM_CMD_PILOT_SETS_TYPE_CANDIDATE, &num);
+ g_message ("%s: Candidate Pilots: %d", __func__, num);
+
+ num = 0;
+ qcdm_cmd_pilot_sets_result_get_num (result, QCDM_CMD_PILOT_SETS_TYPE_NEIGHBOR, &num);
+ g_message ("%s: Neighbor Pilots: %d", __func__, num);
+
+ qcdm_result_unref (result);
+}
+
+void
test_com_cm_subsys_state_info (void *f, void *data)
{
TestComData *d = data;
diff --git a/libqcdm/tests/test-qcdm-com.h b/libqcdm/tests/test-qcdm-com.h
index d9f4ee75..8ea8e605 100644
--- a/libqcdm/tests/test-qcdm-com.h
+++ b/libqcdm/tests/test-qcdm-com.h
@@ -37,6 +37,8 @@ void test_com_status (void *f, void *data);
void test_com_sw_version (void *f, void *data);
+void test_com_pilot_sets (void *f, void *data);
+
void test_com_cm_subsys_state_info (void *f, void *data);
void test_com_hdr_subsys_state_info (void *f, void *data);
diff --git a/libqcdm/tests/test-qcdm.c b/libqcdm/tests/test-qcdm.c
index d87a2e31..0a6801fb 100644
--- a/libqcdm/tests/test-qcdm.c
+++ b/libqcdm/tests/test-qcdm.c
@@ -98,6 +98,7 @@ int main (int argc, char **argv)
g_test_suite_add (suite, TESTCASE (test_com_read_mode_pref, data->com_data));
g_test_suite_add (suite, TESTCASE (test_com_status, data->com_data));
g_test_suite_add (suite, TESTCASE (test_com_sw_version, data->com_data));
+ g_test_suite_add (suite, TESTCASE (test_com_pilot_sets, data->com_data));
g_test_suite_add (suite, TESTCASE (test_com_cm_subsys_state_info, data->com_data));
g_test_suite_add (suite, TESTCASE (test_com_hdr_subsys_state_info, data->com_data));
g_test_suite_add (suite, TESTCASE (test_com_zte_subsys_status, data->com_data));