[PATCH 1/3] qcdm: add IPv6 nvram setting

Bjørn Mork bjorn at mork.no
Wed Nov 27 03:54:09 PST 2013


IPv6 is disabled by default in Qualcomm firmwares. The firmware will
happily let you configure the IPV6 and IPV4V6 PDP types, but any
attempt to connect will fail.

IPv6 is enabled by setting a flag in nvram.

Signed-off-by: Bjørn Mork <bjorn at mork.no>
---
 libqcdm/src/commands.c |   88 ++++++++++++++++++++++++++++++++++++++++++++++++
 libqcdm/src/commands.h |   24 +++++++++++++
 libqcdm/src/nv-items.h |   13 +++++++
 3 files changed, 125 insertions(+)

diff --git a/libqcdm/src/commands.c b/libqcdm/src/commands.c
index 541cad7..c36d138 100644
--- a/libqcdm/src/commands.c
+++ b/libqcdm/src/commands.c
@@ -1087,6 +1087,94 @@ qcdm_cmd_nv_set_hybrid_pref_result (const char *buf, size_t len, int *out_error)
 
 /**********************************************************************/
 
+size_t
+qcdm_cmd_nv_get_ipv6_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_IPV6_PREF);
+
+    return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
+}
+
+QcdmResult *
+qcdm_cmd_nv_get_ipv6_pref_result (const char *buf, size_t len, int *out_error)
+{
+    QcdmResult *result = NULL;
+    DMCmdNVReadWrite *rsp = (DMCmdNVReadWrite *) buf;
+    DMNVItemIPv6Pref *ipv6;
+
+    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_IPV6_PREF, out_error))
+        return NULL;
+
+    ipv6 = (DMNVItemIPv6Pref *) &rsp->data[0];
+
+    if (ipv6->ipv6_pref > 1)
+        qcdm_warn (0, "Unknown ipv6 preference 0x%X", ipv6->ipv6_pref);
+
+    result = qcdm_result_new ();
+    qcdm_result_add_u8 (result, QCDM_CMD_NV_GET_IPV6_PREF_ITEM_IPV6_PREF, ipv6->ipv6_pref);
+
+    return result;
+}
+
+size_t
+qcdm_cmd_nv_set_ipv6_pref_new (char *buf,
+                                 size_t len,
+                                 u_int8_t ipv6_pref)
+{
+    char cmdbuf[sizeof (DMCmdNVReadWrite) + 2];
+    DMCmdNVReadWrite *cmd = (DMCmdNVReadWrite *) &cmdbuf[0];
+    DMNVItemIPv6Pref *req;
+
+    qcdm_return_val_if_fail (buf != NULL, 0);
+    qcdm_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
+
+    if (ipv6_pref > QCDM_CMD_NV_IPV6_PREF_ITEM_REV_IPV6_ON) {
+        qcdm_err (0, "Invalid ipv6 preference %d", ipv6_pref);
+        return 0;
+    }
+
+    memset (cmd, 0, sizeof (*cmd));
+    cmd->code = DIAG_CMD_NV_WRITE;
+    cmd->nv_item = htole16 (DIAG_NV_IPV6_PREF);
+
+    req = (DMNVItemIPv6Pref *) &cmd->data[0];
+    if (ipv6_pref == QCDM_CMD_NV_IPV6_PREF_ITEM_REV_IPV6_OFF)
+        req->ipv6_pref = DIAG_NV_IPV6_PREF_OFF;
+    else if (ipv6_pref == QCDM_CMD_NV_IPV6_PREF_ITEM_REV_IPV6_ON)
+        req->ipv6_pref = DIAG_NV_IPV6_PREF_ON;
+
+    return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
+}
+
+QcdmResult *
+qcdm_cmd_nv_set_ipv6_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_IPV6_PREF, out_error))
+        return NULL;
+
+    return qcdm_result_new ();
+}
+
+/**********************************************************************/
+
 static qcdmbool
 hdr_rev_pref_validate (u_int8_t dm)
 {
diff --git a/libqcdm/src/commands.h b/libqcdm/src/commands.h
index 437261b..60b89b4 100644
--- a/libqcdm/src/commands.h
+++ b/libqcdm/src/commands.h
@@ -351,6 +351,29 @@ QcdmResult *qcdm_cmd_nv_set_hybrid_pref_result (const char *buf,
 
 /**********************************************************************/
 
+enum {
+    QCDM_CMD_NV_IPV6_PREF_ITEM_REV_IPV6_OFF = 0x00,
+    QCDM_CMD_NV_IPV6_PREF_ITEM_REV_IPV6_ON = 0x01,
+};
+
+#define QCDM_CMD_NV_GET_IPV6_PREF_ITEM_IPV6_PREF "ipv6-pref"
+
+size_t      qcdm_cmd_nv_get_ipv6_pref_new    (char *buf, size_t len);
+
+QcdmResult *qcdm_cmd_nv_get_ipv6_pref_result (const char *buf,
+                                                size_t len,
+                                                int *out_error);
+
+size_t      qcdm_cmd_nv_set_ipv6_pref_new    (char *buf,
+                                                size_t len,
+                                                u_int8_t ipv6_pref);
+
+QcdmResult *qcdm_cmd_nv_set_ipv6_pref_result (const char *buf,
+                                                size_t len,
+                                                int *out_error);
+
+/**********************************************************************/
+
 /* Values for QCDM_CMD_NV_GET_HDR_REV_PREF_ITEM_REV_PREF */
 enum {
     QCDM_CMD_NV_HDR_REV_PREF_ITEM_REV_PREF_0 = 0x00,
@@ -447,6 +470,7 @@ enum {
 #define QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_SERVICE_DOMAIN_PREF    "service-domain-pref"
 #define QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_ACQ_ORDER_PREF         "acq-order-pref"
 #define QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_HYBRID_PREF            "hybrid-pref"
+#define QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_IPV6_PREF              "ipv6-pref"
 #define QCDM_CMD_CM_SUBSYS_STATE_INFO_ITEM_NETWORK_SELECTION_PREF "network-selection-pref"
 
 size_t      qcdm_cmd_cm_subsys_state_info_new    (char *buf, size_t len);
diff --git a/libqcdm/src/nv-items.h b/libqcdm/src/nv-items.h
index 1a5db67..ca50fdb 100644
--- a/libqcdm/src/nv-items.h
+++ b/libqcdm/src/nv-items.h
@@ -37,6 +37,7 @@ enum {
     DIAG_NV_DIR_NUMBER   = 178,  /* Mobile Directory Number (MDN) */
     DIAG_NV_ROAM_PREF    = 442,  /* Roaming preference */
     DIAG_NV_HYBRID_PREF  = 562,  /* Hybrid 1x + HDR preference */
+    DIAG_NV_IPV6_PREF    = 1896, /* Enable IPv6 */
     DIAG_NV_HDR_REV_PREF = 4964, /* HDR mode preference(?): rev0, revA, eHRPD */
 };
 
@@ -114,5 +115,17 @@ struct DMNVItemHybridPref {
 } __attribute__ ((packed));
 typedef struct DMNVItemHybridPref DMNVItemHybridPref;
 
+/* IPv6 enable */
+enum {
+    DIAG_NV_IPV6_PREF_OFF   = 0x00,
+    DIAG_NV_IPV6_PREF_ON    = 0x01,
+};
+
+/* DIAG_NV_IPV6_PREF */
+struct DMNVItemIPv6Pref {
+    u_int8_t ipv6_pref;
+} __attribute__ ((packed));
+typedef struct DMNVItemIPv6Pref DMNVItemIPv6Pref;
+
 #endif  /* LIBQCDM_NV_ITEMS_H */
 
-- 
1.7.10.4



More information about the ModemManager-devel mailing list