Add Foxconn FCC Unlock mechanism to quectel-5G-M (#51)
This commit is contained in:
parent
6fe59c1d2b
commit
393dd33334
@ -314,6 +314,11 @@ typedef struct _QMI_TLV
|
|||||||
#define QMUX_CTL_FLAG_TYPE_IND 0x04
|
#define QMUX_CTL_FLAG_TYPE_IND 0x04
|
||||||
#define QMUX_CTL_FLAG_MASK_COMPOUND 0x01
|
#define QMUX_CTL_FLAG_MASK_COMPOUND 0x01
|
||||||
#define QMUX_CTL_FLAG_MASK_TYPE 0x06 // 00-cmd, 01-rsp, 10-ind
|
#define QMUX_CTL_FLAG_MASK_TYPE 0x06 // 00-cmd, 01-rsp, 10-ind
|
||||||
|
// Add these definitions to the DMS message types section
|
||||||
|
#define QMIDMS_FOXCONN_SET_FCC_AUTH_REQ 0x555C
|
||||||
|
#define QMIDMS_FOXCONN_SET_FCC_AUTH_RESP 0x555C
|
||||||
|
#define QMIDMS_FOXCONN_SET_FCC_AUTH_V2_REQ 0x555D
|
||||||
|
#define QMIDMS_FOXCONN_SET_FCC_AUTH_V2_RESP 0x555D
|
||||||
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
@ -399,25 +399,25 @@ typedef struct _QCTLV_PKT_STATISTICS
|
|||||||
//#ifdef QC_IP_MODE
|
//#ifdef QC_IP_MODE
|
||||||
|
|
||||||
/*
|
/*
|
||||||
�Bit 0 �Profile identifier
|
<EFBFBD>?Bit 0 <EFBFBD>?Profile identifier
|
||||||
�Bit 1 �Profile name
|
<EFBFBD>?Bit 1 <EFBFBD>?Profile name
|
||||||
�Bit 2 �PDP type
|
<EFBFBD>?Bit 2 <EFBFBD>?PDP type
|
||||||
�Bit 3 �APN name
|
<EFBFBD>?Bit 3 <EFBFBD>?APN name
|
||||||
�Bit 4 �DNS address
|
<EFBFBD>?Bit 4 <EFBFBD>?DNS address
|
||||||
�Bit 5 �UMTS/GPRS granted QoS
|
<EFBFBD>?Bit 5 <EFBFBD>?UMTS/GPRS granted QoS
|
||||||
�Bit 6 �Username
|
<EFBFBD>?Bit 6 <EFBFBD>?Username
|
||||||
�Bit 7 �Authentication Protocol
|
<EFBFBD>?Bit 7 <EFBFBD>?Authentication Protocol
|
||||||
�Bit 8 �IP address
|
<EFBFBD>?Bit 8 <EFBFBD>?IP address
|
||||||
�Bit 9 �Gateway information (address and subnet mask)
|
<EFBFBD>?Bit 9 <EFBFBD>?Gateway information (address and subnet mask)
|
||||||
�Bit 10 �PCSCF address using a PCO flag
|
<EFBFBD>?Bit 10 <EFBFBD>?PCSCF address using a PCO flag
|
||||||
�Bit 11 �PCSCF server address list
|
<EFBFBD>?Bit 11 <EFBFBD>?PCSCF server address list
|
||||||
�Bit 12 �PCSCF domain name list
|
<EFBFBD>?Bit 12 <EFBFBD>?PCSCF domain name list
|
||||||
�Bit 13 �MTU
|
<EFBFBD>?Bit 13 <EFBFBD>?MTU
|
||||||
�Bit 14 �Domain name list
|
<EFBFBD>?Bit 14 <EFBFBD>?Domain name list
|
||||||
�Bit 15 �IP family
|
<EFBFBD>?Bit 15 <EFBFBD>?IP family
|
||||||
�Bit 16 �IM_CM flag
|
<EFBFBD>?Bit 16 <EFBFBD>?IM_CM flag
|
||||||
�Bit 17 �Technology name
|
<EFBFBD>?Bit 17 <EFBFBD>?Technology name
|
||||||
�Bit 18 �Operator reserved PCO
|
<EFBFBD>?Bit 18 <EFBFBD>?Operator reserved PCO
|
||||||
*/
|
*/
|
||||||
#define QMIWDS_GET_RUNTIME_SETTINGS_MASK_IPV4DNS_ADDR (1 << 4)
|
#define QMIWDS_GET_RUNTIME_SETTINGS_MASK_IPV4DNS_ADDR (1 << 4)
|
||||||
#define QMIWDS_GET_RUNTIME_SETTINGS_MASK_IPV4_ADDR (1 << 8)
|
#define QMIWDS_GET_RUNTIME_SETTINGS_MASK_IPV4_ADDR (1 << 8)
|
||||||
@ -4067,6 +4067,25 @@ typedef struct _QMIUIM_SET_CARD_SLOT_REQ_MSG
|
|||||||
#define QMI_COEX_GET_WWAN_STATE_REQ 0x22
|
#define QMI_COEX_GET_WWAN_STATE_REQ 0x22
|
||||||
#define QMI_COEX_GET_WWAN_STATE_RESP 0x22
|
#define QMI_COEX_GET_WWAN_STATE_RESP 0x22
|
||||||
|
|
||||||
|
// Add these structure definitions after existing message structures
|
||||||
|
|
||||||
|
#ifdef CONFIG_FOXCONN_FCC_AUTH
|
||||||
|
typedef struct _QMIDMS_FOXCONN_SET_FCC_AUTH_REQ_MSG
|
||||||
|
{
|
||||||
|
USHORT Type;
|
||||||
|
USHORT Length;
|
||||||
|
UCHAR TLVType;
|
||||||
|
USHORT TLVLength;
|
||||||
|
UCHAR magic_value;
|
||||||
|
} __attribute__ ((packed)) QMIDMS_FOXCONN_SET_FCC_AUTH_REQ_MSG, *PQMIDMS_FOXCONN_SET_FCC_AUTH_REQ_MSG;
|
||||||
|
|
||||||
|
typedef struct _QMIDMS_FOXCONN_SET_FCC_AUTH_V2_REQ_MSG
|
||||||
|
{
|
||||||
|
USHORT Type;
|
||||||
|
USHORT Length;
|
||||||
|
} __attribute__ ((packed)) QMIDMS_FOXCONN_SET_FCC_AUTH_V2_REQ_MSG, *PQMIDMS_FOXCONN_SET_FCC_AUTH_V2_REQ_MSG;
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
||||||
uint32_t freq;
|
uint32_t freq;
|
||||||
@ -4293,6 +4312,10 @@ typedef struct _QMUX_MSG
|
|||||||
QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG SetDataFormatReq;
|
QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG SetDataFormatReq;
|
||||||
QMI_WDA_SET_LOOPBACK_CONFIG_REQ_MSG SetLoopBackReq;
|
QMI_WDA_SET_LOOPBACK_CONFIG_REQ_MSG SetLoopBackReq;
|
||||||
QMI_WDA_SET_LOOPBACK_CONFIG_IND_MSG SetLoopBackInd;
|
QMI_WDA_SET_LOOPBACK_CONFIG_IND_MSG SetLoopBackInd;
|
||||||
|
#ifdef CONFIG_FOXCONN_FCC_AUTH
|
||||||
|
QMIDMS_FOXCONN_SET_FCC_AUTH_REQ_MSG FoxconnSetFccAuthReq;
|
||||||
|
QMIDMS_FOXCONN_SET_FCC_AUTH_V2_REQ_MSG FoxconnSetFccAuthV2Req;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
} __attribute__ ((packed)) QMUX_MSG, *PQMUX_MSG;
|
} __attribute__ ((packed)) QMUX_MSG, *PQMUX_MSG;
|
||||||
|
|
||||||
|
@ -1832,6 +1832,88 @@ static int requestQueryDataCall(UCHAR *pConnectionStatus, int curIpFamily) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add these implementations after existing function implementations
|
||||||
|
|
||||||
|
#ifdef CONFIG_FOXCONN_FCC_AUTH
|
||||||
|
// Make sure these functions are static to avoid symbol conflicts
|
||||||
|
static USHORT DmsFoxconnSetFccAuthenticationReq(PQMUX_MSG pMUXMsg, void *arg) {
|
||||||
|
UCHAR magic_value = *((UCHAR *)arg);
|
||||||
|
|
||||||
|
pMUXMsg->FoxconnSetFccAuthReq.TLVType = 0x01;
|
||||||
|
pMUXMsg->FoxconnSetFccAuthReq.TLVLength = cpu_to_le16(1);
|
||||||
|
pMUXMsg->FoxconnSetFccAuthReq.magic_value = magic_value;
|
||||||
|
|
||||||
|
return sizeof(QMIDMS_FOXCONN_SET_FCC_AUTH_REQ_MSG);
|
||||||
|
}
|
||||||
|
|
||||||
|
static USHORT DmsFoxconnSetFccAuthenticationV2Req(PQMUX_MSG pMUXMsg, void *arg) {
|
||||||
|
FOXCONN_FCC_AUTH_V2_T *fcc_auth = (FOXCONN_FCC_AUTH_V2_T *)arg;
|
||||||
|
USHORT TLVLength = 0;
|
||||||
|
UCHAR *pTLV;
|
||||||
|
|
||||||
|
pTLV = (UCHAR *)(&pMUXMsg->FoxconnSetFccAuthV2Req + 1);
|
||||||
|
|
||||||
|
// Magic string TLV (0x01)
|
||||||
|
*pTLV++ = 0x01; // TLV Type
|
||||||
|
*(USHORT *)pTLV = cpu_to_le16(strlen(fcc_auth->magic_string));
|
||||||
|
pTLV += 2;
|
||||||
|
memcpy(pTLV, fcc_auth->magic_string, strlen(fcc_auth->magic_string));
|
||||||
|
pTLV += strlen(fcc_auth->magic_string);
|
||||||
|
TLVLength += 3 + strlen(fcc_auth->magic_string);
|
||||||
|
|
||||||
|
// Magic number TLV (0x02)
|
||||||
|
*pTLV++ = 0x02; // TLV Type
|
||||||
|
*(USHORT *)pTLV = cpu_to_le16(1);
|
||||||
|
pTLV += 2;
|
||||||
|
*pTLV++ = fcc_auth->magic_number;
|
||||||
|
TLVLength += 4;
|
||||||
|
|
||||||
|
return sizeof(QMIDMS_FOXCONN_SET_FCC_AUTH_V2_REQ_MSG) + TLVLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
// These functions should NOT be static since they're used externally
|
||||||
|
int requestFoxconnSetFccAuthentication(UCHAR magic_value) {
|
||||||
|
PQCQMIMSG pRequest;
|
||||||
|
PQCQMIMSG pResponse;
|
||||||
|
PQMUX_MSG pMUXMsg;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
dbg_time("%s(magic_value=0x%02x)", __func__, magic_value);
|
||||||
|
|
||||||
|
pRequest = ComposeQMUXMsg(QMUX_TYPE_DMS, QMIDMS_FOXCONN_SET_FCC_AUTH_REQ, DmsFoxconnSetFccAuthenticationReq, &magic_value);
|
||||||
|
err = QmiThreadSendQMI(pRequest, &pResponse);
|
||||||
|
qmi_rsp_check_and_return();
|
||||||
|
|
||||||
|
free(pResponse);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int requestFoxconnSetFccAuthenticationV2(const char *magic_string, UCHAR magic_number) {
|
||||||
|
PQCQMIMSG pRequest;
|
||||||
|
PQCQMIMSG pResponse;
|
||||||
|
PQMUX_MSG pMUXMsg;
|
||||||
|
int err;
|
||||||
|
FOXCONN_FCC_AUTH_V2_T fcc_auth;
|
||||||
|
|
||||||
|
dbg_time("%s(magic_string='%s', magic_number=0x%02x)", __func__, magic_string, magic_number);
|
||||||
|
|
||||||
|
if (!magic_string || strlen(magic_string) >= sizeof(fcc_auth.magic_string)) {
|
||||||
|
dbg_time("%s: Invalid magic_string", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(fcc_auth.magic_string, magic_string);
|
||||||
|
fcc_auth.magic_number = magic_number;
|
||||||
|
|
||||||
|
pRequest = ComposeQMUXMsg(QMUX_TYPE_DMS, QMIDMS_FOXCONN_SET_FCC_AUTH_V2_REQ, DmsFoxconnSetFccAuthenticationV2Req, &fcc_auth);
|
||||||
|
err = QmiThreadSendQMI(pRequest, &pResponse);
|
||||||
|
qmi_rsp_check_and_return();
|
||||||
|
|
||||||
|
free(pResponse);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int requestSetupDataCall(PROFILE_T *profile, int curIpFamily) {
|
static int requestSetupDataCall(PROFILE_T *profile, int curIpFamily) {
|
||||||
PQCQMIMSG pRequest;
|
PQCQMIMSG pRequest;
|
||||||
PQCQMIMSG pResponse;
|
PQCQMIMSG pResponse;
|
||||||
@ -2271,6 +2353,17 @@ static int requestBaseBandVersion(PROFILE_T *profile) {
|
|||||||
{
|
{
|
||||||
uchar2char(profile->BaseBandVersion, sizeof(profile->BaseBandVersion), &revId->RevisionID, le16_to_cpu(revId->TLVLength));
|
uchar2char(profile->BaseBandVersion, sizeof(profile->BaseBandVersion), &revId->RevisionID, le16_to_cpu(revId->TLVLength));
|
||||||
dbg_time("%s %s", __func__, profile->BaseBandVersion);
|
dbg_time("%s %s", __func__, profile->BaseBandVersion);
|
||||||
|
|
||||||
|
#ifdef CONFIG_FOXCONN_FCC_AUTH
|
||||||
|
// Check if this modem model needs FCC authentication
|
||||||
|
if (strstr(profile->BaseBandVersion, "T99W175")) {
|
||||||
|
profile->needs_fcc_auth = 1;
|
||||||
|
dbg_time("Modem model %s requires FCC authentication", profile->BaseBandVersion);
|
||||||
|
} else {
|
||||||
|
profile->needs_fcc_auth = 0;
|
||||||
|
dbg_time("Modem model %s does not require FCC authentication", profile->BaseBandVersion);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
free(pResponse);
|
free(pResponse);
|
||||||
@ -2555,6 +2648,10 @@ const struct request_ops qmi_request_ops = {
|
|||||||
#ifdef CONFIG_COEX_WWAN_STATE
|
#ifdef CONFIG_COEX_WWAN_STATE
|
||||||
.requestGetCoexWWANState = requestGetCoexWWANState,
|
.requestGetCoexWWANState = requestGetCoexWWANState,
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_FOXCONN_FCC_AUTH
|
||||||
|
.requestFoxconnSetFccAuthentication = requestFoxconnSetFccAuthentication,
|
||||||
|
.requestFoxconnSetFccAuthenticationV2 = requestFoxconnSetFccAuthenticationV2,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_CELLINFO
|
#ifdef CONFIG_CELLINFO
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
//#define CONFIG_REG_QOS_IND
|
//#define CONFIG_REG_QOS_IND
|
||||||
//#define CONFIG_GET_QOS_INFO
|
//#define CONFIG_GET_QOS_INFO
|
||||||
//#define CONFIG_GET_QOS_DATA_RATE
|
//#define CONFIG_GET_QOS_DATA_RATE
|
||||||
|
#define CONFIG_FOXCONN_FCC_AUTH
|
||||||
|
|
||||||
#if (defined(CONFIG_REG_QOS_IND) || defined(CONFIG_GET_QOS_INFO) || defined(CONFIG_GET_QOS_DATA_RATE))
|
#if (defined(CONFIG_REG_QOS_IND) || defined(CONFIG_GET_QOS_INFO) || defined(CONFIG_GET_QOS_DATA_RATE))
|
||||||
#ifndef CONFIG_REG_QOS_IND
|
#ifndef CONFIG_REG_QOS_IND
|
||||||
@ -344,7 +345,20 @@ struct request_ops {
|
|||||||
int (*requestRegisterQos)(PROFILE_T *profile);
|
int (*requestRegisterQos)(PROFILE_T *profile);
|
||||||
int (*requestGetQosInfo)(PROFILE_T *profile);
|
int (*requestGetQosInfo)(PROFILE_T *profile);
|
||||||
int (*requestGetCoexWWANState)(void);
|
int (*requestGetCoexWWANState)(void);
|
||||||
|
#ifdef CONFIG_FOXCONN_FCC_AUTH
|
||||||
|
int (*requestFoxconnSetFccAuthentication)(UCHAR magic_value);
|
||||||
|
int (*requestFoxconnSetFccAuthenticationV2)(const char *magic_string, UCHAR magic_number);
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Add structure for V2 parameters
|
||||||
|
#ifdef CONFIG_FOXCONN_FCC_AUTH
|
||||||
|
typedef struct {
|
||||||
|
char magic_string[256];
|
||||||
|
UCHAR magic_number;
|
||||||
|
} FOXCONN_FCC_AUTH_V2_T;
|
||||||
|
#endif
|
||||||
|
|
||||||
extern const struct request_ops qmi_request_ops;
|
extern const struct request_ops qmi_request_ops;
|
||||||
extern const struct request_ops mbim_request_ops;
|
extern const struct request_ops mbim_request_ops;
|
||||||
extern const struct request_ops atc_request_ops;
|
extern const struct request_ops atc_request_ops;
|
||||||
|
@ -325,6 +325,37 @@ static int qmi_main(PROFILE_T *profile)
|
|||||||
if (request_ops->requestSetEthMode)
|
if (request_ops->requestSetEthMode)
|
||||||
request_ops->requestSetEthMode(profile);
|
request_ops->requestSetEthMode(profile);
|
||||||
|
|
||||||
|
#ifdef CONFIG_FOXCONN_FCC_AUTH
|
||||||
|
// Only execute FCC authentication if the modem model requires it
|
||||||
|
if (profile->needs_fcc_auth) {
|
||||||
|
dbg_time("Executing FCC authentication for modem model: %s", profile->BaseBandVersion);
|
||||||
|
|
||||||
|
if (request_ops->requestFoxconnSetFccAuthentication) {
|
||||||
|
// Use magic value 0x01 as seen in libqmi
|
||||||
|
qmierr = request_ops->requestFoxconnSetFccAuthentication(0x01);
|
||||||
|
if (qmierr) {
|
||||||
|
dbg_time("Foxconn FCC Authentication failed with error: %d", qmierr);
|
||||||
|
} else {
|
||||||
|
dbg_time("Foxconn FCC Authentication successful");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request_ops->requestFoxconnSetFccAuthenticationV2) {
|
||||||
|
// Based on libqmi, use "FOXCONN" as magic string for Foxconn modems
|
||||||
|
const char *magic_string = "FOXCONN"; // Correct magic string for Foxconn
|
||||||
|
UCHAR magic_number = 0x01; // Standard magic number from libqmi
|
||||||
|
|
||||||
|
qmierr = request_ops->requestFoxconnSetFccAuthenticationV2(magic_string, magic_number);
|
||||||
|
if (qmierr) {
|
||||||
|
dbg_time("Foxconn FCC Authentication V2 failed with error: %d", qmierr);
|
||||||
|
} else {
|
||||||
|
dbg_time("Foxconn FCC Authentication V2 successful");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dbg_time("Skipping FCC authentication - not required for this modem model");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (request_ops->requestSetLoopBackState && profile->loopback_state) {
|
if (request_ops->requestSetLoopBackState && profile->loopback_state) {
|
||||||
qmierr = request_ops->requestSetLoopBackState(profile->loopback_state, profile->replication_factor);
|
qmierr = request_ops->requestSetLoopBackState(profile->loopback_state, profile->replication_factor);
|
||||||
if (qmierr != QMI_ERR_INVALID_QMI_CMD) //X20 return this error
|
if (qmierr != QMI_ERR_INVALID_QMI_CMD) //X20 return this error
|
||||||
|
Loading…
x
Reference in New Issue
Block a user