summaryrefslogtreecommitdiff
path: root/libqcdm
diff options
context:
space:
mode:
authorBjørn Mork <bjorn@mork.no>2013-12-05 12:43:18 +0100
committerDan Williams <dcbw@redhat.com>2013-12-05 13:16:09 -0600
commit13552aa8b67058caa5a183238f2cfe73737f26c2 (patch)
treedacaa3a912e63d98e3bae620001cf76d7a9f9fae /libqcdm
parent073163fb0b7fd1408029d986b7052638d357f69c (diff)
qcdm: add IPv6 nvram setting
Some Qualcomm firmwares disable IPv6 unless this flag is set in nvram, at least for the LTE default bearer. The firmware will happily let you configure the IPV6 and IPV4V6 PDP types, also including the default profile, but any attempt to connect will fail. Signed-off-by: Bjørn Mork <bjorn@mork.no>
Diffstat (limited to 'libqcdm')
-rw-r--r--libqcdm/src/commands.c88
-rw-r--r--libqcdm/src/commands.h23
-rw-r--r--libqcdm/src/nv-items.h13
3 files changed, 124 insertions, 0 deletions
diff --git a/libqcdm/src/commands.c b/libqcdm/src/commands.c
index 541cad76..ff7d2328 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_enabled_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_ENABLED);
+
+ return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
+}
+
+QcdmResult *
+qcdm_cmd_nv_get_ipv6_enabled_result (const char *buf, size_t len, int *out_error)
+{
+ QcdmResult *result = NULL;
+ DMCmdNVReadWrite *rsp = (DMCmdNVReadWrite *) buf;
+ DMNVItemIPv6Enabled *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_ENABLED, out_error))
+ return NULL;
+
+ ipv6 = (DMNVItemIPv6Enabled *) &rsp->data[0];
+
+ if (ipv6->enabled > 1)
+ qcdm_warn (0, "Unknown ipv6 preference 0x%X", ipv6->enabled);
+
+ result = qcdm_result_new ();
+ qcdm_result_add_u8 (result, QCDM_CMD_NV_GET_IPV6_ENABLED_ITEM_ENABLED, ipv6->enabled);
+
+ return result;
+}
+
+size_t
+qcdm_cmd_nv_set_ipv6_enabled_new (char *buf,
+ size_t len,
+ u_int8_t enabled)
+{
+ char cmdbuf[sizeof (DMCmdNVReadWrite) + 2];
+ DMCmdNVReadWrite *cmd = (DMCmdNVReadWrite *) &cmdbuf[0];
+ DMNVItemIPv6Enabled *req;
+
+ qcdm_return_val_if_fail (buf != NULL, 0);
+ qcdm_return_val_if_fail (len >= sizeof (*cmd) + DIAG_TRAILER_LEN, 0);
+
+ if (enabled > QCDM_CMD_NV_IPV6_ENABLED_ON) {
+ qcdm_err (0, "Invalid ipv6 preference %d", enabled);
+ return 0;
+ }
+
+ memset (cmd, 0, sizeof (*cmd));
+ cmd->code = DIAG_CMD_NV_WRITE;
+ cmd->nv_item = htole16 (DIAG_NV_IPV6_ENABLED);
+
+ req = (DMNVItemIPv6Enabled *) &cmd->data[0];
+ if (enabled == QCDM_CMD_NV_IPV6_ENABLED_OFF)
+ req->enabled = DIAG_NV_IPV6_ENABLED_OFF;
+ else if (enabled == QCDM_CMD_NV_IPV6_ENABLED_ON)
+ req->enabled = DIAG_NV_IPV6_ENABLED_ON;
+
+ return dm_encapsulate_buffer (cmdbuf, sizeof (*cmd), sizeof (cmdbuf), buf, len);
+}
+
+QcdmResult *
+qcdm_cmd_nv_set_ipv6_enabled_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_ENABLED, 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 437261b2..6f05f1c7 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_ENABLED_OFF = 0x00,
+ QCDM_CMD_NV_IPV6_ENABLED_ON = 0x01,
+};
+
+#define QCDM_CMD_NV_GET_IPV6_ENABLED_ITEM_ENABLED "ipv6-enabled"
+
+size_t qcdm_cmd_nv_get_ipv6_enabled_new (char *buf, size_t len);
+
+QcdmResult *qcdm_cmd_nv_get_ipv6_enabled_result (const char *buf,
+ size_t len,
+ int *out_error);
+
+size_t qcdm_cmd_nv_set_ipv6_enabled_new (char *buf,
+ size_t len,
+ u_int8_t enabled);
+
+QcdmResult *qcdm_cmd_nv_set_ipv6_enabled_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,
diff --git a/libqcdm/src/nv-items.h b/libqcdm/src/nv-items.h
index 1a5db670..dae7f9df 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_ENABLED = 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_ENABLED_OFF = 0x00,
+ DIAG_NV_IPV6_ENABLED_ON = 0x01,
+};
+
+/* DIAG_NV_IPV6_ENABLED */
+struct DMNVItemIPv6Enabled {
+ u_int8_t enabled;
+} __attribute__ ((packed));
+typedef struct DMNVItemIPv6Enabled DMNVItemIPv6Enabled;
+
#endif /* LIBQCDM_NV_ITEMS_H */