quectel-cm: update to version 1.6.5

This commit is contained in:
coolsnowwolf 2024-03-17 14:26:15 +08:00
parent 68253688d8
commit 1dce308893
23 changed files with 360 additions and 221 deletions

View File

@ -1,7 +1,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:= quectel-CM-5G PKG_NAME:= quectel-CM-5G
PKG_VERSION:=1.6.4 PKG_VERSION:=1.6.5
PKG_RELEASE:=1 PKG_RELEASE:=1
include $(INCLUDE_DIR)/package.mk include $(INCLUDE_DIR)/package.mk

View File

@ -9,7 +9,7 @@
None. None.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. Copyright (c) 2016 - 2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
Quectel Wireless Solution Proprietary and Confidential. Quectel Wireless Solution Proprietary and Confidential.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
******************************************************************************/ ******************************************************************************/

View File

@ -9,7 +9,7 @@ CC:=$(CROSS-COMPILE)gcc
endif endif
LD:=$(CROSS-COMPILE)ld LD:=$(CROSS-COMPILE)ld
QL_CM_SRC=QmiWwanCM.c GobiNetCM.c main.c MPQMUX.c QMIThread.c util.c qmap_bridge_mode.c mbim-cm.c device.c QL_CM_SRC=QmiWwanCM.c GobiNetCM.c main.c QCQMUX.c QMIThread.c util.c qmap_bridge_mode.c mbim-cm.c device.c
QL_CM_SRC+=atc.c atchannel.c at_tok.c QL_CM_SRC+=atc.c atchannel.c at_tok.c
#QL_CM_SRC+=qrtr.c rmnetctl.c #QL_CM_SRC+=qrtr.c rmnetctl.c
ifeq (1,1) ifeq (1,1)
@ -21,6 +21,7 @@ QL_CM_DHCP=udhcpc_netlink.c
QL_CM_DHCP+=${LIBMNL} QL_CM_DHCP+=${LIBMNL}
endif endif
CFLAGS += -Wall -Wextra -Werror -O1 #-s
LDFLAGS += -lpthread -ldl -lrt LDFLAGS += -lpthread -ldl -lrt
release: clean qmi-proxy mbim-proxy atc-proxy #qrtr-proxy release: clean qmi-proxy mbim-proxy atc-proxy #qrtr-proxy

View File

@ -1,19 +1,23 @@
/*=========================================================================== /******************************************************************************
@file QCQCTL.h
M P Q C T L. H
DESCRIPTION:
DESCRIPTION
This module contains QMI QCTL module. This module contains QMI QCTL module.
INITIALIZATION AND SEQUENCING REQUIREMENTS: INITIALIZATION AND SEQUENCING REQUIREMENTS
None.
Copyright (C) 2011 by Qualcomm Technologies, Incorporated. All Rights Reserved. ---------------------------------------------------------------------------
===========================================================================*/ Copyright (c) 2016 - 2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
Quectel Wireless Solution Proprietary and Confidential.
---------------------------------------------------------------------------
******************************************************************************/
#ifndef MPQCTL_H
#define MPQCTL_H
#include "MPQMI.h" #ifndef QCQCTL_H
#define QCQCTL_H
#include "QCQMI.h"
#pragma pack(push, 1) #pragma pack(push, 1)
@ -387,4 +391,4 @@ typedef struct _QMICTL_MSG
} __attribute__ ((packed)) QMICTL_MSG, *PQMICTL_MSG; } __attribute__ ((packed)) QMICTL_MSG, *PQMICTL_MSG;
#pragma pack(pop) #pragma pack(pop)
#endif // MPQCTL_H #endif //QCQCTL_H

View File

@ -1,23 +1,18 @@
/*=========================================================================== /******************************************************************************
@file QCQMI.h
M P Q M I. H DESCRIPTION
DESCRIPTION: This module contains QMI module.
This module contains forward references to the QMI module. INITIALIZATION AND SEQUENCING REQUIREMENTS
None.
INITIALIZATION AND SEQUENCING REQUIREMENTS: ---------------------------------------------------------------------------
Copyright (c) 2016 - 2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
Quectel Wireless Solution Proprietary and Confidential.
---------------------------------------------------------------------------
******************************************************************************/
Copyright (C) 2011 by Qualcomm Technologies, Incorporated. All Rights Reserved.
===========================================================================*/
/*===========================================================================
EDIT HISTORY FOR FILE
$Header: //depot/QMI/win/qcdrivers/ndis/MPQMI.h#3 $
when who what, where, why
-------- --- ----------------------------------------------------------
11/20/04 hg Initial version.
===========================================================================*/
#ifndef USBQMI_H #ifndef USBQMI_H
#define USBQMI_H #define USBQMI_H

View File

@ -9,7 +9,7 @@
None. None.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. Copyright (c) 2016 - 2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
Quectel Wireless Solution Proprietary and Confidential. Quectel Wireless Solution Proprietary and Confidential.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
******************************************************************************/ ******************************************************************************/

View File

@ -1,19 +1,23 @@
/*=========================================================================== /******************************************************************************
@file QCQMUX.h
M P Q M U X. H DESCRIPTION
DESCRIPTION: This module contains QMI QMUX module.
This file provides support for QMUX. INITIALIZATION AND SEQUENCING REQUIREMENTS
None.
INITIALIZATION AND SEQUENCING REQUIREMENTS: ---------------------------------------------------------------------------
Copyright (c) 2016 - 2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
Quectel Wireless Solution Proprietary and Confidential.
---------------------------------------------------------------------------
******************************************************************************/
Copyright (C) 2011 by Qualcomm Technologies, Incorporated. All Rights Reserved.
===========================================================================*/
#ifndef MPQMUX_H #ifndef QCQMUX_H
#define MPQMUX_H #define QCQMUX_H
#include "MPQMI.h" #include "QCQMI.h"
#pragma pack(push, 1) #pragma pack(push, 1)
@ -35,6 +39,8 @@ Copyright (C) 2011 by Qualcomm Technologies, Incorporated. All Rights Reserved.
#define QMIWDS_CREATE_PROFILE_RESP 0x0027 #define QMIWDS_CREATE_PROFILE_RESP 0x0027
#define QMIWDS_MODIFY_PROFILE_SETTINGS_REQ 0x0028 #define QMIWDS_MODIFY_PROFILE_SETTINGS_REQ 0x0028
#define QMIWDS_MODIFY_PROFILE_SETTINGS_RESP 0x0028 #define QMIWDS_MODIFY_PROFILE_SETTINGS_RESP 0x0028
#define QMIWDS_GET_PROFILE_LIST_REQ 0x002A
#define QMIWDS_GET_PROFILE_LIST_RESP 0x002A
#define QMIWDS_GET_PROFILE_SETTINGS_REQ 0x002B #define QMIWDS_GET_PROFILE_SETTINGS_REQ 0x002B
#define QMIWDS_GET_PROFILE_SETTINGS_RESP 0x002B #define QMIWDS_GET_PROFILE_SETTINGS_RESP 0x002B
#define QMIWDS_GET_DEFAULT_SETTINGS_REQ 0x002C #define QMIWDS_GET_DEFAULT_SETTINGS_REQ 0x002C
@ -643,6 +649,20 @@ typedef struct _QMIWDS_GPRS_QOS
*/ */
#endif #endif
typedef struct _QMIWDS_PDPCONTEXT
{
UCHAR TLVType;
USHORT TLVLength;
UCHAR pdp_context;
} __attribute__ ((packed)) QMIWDS_PDPCONTEXT, *PQMIWDS_PDPCONTEXT;
typedef struct _QMIWDS_PROFILELIST
{
UCHAR TLVType;
USHORT TLVLength;
UCHAR ProfileList[1024];
} __attribute__ ((packed)) QMIWDS_PROFILELIST, *PQMIWDS_PROFILELIST;
typedef struct _QMIWDS_PROFILENAME typedef struct _QMIWDS_PROFILENAME
{ {
UCHAR TLVType; UCHAR TLVType;
@ -819,6 +839,21 @@ typedef struct _QMIWDS_CREATE_PROFILE_SETTINGS_REQ_MSG
UCHAR pdp_context; UCHAR pdp_context;
} __attribute__ ((packed)) QMIWDS_CREATE_PROFILE_SETTINGS_REQ_MSG, *PQMIWDS_CREATE_PROFILE_SETTINGS_REQ_MSG; } __attribute__ ((packed)) QMIWDS_CREATE_PROFILE_SETTINGS_REQ_MSG, *PQMIWDS_CREATE_PROFILE_SETTINGS_REQ_MSG;
typedef struct _QMIWDS_GET_PROFILE_LIST_REQ_MSG
{
USHORT Type;
USHORT Length;
} __attribute__ ((packed)) QMIWDS_GET_PROFILE_LIST_REQ_MSG, *PQMIWDS_GET_PROFILE_LIST_REQ_MSG;
typedef struct _QMIWDS_GET_PROFILE_LIST_RESP_MSG
{
USHORT Type;
USHORT Length;
UCHAR TLVType;
USHORT TLVLength;
UCHAR ProfileList[1024];
} __attribute__ ((packed)) QMIWDS_GET_PROFILE_LIST_RESP_MSG, *PQMIWDS_GET_PROFILE_LIST_RESP_MSG;
#if 0 #if 0
typedef struct _QMIWDS_EVENT_REPORT_IND_DATA_BEARER_TLV typedef struct _QMIWDS_EVENT_REPORT_IND_DATA_BEARER_TLV
{ {
@ -4093,6 +4128,8 @@ typedef struct _QMUX_MSG
QMIWDS_MODIFY_PROFILE_SETTINGS_RESP_MSG ModifyProfileSettingsResp; QMIWDS_MODIFY_PROFILE_SETTINGS_RESP_MSG ModifyProfileSettingsResp;
QMIWDS_GET_PROFILE_SETTINGS_REQ_MSG GetProfileSettingsReq; QMIWDS_GET_PROFILE_SETTINGS_REQ_MSG GetProfileSettingsReq;
QMIWDS_CREATE_PROFILE_SETTINGS_REQ_MSG CreatetProfileSettingsReq; QMIWDS_CREATE_PROFILE_SETTINGS_REQ_MSG CreatetProfileSettingsReq;
QMIWDS_GET_PROFILE_LIST_REQ_MSG GetProfileListReq;
QMIWDS_GET_PROFILE_LIST_RESP_MSG GetProfileListResp;
#if 0 #if 0
QMIWDS_GET_DATA_BEARER_REQ_MSG GetDataBearerReq; QMIWDS_GET_DATA_BEARER_REQ_MSG GetDataBearerReq;
QMIWDS_GET_DATA_BEARER_RESP_MSG GetDataBearerResp; QMIWDS_GET_DATA_BEARER_RESP_MSG GetDataBearerResp;
@ -4269,5 +4306,5 @@ typedef struct _QCQMIMSG {
#pragma pack(pop) #pragma pack(pop)
#endif // MPQMUX_H #endif // QCQMUX_H

View File

@ -9,7 +9,7 @@
None. None.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. Copyright (c) 2016 - 2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
Quectel Wireless Solution Proprietary and Confidential. Quectel Wireless Solution Proprietary and Confidential.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
******************************************************************************/ ******************************************************************************/
@ -255,11 +255,11 @@ static USHORT WdsStartNwInterfaceReq(PQMUX_MSG pMUXMsg, void *arg) {
TLVLength += (le16_to_cpu(pIpFamily->TLVLength) + sizeof(QCQMICTL_TLV_HDR)); TLVLength += (le16_to_cpu(pIpFamily->TLVLength) + sizeof(QCQMICTL_TLV_HDR));
//Set Profile Index //Set Profile Index
if (profile->pdp && !s_is_cdma) { //cdma only support one pdp, so no need to set profile index if (profile->profile_index && !s_is_cdma) { //cdma only support one pdp, so no need to set profile index
PQMIWDS_PROFILE_IDENTIFIER pProfileIndex = (PQMIWDS_PROFILE_IDENTIFIER)(pTLV + TLVLength); PQMIWDS_PROFILE_IDENTIFIER pProfileIndex = (PQMIWDS_PROFILE_IDENTIFIER)(pTLV + TLVLength);
pProfileIndex->TLVLength = cpu_to_le16(0x01); pProfileIndex->TLVLength = cpu_to_le16(0x01);
pProfileIndex->TLVType = 0x31; pProfileIndex->TLVType = 0x31;
pProfileIndex->ProfileIndex = profile->pdp; pProfileIndex->ProfileIndex = profile->profile_index;
if (s_is_cdma && s_hdr_personality == 0x02) { if (s_is_cdma && s_hdr_personality == 0x02) {
pProfileIndex->TLVType = 0x32; //profile_index_3gpp2 pProfileIndex->TLVType = 0x32; //profile_index_3gpp2
pProfileIndex->ProfileIndex = 101; pProfileIndex->ProfileIndex = 101;
@ -478,6 +478,13 @@ static USHORT UimReadTransparentIMSIReqSend(PQMUX_MSG pMUXMsg, void *arg) {
#endif #endif
#ifdef CONFIG_APN #ifdef CONFIG_APN
static USHORT WdsGetProfileListReqSend(PQMUX_MSG pMUXMsg, void *arg) {
(void)(arg);
pMUXMsg->GetProfileListReq.Length = cpu_to_le16(sizeof(QMIWDS_GET_PROFILE_LIST_REQ_MSG) - 4);
return sizeof(QMIWDS_GET_PROFILE_LIST_REQ_MSG);
}
static USHORT WdsCreateProfileSettingsReqSend(PQMUX_MSG pMUXMsg, void *arg) { static USHORT WdsCreateProfileSettingsReqSend(PQMUX_MSG pMUXMsg, void *arg) {
PROFILE_T *profile = (PROFILE_T *)arg; PROFILE_T *profile = (PROFILE_T *)arg;
pMUXMsg->CreatetProfileSettingsReq.Length = cpu_to_le16(sizeof(QMIWDS_CREATE_PROFILE_SETTINGS_REQ_MSG) - 4); pMUXMsg->CreatetProfileSettingsReq.Length = cpu_to_le16(sizeof(QMIWDS_CREATE_PROFILE_SETTINGS_REQ_MSG) - 4);
@ -496,7 +503,7 @@ static USHORT WdsGetProfileSettingsReqSend(PQMUX_MSG pMUXMsg, void *arg) {
pMUXMsg->GetProfileSettingsReq.TLVType = 0x01; pMUXMsg->GetProfileSettingsReq.TLVType = 0x01;
pMUXMsg->GetProfileSettingsReq.TLVLength = cpu_to_le16(0x02); pMUXMsg->GetProfileSettingsReq.TLVLength = cpu_to_le16(0x02);
pMUXMsg->GetProfileSettingsReq.ProfileType = 0x00; // 0 ~ 3GPP, 1 ~ 3GPP2 pMUXMsg->GetProfileSettingsReq.ProfileType = 0x00; // 0 ~ 3GPP, 1 ~ 3GPP2
pMUXMsg->GetProfileSettingsReq.ProfileIndex = profile->pdp; pMUXMsg->GetProfileSettingsReq.ProfileIndex = profile->profile_index;
return sizeof(QMIWDS_GET_PROFILE_SETTINGS_REQ_MSG); return sizeof(QMIWDS_GET_PROFILE_SETTINGS_REQ_MSG);
} }
@ -510,7 +517,7 @@ static USHORT WdsModifyProfileSettingsReq(PQMUX_MSG pMUXMsg, void *arg) {
pMUXMsg->ModifyProfileSettingsReq.TLVType = 0x01; pMUXMsg->ModifyProfileSettingsReq.TLVType = 0x01;
pMUXMsg->ModifyProfileSettingsReq.TLVLength = cpu_to_le16(0x02); pMUXMsg->ModifyProfileSettingsReq.TLVLength = cpu_to_le16(0x02);
pMUXMsg->ModifyProfileSettingsReq.ProfileType = 0x00; // 0 ~ 3GPP, 1 ~ 3GPP2 pMUXMsg->ModifyProfileSettingsReq.ProfileType = 0x00; // 0 ~ 3GPP, 1 ~ 3GPP2
pMUXMsg->ModifyProfileSettingsReq.ProfileIndex = profile->pdp; pMUXMsg->ModifyProfileSettingsReq.ProfileIndex = profile->profile_index;
pTLV = (UCHAR *)(&pMUXMsg->ModifyProfileSettingsReq + 1); pTLV = (UCHAR *)(&pMUXMsg->ModifyProfileSettingsReq + 1);
@ -1858,8 +1865,9 @@ static int requestSetupDataCall(PROFILE_T *profile, int curIpFamily) {
dbg_time("call_end_reason_verbose is %d", verbose_call_end_reason); dbg_time("call_end_reason_verbose is %d", verbose_call_end_reason);
} }
err = le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXError);
free(pResponse); free(pResponse);
return le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXError); return err;
} }
if (curIpFamily == IpFamilyV4) { if (curIpFamily == IpFamilyV4) {
@ -2026,8 +2034,8 @@ static int requestSetProfile(PROFILE_T *profile) {
const char *new_password = profile->password ? profile->password : ""; const char *new_password = profile->password ? profile->password : "";
const char *ipStr[] = {"IPV4", "NULL", "IPV6", "IPV4V6"}; const char *ipStr[] = {"IPV4", "NULL", "IPV6", "IPV4V6"};
dbg_time("%s[%d] %s/%s/%s/%d/%s", __func__, profile->pdp, profile->apn, profile->user, profile->password, profile->auth,ipStr[profile->iptype]); dbg_time("%s[pdp:%d index:%d] %s/%s/%s/%d/%s", __func__, profile->pdp, profile->profile_index, profile->apn, profile->user, profile->password, profile->auth,ipStr[profile->iptype]);
if (!profile->pdp) if (!profile->profile_index)
return -1; return -1;
if ( !strcmp(profile->old_apn, new_apn) && !strcmp(profile->old_user, new_user) if ( !strcmp(profile->old_apn, new_apn) && !strcmp(profile->old_user, new_user)
@ -2057,6 +2065,9 @@ static int requestGetProfile(PROFILE_T *profile) {
PQMIWDS_PASSWD pPassWd; PQMIWDS_PASSWD pPassWd;
PQMIWDS_AUTH_PREFERENCE pAuthPref; PQMIWDS_AUTH_PREFERENCE pAuthPref;
PQMIWDS_IPTYPE pIpType; PQMIWDS_IPTYPE pIpType;
PQMIWDS_PDPCONTEXT pPdpContext;
PQMIWDS_PROFILELIST pProfileList;
const char *ipStr[] = {"IPV4", "NULL", "IPV6", "IPV4V6"}; const char *ipStr[] = {"IPV4", "NULL", "IPV6", "IPV4V6"};
profile->old_apn[0] = profile->old_user[0] = profile->old_password[0] = '\0'; profile->old_apn[0] = profile->old_user[0] = profile->old_password[0] = '\0';
@ -2073,19 +2084,52 @@ static int requestGetProfile(PROFILE_T *profile) {
return 0; return 0;
_re_check: _re_check:
pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS, QMIWDS_GET_PROFILE_LIST_REQ, WdsGetProfileListReqSend, profile);
err = QmiThreadSendQMI(pRequest, &pResponse);s_pResponse = malloc(le16_to_cpu(pResponse->QMIHdr.Length) + 1);
qmi_rsp_check_and_return();
pProfileList = (PQMIWDS_PROFILELIST)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x01);
uint8 profile_indexs[42] = {0};
uint8 profile_num = pProfileList->ProfileList[0];
if(profile_num >= 1)
{
uint8 j = 0;
uint8 k = 2;
for(int i=0; i<profile_num; i++)
{
profile_indexs[j++] = pProfileList->ProfileList[k];
if(pProfileList->ProfileList[++k] == 0)
k+=2;
else
k+=2+pProfileList->ProfileList[k];
}
}
free(pResponse);
for(int i=0; i<profile_num; i++)
{
profile->profile_index = profile_indexs[i];
pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS, QMIWDS_GET_PROFILE_SETTINGS_REQ, WdsGetProfileSettingsReqSend, profile); pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS, QMIWDS_GET_PROFILE_SETTINGS_REQ, WdsGetProfileSettingsReqSend, profile);
err = QmiThreadSendQMI(pRequest, &pResponse); err = QmiThreadSendQMI(pRequest, &pResponse);
if (err == 0 && pResponse && le16_to_cpu(pResponse->MUXMsg.QMUXMsgHdrResp.QMUXResult) qmi_rsp_check_and_return();
&& le16_to_cpu(pResponse->MUXMsg.QMUXMsgHdrResp.QMUXError) == QMI_ERR_EXTENDED_INTERNAL)
{ pPdpContext = (PQMIWDS_PDPCONTEXT)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x25);
if(pPdpContext->pdp_context == profile->pdp)
break;
else
free(pResponse); free(pResponse);
if(i == profile_num-1)
{
pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS, QMIWDS_CREATE_PROFILE_REQ, WdsCreateProfileSettingsReqSend, profile); pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS, QMIWDS_CREATE_PROFILE_REQ, WdsCreateProfileSettingsReqSend, profile);
err = QmiThreadSendQMI(pRequest, &pResponse); err = QmiThreadSendQMI(pRequest, &pResponse);
qmi_rsp_check_and_return(); qmi_rsp_check_and_return();
free(pResponse); free(pResponse);
goto _re_check; goto _re_check;
} }
qmi_rsp_check_and_return(); }
pApnName = (PQMIWDS_APNNAME)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x14); pApnName = (PQMIWDS_APNNAME)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x14);
pUserName = (PQMIWDS_USERNAME)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x1B); pUserName = (PQMIWDS_USERNAME)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x1B);
@ -2106,7 +2150,7 @@ _re_check:
profile->old_iptype = pIpType->IPType; profile->old_iptype = pIpType->IPType;
} }
dbg_time("%s[%d] %s/%s/%s/%d/%s", __func__, profile->pdp, profile->old_apn, profile->old_user, profile->old_password, profile->old_auth, ipStr[profile->old_iptype]); dbg_time("%s[pdp:%d index:%d] %s/%s/%s/%d/%s", __func__, profile->pdp, profile->profile_index, profile->old_apn, profile->old_user, profile->old_password, profile->old_auth, ipStr[profile->old_iptype]);
free(pResponse); free(pResponse);
return 0; return 0;

View File

@ -53,9 +53,9 @@
#include <stddef.h> #include <stddef.h>
#include "qendian.h" #include "qendian.h"
#include "MPQMI.h" #include "QCQMI.h"
#include "MPQCTL.h" #include "QCQCTL.h"
#include "MPQMUX.h" #include "QCQMUX.h"
#include "util.h" #include "util.h"
#define DEVICE_CLASS_UNKNOWN 0 #define DEVICE_CLASS_UNKNOWN 0
@ -196,10 +196,12 @@ typedef struct __PROFILE {
int iptype; int iptype;
const char *pincode; const char *pincode;
char proxy[32]; char proxy[32];
int pdp; int pdp;//pdp_context
int profile_index;//profile_index
int enable_bridge; int enable_bridge;
bool enable_ipv4; bool enable_ipv4;
bool enable_ipv6; bool enable_ipv6;
bool no_dhcp;
const char *logfile; const char *logfile;
const char *usblogfile; const char *usblogfile;
char expect_adapter[32]; char expect_adapter[32];
@ -221,6 +223,7 @@ typedef struct __PROFILE {
UINT qos_id; UINT qos_id;
#endif #endif
int wda_client; int wda_client;
uint32_t udhcpc_ip;
IPV4_T ipv4; IPV4_T ipv4;
IPV6_T ipv6; IPV6_T ipv6;
UINT PCSCFIpv4Addr1; UINT PCSCFIpv4Addr1;

View File

@ -9,7 +9,7 @@
None. None.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. Copyright (c) 2016 - 2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
Quectel Wireless Solution Proprietary and Confidential. Quectel Wireless Solution Proprietary and Confidential.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
******************************************************************************/ ******************************************************************************/
@ -264,7 +264,7 @@ static int QmiWwanDeInit(void) {
{ {
if (qmiclientId[i] != 0) if (qmiclientId[i] != 0)
{ {
QmiWwanReleaseClientID(i, qmiclientId[i]); QmiWwanReleaseClientID((QMUX_TYPE_WDS_IPV6 == i ? QMUX_TYPE_WDS : i), qmiclientId[i]);
qmiclientId[i] = 0; qmiclientId[i] = 0;
} }
} }

View File

@ -1,5 +1,19 @@
Release Notes Release Notes
[V1.6.5]
Date: 7/3/2023
enhancement:
1. Fix the issue of qmi client id leakage caused by kill 9 killing the client of quectel-qmi-proxy
2. Fix wds_ipv6 client ID can't be released issue
3. Fix wds_ipv6 client ID can't be released issue
4. Resolve PDP_ Context&Profile_ The issue of index mixing
5. Add parameter - d to obtain IP and DNS information through qmi
6. Fix mbim dialing. When the user does not specify apn through - s, prompt the user and exit the dialing program
7. Prioritize the use of IP commands for optimization, and use ifconfig if not available
8. Optimize and add/remove copyright
fix:
[V1.6.4] [V1.6.4]
Date: 9/7/2022 Date: 9/7/2022
enhancement: enhancement:

View File

@ -9,7 +9,7 @@
None. None.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. Copyright (c) 2016 - 2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
Quectel Wireless Solution Proprietary and Confidential. Quectel Wireless Solution Proprietary and Confidential.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
******************************************************************************/ ******************************************************************************/
@ -503,6 +503,7 @@ AT< OK
safe_at_response_free(p_response); safe_at_response_free(p_response);
switch (cops_act) { switch (cops_act) {
case 2: //UTRAN case 2: //UTRAN
case 3: //GSM W/EGPRS
case 4: //UTRAN W/HSDPA case 4: //UTRAN W/HSDPA
case 5: //UTRAN W/HSUPA case 5: //UTRAN W/HSUPA
case 6: //UTRAN W/HSDPA and HSUPA case 6: //UTRAN W/HSDPA and HSUPA

View File

@ -9,7 +9,7 @@
None. None.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. Copyright (c) 2016 - 2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
Quectel Wireless Solution Proprietary and Confidential. Quectel Wireless Solution Proprietary and Confidential.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
******************************************************************************/ ******************************************************************************/

View File

@ -9,7 +9,7 @@
None. None.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2016 -2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. Copyright (c) 2016 -2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
Quectel Wireless Solution Proprietary and Confidential. Quectel Wireless Solution Proprietary and Confidential.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
******************************************************************************/ ******************************************************************************/
@ -58,8 +58,10 @@ static int check_ipv4_address(PROFILE_T *profile) {
if (profile->request_ops == &mbim_request_ops) if (profile->request_ops == &mbim_request_ops)
return 1; //we will get a new ipv6 address per requestGetIPAddress() return 1; //we will get a new ipv6 address per requestGetIPAddress()
if (profile->request_ops == &atc_request_ops) if (profile->request_ops == &atc_request_ops) {
return 1; //TODO if (!profile->udhcpc_ip) return 1;
oldAddress = profile->udhcpc_ip;
}
if (profile->request_ops->requestGetIPAddress(profile, IpFamilyV4) == 0) { if (profile->request_ops->requestGetIPAddress(profile, IpFamilyV4) == 0) {
if (profile->ipv4.Address != oldAddress || debug_qmi) { if (profile->ipv4.Address != oldAddress || debug_qmi) {
@ -248,6 +250,7 @@ static int usage(const char *progname) {
dbg_time("-m iface-idx Bind QMI data call to wwan0_<iface idx> when QMAP used. E.g '-n 7 -m 1' bind pdn-7 data call to wwan0_1"); dbg_time("-m iface-idx Bind QMI data call to wwan0_<iface idx> when QMAP used. E.g '-n 7 -m 1' bind pdn-7 data call to wwan0_1");
dbg_time("-b Enable network interface bridge function (default 0)"); dbg_time("-b Enable network interface bridge function (default 0)");
dbg_time("-v Verbose log mode, for debug purpose."); dbg_time("-v Verbose log mode, for debug purpose.");
dbg_time("-d Obtain the IP address and dns through qmi");
dbg_time("[Examples]"); dbg_time("[Examples]");
dbg_time("Example 1: %s ", progname); dbg_time("Example 1: %s ", progname);
dbg_time("Example 2: %s -s 3gnet ", progname); dbg_time("Example 2: %s -s 3gnet ", progname);
@ -367,6 +370,15 @@ static int qmi_main(PROFILE_T *profile)
request_ops->requestRegisterQos(profile); request_ops->requestRegisterQos(profile);
#endif #endif
#if 1 //USB disconnnect and re-connect, but not reboot modem, will get this bug
if (profile->enable_ipv4
&& profile->request_ops == &atc_request_ops
&& !request_ops->requestQueryDataCall(&IPv4ConnectionStatus, IpFamilyV4)
&& IPv4ConnectionStatus == QWDS_PKT_DATA_CONNECTED) {
request_ops->requestDeactivateDefaultPDP(profile, IpFamilyV4);
}
#endif
send_signo_to_main(SIG_EVENT_CHECK); send_signo_to_main(SIG_EVENT_CHECK);
while (1) while (1)
@ -716,6 +728,11 @@ static int quectel_CM(PROFILE_T *profile)
dbg_time("Modem works in MBIM mode"); dbg_time("Modem works in MBIM mode");
profile->request_ops = &mbim_request_ops; profile->request_ops = &mbim_request_ops;
profile->qmi_ops = &mbim_dev_ops; profile->qmi_ops = &mbim_dev_ops;
if (!profile->apn || !profile->apn[0]) {
//see FAE-51804 FAE-59811
dbg_time("When MBIM mode, must specify APN with '-s', or setup data call may fail!");
exit(-404); //if no such issue on your side, please comment this
}
ret = qmi_main(profile); ret = qmi_main(profile);
} }
else if (profile->software_interface == SOFTWARE_QMI) { else if (profile->software_interface == SOFTWARE_QMI) {
@ -757,6 +774,7 @@ static int parse_user_input(int argc, char **argv, PROFILE_T *profile) {
int opt = 1; int opt = 1;
profile->pdp = CONFIG_DEFAULT_PDP; profile->pdp = CONFIG_DEFAULT_PDP;
profile->profile_index = CONFIG_DEFAULT_PDP;
if (!strcmp(argv[argc-1], "&")) if (!strcmp(argv[argc-1], "&"))
argc--; argc--;
@ -865,6 +883,10 @@ static int parse_user_input(int argc, char **argv, PROFILE_T *profile) {
profile->enable_ipv6 = 1; profile->enable_ipv6 = 1;
break; break;
case 'd':
profile->no_dhcp = 1;
break;
case 'u': case 'u':
if (has_more_argv()) { if (has_more_argv()) {
profile->usblogfile = argv[opt++]; profile->usblogfile = argv[opt++];
@ -899,7 +921,7 @@ int main(int argc, char *argv[])
int ret; int ret;
PROFILE_T *ctx = &s_profile; PROFILE_T *ctx = &s_profile;
dbg_time("QConnectManager_Linux_V1.6.4"); dbg_time("QConnectManager_Linux_V1.6.5");
ret = parse_user_input(argc, argv, ctx); ret = parse_user_input(argc, argv, ctx);
if (!ret) if (!ret)

View File

@ -9,7 +9,7 @@
None. None.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. Copyright (c) 2016 - 2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
Quectel Wireless Solution Proprietary and Confidential. Quectel Wireless Solution Proprietary and Confidential.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
******************************************************************************/ ******************************************************************************/

View File

@ -9,7 +9,7 @@
None. None.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. Copyright (c) 2016 - 2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
Quectel Wireless Solution Proprietary and Confidential. Quectel Wireless Solution Proprietary and Confidential.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
******************************************************************************/ ******************************************************************************/

View File

@ -10,7 +10,7 @@
None. None.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. Copyright (c) 2016 - 2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
Quectel Wireless Solution Proprietary and Confidential. Quectel Wireless Solution Proprietary and Confidential.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
******************************************************************************/ ******************************************************************************/

View File

@ -9,7 +9,7 @@
None. None.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. Copyright (c) 2016 - 2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
Quectel Wireless Solution Proprietary and Confidential. Quectel Wireless Solution Proprietary and Confidential.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
******************************************************************************/ ******************************************************************************/

View File

@ -9,7 +9,7 @@
None. None.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. Copyright (c) 2016 - 2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
Quectel Wireless Solution Proprietary and Confidential. Quectel Wireless Solution Proprietary and Confidential.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
******************************************************************************/ ******************************************************************************/
@ -34,9 +34,9 @@
#include "qendian.h" #include "qendian.h"
#include "qlist.h" #include "qlist.h"
#include "MPQMI.h" #include "QCQMI.h"
#include "MPQCTL.h" #include "QCQCTL.h"
#include "MPQMUX.h" #include "QCQMUX.h"
#ifndef MIN #ifndef MIN
#define MIN(a, b) ((a) < (b)? (a): (b)) #define MIN(a, b) ((a) < (b)? (a): (b))
@ -117,6 +117,8 @@ static int modem_reset_flag = 0;
static int qmi_sync_done = 0; static int qmi_sync_done = 0;
static uint8_t qmi_buf[4096]; static uint8_t qmi_buf[4096];
static int send_qmi_to_cdc_wdm(PQCQMIMSG pQMI);
#ifdef QUECTEL_QMI_MERGE #ifdef QUECTEL_QMI_MERGE
static int merge_qmi_rsp_packet(void *buf, ssize_t *src_size) { static int merge_qmi_rsp_packet(void *buf, ssize_t *src_size) {
static QMI_MSG_PACKET s_QMIPacket; static QMI_MSG_PACKET s_QMIPacket;
@ -168,8 +170,8 @@ static int create_local_server(const char *name) {
alen = strlen(name) + offsetof(struct sockaddr_un, sun_path) + 1; alen = strlen(name) + offsetof(struct sockaddr_un, sun_path) + 1;
SYSCHECK(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse_addr,sizeof(reuse_addr))); SYSCHECK(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse_addr,sizeof(reuse_addr)));
if(bind(sockfd, (struct sockaddr *)&sockaddr, alen) < 0) { if(bind(sockfd, (struct sockaddr *)&sockaddr, alen) < 0) {
close(sockfd);
dprintf("bind %s errno: %d (%s)\n", name, errno, strerror(errno)); dprintf("bind %s errno: %d (%s)\n", name, errno, strerror(errno));
close(sockfd);
return -1; return -1;
} }
@ -201,7 +203,7 @@ static void accept_qmi_connection(int serverfd) {
cfmakenoblock(clientfd); cfmakenoblock(clientfd);
} }
static void cleanup_qmi_connection(int clientfd) { static void cleanup_qmi_connection(int clientfd, int clientDisconnect) {
struct qlistnode *con_node, *qmi_node; struct qlistnode *con_node, *qmi_node;
qlist_for_each(con_node, &qmi_proxy_connection) { qlist_for_each(con_node, &qmi_proxy_connection) {
@ -211,7 +213,32 @@ static void cleanup_qmi_connection(int clientfd) {
while (!qlist_empty(&qmi_con->client_qnode)) { while (!qlist_empty(&qmi_con->client_qnode)) {
QMI_PROXY_CLINET *qmi_client = qnode_to_item(qlist_head(&qmi_con->client_qnode), QMI_PROXY_CLINET, qnode); QMI_PROXY_CLINET *qmi_client = qnode_to_item(qlist_head(&qmi_con->client_qnode), QMI_PROXY_CLINET, qnode);
if (clientDisconnect) {
int size = 17;
QMI_PROXY_MSG *qmi_msg = malloc(sizeof(QMI_PROXY_MSG) + size);
PQCQMIMSG pQMI = &qmi_msg->qmi[0];
dprintf("xxx ClientFd=%d QMIType=%d ClientId=%d\n", qmi_con->ClientFd, qmi_client->QMIType, qmi_client->ClientId); dprintf("xxx ClientFd=%d QMIType=%d ClientId=%d\n", qmi_con->ClientFd, qmi_client->QMIType, qmi_client->ClientId);
qlist_init(&qmi_msg->qnode);
qmi_msg->ClientFd = qmi_proxy_server_fd;
pQMI->QMIHdr.IFType = USB_CTL_MSG_TYPE_QMI;
pQMI->QMIHdr.Length = htole16(16);
pQMI->QMIHdr.CtlFlags = 0x00;
pQMI->QMIHdr.QMIType = QMUX_TYPE_CTL;
pQMI->QMIHdr.ClientId= 0x00;
pQMI->CTLMsg.ReleaseClientIdReq.CtlFlags = QMICTL_FLAG_REQUEST;
pQMI->CTLMsg.ReleaseClientIdReq.TransactionId = 255;
pQMI->CTLMsg.ReleaseClientIdReq.QMICTLType = htole16(QMICTL_RELEASE_CLIENT_ID_REQ);
pQMI->CTLMsg.ReleaseClientIdReq.Length = htole16(5);
pQMI->CTLMsg.ReleaseClientIdReq.TLVType = QCTLV_TYPE_REQUIRED_PARAMETER;
pQMI->CTLMsg.ReleaseClientIdReq.TLVLength = htole16(2);
pQMI->CTLMsg.ReleaseClientIdReq.QMIType = qmi_client->QMIType;
pQMI->CTLMsg.ReleaseClientIdReq.ClientId = qmi_client->ClientId;
if (qlist_empty(&qmi_proxy_ctl_msg))
send_qmi_to_cdc_wdm(pQMI);
qlist_add_tail(&qmi_proxy_ctl_msg, &qmi_msg->qnode);
}
qlist_remove(&qmi_client->qnode); qlist_remove(&qmi_client->qnode);
free(qmi_client); free(qmi_client);
@ -273,12 +300,13 @@ static void dump_qmi(PQCQMIMSG pQMI, int fd, const char flag)
{ {
unsigned i; unsigned i;
unsigned size = le16toh(pQMI->QMIHdr.Length) + 1; unsigned size = le16toh(pQMI->QMIHdr.Length) + 1;
printf("%c %d %u: ", flag, fd, size); char buf[128];
if (size > 16) int cnt = 0;
size = 16;
for (i = 0; i < size; i++) cnt += snprintf(buf + cnt, sizeof(buf) - cnt, "%c %d %u: ", flag, fd, size);
printf("%02x ", ((uint8_t *)pQMI)[i]); for (i = 0; i < size && i < 24; i++)
printf("\n"); cnt += snprintf(buf + cnt, sizeof(buf) - cnt, "%02x ", ((uint8_t *)pQMI)[i]);
dprintf("%s\n", buf)
} }
} }
@ -327,41 +355,52 @@ static void recv_qmi_from_dev(PQCQMIMSG pQMI) {
if (!qlist_empty(&qmi_proxy_ctl_msg)) { if (!qlist_empty(&qmi_proxy_ctl_msg)) {
QMI_PROXY_MSG *qmi_msg = qnode_to_item(qlist_head(&qmi_proxy_ctl_msg), QMI_PROXY_MSG, qnode); QMI_PROXY_MSG *qmi_msg = qnode_to_item(qlist_head(&qmi_proxy_ctl_msg), QMI_PROXY_MSG, qnode);
if (qmi_msg->qmi[0].CTLMsg.QMICTLMsgHdrRsp.TransactionId != pQMI->CTLMsg.QMICTLMsgHdrRsp.TransactionId
|| qmi_msg->qmi[0].CTLMsg.QMICTLMsgHdrRsp.QMICTLType != pQMI->CTLMsg.QMICTLMsgHdrRsp.QMICTLType) {
dprintf("ERROR: ctl rsp tid:%d, type:%d - ctl req %d, %d\n",
pQMI->CTLMsg.QMICTLMsgHdrRsp.TransactionId, pQMI->CTLMsg.QMICTLMsgHdrRsp.QMICTLType,
qmi_msg->qmi[0].CTLMsg.QMICTLMsgHdrRsp.TransactionId, qmi_msg->qmi[0].CTLMsg.QMICTLMsgHdrRsp.QMICTLType);
}
else if (qmi_msg->ClientFd == qmi_proxy_server_fd) {
if (le16toh(pQMI->CTLMsg.QMICTLMsgHdrRsp.QMICTLType) == QMICTL_RELEASE_CLIENT_ID_RESP) {
dprintf("--- ClientFd=%d QMIType=%d ClientId=%d\n", qmi_proxy_server_fd,
pQMI->CTLMsg.ReleaseClientIdRsp.QMIType, pQMI->CTLMsg.ReleaseClientIdRsp.ClientId);
}
}
else {
qlist_for_each(con_node, &qmi_proxy_connection) { qlist_for_each(con_node, &qmi_proxy_connection) {
QMI_PROXY_CONNECTION *qmi_con = qnode_to_item(con_node, QMI_PROXY_CONNECTION, qnode); QMI_PROXY_CONNECTION *qmi_con = qnode_to_item(con_node, QMI_PROXY_CONNECTION, qnode);
if (qmi_con->ClientFd == qmi_msg->ClientFd) { if (qmi_con->ClientFd == qmi_msg->ClientFd) {
send_qmi_to_client(pQMI, qmi_msg->ClientFd); send_qmi_to_client(pQMI, qmi_msg->ClientFd);
if (le16toh(pQMI->CTLMsg.QMICTLMsgHdrRsp.QMICTLType) == QMICTL_GET_CLIENT_ID_RESP) if (le16toh(pQMI->CTLMsg.QMICTLMsgHdrRsp.QMICTLType) == QMICTL_GET_CLIENT_ID_RESP) {
get_client_id(qmi_con, &pQMI->CTLMsg.GetClientIdRsp); get_client_id(qmi_con, &pQMI->CTLMsg.GetClientIdRsp);
else if ((le16toh(pQMI->CTLMsg.QMICTLMsgHdrRsp.QMICTLType) == QMICTL_RELEASE_CLIENT_ID_RESP) || }
(le16toh(pQMI->CTLMsg.QMICTLMsgHdrRsp.QMICTLType) == QMICTL_REVOKE_CLIENT_ID_IND)) { else if (le16toh(pQMI->CTLMsg.QMICTLMsgHdrRsp.QMICTLType) == QMICTL_RELEASE_CLIENT_ID_RESP) {
release_client_id(qmi_con, &pQMI->CTLMsg.ReleaseClientIdRsp); release_client_id(qmi_con, &pQMI->CTLMsg.ReleaseClientIdRsp);
if (le16toh(pQMI->CTLMsg.QMICTLMsgHdrRsp.QMICTLType) == QMICTL_REVOKE_CLIENT_ID_IND)
modem_reset_flag = 1;
} }
else { else {
} }
} }
} }
}
qlist_remove(&qmi_msg->qnode); qlist_remove(&qmi_msg->qnode);
free(qmi_msg); free(qmi_msg);
}
}
if (!qlist_empty(&qmi_proxy_ctl_msg)) { if (!qlist_empty(&qmi_proxy_ctl_msg)) {
QMI_PROXY_MSG *qmi_msg = qnode_to_item(qlist_head(&qmi_proxy_ctl_msg), QMI_PROXY_MSG, qnode); QMI_PROXY_MSG *qmi_msg = qnode_to_item(qlist_head(&qmi_proxy_ctl_msg), QMI_PROXY_MSG, qnode);
qlist_for_each(con_node, &qmi_proxy_connection) {
QMI_PROXY_CONNECTION *qmi_con = qnode_to_item(con_node, QMI_PROXY_CONNECTION, qnode);
if (qmi_con->ClientFd == qmi_msg->ClientFd) {
send_qmi_to_cdc_wdm(qmi_msg->qmi); send_qmi_to_cdc_wdm(qmi_msg->qmi);
} }
} }
} }
else if (pQMI->QMIHdr.QMIType == QMICTL_CTL_FLAG_IND) {
if (le16toh(pQMI->CTLMsg.QMICTLMsgHdrRsp.QMICTLType) == QMICTL_REVOKE_CLIENT_ID_IND) {
modem_reset_flag = 1;
}
}
} }
else { else {
qlist_for_each(con_node, &qmi_proxy_connection) { qlist_for_each(con_node, &qmi_proxy_connection) {
@ -380,10 +419,10 @@ static void recv_qmi_from_dev(PQCQMIMSG pQMI) {
} }
static int recv_qmi_from_client(PQCQMIMSG pQMI, unsigned size, int clientfd) { static int recv_qmi_from_client(PQCQMIMSG pQMI, unsigned size, int clientfd) {
if (qmi_proxy_server_fd <= 0) { if (qmi_proxy_server_fd == -1)
send_qmi_to_cdc_wdm(pQMI); return -1;
}
else if (pQMI->QMIHdr.QMIType == QMUX_TYPE_CTL) { if (pQMI->QMIHdr.QMIType == QMUX_TYPE_CTL) {
QMI_PROXY_MSG *qmi_msg; QMI_PROXY_MSG *qmi_msg;
if (pQMI->CTLMsg.QMICTLMsgHdr.QMICTLType == QMICTL_SYNC_REQ) { if (pQMI->CTLMsg.QMICTLMsgHdr.QMICTLType == QMICTL_SYNC_REQ) {
@ -391,13 +430,13 @@ static int recv_qmi_from_client(PQCQMIMSG pQMI, unsigned size, int clientfd) {
return 0; return 0;
} }
if (qlist_empty(&qmi_proxy_ctl_msg))
send_qmi_to_cdc_wdm(pQMI);
qmi_msg = malloc(sizeof(QMI_PROXY_MSG) + size); qmi_msg = malloc(sizeof(QMI_PROXY_MSG) + size);
qlist_init(&qmi_msg->qnode); qlist_init(&qmi_msg->qnode);
qmi_msg->ClientFd = clientfd; qmi_msg->ClientFd = clientfd;
memcpy(qmi_msg->qmi, pQMI, size); memcpy(qmi_msg->qmi, pQMI, size);
if (qlist_empty(&qmi_proxy_ctl_msg))
send_qmi_to_cdc_wdm(pQMI);
qlist_add_tail(&qmi_proxy_ctl_msg, &qmi_msg->qnode); qlist_add_tail(&qmi_proxy_ctl_msg, &qmi_msg->qnode);
} }
else { else {
@ -407,7 +446,7 @@ static int recv_qmi_from_client(PQCQMIMSG pQMI, unsigned size, int clientfd) {
return 0; return 0;
} }
static int qmi_proxy_init(void) { static int qmi_proxy_init(unsigned retry) {
unsigned i; unsigned i;
QCQMIMSG _QMI; QCQMIMSG _QMI;
PQCQMIMSG pQMI = &_QMI; PQCQMIMSG pQMI = &_QMI;
@ -422,10 +461,10 @@ static int qmi_proxy_init(void) {
pQMI->CTLMsg.QMICTLMsgHdr.CtlFlags = QMICTL_FLAG_REQUEST; pQMI->CTLMsg.QMICTLMsgHdr.CtlFlags = QMICTL_FLAG_REQUEST;
qmi_sync_done = 0; qmi_sync_done = 0;
for (i = 0; i < 10; i++) { for (i = 0; i < retry; i++) {
pQMI->CTLMsg.SyncReq.TransactionId = i+1; pQMI->CTLMsg.SyncReq.TransactionId = i+1;
pQMI->CTLMsg.SyncReq.QMICTLType = QMICTL_SYNC_REQ; pQMI->CTLMsg.SyncReq.QMICTLType = htole16(QMICTL_SYNC_REQ);
pQMI->CTLMsg.SyncReq.Length = 0; pQMI->CTLMsg.SyncReq.Length = htole16(0);
pQMI->QMIHdr.Length = pQMI->QMIHdr.Length =
htole16(le16toh(pQMI->CTLMsg.QMICTLMsgHdr.Length) + sizeof(QCQMI_HDR) + sizeof(QCQMICTL_MSG_HDR) - 1); htole16(le16toh(pQMI->CTLMsg.QMICTLMsgHdr.Length) + sizeof(QCQMI_HDR) + sizeof(QCQMICTL_MSG_HDR) - 1);
@ -442,22 +481,6 @@ static int qmi_proxy_init(void) {
return qmi_sync_done ? 0 : -1; return qmi_sync_done ? 0 : -1;
} }
static void qmi_start_server(const char* servername) {
qmi_proxy_server_fd = create_local_server(servername);
dprintf("qmi_proxy_server_fd = %d\n", qmi_proxy_server_fd);
if (qmi_proxy_server_fd == -1) {
dprintf("Failed to create %s, errno: %d (%s)\n", servername, errno, strerror(errno));
}
}
static void qmi_close_server(const char* servername) {
if (qmi_proxy_server_fd != -1) {
dprintf("%s %s close server\n", __func__, servername);
close(qmi_proxy_server_fd);
qmi_proxy_server_fd = -1;
}
}
static void *qmi_proxy_loop(void *param) static void *qmi_proxy_loop(void *param)
{ {
PQCQMIMSG pQMI = (PQCQMIMSG)qmi_buf; PQCQMIMSG pQMI = (PQCQMIMSG)qmi_buf;
@ -528,7 +551,7 @@ static void *qmi_proxy_loop(void *param)
} else if(fd == qmi_proxy_server_fd) { } else if(fd == qmi_proxy_server_fd) {
} else { } else {
cleanup_qmi_connection(fd); cleanup_qmi_connection(fd, 1);
} }
continue; continue;
@ -566,7 +589,7 @@ static void *qmi_proxy_loop(void *param)
if (nreads <= 0) { if (nreads <= 0) {
dprintf("%s read=%d errno: %d (%s)", __func__, (int)nreads, errno, strerror(errno)); dprintf("%s read=%d errno: %d (%s)", __func__, (int)nreads, errno, strerror(errno));
cleanup_qmi_connection(fd); cleanup_qmi_connection(fd, 1);
break; break;
} }
@ -585,7 +608,7 @@ qmi_proxy_loop_exit:
while (!qlist_empty(&qmi_proxy_connection)) { while (!qlist_empty(&qmi_proxy_connection)) {
QMI_PROXY_CONNECTION *qmi_con = qnode_to_item(qlist_head(&qmi_proxy_connection), QMI_PROXY_CONNECTION, qnode); QMI_PROXY_CONNECTION *qmi_con = qnode_to_item(qlist_head(&qmi_proxy_connection), QMI_PROXY_CONNECTION, qnode);
cleanup_qmi_connection(qmi_con->ClientFd); cleanup_qmi_connection(qmi_con->ClientFd, 0);
} }
dprintf("%s exit, thread_id %p\n", __func__, (void *)pthread_self()); dprintf("%s exit, thread_id %p\n", __func__, (void *)pthread_self());
@ -601,8 +624,7 @@ static void usage(void) {
} }
static void sig_action(int sig) { static void sig_action(int sig) {
if (qmi_proxy_quit == 0) { if (qmi_proxy_quit++ == 0) {
qmi_proxy_quit = 1;
if (thread_id) if (thread_id)
pthread_kill(thread_id, sig); pthread_kill(thread_id, sig);
} }
@ -611,7 +633,6 @@ static void sig_action(int sig) {
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
int opt; int opt;
char cdc_wdm[32+1] = "/dev/cdc-wdm0"; char cdc_wdm[32+1] = "/dev/cdc-wdm0";
int retry_times = 0;
char servername[64] = {0}; char servername[64] = {0};
optind = 1; optind = 1;
@ -632,63 +653,48 @@ int main(int argc, char *argv[]) {
} }
} }
if (access(cdc_wdm, R_OK | W_OK)) {
dprintf("Fail to access %s, errno: %d (%s). break\n", cdc_wdm, errno, strerror(errno));
return -1;
}
sprintf(servername, "quectel-qmi-proxy%c", cdc_wdm[strlen(cdc_wdm)-1]); sprintf(servername, "quectel-qmi-proxy%c", cdc_wdm[strlen(cdc_wdm)-1]);
dprintf("Will use cdc-wdm='%s', proxy='%s'\n", cdc_wdm, servername); dprintf("Will use cdc-wdm='%s', proxy='%s'\n", cdc_wdm, servername);
while (qmi_proxy_quit == 0) { while (qmi_proxy_quit == 0) {
if (access(cdc_wdm, R_OK | W_OK)) {
dprintf("Fail to access %s, errno: %d (%s). continue\n", cdc_wdm, errno, strerror(errno));
// wait device
sleep(3);
continue;
}
cdc_wdm_fd = open(cdc_wdm, O_RDWR | O_NONBLOCK | O_NOCTTY); cdc_wdm_fd = open(cdc_wdm, O_RDWR | O_NONBLOCK | O_NOCTTY);
if (cdc_wdm_fd == -1) { if (cdc_wdm_fd == -1) {
dprintf("Failed to open %s, errno: %d (%s). break\n", cdc_wdm, errno, strerror(errno)); dprintf("Failed to open %s, errno: %d (%s)\n", cdc_wdm, errno, strerror(errno));
return -1; sleep(3);
continue;
} }
cfmakenoblock(cdc_wdm_fd); cfmakenoblock(cdc_wdm_fd);
/* no qmi_proxy_loop lives, create one */ /* no qmi_proxy_loop lives, create one */
pthread_create(&thread_id, NULL, qmi_proxy_loop, NULL); pthread_create(&thread_id, NULL, qmi_proxy_loop, NULL);
/* try to redo init if failed, init function must be successfully */
while (qmi_proxy_init() != 0) {
if (retry_times < 5) {
dprintf("fail to init proxy, try again in 2 seconds.\n");
sleep(2);
retry_times++;
} else {
dprintf("has failed too much times, restart the modem and have a try...\n");
break;
}
/* break loop if modem is detached */
if (access(cdc_wdm, F_OK|R_OK|W_OK))
break;
}
retry_times = 0;
qmi_start_server(servername);
if (qmi_proxy_server_fd == -1)
pthread_cancel(thread_id);
pthread_join(thread_id, NULL);
/* close local server at last */ if (qmi_proxy_init(60) == 0) {
qmi_close_server(servername); qmi_proxy_server_fd = create_local_server(servername);
dprintf("qmi_proxy_server_fd = %d\n", qmi_proxy_server_fd);
if (qmi_proxy_server_fd == -1) {
dprintf("Failed to create %s, errno: %d (%s)\n", servername, errno, strerror(errno));
pthread_cancel(thread_id);
}
}
else {
pthread_cancel(thread_id);
}
pthread_join(thread_id, NULL);
thread_id = 0;
if (qmi_proxy_server_fd != -1) {
dprintf("close server %s\n", servername);
close(qmi_proxy_server_fd);
qmi_proxy_server_fd = -1;
}
close(cdc_wdm_fd); close(cdc_wdm_fd);
/* DO RESTART IN 20s IF MODEM RESET ITSELF */ cdc_wdm_fd = -1;
if (modem_reset_flag) {
unsigned int time_to_wait = 20; if (qmi_proxy_quit == 0)
while (time_to_wait) { sleep(modem_reset_flag ? 30 : 3);
time_to_wait = sleep(time_to_wait);
}
modem_reset_flag = 0; modem_reset_flag = 0;
} }
}
return 0; return 0;
} }

View File

@ -9,7 +9,7 @@
None. None.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. Copyright (c) 2016 - 2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
Quectel Wireless Solution Proprietary and Confidential. Quectel Wireless Solution Proprietary and Confidential.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
******************************************************************************/ ******************************************************************************/
@ -36,9 +36,9 @@
#include "qendian.h" #include "qendian.h"
#include "qlist.h" #include "qlist.h"
#include "MPQMI.h" #include "QCQMI.h"
#include "MPQCTL.h" #include "QCQCTL.h"
#include "MPQMUX.h" #include "QCQMUX.h"
static const char * get_time(void) { static const char * get_time(void) {
static char time_buf[128]; static char time_buf[128];

View File

@ -9,7 +9,7 @@
None. None.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. Copyright (c) 2016 - 2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
Quectel Wireless Solution Proprietary and Confidential. Quectel Wireless Solution Proprietary and Confidential.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
******************************************************************************/ ******************************************************************************/
@ -105,6 +105,17 @@ static short ifc_get_flags(const char *ifname)
return ret; return ret;
} }
static void ifc_set_state(const char *ifname, int state) {
char shell_cmd[128];
if (!access("/sbin/ip", X_OK)) {
snprintf(shell_cmd, sizeof(shell_cmd), "ip link set dev %s %s", ifname, state ? "up" : "down");
} else {
snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s %s", ifname, state ? "up" : "down");
}
ql_system(shell_cmd);
}
static int ql_netcard_ipv4_address_check(const char *ifname, in_addr_t ip) { static int ql_netcard_ipv4_address_check(const char *ifname, in_addr_t ip) {
in_addr_t addr = 0; in_addr_t addr = 0;
@ -115,7 +126,6 @@ static int ql_netcard_ipv4_address_check(const char *ifname, in_addr_t ip) {
static int ql_raw_ip_mode_check(const char *ifname, uint32_t ip) { static int ql_raw_ip_mode_check(const char *ifname, uint32_t ip) {
int fd; int fd;
char raw_ip[128]; char raw_ip[128];
char shell_cmd[128];
char mode[2] = "X"; char mode[2] = "X";
int mode_change = 0; int mode_change = 0;
@ -135,14 +145,12 @@ static int ql_raw_ip_mode_check(const char *ifname, uint32_t ip) {
if (read(fd, mode, 2) == -1) {}; if (read(fd, mode, 2) == -1) {};
if (mode[0] == '0' || mode[0] == 'N') { if (mode[0] == '0' || mode[0] == 'N') {
dbg_time("File:%s Line:%d udhcpc fail to get ip address, try next:", __func__, __LINE__); dbg_time("File:%s Line:%d udhcpc fail to get ip address, try next:", __func__, __LINE__);
snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s down", ifname); ifc_set_state(ifname, 0);
ql_system(shell_cmd);
dbg_time("echo Y > /sys/class/net/%s/qmi/raw_ip", ifname); dbg_time("echo Y > /sys/class/net/%s/qmi/raw_ip", ifname);
mode[0] = 'Y'; mode[0] = 'Y';
if (write(fd, mode, 2) == -1) {}; if (write(fd, mode, 2) == -1) {};
mode_change = 1; mode_change = 1;
snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s up", ifname); ifc_set_state(ifname, 1);
ql_system(shell_cmd);
} }
close(fd); close(fd);
@ -211,8 +219,7 @@ void ql_set_driver_link_state(PROFILE_T *profile, int link_state) {
lseek(fd, 0, SEEK_SET); lseek(fd, 0, SEEK_SET);
rc = read(fd, link_file, sizeof(link_file)); rc = read(fd, link_file, sizeof(link_file));
if (rc > 1 && (!strncasecmp(link_file, "0\n", 2) || !strncasecmp(link_file, "0x0\n", 4))) { if (rc > 1 && (!strncasecmp(link_file, "0\n", 2) || !strncasecmp(link_file, "0x0\n", 4))) {
snprintf(link_file, sizeof(link_file), "ifconfig %s down", profile->usbnet_adapter); ifc_set_state(profile->usbnet_adapter, 0);
ql_system(link_file);
} }
} }
@ -470,7 +477,6 @@ static void ql_openwrt_setup_wan6(const char *ifname, const IPV6_T *ipv6) {
void udhcpc_start(PROFILE_T *profile) { void udhcpc_start(PROFILE_T *profile) {
char *ifname = profile->usbnet_adapter; char *ifname = profile->usbnet_adapter;
char shell_cmd[128];
ql_set_driver_link_state(profile, 1); ql_set_driver_link_state(profile, 1);
@ -483,17 +489,13 @@ void udhcpc_start(PROFILE_T *profile) {
} }
if (strcmp(ifname, profile->usbnet_adapter)) { if (strcmp(ifname, profile->usbnet_adapter)) {
snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s up", profile->usbnet_adapter); ifc_set_state(profile->usbnet_adapter, 1);
ql_system(shell_cmd);
if (ifc_get_flags(ifname)&IFF_UP) { if (ifc_get_flags(ifname)&IFF_UP) {
snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s down", ifname); ifc_set_state(ifname, 0);
ql_system(shell_cmd);
} }
} }
snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s up", ifname); ifc_set_state(ifname, 1);
ql_system(shell_cmd);
if (profile->ipv4.Address) { if (profile->ipv4.Address) {
if (profile->PCSCFIpv4Addr1) if (profile->PCSCFIpv4Addr1)
dbg_time("pcscf1: %s", ipv4Str(profile->PCSCFIpv4Addr1)); dbg_time("pcscf1: %s", ipv4Str(profile->PCSCFIpv4Addr1));
@ -528,7 +530,7 @@ void udhcpc_start(PROFILE_T *profile) {
if (profile->ipv4.Address == 0) if (profile->ipv4.Address == 0)
goto set_ipv6; goto set_ipv6;
if (profile->request_ops == &mbim_request_ops) { //lots of mbim modem do not support DHCP if (profile->no_dhcp || profile->request_ops == &mbim_request_ops) { //lots of mbim modem do not support DHCP
update_ip_address_by_qmi(ifname, &profile->ipv4, NULL); update_ip_address_by_qmi(ifname, &profile->ipv4, NULL);
} }
else else
@ -579,9 +581,16 @@ void udhcpc_start(PROFILE_T *profile) {
pthread_create(&udhcpc_thread_id, NULL, udhcpc_thread_function, (void*)strdup(udhcpc_cmd)); pthread_create(&udhcpc_thread_id, NULL, udhcpc_thread_function, (void*)strdup(udhcpc_cmd));
pthread_join(udhcpc_thread_id, NULL); pthread_join(udhcpc_thread_id, NULL);
if (profile->request_ops == &atc_request_ops if (profile->request_ops == &atc_request_ops) {
&& !ql_netcard_ipv4_address_check(ifname, qmi2addr(profile->ipv4.Address))) { profile->udhcpc_ip = 0;
ql_get_netcard_carrier_state(ifname); ifc_get_addr(ifname, &profile->udhcpc_ip);
if (profile->udhcpc_ip != profile->ipv4.Address) {
unsigned char *l = (unsigned char *)&profile->udhcpc_ip;
unsigned char *r = (unsigned char *)&profile->ipv4.Address;
dbg_time("ERROR: IP from udhcpc (%d.%d.%d.%d) is different to IP from ATC (%d.%d.%d.%d)!",
l[0], l[1], l[2], l[3], r[0], r[1], r[2], r[3]);
ql_get_netcard_carrier_state(ifname); //miss udhcpc default.script or modem not report usb-net-cdc-linkup
}
} }
if (profile->request_ops != &qmi_request_ops) { //only QMI modem support next fixup! if (profile->request_ops != &qmi_request_ops) { //only QMI modem support next fixup!
@ -720,11 +729,14 @@ void udhcpc_stop(PROFILE_T *profile) {
dibbler_client_alive = 0; dibbler_client_alive = 0;
} }
profile->udhcpc_ip = 0;
//it seems when call netif_carrier_on(), and netcard 's IP is "0.0.0.0", will cause netif_queue_stopped() //it seems when call netif_carrier_on(), and netcard 's IP is "0.0.0.0", will cause netif_queue_stopped()
if (!access("/sbin/ip", X_OK))
snprintf(shell_cmd, sizeof(shell_cmd), "ip addr flush dev %s", ifname);
else
snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s 0.0.0.0", ifname); snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s 0.0.0.0", ifname);
ql_system(shell_cmd); ql_system(shell_cmd);
snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s down", ifname); ifc_set_state(ifname, 0);
ql_system(shell_cmd);
#ifdef QL_OPENWER_NETWORK_SETUP #ifdef QL_OPENWER_NETWORK_SETUP
ql_openwrt_setup_wan(ifname, NULL); ql_openwrt_setup_wan(ifname, NULL);

View File

@ -9,7 +9,7 @@
None. None.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. Copyright (c) 2016 - 2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
Quectel Wireless Solution Proprietary and Confidential. Quectel Wireless Solution Proprietary and Confidential.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
******************************************************************************/ ******************************************************************************/

View File

@ -9,7 +9,7 @@
None. None.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. Copyright (c) 2016 - 2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
Quectel Wireless Solution Proprietary and Confidential. Quectel Wireless Solution Proprietary and Confidential.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
******************************************************************************/ ******************************************************************************/