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>
This commit is contained in:
Bjørn Mork
2013-12-05 13:16:09 -06:00
committed by Dan Williams
parent 073163fb0b
commit 13552aa8b6
3 changed files with 124 additions and 0 deletions
+88
View File
@@ -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)
{
+23
View File
@@ -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,
+13
View File
@@ -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 */