aboutsummaryrefslogtreecommitdiff
path: root/libqcdm/src/commands.c
diff options
context:
space:
mode:
Diffstat (limited to 'libqcdm/src/commands.c')
-rw-r--r--libqcdm/src/commands.c310
1 files changed, 272 insertions, 38 deletions
diff --git a/libqcdm/src/commands.c b/libqcdm/src/commands.c
index f906f1a..541cad7 100644
--- a/libqcdm/src/commands.c
+++ b/libqcdm/src/commands.c
@@ -103,6 +103,43 @@ cdma_band_class_to_qcdm (u_int8_t cdma)
return QCDM_CDMA_BAND_CLASS_UNKNOWN;
}
+static u_int8_t
+nv_mode_pref_from_qcdm (u_int8_t qcdm)
+{
+ switch (qcdm) {
+ case QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_DIGITAL:
+ return DIAG_NV_MODE_PREF_DIGITAL;
+ case QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_DIGITAL_ONLY:
+ return DIAG_NV_MODE_PREF_DIGITAL_ONLY;
+ case QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_ANALOG:
+ return DIAG_NV_MODE_PREF_ANALOG;
+ case QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_ANALOG_ONLY:
+ return DIAG_NV_MODE_PREF_ANALOG_ONLY;
+ case QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_AUTO:
+ return DIAG_NV_MODE_PREF_AUTO;
+ case QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_1X_ONLY:
+ return DIAG_NV_MODE_PREF_1X_ONLY;
+ case QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_HDR_ONLY:
+ return DIAG_NV_MODE_PREF_HDR_ONLY;
+ case QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_GPRS_ONLY:
+ return DIAG_NV_MODE_PREF_GPRS_ONLY;
+ case QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_UMTS_ONLY:
+ return DIAG_NV_MODE_PREF_UMTS_ONLY;
+ case QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_GSM_UMTS_ONLY:
+ return DIAG_NV_MODE_PREF_GSM_UMTS_ONLY;
+ case QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_1X_HDR_ONLY:
+ return DIAG_NV_MODE_PREF_1X_HDR_ONLY;
+ case QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_LTE_ONLY:
+ return DIAG_NV_MODE_PREF_LTE_ONLY;
+ case QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_GSM_UMTS_LTE_ONLY:
+ return DIAG_NV_MODE_PREF_GSM_UMTS_LTE_ONLY;
+ case QCDM_CMD_NV_MODE_PREF_ITEM_MODE_PREF_1X_HDR_LTE_ONLY:
+ return DIAG_NV_MODE_PREF_1X_HDR_LTE_ONLY;
+ }
+ return DIAG_NV_MODE_PREF_AUTO;
+};
+
+
/**********************************************************************/
/*
@@ -366,6 +403,35 @@ qcdm_cmd_esn_result (const char *buf, size_t len, int *out_error)
/**********************************************************************/
size_t
+qcdm_cmd_control_new (char *buf, size_t len, u_int8_t mode)
+{
+ char cmdbuf[5];
+ DMCmdControl *cmd = (DMCmdControl *) &cmdbuf[0];
+
+ qcdm_return_val_if_fail (buf != NULL, 0);
+ qcdm_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
+
+ memset (cmd, 0, sizeof (*cmd));
+ cmd->code = DIAG_CMD_CONTROL;
+ cmd->mode = htole16 ((u_int16_t) mode);
+
+ return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
+}
+
+QcdmResult *
+qcdm_cmd_control_result (const char *buf, size_t len, int *out_error)
+{
+ qcdm_return_val_if_fail (buf != NULL, NULL);
+
+ if (!check_command (buf, len, DIAG_CMD_CONTROL, sizeof (DMCmdControl), out_error))
+ return NULL;
+
+ return qcdm_result_new ();
+}
+
+/**********************************************************************/
+
+size_t
qcdm_cmd_cdma_status_new (char *buf, size_t len)
{
char cmdbuf[3];
@@ -507,11 +573,26 @@ snapshot_state_to_qcdm (u_int8_t cdma_state)
return cdma_state + 1;
}
+static inline u_int8_t
+digit_fixup (u_int8_t d)
+{
+ /* CDMA MCC/IMSI conversion adds 1 to each digit, and digits equal to
+ * 10 are really zero.
+ */
+ if (d + 1 < 10)
+ return d + 1;
+ return 0;
+}
+
QcdmResult *
qcdm_cmd_status_snapshot_result (const char *buf, size_t len, int *out_error)
{
QcdmResult *result = NULL;
DMCmdStatusSnapshotRsp *rsp = (DMCmdStatusSnapshotRsp *) buf;
+ char *tmp;
+ u_int8_t swapped[4];
+ u_int8_t tmcc[3];
+ u_int16_t mcc, hmcc;
qcdm_return_val_if_fail (buf != NULL, NULL);
@@ -520,6 +601,27 @@ qcdm_cmd_status_snapshot_result (const char *buf, size_t len, int *out_error)
result = qcdm_result_new ();
+ /* Convert the ESN from binary to a hex string; it's LE so we have to
+ * swap it to get the correct ordering.
+ */
+ swapped[0] = rsp->esn[3];
+ swapped[1] = rsp->esn[2];
+ swapped[2] = rsp->esn[1];
+ swapped[3] = rsp->esn[0];
+
+ tmp = bin2hexstr (&swapped[0], sizeof (swapped));
+ qcdm_result_add_string (result, QCDM_CMD_STATUS_SNAPSHOT_ITEM_ESN, tmp);
+ free (tmp);
+
+ /* Cheap binary -> decimal conversion */
+ hmcc = le16toh (rsp->mcc);
+ tmcc[2] = hmcc / 100;
+ tmcc[1] = (hmcc - (tmcc[2] * 100)) / 10;
+ tmcc[0] = (hmcc - (tmcc[2] * 100) - (tmcc[1] * 10));
+
+ mcc = (100 * digit_fixup (tmcc[2])) + (10 * digit_fixup (tmcc[1])) + digit_fixup (tmcc[0]);
+ qcdm_result_add_u32 (result, QCDM_CMD_STATUS_SNAPSHOT_ITEM_HOME_MCC, mcc);
+
qcdm_result_add_u8 (result, QCDM_CMD_STATUS_SNAPSHOT_ITEM_BAND_CLASS, cdma_band_class_to_qcdm (rsp->band_class));
qcdm_result_add_u8 (result, QCDM_CMD_STATUS_SNAPSHOT_ITEM_BASE_STATION_PREV, cdma_prev_to_qcdm (rsp->prev));
qcdm_result_add_u8 (result, QCDM_CMD_STATUS_SNAPSHOT_ITEM_MOBILE_PREV, cdma_prev_to_qcdm (rsp->mob_prev));
@@ -587,7 +689,7 @@ qcdm_cmd_pilot_sets_result (const char *buf, size_t len, int *out_error)
sets_len = rsp->candidate_count * sizeof (DMCmdPilotSetsSet);
if (sets_len > 0) {
qcdm_result_add_u8_array (result,
- PILOT_SETS_CMD_ACTIVE_SET,
+ PILOT_SETS_CMD_CANDIDATE_SET,
(const u_int8_t *) &rsp->sets[rsp->active_count],
sets_len);
}
@@ -595,7 +697,7 @@ qcdm_cmd_pilot_sets_result (const char *buf, size_t len, int *out_error)
sets_len = rsp->neighbor_count * sizeof (DMCmdPilotSetsSet);
if (sets_len > 0) {
qcdm_result_add_u8_array (result,
- PILOT_SETS_CMD_ACTIVE_SET,
+ PILOT_SETS_CMD_NEIGHBOR_SET,
(const u_int8_t *) &rsp->sets[rsp->active_count + rsp->candidate_count],
sets_len);
}
@@ -617,7 +719,7 @@ qcdm_cmd_pilot_sets_result_get_num (QcdmResult *result,
set_name = set_num_to_str (set_type);
qcdm_return_val_if_fail (set_name != NULL, FALSE);
- if (!qcdm_result_get_u8_array (result, set_name, &array, &array_len))
+ if (qcdm_result_get_u8_array (result, set_name, &array, &array_len))
return FALSE;
*out_num = array_len / sizeof (DMCmdPilotSetsSet);
@@ -642,7 +744,7 @@ qcdm_cmd_pilot_sets_result_get_pilot (QcdmResult *result,
set_name = set_num_to_str (set_type);
qcdm_return_val_if_fail (set_name != NULL, FALSE);
- if (!qcdm_result_get_u8_array (result, set_name, &array, &array_len))
+ if (qcdm_result_get_u8_array (result, set_name, &array, &array_len))
return FALSE;
qcdm_return_val_if_fail (num < array_len / sizeof (DMCmdPilotSetsSet), FALSE);
@@ -813,24 +915,6 @@ qcdm_cmd_nv_set_roam_pref_result (const char *buf, size_t len, int *out_error)
/**********************************************************************/
-static qcdmbool
-mode_pref_validate (u_int8_t dm)
-{
- switch (dm) {
- case DIAG_NV_MODE_PREF_DIGITAL:
- case DIAG_NV_MODE_PREF_DIGITAL_ONLY:
- case DIAG_NV_MODE_PREF_AUTO:
- case DIAG_NV_MODE_PREF_1X_ONLY:
- case DIAG_NV_MODE_PREF_HDR_ONLY:
- case DIAG_NV_MODE_PREF_1X_HDR_ONLY:
- case DIAG_NV_MODE_PREF_LTE_ONLY:
- case DIAG_NV_MODE_PREF_1X_HDR_LTE_ONLY:
- return TRUE;
- default:
- return FALSE;
- }
-}
-
size_t
qcdm_cmd_nv_get_mode_pref_new (char *buf, size_t len, u_int8_t profile)
{
@@ -868,9 +952,6 @@ qcdm_cmd_nv_get_mode_pref_result (const char *buf, size_t len, int *out_error)
mode = (DMNVItemModePref *) &rsp->data[0];
- if (!mode_pref_validate (mode->mode_pref))
- qcdm_warn (0, "Unknown mode preference 0x%X", mode->mode_pref);
-
result = qcdm_result_new ();
qcdm_result_add_u8 (result, QCDM_CMD_NV_GET_MODE_PREF_ITEM_PROFILE, mode->profile);
qcdm_result_add_u8 (result, QCDM_CMD_NV_GET_MODE_PREF_ITEM_MODE_PREF, mode->mode_pref);
@@ -891,18 +972,13 @@ qcdm_cmd_nv_set_mode_pref_new (char *buf,
qcdm_return_val_if_fail (buf != NULL, 0);
qcdm_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
- if (!mode_pref_validate (mode_pref)) {
- qcdm_err (0, "Invalid mode preference %d", mode_pref);
- return 0;
- }
-
memset (cmd, 0, sizeof (*cmd));
cmd->code = DIAG_CMD_NV_WRITE;
cmd->nv_item = htole16 (DIAG_NV_MODE_PREF);
req = (DMNVItemModePref *) &cmd->data[0];
req->profile = profile;
- req->mode_pref = mode_pref;
+ req->mode_pref = nv_mode_pref_from_qcdm (mode_pref);
return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
}
@@ -923,6 +999,94 @@ qcdm_cmd_nv_set_mode_pref_result (const char *buf, size_t len, int *out_error)
/**********************************************************************/
+size_t
+qcdm_cmd_nv_get_hybrid_pref_new (char *buf, size_t len)
+{
+ char cmdbuf[sizeof (DMCmdNVReadWrite) + 2];
+ DMCmdNVReadWrite *cmd = (DMCmdNVReadWrite *) &cmdbuf[0];
+
+ qcdm_return_val_if_fail (buf != NULL, 0);
+ qcdm_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
+
+ memset (cmd, 0, sizeof (*cmd));
+ cmd->code = DIAG_CMD_NV_READ;
+ cmd->nv_item = htole16 (DIAG_NV_HYBRID_PREF);
+
+ return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
+}
+
+QcdmResult *
+qcdm_cmd_nv_get_hybrid_pref_result (const char *buf, size_t len, int *out_error)
+{
+ QcdmResult *result = NULL;
+ DMCmdNVReadWrite *rsp = (DMCmdNVReadWrite *) buf;
+ DMNVItemHybridPref *hybrid;
+
+ qcdm_return_val_if_fail (buf != NULL, NULL);
+
+ if (!check_command (buf, len, DIAG_CMD_NV_READ, sizeof (DMCmdNVReadWrite), out_error))
+ return NULL;
+
+ if (!check_nv_cmd (rsp, DIAG_NV_HYBRID_PREF, out_error))
+ return NULL;
+
+ hybrid = (DMNVItemHybridPref *) &rsp->data[0];
+
+ if (hybrid->hybrid_pref > 1)
+ qcdm_warn (0, "Unknown hybrid preference 0x%X", hybrid->hybrid_pref);
+
+ result = qcdm_result_new ();
+ qcdm_result_add_u8 (result, QCDM_CMD_NV_GET_HYBRID_PREF_ITEM_HYBRID_PREF, hybrid->hybrid_pref);
+
+ return result;
+}
+
+size_t
+qcdm_cmd_nv_set_hybrid_pref_new (char *buf,
+ size_t len,
+ u_int8_t hybrid_pref)
+{
+ char cmdbuf[sizeof (DMCmdNVReadWrite) + 2];
+ DMCmdNVReadWrite *cmd = (DMCmdNVReadWrite *) &cmdbuf[0];
+ DMNVItemHybridPref *req;
+
+ qcdm_return_val_if_fail (buf != NULL, 0);
+ qcdm_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
+
+ if (hybrid_pref > QCDM_CMD_NV_HYBRID_PREF_ITEM_REV_HYBRID_ON) {
+ qcdm_err (0, "Invalid hybrid preference %d", hybrid_pref);
+ return 0;
+ }
+
+ memset (cmd, 0, sizeof (*cmd));
+ cmd->code = DIAG_CMD_NV_WRITE;
+ cmd->nv_item = htole16 (DIAG_NV_HYBRID_PREF);
+
+ req = (DMNVItemHybridPref *) &cmd->data[0];
+ if (hybrid_pref == QCDM_CMD_NV_HYBRID_PREF_ITEM_REV_HYBRID_OFF)
+ req->hybrid_pref = DIAG_NV_HYBRID_PREF_OFF;
+ else if (hybrid_pref == QCDM_CMD_NV_HYBRID_PREF_ITEM_REV_HYBRID_ON)
+ req->hybrid_pref = DIAG_NV_HYBRID_PREF_ON;
+
+ return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
+}
+
+QcdmResult *
+qcdm_cmd_nv_set_hybrid_pref_result (const char *buf, size_t len, int *out_error)
+{
+ qcdm_return_val_if_fail (buf != NULL, NULL);
+
+ if (!check_command (buf, len, DIAG_CMD_NV_WRITE, sizeof (DMCmdNVReadWrite), out_error))
+ return NULL;
+
+ if (!check_nv_cmd ((DMCmdNVReadWrite *) buf, DIAG_NV_HYBRID_PREF, out_error))
+ return NULL;
+
+ return qcdm_result_new ();
+}
+
+/**********************************************************************/
+
static qcdmbool
hdr_rev_pref_validate (u_int8_t dm)
{
@@ -1321,16 +1485,16 @@ qcdm_cmd_nw_subsys_modem_snapshot_cdma_new (char *buf,
cmd->hdr.code = DIAG_CMD_SUBSYS;
switch (chipset) {
case QCDM_NW_CHIPSET_6500:
- cmd->hdr.subsys_id = DIAG_SUBSYS_NW_CONTROL_6500;
+ cmd->hdr.subsys_id = DIAG_SUBSYS_NOVATEL_6500;
break;
case QCDM_NW_CHIPSET_6800:
- cmd->hdr.subsys_id = DIAG_SUBSYS_NW_CONTROL_6800;
+ cmd->hdr.subsys_id = DIAG_SUBSYS_NOVATEL_6800;
break;
default:
qcdm_assert_not_reached ();
}
- cmd->hdr.subsys_cmd = htole16 (DIAG_SUBSYS_NW_CONTROL_MODEM_SNAPSHOT);
- cmd->technology = DIAG_SUBSYS_NW_CONTROL_MODEM_SNAPSHOT_TECH_CDMA_EVDO;
+ cmd->hdr.subsys_cmd = htole16 (DIAG_SUBSYS_NOVATEL_MODEM_SNAPSHOT);
+ cmd->technology = DIAG_SUBSYS_NOVATEL_MODEM_SNAPSHOT_TECH_CDMA_EVDO;
cmd->snapshot_mask = htole32 (0xFFFF);
return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
@@ -1383,6 +1547,76 @@ qcdm_cmd_nw_subsys_modem_snapshot_cdma_result (const char *buf, size_t len, int
/**********************************************************************/
+size_t
+qcdm_cmd_nw_subsys_eri_new (char *buf,
+ size_t len,
+ u_int8_t chipset)
+{
+ char cmdbuf[sizeof (DMCmdSubsysHeader) + 2];
+ DMCmdSubsysHeader *cmd = (DMCmdSubsysHeader *) &cmdbuf[0];
+
+ qcdm_return_val_if_fail (buf != NULL, 0);
+ qcdm_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
+
+ /* Validate chipset */
+ if (chipset != QCDM_NW_CHIPSET_6500 && chipset != QCDM_NW_CHIPSET_6800) {
+ qcdm_err (0, "Unknown Novatel chipset 0x%X", chipset);
+ return 0;
+ }
+
+ memset (cmd, 0, sizeof (*cmd));
+ cmd->code = DIAG_CMD_SUBSYS;
+ switch (chipset) {
+ case QCDM_NW_CHIPSET_6500:
+ cmd->subsys_id = DIAG_SUBSYS_NOVATEL_6500;
+ break;
+ case QCDM_NW_CHIPSET_6800:
+ cmd->subsys_id = DIAG_SUBSYS_NOVATEL_6800;
+ break;
+ default:
+ qcdm_assert_not_reached ();
+ }
+ cmd->subsys_cmd = htole16 (DIAG_SUBSYS_NOVATEL_ERI);
+
+ return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
+}
+
+QcdmResult *
+qcdm_cmd_nw_subsys_eri_result (const char *buf, size_t len, int *out_error)
+{
+ QcdmResult *result = NULL;
+ DMCmdSubsysNwEriRsp *rsp = (DMCmdSubsysNwEriRsp *) buf;
+ char str[50];
+
+ qcdm_return_val_if_fail (buf != NULL, NULL);
+
+ if (!check_command (buf, len, DIAG_CMD_SUBSYS, sizeof (DMCmdSubsysNwEriRsp), out_error))
+ return NULL;
+
+ /* FIXME: check 'status' when we know what it means */
+
+ result = qcdm_result_new ();
+
+ qcdm_result_add_u8 (result, QCDM_CMD_NW_SUBSYS_ERI_ITEM_ROAM, rsp->roam);
+ qcdm_result_add_u8 (result, QCDM_CMD_NW_SUBSYS_ERI_ITEM_INDICATOR_ID, rsp->indicator_id);
+ qcdm_result_add_u8 (result, QCDM_CMD_NW_SUBSYS_ERI_ITEM_ICON_ID, rsp->icon_id);
+ qcdm_result_add_u8 (result, QCDM_CMD_NW_SUBSYS_ERI_ITEM_ICON_MODE, rsp->icon_mode);
+ qcdm_result_add_u8 (result, QCDM_CMD_NW_SUBSYS_ERI_ITEM_CALL_PROMPT_ID, rsp->call_prompt_id);
+ qcdm_result_add_u8 (result, QCDM_CMD_NW_SUBSYS_ERI_ITEM_ALERT_ID, rsp->alert_id);
+
+ qcdm_warn_if_fail (rsp->text_len < sizeof (str));
+ if (rsp->text_len < sizeof (str)) {
+ qcdm_assert (sizeof (str) > sizeof (rsp->text));
+ memcpy (str, rsp->text, sizeof (rsp->text));
+ str[rsp->text_len] = '\0';
+ qcdm_result_add_string (result, QCDM_CMD_NW_SUBSYS_ERI_ITEM_TEXT, str);
+ }
+
+ return result;
+}
+
+/**********************************************************************/
+
static size_t
qcdm_cmd_log_config_new (char *buf,
size_t len,
@@ -1629,7 +1863,7 @@ imxi_bcd_to_string (u_int8_t bytes[8], size_t len, char *buf, size_t buflen)
qcdm_return_val_if_fail (len == 8, FALSE);
qcdm_return_val_if_fail (buf != NULL, FALSE);
- qcdm_return_val_if_fail (buflen > len, FALSE);
+ qcdm_return_val_if_fail (buflen > (len * 2), FALSE);
p = buf;
for (i = 0 ; i < len; i++) {
@@ -1673,7 +1907,7 @@ qcdm_cmd_wcdma_subsys_state_info_result (const char *buf, size_t len, int *out_e
{
QcdmResult *result = NULL;
DMCmdSubsysWcdmaStateInfoRsp *rsp = (DMCmdSubsysWcdmaStateInfoRsp *) buf;
- char imxi[10];
+ char imxi[18];
qcdm_return_val_if_fail (buf != NULL, NULL);
@@ -1719,7 +1953,7 @@ qcdm_cmd_gsm_subsys_state_info_result (const char *buf, size_t len, int *out_err
{
QcdmResult *result = NULL;
DMCmdSubsysGsmStateInfoRsp *rsp = (DMCmdSubsysGsmStateInfoRsp *) buf;
- char imxi[10];
+ char imxi[18];
u_int32_t mcc = 0, mnc = 0;
u_int8_t mnc3;