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:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user