更新
This commit is contained in:
parent
8d51b2a02f
commit
4961558c9c
@ -2096,8 +2096,8 @@ static int qmi_wwan_reset_resume(struct usb_interface *intf)
|
|||||||
|
|
||||||
static int rmnet_usb_bind(struct usbnet *dev, struct usb_interface *intf)
|
static int rmnet_usb_bind(struct usbnet *dev, struct usb_interface *intf)
|
||||||
{
|
{
|
||||||
dev_err(&intf->dev, "rmnet_usb_bind\n");
|
|
||||||
int status = qmi_wwan_bind(dev, intf);
|
int status = qmi_wwan_bind(dev, intf);
|
||||||
|
dev_err(&intf->dev, "rmnet_usb_bind\n");
|
||||||
|
|
||||||
if (!status) {
|
if (!status) {
|
||||||
struct qmi_wwan_state *info = (void *)&dev->data;
|
struct qmi_wwan_state *info = (void *)&dev->data;
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
---------------------------------------------------------------------------
|
---------------------------------------------------------------------------
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
@ -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,25 +21,26 @@ 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
|
||||||
$(CC) ${CFLAGS} ${QL_CM_SRC} ${QL_CM_DHCP} -o quectel-CM ${LDFLAGS}
|
$(CC) ${CFLAGS} ${QL_CM_SRC} ${QL_CM_DHCP} -o out/quectel-CM ${LDFLAGS}
|
||||||
|
|
||||||
debug: clean
|
debug: clean
|
||||||
$(CC) ${CFLAGS} -g -DCM_DEBUG ${QL_CM_SRC} ${QL_CM_DHCP} -o quectel-CM -lpthread -ldl -lrt
|
$(CC) ${CFLAGS} -g -DCM_DEBUG ${QL_CM_SRC} ${QL_CM_DHCP} -o out/quectel-CM -lpthread -ldl -lrt
|
||||||
|
|
||||||
qmi-proxy:
|
qmi-proxy:
|
||||||
$(CC) ${CFLAGS} quectel-qmi-proxy.c -o quectel-qmi-proxy ${LDFLAGS}
|
$(CC) ${CFLAGS} quectel-qmi-proxy.c -o out/quectel-qmi-proxy ${LDFLAGS}
|
||||||
|
|
||||||
mbim-proxy:
|
mbim-proxy:
|
||||||
$(CC) ${CFLAGS} quectel-mbim-proxy.c -o quectel-mbim-proxy ${LDFLAGS}
|
$(CC) ${CFLAGS} quectel-mbim-proxy.c -o out/quectel-mbim-proxy ${LDFLAGS}
|
||||||
|
|
||||||
qrtr-proxy:
|
qrtr-proxy:
|
||||||
$(CC) ${CFLAGS} quectel-qrtr-proxy.c -o quectel-qrtr-proxy ${LDFLAGS}
|
$(CC) ${CFLAGS} quectel-qrtr-proxy.c -o out/quectel-qrtr-proxy ${LDFLAGS}
|
||||||
|
|
||||||
atc-proxy:
|
atc-proxy:
|
||||||
$(CC) ${CFLAGS} quectel-atc-proxy.c atchannel.c at_tok.c util.c -o quectel-atc-proxy ${LDFLAGS}
|
$(CC) ${CFLAGS} quectel-atc-proxy.c atchannel.c at_tok.c util.c -o out/quectel-atc-proxy ${LDFLAGS}
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf *.o libmnl/*.o quectel-CM quectel-qmi-proxy quectel-mbim-proxy quectel-atc-proxy
|
cd out/; rm -rf *.o libmnl/*.o quectel-CM quectel-qmi-proxy quectel-mbim-proxy quectel-atc-proxy
|
||||||
|
394
quectel_cm_5G/src/QCQCTL.h
Normal file
394
quectel_cm_5G/src/QCQCTL.h
Normal file
@ -0,0 +1,394 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
@file QCQCTL.h
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
This module contains QMI QCTL module.
|
||||||
|
|
||||||
|
INITIALIZATION AND SEQUENCING REQUIREMENTS
|
||||||
|
None.
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
Copyright (c) 2016 - 2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
|
||||||
|
Quectel Wireless Solution Proprietary and Confidential.
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef QCQCTL_H
|
||||||
|
#define QCQCTL_H
|
||||||
|
|
||||||
|
#include "QCQMI.h"
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
|
// ================= QMICTL ==================
|
||||||
|
|
||||||
|
// QMICTL Control Flags
|
||||||
|
#define QMICTL_CTL_FLAG_CMD 0x00
|
||||||
|
#define QMICTL_CTL_FLAG_RSP 0x01
|
||||||
|
#define QMICTL_CTL_FLAG_IND 0x02
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
typedef struct _QMICTL_TRANSACTION_ITEM
|
||||||
|
{
|
||||||
|
LIST_ENTRY List;
|
||||||
|
UCHAR TransactionId; // QMICTL transaction id
|
||||||
|
PVOID Context; // Adapter or IocDev
|
||||||
|
PIRP Irp;
|
||||||
|
} QMICTL_TRANSACTION_ITEM, *PQMICTL_TRANSACTION_ITEM;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct _QCQMICTL_MSG_HDR
|
||||||
|
{
|
||||||
|
UCHAR CtlFlags; // 00-cmd, 01-rsp, 10-ind
|
||||||
|
UCHAR TransactionId;
|
||||||
|
USHORT QMICTLType;
|
||||||
|
USHORT Length;
|
||||||
|
} __attribute__ ((packed)) QCQMICTL_MSG_HDR, *PQCQMICTL_MSG_HDR;
|
||||||
|
|
||||||
|
#define QCQMICTL_MSG_HDR_SIZE sizeof(QCQMICTL_MSG_HDR)
|
||||||
|
|
||||||
|
typedef struct _QCQMICTL_MSG_HDR_RESP
|
||||||
|
{
|
||||||
|
UCHAR CtlFlags; // 00-cmd, 01-rsp, 10-ind
|
||||||
|
UCHAR TransactionId;
|
||||||
|
USHORT QMICTLType;
|
||||||
|
USHORT Length;
|
||||||
|
UCHAR TLVType; // 0x02 - result code
|
||||||
|
USHORT TLVLength; // 4
|
||||||
|
USHORT QMUXResult; // QMI_RESULT_SUCCESS
|
||||||
|
// QMI_RESULT_FAILURE
|
||||||
|
USHORT QMUXError; // QMI_ERR_INVALID_ARG
|
||||||
|
// QMI_ERR_NO_MEMORY
|
||||||
|
// QMI_ERR_INTERNAL
|
||||||
|
// QMI_ERR_FAULT
|
||||||
|
} __attribute__ ((packed)) QCQMICTL_MSG_HDR_RESP, *PQCQMICTL_MSG_HDR_RESP;
|
||||||
|
|
||||||
|
typedef struct _QCQMICTL_MSG
|
||||||
|
{
|
||||||
|
UCHAR CtlFlags; // 00-cmd, 01-rsp, 10-ind
|
||||||
|
UCHAR TransactionId;
|
||||||
|
USHORT QMICTLType;
|
||||||
|
USHORT Length;
|
||||||
|
UCHAR Payload;
|
||||||
|
} __attribute__ ((packed)) QCQMICTL_MSG, *PQCQMICTL_MSG;
|
||||||
|
|
||||||
|
// TLV Header
|
||||||
|
typedef struct _QCQMICTL_TLV_HDR
|
||||||
|
{
|
||||||
|
UCHAR TLVType;
|
||||||
|
USHORT TLVLength;
|
||||||
|
} __attribute__ ((packed)) QCQMICTL_TLV_HDR, *PQCQMICTL_TLV_HDR;
|
||||||
|
|
||||||
|
#define QCQMICTL_TLV_HDR_SIZE sizeof(QCQMICTL_TLV_HDR)
|
||||||
|
|
||||||
|
// QMICTL Type
|
||||||
|
#define QMICTL_SET_INSTANCE_ID_REQ 0x0020
|
||||||
|
#define QMICTL_SET_INSTANCE_ID_RESP 0x0020
|
||||||
|
#define QMICTL_GET_VERSION_REQ 0x0021
|
||||||
|
#define QMICTL_GET_VERSION_RESP 0x0021
|
||||||
|
#define QMICTL_GET_CLIENT_ID_REQ 0x0022
|
||||||
|
#define QMICTL_GET_CLIENT_ID_RESP 0x0022
|
||||||
|
#define QMICTL_RELEASE_CLIENT_ID_REQ 0x0023
|
||||||
|
#define QMICTL_RELEASE_CLIENT_ID_RESP 0x0023
|
||||||
|
#define QMICTL_REVOKE_CLIENT_ID_IND 0x0024
|
||||||
|
#define QMICTL_INVALID_CLIENT_ID_IND 0x0025
|
||||||
|
#define QMICTL_SET_DATA_FORMAT_REQ 0x0026
|
||||||
|
#define QMICTL_SET_DATA_FORMAT_RESP 0x0026
|
||||||
|
#define QMICTL_SYNC_REQ 0x0027
|
||||||
|
#define QMICTL_SYNC_RESP 0x0027
|
||||||
|
#define QMICTL_SYNC_IND 0x0027
|
||||||
|
#define QMI_MESSAGE_CTL_INTERNAL_PROXY_OPEN 0xFF00
|
||||||
|
|
||||||
|
#define QMICTL_FLAG_REQUEST 0x00
|
||||||
|
#define QMICTL_FLAG_RESPONSE 0x01
|
||||||
|
#define QMICTL_FLAG_INDICATION 0x02
|
||||||
|
|
||||||
|
// QMICTL Message Definitions
|
||||||
|
|
||||||
|
typedef struct _QMICTL_SET_INSTANCE_ID_REQ_MSG
|
||||||
|
{
|
||||||
|
UCHAR CtlFlags; // QMICTL_FLAG_REQUEST
|
||||||
|
UCHAR TransactionId;
|
||||||
|
USHORT QMICTLType; // QMICTL_SET_INSTANCE_ID_REQ
|
||||||
|
USHORT Length; // 4
|
||||||
|
UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||||
|
USHORT TLVLength; // 1
|
||||||
|
UCHAR Value; // Host-unique QMI instance for this device driver
|
||||||
|
} __attribute__ ((packed)) QMICTL_SET_INSTANCE_ID_REQ_MSG, *PQMICTL_SET_INSTANCE_ID_REQ_MSG;
|
||||||
|
|
||||||
|
typedef struct _QMICTL_SET_INSTANCE_ID_RESP_MSG
|
||||||
|
{
|
||||||
|
UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE
|
||||||
|
UCHAR TransactionId;
|
||||||
|
USHORT QMICTLType; // QMICTL_SET_INSTANCE_ID_RESP
|
||||||
|
USHORT Length;
|
||||||
|
UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE
|
||||||
|
USHORT TLVLength; // 0x0004
|
||||||
|
USHORT QMIResult;
|
||||||
|
USHORT QMIError;
|
||||||
|
UCHAR TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||||
|
USHORT TLV2Length; // 0x0002
|
||||||
|
USHORT QMI_ID; // Upper byte is assigned by MSM,
|
||||||
|
// lower assigned by host
|
||||||
|
} __attribute__ ((packed)) QMICTL_SET_INSTANCE_ID_RESP_MSG, *PQMICTL_SET_INSTANCE_ID_RESP_MSG;
|
||||||
|
|
||||||
|
typedef struct _QMICTL_GET_VERSION_REQ_MSG
|
||||||
|
{
|
||||||
|
UCHAR CtlFlags; // QMICTL_FLAG_REQUEST
|
||||||
|
UCHAR TransactionId;
|
||||||
|
USHORT QMICTLType; // QMICTL_GET_VERSION_REQ
|
||||||
|
USHORT Length; // 0
|
||||||
|
UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||||
|
USHORT TLVLength; // var
|
||||||
|
UCHAR QMUXTypes; // List of one byte QMUX_TYPE values
|
||||||
|
// 0xFF returns a list of versions for all
|
||||||
|
// QMUX_TYPEs implemented on the device
|
||||||
|
} __attribute__ ((packed)) QMICTL_GET_VERSION_REQ_MSG, *PQMICTL_GET_VERSION_REQ_MSG;
|
||||||
|
|
||||||
|
typedef struct _QMUX_TYPE_VERSION_STRUCT
|
||||||
|
{
|
||||||
|
UCHAR QMUXType;
|
||||||
|
USHORT MajorVersion;
|
||||||
|
USHORT MinorVersion;
|
||||||
|
} __attribute__ ((packed)) QMUX_TYPE_VERSION_STRUCT, *PQMUX_TYPE_VERSION_STRUCT;
|
||||||
|
|
||||||
|
typedef struct _ADDENDUM_VERSION_PREAMBLE
|
||||||
|
{
|
||||||
|
UCHAR LabelLength;
|
||||||
|
UCHAR Label;
|
||||||
|
} __attribute__ ((packed)) ADDENDUM_VERSION_PREAMBLE, *PADDENDUM_VERSION_PREAMBLE;
|
||||||
|
|
||||||
|
#define QMICTL_GET_VERSION_RSP_TLV_TYPE_VERSION 0x01
|
||||||
|
#define QMICTL_GET_VERSION_RSP_TLV_TYPE_ADD_VERSION 0x10
|
||||||
|
|
||||||
|
typedef struct _QMICTL_GET_VERSION_RESP_MSG
|
||||||
|
{
|
||||||
|
UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE
|
||||||
|
UCHAR TransactionId;
|
||||||
|
USHORT QMICTLType; // QMICTL_GET_VERSION_RESP
|
||||||
|
USHORT Length;
|
||||||
|
UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE
|
||||||
|
USHORT TLVLength; // 0x0004
|
||||||
|
USHORT QMIResult;
|
||||||
|
USHORT QMIError;
|
||||||
|
UCHAR TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||||
|
USHORT TLV2Length; // var
|
||||||
|
UCHAR NumElements; // Num of QMUX_TYPE_VERSION_STRUCT
|
||||||
|
QMUX_TYPE_VERSION_STRUCT TypeVersion[0];
|
||||||
|
} __attribute__ ((packed)) QMICTL_GET_VERSION_RESP_MSG, *PQMICTL_GET_VERSION_RESP_MSG;
|
||||||
|
|
||||||
|
typedef struct _QMICTL_GET_CLIENT_ID_REQ_MSG
|
||||||
|
{
|
||||||
|
UCHAR CtlFlags; // QMICTL_FLAG_REQUEST
|
||||||
|
UCHAR TransactionId;
|
||||||
|
USHORT QMICTLType; // QMICTL_GET_CLIENT_ID_REQ
|
||||||
|
USHORT Length;
|
||||||
|
UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||||
|
USHORT TLVLength; // 1
|
||||||
|
UCHAR QMIType; // QMUX type
|
||||||
|
} __attribute__ ((packed)) QMICTL_GET_CLIENT_ID_REQ_MSG, *PQMICTL_GET_CLIENT_ID_REQ_MSG;
|
||||||
|
|
||||||
|
typedef struct _QMICTL_GET_CLIENT_ID_RESP_MSG
|
||||||
|
{
|
||||||
|
UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE
|
||||||
|
UCHAR TransactionId;
|
||||||
|
USHORT QMICTLType; // QMICTL_GET_CLIENT_ID_RESP
|
||||||
|
USHORT Length;
|
||||||
|
UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE
|
||||||
|
USHORT TLVLength; // 0x0004
|
||||||
|
USHORT QMIResult; // result code
|
||||||
|
USHORT QMIError; // error code
|
||||||
|
UCHAR TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||||
|
USHORT TLV2Length; // 2
|
||||||
|
UCHAR QMIType;
|
||||||
|
UCHAR ClientId;
|
||||||
|
} __attribute__ ((packed)) QMICTL_GET_CLIENT_ID_RESP_MSG, *PQMICTL_GET_CLIENT_ID_RESP_MSG;
|
||||||
|
|
||||||
|
typedef struct _QMICTL_RELEASE_CLIENT_ID_REQ_MSG
|
||||||
|
{
|
||||||
|
UCHAR CtlFlags; // QMICTL_FLAG_REQUEST
|
||||||
|
UCHAR TransactionId;
|
||||||
|
USHORT QMICTLType; // QMICTL_RELEASE_CLIENT_ID_REQ
|
||||||
|
USHORT Length;
|
||||||
|
UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||||
|
USHORT TLVLength; // 0x0002
|
||||||
|
UCHAR QMIType;
|
||||||
|
UCHAR ClientId;
|
||||||
|
} __attribute__ ((packed)) QMICTL_RELEASE_CLIENT_ID_REQ_MSG, *PQMICTL_RELEASE_CLIENT_ID_REQ_MSG;
|
||||||
|
|
||||||
|
typedef struct _QMICTL_RELEASE_CLIENT_ID_RESP_MSG
|
||||||
|
{
|
||||||
|
UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE
|
||||||
|
UCHAR TransactionId;
|
||||||
|
USHORT QMICTLType; // QMICTL_RELEASE_CLIENT_ID_RESP
|
||||||
|
USHORT Length;
|
||||||
|
UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE
|
||||||
|
USHORT TLVLength; // 0x0004
|
||||||
|
USHORT QMIResult; // result code
|
||||||
|
USHORT QMIError; // error code
|
||||||
|
UCHAR TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||||
|
USHORT TLV2Length; // 2
|
||||||
|
UCHAR QMIType;
|
||||||
|
UCHAR ClientId;
|
||||||
|
} __attribute__ ((packed)) QMICTL_RELEASE_CLIENT_ID_RESP_MSG, *PQMICTL_RELEASE_CLIENT_ID_RESP_MSG;
|
||||||
|
|
||||||
|
typedef struct _QMICTL_REVOKE_CLIENT_ID_IND_MSG
|
||||||
|
{
|
||||||
|
UCHAR CtlFlags; // QMICTL_FLAG_INDICATION
|
||||||
|
UCHAR TransactionId;
|
||||||
|
USHORT QMICTLType; // QMICTL_REVOKE_CLIENT_ID_IND
|
||||||
|
USHORT Length;
|
||||||
|
UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||||
|
USHORT TLVLength; // 0x0002
|
||||||
|
UCHAR QMIType;
|
||||||
|
UCHAR ClientId;
|
||||||
|
} __attribute__ ((packed)) QMICTL_REVOKE_CLIENT_ID_IND_MSG, *PQMICTL_REVOKE_CLIENT_ID_IND_MSG;
|
||||||
|
|
||||||
|
typedef struct _QMICTL_INVALID_CLIENT_ID_IND_MSG
|
||||||
|
{
|
||||||
|
UCHAR CtlFlags; // QMICTL_FLAG_INDICATION
|
||||||
|
UCHAR TransactionId;
|
||||||
|
USHORT QMICTLType; // QMICTL_REVOKE_CLIENT_ID_IND
|
||||||
|
USHORT Length;
|
||||||
|
UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||||
|
USHORT TLVLength; // 0x0002
|
||||||
|
UCHAR QMIType;
|
||||||
|
UCHAR ClientId;
|
||||||
|
} __attribute__ ((packed)) QMICTL_INVALID_CLIENT_ID_IND_MSG, *PQMICTL_INVALID_CLIENT_ID_IND_MSG;
|
||||||
|
|
||||||
|
typedef struct _QMICTL_SET_DATA_FORMAT_REQ_MSG
|
||||||
|
{
|
||||||
|
UCHAR CtlFlags; // QMICTL_FLAG_REQUEST
|
||||||
|
UCHAR TransactionId;
|
||||||
|
USHORT QMICTLType; // QMICTL_SET_DATA_FORMAT_REQ
|
||||||
|
USHORT Length;
|
||||||
|
UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER
|
||||||
|
USHORT TLVLength; // 1
|
||||||
|
UCHAR DataFormat; // 0-default; 1-QoS hdr present
|
||||||
|
} __attribute__ ((packed)) QMICTL_SET_DATA_FORMAT_REQ_MSG, *PQMICTL_SET_DATA_FORMAT_REQ_MSG;
|
||||||
|
|
||||||
|
#ifdef QC_IP_MODE
|
||||||
|
#define SET_DATA_FORMAT_TLV_TYPE_LINK_PROTO 0x10
|
||||||
|
#define SET_DATA_FORMAT_LINK_PROTO_ETH 0x0001
|
||||||
|
#define SET_DATA_FORMAT_LINK_PROTO_IP 0x0002
|
||||||
|
typedef struct _QMICTL_SET_DATA_FORMAT_TLV_LINK_PROT
|
||||||
|
{
|
||||||
|
UCHAR TLVType; // Link-Layer Protocol
|
||||||
|
USHORT TLVLength; // 2
|
||||||
|
USHORT LinkProt; // 0x1: ETH; 0x2: IP
|
||||||
|
} QMICTL_SET_DATA_FORMAT_TLV_LINK_PROT, *PQMICTL_SET_DATA_FORMAT_TLV_LINK_PROT;
|
||||||
|
|
||||||
|
#ifdef QCMP_UL_TLP
|
||||||
|
#define SET_DATA_FORMAT_TLV_TYPE_UL_TLP 0x11
|
||||||
|
typedef struct _QMICTL_SET_DATA_FORMAT_TLV_UL_TLP
|
||||||
|
{
|
||||||
|
UCHAR TLVType; // 0x11, Uplink TLP Setting
|
||||||
|
USHORT TLVLength; // 1
|
||||||
|
UCHAR UlTlpSetting; // 0x0: Disable; 0x01: Enable
|
||||||
|
} QMICTL_SET_DATA_FORMAT_TLV_UL_TLP, *PQMICTL_SET_DATA_FORMAT_TLV_UL_TLP;
|
||||||
|
#endif // QCMP_UL_TLP
|
||||||
|
|
||||||
|
#ifdef QCMP_DL_TLP
|
||||||
|
#define SET_DATA_FORMAT_TLV_TYPE_DL_TLP 0x13
|
||||||
|
typedef struct _QMICTL_SET_DATA_FORMAT_TLV_DL_TLP
|
||||||
|
{
|
||||||
|
UCHAR TLVType; // 0x11, Uplink TLP Setting
|
||||||
|
USHORT TLVLength; // 1
|
||||||
|
UCHAR DlTlpSetting; // 0x0: Disable; 0x01: Enable
|
||||||
|
} QMICTL_SET_DATA_FORMAT_TLV_DL_TLP, *PQMICTL_SET_DATA_FORMAT_TLV_DL_TLP;
|
||||||
|
#endif // QCMP_DL_TLP
|
||||||
|
|
||||||
|
#endif // QC_IP_MODE
|
||||||
|
|
||||||
|
#ifdef MP_QCQOS_ENABLED
|
||||||
|
#define SET_DATA_FORMAT_TLV_TYPE_QOS_SETTING 0x12
|
||||||
|
typedef struct _QMICTL_SET_DATA_FORMAT_TLV_QOS_SETTING
|
||||||
|
{
|
||||||
|
UCHAR TLVType; // 0x12, QoS setting
|
||||||
|
USHORT TLVLength; // 1
|
||||||
|
UCHAR QosSetting; // 0x0: Disable; 0x01: Enable
|
||||||
|
} QMICTL_SET_DATA_FORMAT_TLV_QOS_SETTING, *PQMICTL_SET_DATA_FORMAT_TLV_QOS_SETTING;
|
||||||
|
#endif // MP_QCQOS_ENABLED
|
||||||
|
|
||||||
|
typedef struct _QMICTL_SET_DATA_FORMAT_RESP_MSG
|
||||||
|
{
|
||||||
|
UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE
|
||||||
|
UCHAR TransactionId;
|
||||||
|
USHORT QMICTLType; // QMICTL_SET_DATA_FORMAT_RESP
|
||||||
|
USHORT Length;
|
||||||
|
UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE
|
||||||
|
USHORT TLVLength; // 0x0004
|
||||||
|
USHORT QMIResult; // result code
|
||||||
|
USHORT QMIError; // error code
|
||||||
|
} __attribute__ ((packed)) QMICTL_SET_DATA_FORMAT_RESP_MSG, *PQMICTL_SET_DATA_FORMAT_RESP_MSG;
|
||||||
|
|
||||||
|
typedef struct _QMICTL_SYNC_REQ_MSG
|
||||||
|
{
|
||||||
|
UCHAR CtlFlags; // QMICTL_FLAG_REQUEST
|
||||||
|
UCHAR TransactionId;
|
||||||
|
USHORT QMICTLType; // QMICTL_CTL_SYNC_REQ
|
||||||
|
USHORT Length; // 0
|
||||||
|
} __attribute__ ((packed)) QMICTL_SYNC_REQ_MSG, *PQMICTL_SYNC_REQ_MSG;
|
||||||
|
|
||||||
|
typedef struct _QMICTL_SYNC_RESP_MSG
|
||||||
|
{
|
||||||
|
UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE
|
||||||
|
UCHAR TransactionId;
|
||||||
|
USHORT QMICTLType; // QMICTL_CTL_SYNC_RESP
|
||||||
|
USHORT Length;
|
||||||
|
UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE
|
||||||
|
USHORT TLVLength; // 0x0004
|
||||||
|
USHORT QMIResult;
|
||||||
|
USHORT QMIError;
|
||||||
|
} __attribute__ ((packed)) QMICTL_SYNC_RESP_MSG, *PQMICTL_SYNC_RESP_MSG;
|
||||||
|
|
||||||
|
typedef struct _QMICTL_SYNC_IND_MSG
|
||||||
|
{
|
||||||
|
UCHAR CtlFlags; // QMICTL_FLAG_INDICATION
|
||||||
|
UCHAR TransactionId;
|
||||||
|
USHORT QMICTLType; // QMICTL_REVOKE_CLIENT_ID_IND
|
||||||
|
USHORT Length;
|
||||||
|
} __attribute__ ((packed)) QMICTL_SYNC_IND_MSG, *PQMICTL_SYNC_IND_MSG;
|
||||||
|
|
||||||
|
typedef struct _QMICTL_LIBQMI_PROXY_OPEN_MSG
|
||||||
|
{
|
||||||
|
UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE
|
||||||
|
UCHAR TransactionId;
|
||||||
|
USHORT QMICTLType; // QMICTL_SET_DATA_FORMAT_RESP
|
||||||
|
USHORT Length;
|
||||||
|
UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE
|
||||||
|
USHORT TLVLength; // 0x0004
|
||||||
|
char device_path[0]; // result code
|
||||||
|
} __attribute__ ((packed)) QMICTL_LIBQMI_PROXY_OPEN_MSG, *PQMICTL_LIBQMI_PROXY_OPEN_MSG;
|
||||||
|
|
||||||
|
typedef struct _QMICTL_MSG
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
// Message Header
|
||||||
|
QCQMICTL_MSG_HDR QMICTLMsgHdr;
|
||||||
|
QCQMICTL_MSG_HDR_RESP QMICTLMsgHdrRsp;
|
||||||
|
|
||||||
|
// QMICTL Message
|
||||||
|
QMICTL_SET_INSTANCE_ID_REQ_MSG SetInstanceIdReq;
|
||||||
|
QMICTL_SET_INSTANCE_ID_RESP_MSG SetInstanceIdRsp;
|
||||||
|
QMICTL_GET_VERSION_REQ_MSG GetVersionReq;
|
||||||
|
QMICTL_GET_VERSION_RESP_MSG GetVersionRsp;
|
||||||
|
QMICTL_GET_CLIENT_ID_REQ_MSG GetClientIdReq;
|
||||||
|
QMICTL_GET_CLIENT_ID_RESP_MSG GetClientIdRsp;
|
||||||
|
QMICTL_RELEASE_CLIENT_ID_REQ_MSG ReleaseClientIdReq;
|
||||||
|
QMICTL_RELEASE_CLIENT_ID_RESP_MSG ReleaseClientIdRsp;
|
||||||
|
QMICTL_REVOKE_CLIENT_ID_IND_MSG RevokeClientIdInd;
|
||||||
|
QMICTL_INVALID_CLIENT_ID_IND_MSG InvalidClientIdInd;
|
||||||
|
QMICTL_SET_DATA_FORMAT_REQ_MSG SetDataFormatReq;
|
||||||
|
QMICTL_SET_DATA_FORMAT_RESP_MSG SetDataFormatRsp;
|
||||||
|
QMICTL_SYNC_REQ_MSG SyncReq;
|
||||||
|
QMICTL_SYNC_RESP_MSG SyncRsp;
|
||||||
|
QMICTL_SYNC_IND_MSG SyncInd;
|
||||||
|
QMICTL_LIBQMI_PROXY_OPEN_MSG LibQmiProxyOpenReq;
|
||||||
|
};
|
||||||
|
} __attribute__ ((packed)) QMICTL_MSG, *PQMICTL_MSG;
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
#endif //QCQCTL_H
|
320
quectel_cm_5G/src/QCQMI.h
Normal file
320
quectel_cm_5G/src/QCQMI.h
Normal file
@ -0,0 +1,320 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
@file QCQMI.h
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
This module contains QMI module.
|
||||||
|
|
||||||
|
INITIALIZATION AND SEQUENCING REQUIREMENTS
|
||||||
|
None.
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
Copyright (c) 2016 - 2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
|
||||||
|
Quectel Wireless Solution Proprietary and Confidential.
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef USBQMI_H
|
||||||
|
#define USBQMI_H
|
||||||
|
|
||||||
|
typedef uint8_t uint8;
|
||||||
|
typedef int8_t int8;
|
||||||
|
typedef uint16_t uint16;
|
||||||
|
typedef int16_t int16;
|
||||||
|
typedef uint32_t uint32;
|
||||||
|
typedef uint64_t uint64;
|
||||||
|
|
||||||
|
typedef signed char CHAR;
|
||||||
|
typedef unsigned char UCHAR;
|
||||||
|
typedef short SHORT;
|
||||||
|
typedef unsigned short USHORT;
|
||||||
|
typedef int INT;
|
||||||
|
typedef unsigned int UINT;
|
||||||
|
typedef long LONG;
|
||||||
|
typedef unsigned int ULONG;
|
||||||
|
typedef unsigned long long ULONG64;
|
||||||
|
typedef signed char *PCHAR;
|
||||||
|
typedef unsigned char *PUCHAR;
|
||||||
|
typedef int *PINT;
|
||||||
|
typedef int BOOL;
|
||||||
|
|
||||||
|
#define TRUE (1 == 1)
|
||||||
|
#define FALSE (1 != 1)
|
||||||
|
|
||||||
|
#define QMICTL_SUPPORTED_MAJOR_VERSION 1
|
||||||
|
#define QMICTL_SUPPORTED_MINOR_VERSION 0
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
|
// ========= USB Control Message ==========
|
||||||
|
|
||||||
|
#define USB_CTL_MSG_TYPE_QMI 0x01
|
||||||
|
|
||||||
|
// USB Control Message
|
||||||
|
typedef struct _QCUSB_CTL_MSG_HDR
|
||||||
|
{
|
||||||
|
UCHAR IFType;
|
||||||
|
} __attribute__ ((packed)) QCUSB_CTL_MSG_HDR, *PQCUSB_CTL_MSG_HDR;
|
||||||
|
|
||||||
|
#define QCUSB_CTL_MSG_HDR_SIZE sizeof(QCUSB_CTL_MSG_HDR)
|
||||||
|
|
||||||
|
typedef struct _QCUSB_CTL_MSG
|
||||||
|
{
|
||||||
|
UCHAR IFType;
|
||||||
|
UCHAR Message;
|
||||||
|
} __attribute__ ((packed)) QCUSB_CTL_MSG, *PQCUSB_CTL_MSG;
|
||||||
|
|
||||||
|
#define QCTLV_TYPE_REQUIRED_PARAMETER 0x01
|
||||||
|
#define QCTLV_TYPE_RESULT_CODE 0x02
|
||||||
|
|
||||||
|
// ================= QMI ==================
|
||||||
|
|
||||||
|
// Define QMI Type
|
||||||
|
typedef enum _QMI_SERVICE_TYPE
|
||||||
|
{
|
||||||
|
QMUX_TYPE_CTL = 0x00,
|
||||||
|
QMUX_TYPE_WDS = 0x01,
|
||||||
|
QMUX_TYPE_DMS = 0x02,
|
||||||
|
QMUX_TYPE_NAS = 0x03,
|
||||||
|
QMUX_TYPE_QOS = 0x04,
|
||||||
|
QMUX_TYPE_WMS = 0x05,
|
||||||
|
QMUX_TYPE_PDS = 0x06,
|
||||||
|
QMUX_TYPE_UIM = 0x0B,
|
||||||
|
QMUX_TYPE_WDS_IPV6 = 0x11,
|
||||||
|
QMUX_TYPE_WDS_ADMIN = 0x1A,
|
||||||
|
QMUX_TYPE_COEX = 0x22,
|
||||||
|
QMUX_TYPE_MAX = 0xFF,
|
||||||
|
QMUX_TYPE_ALL = 0xFF
|
||||||
|
} QMI_SERVICE_TYPE;
|
||||||
|
|
||||||
|
typedef enum _QMI_RESULT_CODE_TYPE
|
||||||
|
{
|
||||||
|
QMI_RESULT_SUCCESS = 0x0000,
|
||||||
|
QMI_RESULT_FAILURE = 0x0001
|
||||||
|
} QMI_RESULT_CODE_TYPE;
|
||||||
|
|
||||||
|
typedef enum _QMI_ERROR_CODE_TYPE
|
||||||
|
{
|
||||||
|
QMI_ERR_NONE = 0x0000
|
||||||
|
,QMI_ERR_MALFORMED_MSG = 0x0001
|
||||||
|
,QMI_ERR_NO_MEMORY = 0x0002
|
||||||
|
,QMI_ERR_INTERNAL = 0x0003
|
||||||
|
,QMI_ERR_ABORTED = 0x0004
|
||||||
|
,QMI_ERR_CLIENT_IDS_EXHAUSTED = 0x0005
|
||||||
|
,QMI_ERR_UNABORTABLE_TRANSACTION = 0x0006
|
||||||
|
,QMI_ERR_INVALID_CLIENT_ID = 0x0007
|
||||||
|
,QMI_ERR_NO_THRESHOLDS = 0x0008
|
||||||
|
,QMI_ERR_INVALID_HANDLE = 0x0009
|
||||||
|
,QMI_ERR_INVALID_PROFILE = 0x000A
|
||||||
|
,QMI_ERR_INVALID_PINID = 0x000B
|
||||||
|
,QMI_ERR_INCORRECT_PIN = 0x000C
|
||||||
|
,QMI_ERR_NO_NETWORK_FOUND = 0x000D
|
||||||
|
,QMI_ERR_CALL_FAILED = 0x000E
|
||||||
|
,QMI_ERR_OUT_OF_CALL = 0x000F
|
||||||
|
,QMI_ERR_NOT_PROVISIONED = 0x0010
|
||||||
|
,QMI_ERR_MISSING_ARG = 0x0011
|
||||||
|
,QMI_ERR_ARG_TOO_LONG = 0x0013
|
||||||
|
,QMI_ERR_INVALID_TX_ID = 0x0016
|
||||||
|
,QMI_ERR_DEVICE_IN_USE = 0x0017
|
||||||
|
,QMI_ERR_OP_NETWORK_UNSUPPORTED = 0x0018
|
||||||
|
,QMI_ERR_OP_DEVICE_UNSUPPORTED = 0x0019
|
||||||
|
,QMI_ERR_NO_EFFECT = 0x001A
|
||||||
|
,QMI_ERR_NO_FREE_PROFILE = 0x001B
|
||||||
|
,QMI_ERR_INVALID_PDP_TYPE = 0x001C
|
||||||
|
,QMI_ERR_INVALID_TECH_PREF = 0x001D
|
||||||
|
,QMI_ERR_INVALID_PROFILE_TYPE = 0x001E
|
||||||
|
,QMI_ERR_INVALID_SERVICE_TYPE = 0x001F
|
||||||
|
,QMI_ERR_INVALID_REGISTER_ACTION = 0x0020
|
||||||
|
,QMI_ERR_INVALID_PS_ATTACH_ACTION = 0x0021
|
||||||
|
,QMI_ERR_AUTHENTICATION_FAILED = 0x0022
|
||||||
|
,QMI_ERR_PIN_BLOCKED = 0x0023
|
||||||
|
,QMI_ERR_PIN_PERM_BLOCKED = 0x0024
|
||||||
|
,QMI_ERR_SIM_NOT_INITIALIZED = 0x0025
|
||||||
|
,QMI_ERR_MAX_QOS_REQUESTS_IN_USE = 0x0026
|
||||||
|
,QMI_ERR_INCORRECT_FLOW_FILTER = 0x0027
|
||||||
|
,QMI_ERR_NETWORK_QOS_UNAWARE = 0x0028
|
||||||
|
,QMI_ERR_INVALID_QOS_ID = 0x0029
|
||||||
|
,QMI_ERR_INVALID_ID = 0x0029
|
||||||
|
,QMI_ERR_REQUESTED_NUM_UNSUPPORTED = 0x002A
|
||||||
|
,QMI_ERR_INTERFACE_NOT_FOUND = 0x002B
|
||||||
|
,QMI_ERR_FLOW_SUSPENDED = 0x002C
|
||||||
|
,QMI_ERR_INVALID_DATA_FORMAT = 0x002D
|
||||||
|
,QMI_ERR_GENERAL = 0x002E
|
||||||
|
,QMI_ERR_UNKNOWN = 0x002F
|
||||||
|
,QMI_ERR_INVALID_ARG = 0x0030
|
||||||
|
,QMI_ERR_INVALID_INDEX = 0x0031
|
||||||
|
,QMI_ERR_NO_ENTRY = 0x0032
|
||||||
|
,QMI_ERR_DEVICE_STORAGE_FULL = 0x0033
|
||||||
|
,QMI_ERR_DEVICE_NOT_READY = 0x0034
|
||||||
|
,QMI_ERR_NETWORK_NOT_READY = 0x0035
|
||||||
|
,QMI_ERR_CAUSE_CODE = 0x0036
|
||||||
|
,QMI_ERR_MESSAGE_NOT_SENT = 0x0037
|
||||||
|
,QMI_ERR_MESSAGE_DELIVERY_FAILURE = 0x0038
|
||||||
|
,QMI_ERR_INVALID_MESSAGE_ID = 0x0039
|
||||||
|
,QMI_ERR_ENCODING = 0x003A
|
||||||
|
,QMI_ERR_AUTHENTICATION_LOCK = 0x003B
|
||||||
|
,QMI_ERR_INVALID_TRANSITION = 0x003C
|
||||||
|
,QMI_ERR_NOT_A_MCAST_IFACE = 0x003D
|
||||||
|
,QMI_ERR_MAX_MCAST_REQUESTS_IN_USE = 0x003E
|
||||||
|
,QMI_ERR_INVALID_MCAST_HANDLE = 0x003F
|
||||||
|
,QMI_ERR_INVALID_IP_FAMILY_PREF = 0x0040
|
||||||
|
,QMI_ERR_SESSION_INACTIVE = 0x0041
|
||||||
|
,QMI_ERR_SESSION_INVALID = 0x0042
|
||||||
|
,QMI_ERR_SESSION_OWNERSHIP = 0x0043
|
||||||
|
,QMI_ERR_INSUFFICIENT_RESOURCES = 0x0044
|
||||||
|
,QMI_ERR_DISABLED = 0x0045
|
||||||
|
,QMI_ERR_INVALID_OPERATION = 0x0046
|
||||||
|
,QMI_ERR_INVALID_QMI_CMD = 0x0047
|
||||||
|
,QMI_ERR_TPDU_TYPE = 0x0048
|
||||||
|
,QMI_ERR_SMSC_ADDR = 0x0049
|
||||||
|
,QMI_ERR_INFO_UNAVAILABLE = 0x004A
|
||||||
|
,QMI_ERR_SEGMENT_TOO_LONG = 0x004B
|
||||||
|
,QMI_ERR_SEGMENT_ORDER = 0x004C
|
||||||
|
,QMI_ERR_BUNDLING_NOT_SUPPORTED = 0x004D
|
||||||
|
,QMI_ERR_OP_PARTIAL_FAILURE = 0x004E
|
||||||
|
,QMI_ERR_POLICY_MISMATCH = 0x004F
|
||||||
|
,QMI_ERR_SIM_FILE_NOT_FOUND = 0x0050
|
||||||
|
,QMI_ERR_EXTENDED_INTERNAL = 0x0051
|
||||||
|
,QMI_ERR_ACCESS_DENIED = 0x0052
|
||||||
|
,QMI_ERR_HARDWARE_RESTRICTED = 0x0053
|
||||||
|
,QMI_ERR_ACK_NOT_SENT = 0x0054
|
||||||
|
,QMI_ERR_INJECT_TIMEOUT = 0x0055
|
||||||
|
,QMI_ERR_INCOMPATIBLE_STATE = 0x005A
|
||||||
|
,QMI_ERR_FDN_RESTRICT = 0x005B
|
||||||
|
,QMI_ERR_SUPS_FAILURE_CAUSE = 0x005C
|
||||||
|
,QMI_ERR_NO_RADIO = 0x005D
|
||||||
|
,QMI_ERR_NOT_SUPPORTED = 0x005E
|
||||||
|
,QMI_ERR_NO_SUBSCRIPTION = 0x005F
|
||||||
|
,QMI_ERR_CARD_CALL_CONTROL_FAILED = 0x0060
|
||||||
|
,QMI_ERR_NETWORK_ABORTED = 0x0061
|
||||||
|
,QMI_ERR_MSG_BLOCKED = 0x0062
|
||||||
|
,QMI_ERR_INVALID_SESSION_TYPE = 0x0064
|
||||||
|
,QMI_ERR_INVALID_PB_TYPE = 0x0065
|
||||||
|
,QMI_ERR_NO_SIM = 0x0066
|
||||||
|
,QMI_ERR_PB_NOT_READY = 0x0067
|
||||||
|
,QMI_ERR_PIN_RESTRICTION = 0x0068
|
||||||
|
,QMI_ERR_PIN2_RESTRICTION = 0x0069
|
||||||
|
,QMI_ERR_PUK_RESTRICTION = 0x006A
|
||||||
|
,QMI_ERR_PUK2_RESTRICTION = 0x006B
|
||||||
|
,QMI_ERR_PB_ACCESS_RESTRICTED = 0x006C
|
||||||
|
,QMI_ERR_PB_DELETE_IN_PROG = 0x006D
|
||||||
|
,QMI_ERR_PB_TEXT_TOO_LONG = 0x006E
|
||||||
|
,QMI_ERR_PB_NUMBER_TOO_LONG = 0x006F
|
||||||
|
,QMI_ERR_PB_HIDDEN_KEY_RESTRICTION = 0x0070
|
||||||
|
} QMI_ERROR_CODE_TYPE;
|
||||||
|
|
||||||
|
#define QCQMI_CTL_FLAG_SERVICE 0x80
|
||||||
|
#define QCQMI_CTL_FLAG_CTL_POINT 0x00
|
||||||
|
|
||||||
|
typedef struct _QCQMI_HDR
|
||||||
|
{
|
||||||
|
UCHAR IFType;
|
||||||
|
USHORT Length;
|
||||||
|
UCHAR CtlFlags; // reserved
|
||||||
|
UCHAR QMIType;
|
||||||
|
UCHAR ClientId;
|
||||||
|
} __attribute__ ((packed)) QCQMI_HDR, *PQCQMI_HDR;
|
||||||
|
|
||||||
|
#define QCQMI_HDR_SIZE (sizeof(QCQMI_HDR)-1)
|
||||||
|
|
||||||
|
typedef struct _QCQMI
|
||||||
|
{
|
||||||
|
UCHAR IFType;
|
||||||
|
USHORT Length;
|
||||||
|
UCHAR CtlFlags; // reserved
|
||||||
|
UCHAR QMIType;
|
||||||
|
UCHAR ClientId;
|
||||||
|
UCHAR SDU;
|
||||||
|
} __attribute__ ((packed)) QCQMI, *PQCQMI;
|
||||||
|
|
||||||
|
typedef struct _QMI_SERVICE_VERSION
|
||||||
|
{
|
||||||
|
USHORT Major;
|
||||||
|
USHORT Minor;
|
||||||
|
USHORT AddendumMajor;
|
||||||
|
USHORT AddendumMinor;
|
||||||
|
} __attribute__ ((packed)) QMI_SERVICE_VERSION, *PQMI_SERVICE_VERSION;
|
||||||
|
|
||||||
|
// ================= QMUX ==================
|
||||||
|
|
||||||
|
#define QMUX_MSG_OVERHEAD_BYTES 4 // Type(USHORT) Length(USHORT) -- header
|
||||||
|
|
||||||
|
#define QMUX_BROADCAST_CID 0xFF
|
||||||
|
|
||||||
|
typedef struct _QCQMUX_HDR
|
||||||
|
{
|
||||||
|
UCHAR CtlFlags; // 0: single QMUX Msg; 1:
|
||||||
|
USHORT TransactionId;
|
||||||
|
} __attribute__ ((packed)) QCQMUX_HDR, *PQCQMUX_HDR;
|
||||||
|
|
||||||
|
typedef struct _QCQMUX
|
||||||
|
{
|
||||||
|
UCHAR CtlFlags; // 0: single QMUX Msg; 1:
|
||||||
|
USHORT TransactionId;
|
||||||
|
UCHAR Message; // Type(2), Length(2), Value
|
||||||
|
} __attribute__ ((packed)) QCQMUX, *PQCQMUX;
|
||||||
|
|
||||||
|
#define QCQMUX_HDR_SIZE sizeof(QCQMUX_HDR)
|
||||||
|
|
||||||
|
typedef struct _QCQMUX_MSG_HDR
|
||||||
|
{
|
||||||
|
USHORT Type;
|
||||||
|
USHORT Length;
|
||||||
|
} __attribute__ ((packed)) QCQMUX_MSG_HDR, *PQCQMUX_MSG_HDR;
|
||||||
|
|
||||||
|
#define QCQMUX_MSG_HDR_SIZE sizeof(QCQMUX_MSG_HDR)
|
||||||
|
|
||||||
|
typedef struct _QCQMUX_MSG_HDR_RESP
|
||||||
|
{
|
||||||
|
USHORT Type;
|
||||||
|
USHORT Length;
|
||||||
|
UCHAR TLVType; // 0x02 - result code
|
||||||
|
USHORT TLVLength; // 4
|
||||||
|
USHORT QMUXResult; // QMI_RESULT_SUCCESS
|
||||||
|
// QMI_RESULT_FAILURE
|
||||||
|
USHORT QMUXError; // QMI_ERR_INVALID_ARG
|
||||||
|
// QMI_ERR_NO_MEMORY
|
||||||
|
// QMI_ERR_INTERNAL
|
||||||
|
// QMI_ERR_FAULT
|
||||||
|
} __attribute__ ((packed)) QCQMUX_MSG_HDR_RESP, *PQCQMUX_MSG_HDR_RESP;
|
||||||
|
|
||||||
|
typedef struct _QCQMUX_TLV
|
||||||
|
{
|
||||||
|
UCHAR Type;
|
||||||
|
USHORT Length;
|
||||||
|
UCHAR Value;
|
||||||
|
} __attribute__ ((packed)) QCQMUX_TLV, *PQCQMUX_TLV;
|
||||||
|
|
||||||
|
typedef struct _QMI_TLV_HDR
|
||||||
|
{
|
||||||
|
UCHAR TLVType;
|
||||||
|
USHORT TLVLength;
|
||||||
|
} __attribute__ ((packed)) QMI_TLV_HDR, *PQMI_TLV_HDR;
|
||||||
|
|
||||||
|
typedef struct _QMI_TLV
|
||||||
|
{
|
||||||
|
UCHAR TLVType;
|
||||||
|
USHORT TLVLength;
|
||||||
|
union {
|
||||||
|
int8_t s8;
|
||||||
|
uint8_t u8;
|
||||||
|
int16_t s16;
|
||||||
|
uint16_t u16;
|
||||||
|
int32_t s32;
|
||||||
|
uint32_t u32;
|
||||||
|
uint64_t u64;
|
||||||
|
};
|
||||||
|
} __attribute__ ((packed)) QMI_TLV, *PQMI_TLV;
|
||||||
|
|
||||||
|
// QMUX Message Definitions -- QMI SDU
|
||||||
|
#define QMUX_CTL_FLAG_SINGLE_MSG 0x00
|
||||||
|
#define QMUX_CTL_FLAG_COMPOUND_MSG 0x01
|
||||||
|
#define QMUX_CTL_FLAG_TYPE_CMD 0x00
|
||||||
|
#define QMUX_CTL_FLAG_TYPE_RSP 0x02
|
||||||
|
#define QMUX_CTL_FLAG_TYPE_IND 0x04
|
||||||
|
#define QMUX_CTL_FLAG_MASK_COMPOUND 0x01
|
||||||
|
#define QMUX_CTL_FLAG_MASK_TYPE 0x06 // 00-cmd, 01-rsp, 10-ind
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
#endif // USBQMI_H
|
477
quectel_cm_5G/src/QCQMUX.c
Normal file
477
quectel_cm_5G/src/QCQMUX.c
Normal file
@ -0,0 +1,477 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
@file MPQMUX.c
|
||||||
|
@brief QMI mux.
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
Connectivity Management Tool for USB network adapter of Quectel wireless cellular modules.
|
||||||
|
|
||||||
|
INITIALIZATION AND SEQUENCING REQUIREMENTS
|
||||||
|
None.
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
Copyright (c) 2016 - 2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
|
||||||
|
Quectel Wireless Solution Proprietary and Confidential.
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "QMIThread.h"
|
||||||
|
static char line[1024];
|
||||||
|
static pthread_mutex_t dumpQMIMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
#undef dbg
|
||||||
|
#define dbg( format, arg... ) do {if (strlen(line) < sizeof(line)) snprintf(&line[strlen(line)], sizeof(line) - strlen(line), format, ## arg);} while (0)
|
||||||
|
|
||||||
|
PQMI_TLV_HDR GetTLV (PQCQMUX_MSG_HDR pQMUXMsgHdr, int TLVType);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT type;
|
||||||
|
const char *name;
|
||||||
|
} QMI_NAME_T;
|
||||||
|
|
||||||
|
#define qmi_name_item(type) {type, #type}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static const QMI_NAME_T qmi_IFType[] = {
|
||||||
|
{USB_CTL_MSG_TYPE_QMI, "USB_CTL_MSG_TYPE_QMI"},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const QMI_NAME_T qmi_CtlFlags[] = {
|
||||||
|
qmi_name_item(QMICTL_CTL_FLAG_CMD),
|
||||||
|
qmi_name_item(QCQMI_CTL_FLAG_SERVICE),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const QMI_NAME_T qmi_QMIType[] = {
|
||||||
|
qmi_name_item(QMUX_TYPE_CTL),
|
||||||
|
qmi_name_item(QMUX_TYPE_WDS),
|
||||||
|
qmi_name_item(QMUX_TYPE_DMS),
|
||||||
|
qmi_name_item(QMUX_TYPE_NAS),
|
||||||
|
qmi_name_item(QMUX_TYPE_QOS),
|
||||||
|
qmi_name_item(QMUX_TYPE_WMS),
|
||||||
|
qmi_name_item(QMUX_TYPE_PDS),
|
||||||
|
qmi_name_item(QMUX_TYPE_WDS_ADMIN),
|
||||||
|
qmi_name_item(QMUX_TYPE_COEX),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const QMI_NAME_T qmi_ctl_CtlFlags[] = {
|
||||||
|
qmi_name_item(QMICTL_FLAG_REQUEST),
|
||||||
|
qmi_name_item(QMICTL_FLAG_RESPONSE),
|
||||||
|
qmi_name_item(QMICTL_FLAG_INDICATION),
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const QMI_NAME_T qmux_ctl_QMICTLType[] = {
|
||||||
|
// QMICTL Type
|
||||||
|
qmi_name_item(QMICTL_SET_INSTANCE_ID_REQ), // 0x0020
|
||||||
|
qmi_name_item(QMICTL_SET_INSTANCE_ID_RESP), // 0x0020
|
||||||
|
qmi_name_item(QMICTL_GET_VERSION_REQ), // 0x0021
|
||||||
|
qmi_name_item(QMICTL_GET_VERSION_RESP), // 0x0021
|
||||||
|
qmi_name_item(QMICTL_GET_CLIENT_ID_REQ), // 0x0022
|
||||||
|
qmi_name_item(QMICTL_GET_CLIENT_ID_RESP), // 0x0022
|
||||||
|
qmi_name_item(QMICTL_RELEASE_CLIENT_ID_REQ), // 0x0023
|
||||||
|
qmi_name_item(QMICTL_RELEASE_CLIENT_ID_RESP), // 0x0023
|
||||||
|
qmi_name_item(QMICTL_REVOKE_CLIENT_ID_IND), // 0x0024
|
||||||
|
qmi_name_item(QMICTL_INVALID_CLIENT_ID_IND), // 0x0025
|
||||||
|
qmi_name_item(QMICTL_SET_DATA_FORMAT_REQ), // 0x0026
|
||||||
|
qmi_name_item(QMICTL_SET_DATA_FORMAT_RESP), // 0x0026
|
||||||
|
qmi_name_item(QMICTL_SYNC_REQ), // 0x0027
|
||||||
|
qmi_name_item(QMICTL_SYNC_RESP), // 0x0027
|
||||||
|
qmi_name_item(QMICTL_SYNC_IND), // 0x0027
|
||||||
|
};
|
||||||
|
|
||||||
|
static const QMI_NAME_T qmux_CtlFlags[] = {
|
||||||
|
qmi_name_item(QMUX_CTL_FLAG_TYPE_CMD),
|
||||||
|
qmi_name_item(QMUX_CTL_FLAG_TYPE_RSP),
|
||||||
|
qmi_name_item(QMUX_CTL_FLAG_TYPE_IND),
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static const QMI_NAME_T qmux_wds_Type[] = {
|
||||||
|
qmi_name_item(QMIWDS_SET_EVENT_REPORT_REQ), // 0x0001
|
||||||
|
qmi_name_item(QMIWDS_SET_EVENT_REPORT_RESP), // 0x0001
|
||||||
|
qmi_name_item(QMIWDS_EVENT_REPORT_IND), // 0x0001
|
||||||
|
qmi_name_item(QMIWDS_START_NETWORK_INTERFACE_REQ), // 0x0020
|
||||||
|
qmi_name_item(QMIWDS_START_NETWORK_INTERFACE_RESP), // 0x0020
|
||||||
|
qmi_name_item(QMIWDS_STOP_NETWORK_INTERFACE_REQ), // 0x0021
|
||||||
|
qmi_name_item(QMIWDS_STOP_NETWORK_INTERFACE_RESP), // 0x0021
|
||||||
|
qmi_name_item(QMIWDS_GET_PKT_SRVC_STATUS_REQ), // 0x0022
|
||||||
|
qmi_name_item(QMIWDS_GET_PKT_SRVC_STATUS_RESP), // 0x0022
|
||||||
|
qmi_name_item(QMIWDS_GET_PKT_SRVC_STATUS_IND), // 0x0022
|
||||||
|
qmi_name_item(QMIWDS_GET_CURRENT_CHANNEL_RATE_REQ), // 0x0023
|
||||||
|
qmi_name_item(QMIWDS_GET_CURRENT_CHANNEL_RATE_RESP), // 0x0023
|
||||||
|
qmi_name_item(QMIWDS_GET_PKT_STATISTICS_REQ), // 0x0024
|
||||||
|
qmi_name_item(QMIWDS_GET_PKT_STATISTICS_RESP), // 0x0024
|
||||||
|
qmi_name_item(QMIWDS_MODIFY_PROFILE_SETTINGS_REQ), // 0x0028
|
||||||
|
qmi_name_item(QMIWDS_MODIFY_PROFILE_SETTINGS_RESP), // 0x0028
|
||||||
|
qmi_name_item(QMIWDS_GET_PROFILE_SETTINGS_REQ), // 0x002B
|
||||||
|
qmi_name_item(QMIWDS_GET_PROFILE_SETTINGS_RESP), // 0x002BD
|
||||||
|
qmi_name_item(QMIWDS_GET_DEFAULT_SETTINGS_REQ), // 0x002C
|
||||||
|
qmi_name_item(QMIWDS_GET_DEFAULT_SETTINGS_RESP), // 0x002C
|
||||||
|
qmi_name_item(QMIWDS_GET_RUNTIME_SETTINGS_REQ), // 0x002D
|
||||||
|
qmi_name_item(QMIWDS_GET_RUNTIME_SETTINGS_RESP), // 0x002D
|
||||||
|
qmi_name_item(QMIWDS_GET_MIP_MODE_REQ), // 0x002F
|
||||||
|
qmi_name_item(QMIWDS_GET_MIP_MODE_RESP), // 0x002F
|
||||||
|
qmi_name_item(QMIWDS_GET_DATA_BEARER_REQ), // 0x0037
|
||||||
|
qmi_name_item(QMIWDS_GET_DATA_BEARER_RESP), // 0x0037
|
||||||
|
qmi_name_item(QMIWDS_DUN_CALL_INFO_REQ), // 0x0038
|
||||||
|
qmi_name_item(QMIWDS_DUN_CALL_INFO_RESP), // 0x0038
|
||||||
|
qmi_name_item(QMIWDS_DUN_CALL_INFO_IND), // 0x0038
|
||||||
|
qmi_name_item(QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ), // 0x004D
|
||||||
|
qmi_name_item(QMIWDS_SET_CLIENT_IP_FAMILY_PREF_RESP), // 0x004D
|
||||||
|
qmi_name_item(QMIWDS_SET_AUTO_CONNECT_REQ), // 0x0051
|
||||||
|
qmi_name_item(QMIWDS_SET_AUTO_CONNECT_RESP), // 0x0051
|
||||||
|
qmi_name_item(QMIWDS_BIND_MUX_DATA_PORT_REQ), // 0x00A2
|
||||||
|
qmi_name_item(QMIWDS_BIND_MUX_DATA_PORT_RESP), // 0x00A2
|
||||||
|
};
|
||||||
|
|
||||||
|
static const QMI_NAME_T qmux_dms_Type[] = {
|
||||||
|
// ======================= DMS ==============================
|
||||||
|
qmi_name_item(QMIDMS_SET_EVENT_REPORT_REQ), // 0x0001
|
||||||
|
qmi_name_item(QMIDMS_SET_EVENT_REPORT_RESP), // 0x0001
|
||||||
|
qmi_name_item(QMIDMS_EVENT_REPORT_IND), // 0x0001
|
||||||
|
qmi_name_item(QMIDMS_GET_DEVICE_CAP_REQ), // 0x0020
|
||||||
|
qmi_name_item(QMIDMS_GET_DEVICE_CAP_RESP), // 0x0020
|
||||||
|
qmi_name_item(QMIDMS_GET_DEVICE_MFR_REQ), // 0x0021
|
||||||
|
qmi_name_item(QMIDMS_GET_DEVICE_MFR_RESP), // 0x0021
|
||||||
|
qmi_name_item(QMIDMS_GET_DEVICE_MODEL_ID_REQ), // 0x0022
|
||||||
|
qmi_name_item(QMIDMS_GET_DEVICE_MODEL_ID_RESP), // 0x0022
|
||||||
|
qmi_name_item(QMIDMS_GET_DEVICE_REV_ID_REQ), // 0x0023
|
||||||
|
qmi_name_item(QMIDMS_GET_DEVICE_REV_ID_RESP), // 0x0023
|
||||||
|
qmi_name_item(QMIDMS_GET_MSISDN_REQ), // 0x0024
|
||||||
|
qmi_name_item(QMIDMS_GET_MSISDN_RESP), // 0x0024
|
||||||
|
qmi_name_item(QMIDMS_GET_DEVICE_SERIAL_NUMBERS_REQ), // 0x0025
|
||||||
|
qmi_name_item(QMIDMS_GET_DEVICE_SERIAL_NUMBERS_RESP), // 0x0025
|
||||||
|
qmi_name_item(QMIDMS_UIM_SET_PIN_PROTECTION_REQ), // 0x0027
|
||||||
|
qmi_name_item(QMIDMS_UIM_SET_PIN_PROTECTION_RESP), // 0x0027
|
||||||
|
qmi_name_item(QMIDMS_UIM_VERIFY_PIN_REQ), // 0x0028
|
||||||
|
qmi_name_item(QMIDMS_UIM_VERIFY_PIN_RESP), // 0x0028
|
||||||
|
qmi_name_item(QMIDMS_UIM_UNBLOCK_PIN_REQ), // 0x0029
|
||||||
|
qmi_name_item(QMIDMS_UIM_UNBLOCK_PIN_RESP), // 0x0029
|
||||||
|
qmi_name_item(QMIDMS_UIM_CHANGE_PIN_REQ), // 0x002A
|
||||||
|
qmi_name_item(QMIDMS_UIM_CHANGE_PIN_RESP), // 0x002A
|
||||||
|
qmi_name_item(QMIDMS_UIM_GET_PIN_STATUS_REQ), // 0x002B
|
||||||
|
qmi_name_item(QMIDMS_UIM_GET_PIN_STATUS_RESP), // 0x002B
|
||||||
|
qmi_name_item(QMIDMS_GET_DEVICE_HARDWARE_REV_REQ), // 0x002C
|
||||||
|
qmi_name_item(QMIDMS_GET_DEVICE_HARDWARE_REV_RESP), // 0x002C
|
||||||
|
qmi_name_item(QMIDMS_GET_OPERATING_MODE_REQ), // 0x002D
|
||||||
|
qmi_name_item(QMIDMS_GET_OPERATING_MODE_RESP), // 0x002D
|
||||||
|
qmi_name_item(QMIDMS_SET_OPERATING_MODE_REQ), // 0x002E
|
||||||
|
qmi_name_item(QMIDMS_SET_OPERATING_MODE_RESP), // 0x002E
|
||||||
|
qmi_name_item(QMIDMS_GET_ACTIVATED_STATUS_REQ), // 0x0031
|
||||||
|
qmi_name_item(QMIDMS_GET_ACTIVATED_STATUS_RESP), // 0x0031
|
||||||
|
qmi_name_item(QMIDMS_ACTIVATE_AUTOMATIC_REQ), // 0x0032
|
||||||
|
qmi_name_item(QMIDMS_ACTIVATE_AUTOMATIC_RESP), // 0x0032
|
||||||
|
qmi_name_item(QMIDMS_ACTIVATE_MANUAL_REQ), // 0x0033
|
||||||
|
qmi_name_item(QMIDMS_ACTIVATE_MANUAL_RESP), // 0x0033
|
||||||
|
qmi_name_item(QMIDMS_UIM_GET_ICCID_REQ), // 0x003C
|
||||||
|
qmi_name_item(QMIDMS_UIM_GET_ICCID_RESP), // 0x003C
|
||||||
|
qmi_name_item(QMIDMS_UIM_GET_CK_STATUS_REQ), // 0x0040
|
||||||
|
qmi_name_item(QMIDMS_UIM_GET_CK_STATUS_RESP), // 0x0040
|
||||||
|
qmi_name_item(QMIDMS_UIM_SET_CK_PROTECTION_REQ), // 0x0041
|
||||||
|
qmi_name_item(QMIDMS_UIM_SET_CK_PROTECTION_RESP), // 0x0041
|
||||||
|
qmi_name_item(QMIDMS_UIM_UNBLOCK_CK_REQ), // 0x0042
|
||||||
|
qmi_name_item(QMIDMS_UIM_UNBLOCK_CK_RESP), // 0x0042
|
||||||
|
qmi_name_item(QMIDMS_UIM_GET_IMSI_REQ), // 0x0043
|
||||||
|
qmi_name_item(QMIDMS_UIM_GET_IMSI_RESP), // 0x0043
|
||||||
|
qmi_name_item(QMIDMS_UIM_GET_STATE_REQ), // 0x0044
|
||||||
|
qmi_name_item(QMIDMS_UIM_GET_STATE_RESP), // 0x0044
|
||||||
|
qmi_name_item(QMIDMS_GET_BAND_CAP_REQ), // 0x0045
|
||||||
|
qmi_name_item(QMIDMS_GET_BAND_CAP_RESP), // 0x0045
|
||||||
|
};
|
||||||
|
|
||||||
|
static const QMI_NAME_T qmux_qos_Type[] = {
|
||||||
|
qmi_name_item( QMI_QOS_SET_EVENT_REPORT_REQ), // 0x0001
|
||||||
|
qmi_name_item( QMI_QOS_SET_EVENT_REPORT_RESP), // 0x0001
|
||||||
|
qmi_name_item( QMI_QOS_SET_EVENT_REPORT_IND), // 0x0001
|
||||||
|
qmi_name_item( QMI_QOS_BIND_DATA_PORT_REQ), // 0x002B
|
||||||
|
qmi_name_item( QMI_QOS_BIND_DATA_PORT_RESP), // 0x002B
|
||||||
|
qmi_name_item( QMI_QOS_INDICATION_REGISTER_REQ), // 0x002F
|
||||||
|
qmi_name_item( QMI_QOS_INDICATION_REGISTER_RESP), // 0x002F
|
||||||
|
qmi_name_item( QMI_QOS_GLOBAL_QOS_FLOW_IND), // 0x0031
|
||||||
|
qmi_name_item( QMI_QOS_GET_QOS_INFO_REQ), // 0x0033
|
||||||
|
qmi_name_item( QMI_QOS_GET_QOS_INFO_RESP), // 0x0033
|
||||||
|
};
|
||||||
|
|
||||||
|
static const QMI_NAME_T qmux_nas_Type[] = {
|
||||||
|
// ======================= NAS ==============================
|
||||||
|
qmi_name_item(QMINAS_SET_EVENT_REPORT_REQ), // 0x0002
|
||||||
|
qmi_name_item(QMINAS_SET_EVENT_REPORT_RESP), // 0x0002
|
||||||
|
qmi_name_item(QMINAS_EVENT_REPORT_IND), // 0x0002
|
||||||
|
qmi_name_item(QMINAS_GET_SIGNAL_STRENGTH_REQ), // 0x0020
|
||||||
|
qmi_name_item(QMINAS_GET_SIGNAL_STRENGTH_RESP), // 0x0020
|
||||||
|
qmi_name_item(QMINAS_PERFORM_NETWORK_SCAN_REQ), // 0x0021
|
||||||
|
qmi_name_item(QMINAS_PERFORM_NETWORK_SCAN_RESP), // 0x0021
|
||||||
|
qmi_name_item(QMINAS_INITIATE_NW_REGISTER_REQ), // 0x0022
|
||||||
|
qmi_name_item(QMINAS_INITIATE_NW_REGISTER_RESP), // 0x0022
|
||||||
|
qmi_name_item(QMINAS_INITIATE_ATTACH_REQ), // 0x0023
|
||||||
|
qmi_name_item(QMINAS_INITIATE_ATTACH_RESP), // 0x0023
|
||||||
|
qmi_name_item(QMINAS_GET_SERVING_SYSTEM_REQ), // 0x0024
|
||||||
|
qmi_name_item(QMINAS_GET_SERVING_SYSTEM_RESP), // 0x0024
|
||||||
|
qmi_name_item(QMINAS_SERVING_SYSTEM_IND), // 0x0024
|
||||||
|
qmi_name_item(QMINAS_GET_HOME_NETWORK_REQ), // 0x0025
|
||||||
|
qmi_name_item(QMINAS_GET_HOME_NETWORK_RESP), // 0x0025
|
||||||
|
qmi_name_item(QMINAS_GET_PREFERRED_NETWORK_REQ), // 0x0026
|
||||||
|
qmi_name_item(QMINAS_GET_PREFERRED_NETWORK_RESP), // 0x0026
|
||||||
|
qmi_name_item(QMINAS_SET_PREFERRED_NETWORK_REQ), // 0x0027
|
||||||
|
qmi_name_item(QMINAS_SET_PREFERRED_NETWORK_RESP), // 0x0027
|
||||||
|
qmi_name_item(QMINAS_GET_FORBIDDEN_NETWORK_REQ), // 0x0028
|
||||||
|
qmi_name_item(QMINAS_GET_FORBIDDEN_NETWORK_RESP), // 0x0028
|
||||||
|
qmi_name_item(QMINAS_SET_FORBIDDEN_NETWORK_REQ), // 0x0029
|
||||||
|
qmi_name_item(QMINAS_SET_FORBIDDEN_NETWORK_RESP), // 0x0029
|
||||||
|
qmi_name_item(QMINAS_SET_TECHNOLOGY_PREF_REQ), // 0x002A
|
||||||
|
qmi_name_item(QMINAS_SET_TECHNOLOGY_PREF_RESP), // 0x002A
|
||||||
|
qmi_name_item(QMINAS_GET_RF_BAND_INFO_REQ), // 0x0031
|
||||||
|
qmi_name_item(QMINAS_GET_RF_BAND_INFO_RESP), // 0x0031
|
||||||
|
qmi_name_item(QMINAS_GET_CELL_LOCATION_INFO_REQ),
|
||||||
|
qmi_name_item(QMINAS_GET_CELL_LOCATION_INFO_RESP),
|
||||||
|
qmi_name_item(QMINAS_GET_PLMN_NAME_REQ), // 0x0044
|
||||||
|
qmi_name_item(QMINAS_GET_PLMN_NAME_RESP), // 0x0044
|
||||||
|
qmi_name_item(QUECTEL_PACKET_TRANSFER_START_IND), // 0X100
|
||||||
|
qmi_name_item(QUECTEL_PACKET_TRANSFER_END_IND), // 0X101
|
||||||
|
qmi_name_item(QMINAS_GET_SYS_INFO_REQ), // 0x004D
|
||||||
|
qmi_name_item(QMINAS_GET_SYS_INFO_RESP), // 0x004D
|
||||||
|
qmi_name_item(QMINAS_SYS_INFO_IND), // 0x004D
|
||||||
|
qmi_name_item(QMINAS_GET_SIG_INFO_REQ),
|
||||||
|
qmi_name_item(QMINAS_GET_SIG_INFO_RESP),
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
static const QMI_NAME_T qmux_wms_Type[] = {
|
||||||
|
// ======================= WMS ==============================
|
||||||
|
qmi_name_item(QMIWMS_SET_EVENT_REPORT_REQ), // 0x0001
|
||||||
|
qmi_name_item(QMIWMS_SET_EVENT_REPORT_RESP), // 0x0001
|
||||||
|
qmi_name_item(QMIWMS_EVENT_REPORT_IND), // 0x0001
|
||||||
|
qmi_name_item(QMIWMS_RAW_SEND_REQ), // 0x0020
|
||||||
|
qmi_name_item(QMIWMS_RAW_SEND_RESP), // 0x0020
|
||||||
|
qmi_name_item(QMIWMS_RAW_WRITE_REQ), // 0x0021
|
||||||
|
qmi_name_item(QMIWMS_RAW_WRITE_RESP), // 0x0021
|
||||||
|
qmi_name_item(QMIWMS_RAW_READ_REQ), // 0x0022
|
||||||
|
qmi_name_item(QMIWMS_RAW_READ_RESP), // 0x0022
|
||||||
|
qmi_name_item(QMIWMS_MODIFY_TAG_REQ), // 0x0023
|
||||||
|
qmi_name_item(QMIWMS_MODIFY_TAG_RESP), // 0x0023
|
||||||
|
qmi_name_item(QMIWMS_DELETE_REQ), // 0x0024
|
||||||
|
qmi_name_item(QMIWMS_DELETE_RESP), // 0x0024
|
||||||
|
qmi_name_item(QMIWMS_GET_MESSAGE_PROTOCOL_REQ), // 0x0030
|
||||||
|
qmi_name_item(QMIWMS_GET_MESSAGE_PROTOCOL_RESP), // 0x0030
|
||||||
|
qmi_name_item(QMIWMS_LIST_MESSAGES_REQ), // 0x0031
|
||||||
|
qmi_name_item(QMIWMS_LIST_MESSAGES_RESP), // 0x0031
|
||||||
|
qmi_name_item(QMIWMS_GET_SMSC_ADDRESS_REQ), // 0x0034
|
||||||
|
qmi_name_item(QMIWMS_GET_SMSC_ADDRESS_RESP), // 0x0034
|
||||||
|
qmi_name_item(QMIWMS_SET_SMSC_ADDRESS_REQ), // 0x0035
|
||||||
|
qmi_name_item(QMIWMS_SET_SMSC_ADDRESS_RESP), // 0x0035
|
||||||
|
qmi_name_item(QMIWMS_GET_STORE_MAX_SIZE_REQ), // 0x0036
|
||||||
|
qmi_name_item(QMIWMS_GET_STORE_MAX_SIZE_RESP), // 0x0036
|
||||||
|
};
|
||||||
|
|
||||||
|
static const QMI_NAME_T qmux_wds_admin_Type[] = {
|
||||||
|
qmi_name_item(QMIWDS_ADMIN_SET_DATA_FORMAT_REQ), // 0x0020
|
||||||
|
qmi_name_item(QMIWDS_ADMIN_SET_DATA_FORMAT_RESP), // 0x0020
|
||||||
|
qmi_name_item(QMIWDS_ADMIN_GET_DATA_FORMAT_REQ), // 0x0021
|
||||||
|
qmi_name_item(QMIWDS_ADMIN_GET_DATA_FORMAT_RESP), // 0x0021
|
||||||
|
qmi_name_item(QMIWDS_ADMIN_SET_QMAP_SETTINGS_REQ), // 0x002B
|
||||||
|
qmi_name_item(QMIWDS_ADMIN_SET_QMAP_SETTINGS_RESP), // 0x002B
|
||||||
|
qmi_name_item(QMIWDS_ADMIN_GET_QMAP_SETTINGS_REQ), // 0x002C
|
||||||
|
qmi_name_item(QMIWDS_ADMIN_GET_QMAP_SETTINGS_RESP), // 0x002C
|
||||||
|
qmi_name_item(QMI_WDA_SET_LOOPBACK_CONFIG_REQ), // 0x002F
|
||||||
|
qmi_name_item(QMI_WDA_SET_LOOPBACK_CONFIG_RESP), // 0x002F
|
||||||
|
qmi_name_item(QMI_WDA_SET_LOOPBACK_CONFIG_IND), // 0x002F
|
||||||
|
};
|
||||||
|
|
||||||
|
static const QMI_NAME_T qmux_uim_Type[] = {
|
||||||
|
qmi_name_item( QMIUIM_READ_TRANSPARENT_REQ), // 0x0020
|
||||||
|
qmi_name_item( QMIUIM_READ_TRANSPARENT_RESP), // 0x0020
|
||||||
|
qmi_name_item( QMIUIM_READ_TRANSPARENT_IND), // 0x0020
|
||||||
|
qmi_name_item( QMIUIM_READ_RECORD_REQ), // 0x0021
|
||||||
|
qmi_name_item( QMIUIM_READ_RECORD_RESP), // 0x0021
|
||||||
|
qmi_name_item( QMIUIM_READ_RECORD_IND), // 0x0021
|
||||||
|
qmi_name_item( QMIUIM_WRITE_TRANSPARENT_REQ), // 0x0022
|
||||||
|
qmi_name_item( QMIUIM_WRITE_TRANSPARENT_RESP), // 0x0022
|
||||||
|
qmi_name_item( QMIUIM_WRITE_TRANSPARENT_IND), // 0x0022
|
||||||
|
qmi_name_item( QMIUIM_WRITE_RECORD_REQ), // 0x0023
|
||||||
|
qmi_name_item( QMIUIM_WRITE_RECORD_RESP), // 0x0023
|
||||||
|
qmi_name_item( QMIUIM_WRITE_RECORD_IND), // 0x0023
|
||||||
|
qmi_name_item( QMIUIM_SET_PIN_PROTECTION_REQ), // 0x0025
|
||||||
|
qmi_name_item( QMIUIM_SET_PIN_PROTECTION_RESP), // 0x0025
|
||||||
|
qmi_name_item( QMIUIM_SET_PIN_PROTECTION_IND), // 0x0025
|
||||||
|
qmi_name_item( QMIUIM_VERIFY_PIN_REQ), // 0x0026
|
||||||
|
qmi_name_item( QMIUIM_VERIFY_PIN_RESP), // 0x0026
|
||||||
|
qmi_name_item( QMIUIM_VERIFY_PIN_IND), // 0x0026
|
||||||
|
qmi_name_item( QMIUIM_UNBLOCK_PIN_REQ), // 0x0027
|
||||||
|
qmi_name_item( QMIUIM_UNBLOCK_PIN_RESP), // 0x0027
|
||||||
|
qmi_name_item( QMIUIM_UNBLOCK_PIN_IND), // 0x0027
|
||||||
|
qmi_name_item( QMIUIM_CHANGE_PIN_REQ), // 0x0028
|
||||||
|
qmi_name_item( QMIUIM_CHANGE_PIN_RESP), // 0x0028
|
||||||
|
qmi_name_item( QMIUIM_CHANGE_PIN_IND), // 0x0028
|
||||||
|
qmi_name_item( QMIUIM_DEPERSONALIZATION_REQ), // 0x0029
|
||||||
|
qmi_name_item( QMIUIM_DEPERSONALIZATION_RESP), // 0x0029
|
||||||
|
qmi_name_item( QMIUIM_EVENT_REG_REQ), // 0x002E
|
||||||
|
qmi_name_item( QMIUIM_EVENT_REG_RESP), // 0x002E
|
||||||
|
qmi_name_item( QMIUIM_GET_CARD_STATUS_REQ), // 0x002F
|
||||||
|
qmi_name_item( QMIUIM_GET_CARD_STATUS_RESP), // 0x002F
|
||||||
|
qmi_name_item( QMIUIM_STATUS_CHANGE_IND), // 0x0032
|
||||||
|
};
|
||||||
|
|
||||||
|
static const QMI_NAME_T qmux_coex_Type[] = {
|
||||||
|
qmi_name_item(QMI_COEX_GET_WWAN_STATE_REQ), // 0x0022
|
||||||
|
qmi_name_item(QMI_COEX_GET_WWAN_STATE_RESP), // 0x0022
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char * qmi_name_get(const QMI_NAME_T *table, size_t size, int type, const char *tag) {
|
||||||
|
static char unknow[40];
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (qmux_CtlFlags == table) {
|
||||||
|
if (!strcmp(tag, "_REQ"))
|
||||||
|
tag = "_CMD";
|
||||||
|
else if (!strcmp(tag, "_RESP"))
|
||||||
|
tag = "_RSP";
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < size; i++) {
|
||||||
|
if (table[i].type == (UINT)type) {
|
||||||
|
if (!tag || (strstr(table[i].name, tag)))
|
||||||
|
return table[i].name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sprintf(unknow, "unknow_%x", type);
|
||||||
|
return unknow;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define QMI_NAME(table, type) qmi_name_get(table, sizeof(table) / sizeof(table[0]), type, 0)
|
||||||
|
#define QMUX_NAME(table, type, tag) qmi_name_get(table, sizeof(table) / sizeof(table[0]), type, tag)
|
||||||
|
|
||||||
|
void dump_tlv(PQCQMUX_MSG_HDR pQMUXMsgHdr) {
|
||||||
|
int TLVFind = 0;
|
||||||
|
int i;
|
||||||
|
//dbg("QCQMUX_TLV-----------------------------------\n");
|
||||||
|
//dbg("{Type,\tLength,\tValue}\n");
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
PQMI_TLV_HDR TLVHdr = GetTLV(pQMUXMsgHdr, 0x1000 + (++TLVFind));
|
||||||
|
if (TLVHdr == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
//if ((TLVHdr->TLVType == 0x02) && ((USHORT *)(TLVHdr+1))[0])
|
||||||
|
{
|
||||||
|
dbg("{%02x,\t%04x,\t", TLVHdr->TLVType, le16_to_cpu(TLVHdr->TLVLength));
|
||||||
|
for (i = 0; i < le16_to_cpu(TLVHdr->TLVLength); i++) {
|
||||||
|
dbg("%02x ", ((UCHAR *)(TLVHdr+1))[i]);
|
||||||
|
}
|
||||||
|
dbg("}\n");
|
||||||
|
}
|
||||||
|
} // while
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_ctl(PQCQMICTL_MSG_HDR CTLHdr) {
|
||||||
|
const char *tag;
|
||||||
|
|
||||||
|
//dbg("QCQMICTL_MSG--------------------------------------------\n");
|
||||||
|
//dbg("CtlFlags: %02x\t\t%s\n", CTLHdr->CtlFlags, QMI_NAME(qmi_ctl_CtlFlags, CTLHdr->CtlFlags));
|
||||||
|
dbg("TransactionId: %02x\n", CTLHdr->TransactionId);
|
||||||
|
switch (CTLHdr->CtlFlags) {
|
||||||
|
case QMICTL_FLAG_REQUEST: tag = "_REQ"; break;
|
||||||
|
case QMICTL_FLAG_RESPONSE: tag = "_RESP"; break;
|
||||||
|
case QMICTL_FLAG_INDICATION: tag = "_IND"; break;
|
||||||
|
default: tag = 0; break;
|
||||||
|
}
|
||||||
|
dbg("QMICTLType: %04x\t%s\n", le16_to_cpu(CTLHdr->QMICTLType),
|
||||||
|
QMUX_NAME(qmux_ctl_QMICTLType, le16_to_cpu(CTLHdr->QMICTLType), tag));
|
||||||
|
dbg("Length: %04x\n", le16_to_cpu(CTLHdr->Length));
|
||||||
|
|
||||||
|
dump_tlv((PQCQMUX_MSG_HDR)(&CTLHdr->QMICTLType));
|
||||||
|
}
|
||||||
|
|
||||||
|
int dump_qmux(QMI_SERVICE_TYPE serviceType, PQCQMUX_HDR QMUXHdr) {
|
||||||
|
PQCQMUX_MSG_HDR QMUXMsgHdr = (PQCQMUX_MSG_HDR) (QMUXHdr + 1);
|
||||||
|
const char *tag;
|
||||||
|
|
||||||
|
//dbg("QCQMUX--------------------------------------------\n");
|
||||||
|
switch (QMUXHdr->CtlFlags&QMUX_CTL_FLAG_MASK_TYPE) {
|
||||||
|
case QMUX_CTL_FLAG_TYPE_CMD: tag = "_REQ"; break;
|
||||||
|
case QMUX_CTL_FLAG_TYPE_RSP: tag = "_RESP"; break;
|
||||||
|
case QMUX_CTL_FLAG_TYPE_IND: tag = "_IND"; break;
|
||||||
|
default: tag = 0; break;
|
||||||
|
}
|
||||||
|
//dbg("CtlFlags: %02x\t\t%s\n", QMUXHdr->CtlFlags, QMUX_NAME(qmux_CtlFlags, QMUXHdr->CtlFlags, tag));
|
||||||
|
dbg("TransactionId: %04x\n", le16_to_cpu(QMUXHdr->TransactionId));
|
||||||
|
|
||||||
|
//dbg("QCQMUX_MSG_HDR-----------------------------------\n");
|
||||||
|
switch (serviceType) {
|
||||||
|
case QMUX_TYPE_DMS:
|
||||||
|
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type),
|
||||||
|
QMUX_NAME(qmux_dms_Type, le16_to_cpu(QMUXMsgHdr->Type), tag));
|
||||||
|
break;
|
||||||
|
case QMUX_TYPE_NAS:
|
||||||
|
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type),
|
||||||
|
QMUX_NAME(qmux_nas_Type, le16_to_cpu(QMUXMsgHdr->Type), tag));
|
||||||
|
break;
|
||||||
|
case QMUX_TYPE_WDS:
|
||||||
|
case QMUX_TYPE_WDS_IPV6:
|
||||||
|
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type),
|
||||||
|
QMUX_NAME(qmux_wds_Type, le16_to_cpu(QMUXMsgHdr->Type), tag));
|
||||||
|
break;
|
||||||
|
case QMUX_TYPE_WMS:
|
||||||
|
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type),
|
||||||
|
QMUX_NAME(qmux_wms_Type, le16_to_cpu(QMUXMsgHdr->Type), tag));
|
||||||
|
break;
|
||||||
|
case QMUX_TYPE_WDS_ADMIN:
|
||||||
|
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type),
|
||||||
|
QMUX_NAME(qmux_wds_admin_Type, le16_to_cpu(QMUXMsgHdr->Type), tag));
|
||||||
|
break;
|
||||||
|
case QMUX_TYPE_UIM:
|
||||||
|
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type),
|
||||||
|
QMUX_NAME(qmux_uim_Type, le16_to_cpu(QMUXMsgHdr->Type), tag));
|
||||||
|
break;
|
||||||
|
case QMUX_TYPE_PDS:
|
||||||
|
case QMUX_TYPE_QOS:
|
||||||
|
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type),
|
||||||
|
QMUX_NAME(qmux_qos_Type, le16_to_cpu(QMUXMsgHdr->Type), tag));
|
||||||
|
break;
|
||||||
|
case QMUX_TYPE_COEX:
|
||||||
|
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type),
|
||||||
|
QMUX_NAME(qmux_coex_Type, le16_to_cpu(QMUXMsgHdr->Type), tag));
|
||||||
|
break;
|
||||||
|
case QMUX_TYPE_CTL:
|
||||||
|
default:
|
||||||
|
dbg("Type: %04x\t%s\n", le16_to_cpu(QMUXMsgHdr->Type), "PDS/QOS/CTL/unknown!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dbg("Length: %04x\n", le16_to_cpu(QMUXMsgHdr->Length));
|
||||||
|
|
||||||
|
dump_tlv(QMUXMsgHdr);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_qmi(void *dataBuffer, int dataLen)
|
||||||
|
{
|
||||||
|
PQCQMI_HDR QMIHdr = (PQCQMI_HDR)dataBuffer;
|
||||||
|
PQCQMUX_HDR QMUXHdr = (PQCQMUX_HDR) (QMIHdr + 1);
|
||||||
|
PQCQMICTL_MSG_HDR CTLHdr = (PQCQMICTL_MSG_HDR) (QMIHdr + 1);
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!debug_qmi)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&dumpQMIMutex);
|
||||||
|
line[0] = 0;
|
||||||
|
for (i = 0; i < dataLen; i++) {
|
||||||
|
dbg("%02x ", ((unsigned char *)dataBuffer)[i]);
|
||||||
|
}
|
||||||
|
dbg_time("%s", line);
|
||||||
|
line[0] = 0;
|
||||||
|
|
||||||
|
//dbg("QCQMI_HDR-----------------------------------------");
|
||||||
|
//dbg("IFType: %02x\t\t%s", QMIHdr->IFType, QMI_NAME(qmi_IFType, QMIHdr->IFType));
|
||||||
|
//dbg("Length: %04x", le16_to_cpu(QMIHdr->Length));
|
||||||
|
//dbg("CtlFlags: %02x\t\t%s", QMIHdr->CtlFlags, QMI_NAME(qmi_CtlFlags, QMIHdr->CtlFlags));
|
||||||
|
//dbg("QMIType: %02x\t\t%s", QMIHdr->QMIType, QMI_NAME(qmi_QMIType, QMIHdr->QMIType));
|
||||||
|
//dbg("ClientId: %02x", QMIHdr->ClientId);
|
||||||
|
|
||||||
|
if (QMIHdr->QMIType == QMUX_TYPE_CTL) {
|
||||||
|
dump_ctl(CTLHdr);
|
||||||
|
} else {
|
||||||
|
dump_qmux(QMIHdr->QMIType, QMUXHdr);
|
||||||
|
}
|
||||||
|
dbg_time("%s", line);
|
||||||
|
pthread_mutex_unlock(&dumpQMIMutex);
|
||||||
|
}
|
4310
quectel_cm_5G/src/QCQMUX.h
Normal file
4310
quectel_cm_5G/src/QCQMUX.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||||
|
|
||||||
@ -759,6 +766,8 @@ static int requestSetEthMode(PROFILE_T *profile) {
|
|||||||
qmap_settings.rx_urb_size = profile->qmap_size; //SDX24&SDX55 support 32KB
|
qmap_settings.rx_urb_size = profile->qmap_size; //SDX24&SDX55 support 32KB
|
||||||
qmap_settings.ep_type = DATA_EP_TYPE_HSUSB;
|
qmap_settings.ep_type = DATA_EP_TYPE_HSUSB;
|
||||||
qmap_settings.iface_id = 0x04;
|
qmap_settings.iface_id = 0x04;
|
||||||
|
if(profile->usb_dev.idProduct == 0x0316) //X35 Rmnet interface is 3
|
||||||
|
qmap_settings.iface_id = 0x03;
|
||||||
}
|
}
|
||||||
|
|
||||||
qmap_settings.ul_data_aggregation_max_datagrams = 11; //by test result, 11 can get best TPUT
|
qmap_settings.ul_data_aggregation_max_datagrams = 11; //by test result, 11 can get best TPUT
|
||||||
@ -1858,8 +1867,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 +2036,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 +2067,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 +2086,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 +2152,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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,26 @@
|
|||||||
Release Notes
|
Release Notes
|
||||||
|
|
||||||
|
[V1.6.5]
|
||||||
|
Date: 1/22/2024
|
||||||
|
enhancement:
|
||||||
|
1. To support more modems such as EC200G
|
||||||
|
2. To support more modems such as X35 RG255C
|
||||||
|
3. To support big endian MCU work with Unisoc and ASR modems
|
||||||
|
|
||||||
|
[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:
|
||||||
|
@ -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.
|
||||||
---------------------------------------------------------------------------
|
---------------------------------------------------------------------------
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
@ -45,6 +45,18 @@ static int s_pdp;
|
|||||||
#define safe_free(__x) do { if (__x) { free((void *)__x); __x = NULL;}} while(0)
|
#define safe_free(__x) do { if (__x) { free((void *)__x); __x = NULL;}} while(0)
|
||||||
#define safe_at_response_free(__x) { if (__x) { at_response_free(__x); __x = NULL;}}
|
#define safe_at_response_free(__x) { if (__x) { at_response_free(__x); __x = NULL;}}
|
||||||
|
|
||||||
|
int check_mcu_endian()
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
int a;
|
||||||
|
char b;
|
||||||
|
}u;
|
||||||
|
|
||||||
|
u.a = 1;
|
||||||
|
return u.b;
|
||||||
|
}
|
||||||
|
|
||||||
#define at_response_error(err, p_response) \
|
#define at_response_error(err, p_response) \
|
||||||
(err \
|
(err \
|
||||||
|| p_response == NULL \
|
|| p_response == NULL \
|
||||||
@ -503,6 +515,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
|
||||||
@ -699,7 +712,11 @@ static int at_netdevstatus(int pdp, unsigned int *pV4Addr) {
|
|||||||
else {
|
else {
|
||||||
sscanf(ipv4_address, "%02X%02X%02X%02X", &addr[3], &addr[2], &addr[1], &addr[0]);
|
sscanf(ipv4_address, "%02X%02X%02X%02X", &addr[3], &addr[2], &addr[1], &addr[0]);
|
||||||
}
|
}
|
||||||
|
if(check_mcu_endian()){
|
||||||
*pV4Addr = (addr[0]) | (addr[1]<<8) | (addr[2]<<16) | (addr[3]<<24);
|
*pV4Addr = (addr[0]) | (addr[1]<<8) | (addr[2]<<16) | (addr[3]<<24);
|
||||||
|
}else{
|
||||||
|
*pV4Addr = (addr[0])<<24 | (addr[1]<<16) | (addr[2]<<8) | (addr[3]<<0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -825,7 +842,11 @@ static int requestGetIPAddress(PROFILE_T *profile, int curIpFamily) {
|
|||||||
int addr[4] = {0, 0, 0, 0};
|
int addr[4] = {0, 0, 0, 0};
|
||||||
|
|
||||||
sscanf(ipv4, "%d.%d.%d.%d", &addr[0], &addr[1], &addr[2], &addr[3]);
|
sscanf(ipv4, "%d.%d.%d.%d", &addr[0], &addr[1], &addr[2], &addr[3]);
|
||||||
|
if(check_mcu_endian()){
|
||||||
v4Addr = (addr[0]) | (addr[1]<<8) | (addr[2]<<16) | (addr[3]<<24);
|
v4Addr = (addr[0]) | (addr[1]<<8) | (addr[2]<<16) | (addr[3]<<24);
|
||||||
|
}else{
|
||||||
|
v4Addr = (addr[0])<< 24 | (addr[1]<<16) | (addr[2]<<8) | (addr[3]);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
---------------------------------------------------------------------------
|
---------------------------------------------------------------------------
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
@ -43,10 +43,10 @@
|
|||||||
#define CM_MAX_PATHLEN 256
|
#define CM_MAX_PATHLEN 256
|
||||||
|
|
||||||
#define CM_INVALID_VAL (~((int)0))
|
#define CM_INVALID_VAL (~((int)0))
|
||||||
|
|
||||||
/* get first line from file 'fname'
|
/* get first line from file 'fname'
|
||||||
* And convert the content into a hex number, then return this number */
|
* And convert the content into a hex number, then return this number */
|
||||||
static int file_get_value(const char *fname, int base) {
|
static int file_get_value(const char *fname, int base)
|
||||||
|
{
|
||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
long num;
|
long num;
|
||||||
char buff[32 + 1] = {'\0'};
|
char buff[32 + 1] = {'\0'};
|
||||||
@ -58,7 +58,7 @@ static int file_get_value(const char *fname, int base) {
|
|||||||
goto error;
|
goto error;
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
num = (int) strtol(buff, &endptr, base);
|
num = (int)strtol(buff, &endptr, base);
|
||||||
if (errno == ERANGE && (num == LONG_MAX || num == LONG_MIN))
|
if (errno == ERANGE && (num == LONG_MAX || num == LONG_MIN))
|
||||||
goto error;
|
goto error;
|
||||||
/* if there is no digit in buff */
|
/* if there is no digit in buff */
|
||||||
@ -67,9 +67,9 @@ static int file_get_value(const char *fname, int base) {
|
|||||||
|
|
||||||
if (debug_qmi)
|
if (debug_qmi)
|
||||||
dbg_time("(%s) = %lx", fname, num);
|
dbg_time("(%s) = %lx", fname, num);
|
||||||
return (int) num;
|
return (int)num;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
if (fp) fclose(fp);
|
if (fp) fclose(fp);
|
||||||
return CM_INVALID_VAL;
|
return CM_INVALID_VAL;
|
||||||
}
|
}
|
||||||
@ -78,7 +78,8 @@ static int file_get_value(const char *fname, int base) {
|
|||||||
* This function will search the directory 'dirname' and return the first child.
|
* This function will search the directory 'dirname' and return the first child.
|
||||||
* '.' and '..' is ignored by default
|
* '.' and '..' is ignored by default
|
||||||
*/
|
*/
|
||||||
static int dir_get_child(const char *dirname, char *buff, unsigned bufsize, const char *prefix) {
|
static int dir_get_child(const char *dirname, char *buff, unsigned bufsize, const char *prefix)
|
||||||
|
{
|
||||||
struct dirent *entptr = NULL;
|
struct dirent *entptr = NULL;
|
||||||
DIR *dirptr;
|
DIR *dirptr;
|
||||||
|
|
||||||
@ -101,13 +102,14 @@ static int dir_get_child(const char *dirname, char *buff, unsigned bufsize, cons
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int conf_get_val(const char *fname, const char *key) {
|
static int conf_get_val(const char *fname, const char *key)
|
||||||
|
{
|
||||||
char buff[128] = {'\0'};
|
char buff[128] = {'\0'};
|
||||||
FILE *fp = fopen(fname, "r");
|
FILE *fp = fopen(fname, "r");
|
||||||
if (!fp)
|
if (!fp)
|
||||||
return CM_INVALID_VAL;
|
return CM_INVALID_VAL;
|
||||||
|
|
||||||
while (fgets(buff, sizeof(buff) - 1, fp)) {
|
while (fgets(buff, sizeof(buff)-1, fp)) {
|
||||||
char prefix[128] = {'\0'};
|
char prefix[128] = {'\0'};
|
||||||
char tail[128] = {'\0'};
|
char tail[128] = {'\0'};
|
||||||
/* To eliminate cppcheck warnning: Assume string length is no more than 15 */
|
/* To eliminate cppcheck warnning: Assume string length is no more than 15 */
|
||||||
@ -188,13 +190,14 @@ static void query_usb_interface_info(char *path, struct usb_interface_info *p) {
|
|||||||
break;
|
break;
|
||||||
n--;
|
n--;
|
||||||
}
|
}
|
||||||
strncpy(p->driver, &driver[n + 1], sizeof(p->driver) - 1);
|
strncpy(p->driver, &driver[n+1], sizeof(p->driver) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
path[offset] = '\0';
|
path[offset] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
static int detect_path_cdc_wdm_or_qcqmi(char *path, char *devname, size_t bufsize) {
|
static int detect_path_cdc_wdm_or_qcqmi(char *path, char *devname, size_t bufsize)
|
||||||
|
{
|
||||||
size_t offset = strlen(path);
|
size_t offset = strlen(path);
|
||||||
char tmp[32];
|
char tmp[32];
|
||||||
|
|
||||||
@ -220,7 +223,7 @@ static int detect_path_cdc_wdm_or_qcqmi(char *path, char *devname, size_t bufsiz
|
|||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
step_1:
|
step_1:
|
||||||
/* get device(qcqmiX|cdc-wdmX) */
|
/* get device(qcqmiX|cdc-wdmX) */
|
||||||
if (debug_qmi) dbg_time("%s", path);
|
if (debug_qmi) dbg_time("%s", path);
|
||||||
dir_get_child(path, tmp, sizeof(tmp), NULL);
|
dir_get_child(path, tmp, sizeof(tmp), NULL);
|
||||||
@ -229,7 +232,8 @@ static int detect_path_cdc_wdm_or_qcqmi(char *path, char *devname, size_t bufsiz
|
|||||||
|
|
||||||
/* There is a chance that, no device(qcqmiX|cdc-wdmX) is generated. We should warn user about that! */
|
/* There is a chance that, no device(qcqmiX|cdc-wdmX) is generated. We should warn user about that! */
|
||||||
snprintf(devname, bufsize, "/dev/%s", tmp);
|
snprintf(devname, bufsize, "/dev/%s", tmp);
|
||||||
if (access(devname, R_OK | F_OK) && errno == ENOENT) {
|
if (access(devname, R_OK | F_OK) && errno == ENOENT)
|
||||||
|
{
|
||||||
int major, minor;
|
int major, minor;
|
||||||
|
|
||||||
dbg_time("access %s failed, errno: %d (%s)", devname, errno, strerror(errno));
|
dbg_time("access %s failed, errno: %d (%s)", devname, errno, strerror(errno));
|
||||||
@ -239,9 +243,9 @@ static int detect_path_cdc_wdm_or_qcqmi(char *path, char *devname, size_t bufsiz
|
|||||||
major = conf_get_val(path, "MAJOR");
|
major = conf_get_val(path, "MAJOR");
|
||||||
minor = conf_get_val(path, "MINOR");
|
minor = conf_get_val(path, "MINOR");
|
||||||
|
|
||||||
if (major == CM_INVALID_VAL || minor == CM_INVALID_VAL)
|
if(major == CM_INVALID_VAL || minor == CM_INVALID_VAL)
|
||||||
dbg_time("get major and minor failed");
|
dbg_time("get major and minor failed");
|
||||||
else if (mknod(devname, S_IFCHR | 0666, (((major & 0xfff) << 8) | (minor & 0xff) | ((minor & 0xfff00) << 12))))
|
else if (mknod(devname, S_IFCHR|0666, (((major & 0xfff) << 8) | (minor & 0xff) | ((minor & 0xfff00) << 12))))
|
||||||
dbg_time("please mknod %s c %d %d", devname, major, minor);
|
dbg_time("please mknod %s c %d %d", devname, major, minor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,11 +258,11 @@ static int detect_path_cdc_wdm_or_qcqmi(char *path, char *devname, size_t bufsiz
|
|||||||
* TRUE -> ok
|
* TRUE -> ok
|
||||||
*/
|
*/
|
||||||
BOOL qmidevice_detect(char *qmichannel, char *usbnet_adapter, unsigned bufsize, PROFILE_T *profile) {
|
BOOL qmidevice_detect(char *qmichannel, char *usbnet_adapter, unsigned bufsize, PROFILE_T *profile) {
|
||||||
struct dirent *ent = NULL;
|
struct dirent* ent = NULL;
|
||||||
DIR *pDir;
|
DIR *pDir;
|
||||||
const char *rootdir = "/sys/bus/usb/devices";
|
const char *rootdir = "/sys/bus/usb/devices";
|
||||||
struct {
|
struct {
|
||||||
char path[255 * 2];
|
char path[255*2];
|
||||||
} *pl;
|
} *pl;
|
||||||
pl = (typeof(pl)) malloc(sizeof(*pl));
|
pl = (typeof(pl)) malloc(sizeof(*pl));
|
||||||
memset(pl, 0x00, sizeof(*pl));
|
memset(pl, 0x00, sizeof(*pl));
|
||||||
@ -270,8 +274,8 @@ BOOL qmidevice_detect(char *qmichannel, char *usbnet_adapter, unsigned bufsize,
|
|||||||
}
|
}
|
||||||
|
|
||||||
while ((ent = readdir(pDir)) != NULL) {
|
while ((ent = readdir(pDir)) != NULL) {
|
||||||
char netcard[32 + 1] = {'\0'};
|
char netcard[32+1] = {'\0'};
|
||||||
char devname[32 + 5] = {'\0'}; //+strlen("/dev/")
|
char devname[32+5] = {'\0'}; //+strlen("/dev/")
|
||||||
int netIntf;
|
int netIntf;
|
||||||
int driver_type;
|
int driver_type;
|
||||||
|
|
||||||
@ -301,7 +305,7 @@ BOOL qmidevice_detect(char *qmichannel, char *usbnet_adapter, unsigned bufsize,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (netcard[0] == '\0') { //for centos 2.6.x
|
if (netcard[0] == '\0') { //for centos 2.6.x
|
||||||
const char *n = "usb0";
|
const char *n= "usb0";
|
||||||
const char *c = "qcqmi0";
|
const char *c = "qcqmi0";
|
||||||
|
|
||||||
snprintf(pl->path, sizeof(pl->path), "%s/%s:1.4/net:%s", rootdir, ent->d_name, n);
|
snprintf(pl->path, sizeof(pl->path), "%s/%s:1.4/net:%s", rootdir, ent->d_name, n);
|
||||||
@ -330,12 +334,15 @@ BOOL qmidevice_detect(char *qmichannel, char *usbnet_adapter, unsigned bufsize,
|
|||||||
|
|
||||||
if (driver_type == SOFTWARE_QMI || driver_type == SOFTWARE_MBIM) {
|
if (driver_type == SOFTWARE_QMI || driver_type == SOFTWARE_MBIM) {
|
||||||
detect_path_cdc_wdm_or_qcqmi(pl->path, devname, sizeof(devname));
|
detect_path_cdc_wdm_or_qcqmi(pl->path, devname, sizeof(devname));
|
||||||
} else if (driver_type == SOFTWARE_ECM_RNDIS_NCM) {
|
}
|
||||||
|
else if (driver_type == SOFTWARE_ECM_RNDIS_NCM)
|
||||||
|
{
|
||||||
int atIntf = -1;
|
int atIntf = -1;
|
||||||
|
|
||||||
if (profile->usb_dev.idVendor == 0x2c7c) { //Quectel
|
if (profile->usb_dev.idVendor == 0x2c7c) { //Quectel
|
||||||
switch (profile->usb_dev.idProduct) { //EC200U
|
switch (profile->usb_dev.idProduct) { //EC200U
|
||||||
case 0x0901: //EC200U
|
case 0x0901: //EC200U
|
||||||
|
case 0x0904: //EC200G
|
||||||
case 0x8101: //RG801H
|
case 0x8101: //RG801H
|
||||||
atIntf = 2;
|
atIntf = 2;
|
||||||
break;
|
break;
|
||||||
@ -346,6 +353,7 @@ BOOL qmidevice_detect(char *qmichannel, char *usbnet_adapter, unsigned bufsize,
|
|||||||
case 0x6005: //EC200A
|
case 0x6005: //EC200A
|
||||||
case 0x6002: //EC200S
|
case 0x6002: //EC200S
|
||||||
case 0x6001: //EC100Y
|
case 0x6001: //EC100Y
|
||||||
|
case 0x6007: //EG915Q-NA in ECM mode, it also could set atIntf to 4
|
||||||
atIntf = 3;
|
atIntf = 3;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -383,74 +391,49 @@ BOOL qmidevice_detect(char *qmichannel, char *usbnet_adapter, unsigned bufsize,
|
|||||||
}
|
}
|
||||||
free(pl);
|
free(pl);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
error:
|
error:
|
||||||
free(pl);
|
free(pl);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int isContain(const char *str1, const char *str2) {
|
|
||||||
if (strstr(str1, str2) != NULL) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void replaceStr(char *str, char *orig, char *rep) {
|
|
||||||
char buffer[1024];
|
|
||||||
char *p;
|
|
||||||
while (p = strstr(str, orig)) {
|
|
||||||
memcpy(buffer, str, p - str);
|
|
||||||
buffer[p - str] = '\0';
|
|
||||||
sprintf(buffer + strlen(buffer), "%s%s", rep, p + strlen(orig));
|
|
||||||
strcpy(str, buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int mhidevice_detect(char *qmichannel, char *usbnet_adapter, PROFILE_T *profile) {
|
int mhidevice_detect(char *qmichannel, char *usbnet_adapter, PROFILE_T *profile) {
|
||||||
struct dirent *ent = NULL;
|
struct dirent* ent = NULL;
|
||||||
DIR *pDir;
|
DIR *pDir;
|
||||||
const char *rootdir_mhi[] = {"/sys/bus/mhi_q/devices", "/sys/bus/mhi/devices", NULL};
|
const char *rootdir_mhi[] = {"/sys/bus/mhi_q/devices", "/sys/bus/mhi/devices", NULL};
|
||||||
int i = 0;
|
int i = 0;
|
||||||
char path[256];
|
char path[256];
|
||||||
int find = 0;
|
int find = 0;
|
||||||
|
|
||||||
while (rootdir_mhi[i]) {
|
while (rootdir_mhi[i]) {
|
||||||
const char *rootdir = rootdir_mhi[i++];
|
const char *rootdir = rootdir_mhi[i++];
|
||||||
dbg_time("rootdir : %s ", rootdir);
|
|
||||||
pDir = opendir(rootdir);
|
pDir = opendir(rootdir);
|
||||||
if (!pDir) {
|
if (!pDir) {
|
||||||
if (errno != ENOENT) {
|
if (errno != ENOENT)
|
||||||
dbg_time("opendir %s failed: %s", rootdir, strerror(errno));
|
dbg_time("opendir %s failed: %s", rootdir, strerror(errno));
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((ent = readdir(pDir)) != NULL) {
|
while ((ent = readdir(pDir)) != NULL) {
|
||||||
char netcard[32] = {'\0'};
|
char netcard[32] = {'\0'};
|
||||||
char devname[32] = {'\0'};
|
char devname[32] = {'\0'};
|
||||||
int software_interface = SOFTWARE_QMI;
|
int software_interface = SOFTWARE_QMI;
|
||||||
char *pNode = NULL;
|
char *pNode = NULL;
|
||||||
pNode = strstr(ent->d_name, "_IP_HW0"); //0306_00.01.00_IP_HW0
|
|
||||||
if (!pNode) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *d_name[32];
|
pNode = strstr(ent->d_name, "_IP_HW0"); //0306_00.01.00_IP_HW0
|
||||||
strcpy(d_name, ent->d_name);
|
if (!pNode)
|
||||||
replaceStr(d_name, "_IP_HW0", "");
|
continue;
|
||||||
dbg_time("while -> pcie_name = : %s ", d_name);
|
|
||||||
|
|
||||||
snprintf(path, sizeof(path), "%s/%.32s/net", rootdir, ent->d_name);
|
snprintf(path, sizeof(path), "%s/%.32s/net", rootdir, ent->d_name);
|
||||||
dir_get_child(path, netcard, sizeof(netcard), NULL);
|
dir_get_child(path, netcard, sizeof(netcard), NULL);
|
||||||
if (!netcard[0]) {
|
if (!netcard[0])
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
if (usbnet_adapter[0] && strcmp(netcard, usbnet_adapter)) { //not '-i x
|
if (usbnet_adapter[0] && strcmp(netcard, usbnet_adapter)) //not '-i x'
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
if (!strcmp(rootdir, "/sys/bus/mhi/devices")) {
|
if (!strcmp(rootdir, "/sys/bus/mhi/devices")) {
|
||||||
// snprintf(path, sizeof(path), "%s/%.13s_IPCR", rootdir, ent->d_name); // 13 is sizeof(0306_00.01.00)
|
snprintf(path, sizeof(path), "%s/%.13s_IPCR", rootdir, ent->d_name); // 13 is sizeof(0306_00.01.00)
|
||||||
snprintf(path, sizeof(path), "%s/%s_IPCR", rootdir, d_name);
|
|
||||||
if (!access(path, F_OK)) {
|
if (!access(path, F_OK)) {
|
||||||
/* we also need 'cat /dev/mhi_0306_00.01.00_pipe_14' to enable rmnet as like USB's DTR
|
/* we also need 'cat /dev/mhi_0306_00.01.00_pipe_14' to enable rmnet as like USB's DTR
|
||||||
or will get error 'requestSetEthMode QMUXResult = 0x1, QMUXError = 0x46' */
|
or will get error 'requestSetEthMode QMUXResult = 0x1, QMUXError = 0x46' */
|
||||||
@ -463,51 +446,33 @@ int mhidevice_detect(char *qmichannel, char *usbnet_adapter, PROFILE_T *profile)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//解决PCIE硬编码导致不兼容hv问题
|
snprintf(path, sizeof(path), "%s/%.13s_IPCR", rootdir, ent->d_name);
|
||||||
snprintf(path, sizeof(path), "%s/%s_IPCR", rootdir, d_name);
|
|
||||||
if (access(path, F_OK)) {
|
if (access(path, F_OK)) {
|
||||||
snprintf(path, sizeof(path), "%s/%s_QMI0", rootdir, d_name);
|
snprintf(path, sizeof(path), "%s/%.13s_QMI0", rootdir, ent->d_name);
|
||||||
if (access(path, F_OK)) {
|
if (access(path, F_OK)) {
|
||||||
snprintf(path, sizeof(path), "%s/%s_MBIM", rootdir, d_name);
|
snprintf(path, sizeof(path), "%s/%.13s_MBIM", rootdir, ent->d_name);
|
||||||
if (!access(path, F_OK)) {
|
if (!access(path, F_OK))
|
||||||
software_interface = SOFTWARE_MBIM;
|
software_interface = SOFTWARE_MBIM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if (access(path, F_OK))
|
||||||
|
|
||||||
//原
|
|
||||||
// snprintf(path, sizeof(path), "%s/%.14s_IPCR", rootdir, ent->d_name);
|
|
||||||
// dbg_time("while -> path3 : %s ", path);
|
|
||||||
// if (access(path, F_OK)) {
|
|
||||||
// snprintf(path, sizeof(path), "%s/%.14s_QMI0", rootdir, ent->d_name);
|
|
||||||
// dbg_time("while -> path4 : %s ", path);
|
|
||||||
// if (access(path, F_OK)) {
|
|
||||||
// snprintf(path, sizeof(path), "%s/%.14s_MBIM", rootdir, ent->d_name);
|
|
||||||
// dbg_time("while -> path5 : %s ", path);
|
|
||||||
// if (!access(path, F_OK)) {
|
|
||||||
// software_interface = SOFTWARE_MBIM;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
dbg_time("while -> path_final : %s ", path);
|
|
||||||
if (access(path, F_OK)) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
strncat(path, "/mhi_uci_q", sizeof(path) - 1);
|
strncat(path, "/mhi_uci_q", sizeof(path)-1);
|
||||||
dir_get_child(path, devname, sizeof(devname), NULL);
|
dir_get_child(path, devname, sizeof(devname), NULL);
|
||||||
if (!devname[0]) {
|
if (!devname[0])
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
dbg_time("while -> path_final_sub : %s ,dev_name: %s ", path, devname);
|
|
||||||
sprintf(usbnet_adapter, "%s", netcard);
|
sprintf(usbnet_adapter, "%s", netcard);
|
||||||
sprintf(qmichannel, "/dev/%s", devname);
|
sprintf(qmichannel, "/dev/%s", devname);
|
||||||
profile->software_interface = software_interface;
|
profile->software_interface = software_interface;
|
||||||
find = 1;
|
find = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
closedir(pDir);
|
closedir(pDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
return find;
|
return find;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -515,7 +480,8 @@ int atdevice_detect(char *atchannel, char *usbnet_adapter, PROFILE_T *profile) {
|
|||||||
if (!access("/sys/class/net/sipa_dummy0", F_OK)) {
|
if (!access("/sys/class/net/sipa_dummy0", F_OK)) {
|
||||||
strcpy(usbnet_adapter, "sipa_dummy0");
|
strcpy(usbnet_adapter, "sipa_dummy0");
|
||||||
snprintf(profile->qmapnet_adapter, sizeof(profile->qmapnet_adapter), "%s%d", "pcie", profile->pdp - 1);
|
snprintf(profile->qmapnet_adapter, sizeof(profile->qmapnet_adapter), "%s%d", "pcie", profile->pdp - 1);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
dbg_time("atdevice_detect failed");
|
dbg_time("atdevice_detect failed");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@ -523,21 +489,24 @@ int atdevice_detect(char *atchannel, char *usbnet_adapter, PROFILE_T *profile) {
|
|||||||
if (!access("/dev/stty_nr31", F_OK)) {
|
if (!access("/dev/stty_nr31", F_OK)) {
|
||||||
strcpy(atchannel, "/dev/stty_nr31");
|
strcpy(atchannel, "/dev/stty_nr31");
|
||||||
profile->software_interface = SOFTWARE_ECM_RNDIS_NCM;
|
profile->software_interface = SOFTWARE_ECM_RNDIS_NCM;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
error:
|
error:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int get_driver_type(PROFILE_T *profile) {
|
int get_driver_type(PROFILE_T *profile)
|
||||||
|
{
|
||||||
/* QMI_WWAN */
|
/* QMI_WWAN */
|
||||||
if (profile->usb_intf.bInterfaceClass == USB_CLASS_VENDOR_SPEC) {
|
if (profile->usb_intf.bInterfaceClass == USB_CLASS_VENDOR_SPEC) {
|
||||||
return SOFTWARE_QMI;
|
return SOFTWARE_QMI;
|
||||||
} else if (profile->usb_intf.bInterfaceClass == USB_CLASS_COMM) {
|
}
|
||||||
|
else if (profile->usb_intf.bInterfaceClass == USB_CLASS_COMM) {
|
||||||
switch (profile->usb_intf.bInterfaceSubClass) {
|
switch (profile->usb_intf.bInterfaceSubClass) {
|
||||||
case USB_CDC_SUBCLASS_MBIM:
|
case USB_CDC_SUBCLASS_MBIM:
|
||||||
return SOFTWARE_MBIM;
|
return SOFTWARE_MBIM;
|
||||||
@ -549,7 +518,8 @@ int get_driver_type(PROFILE_T *profile) {
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (profile->usb_intf.bInterfaceClass == USB_CLASS_WIRELESS_CONTROLLER) {
|
}
|
||||||
|
else if (profile->usb_intf.bInterfaceClass == USB_CLASS_WIRELESS_CONTROLLER) {
|
||||||
if (profile->usb_intf.bInterfaceSubClass == 1 && profile->usb_intf.bInterfaceProtocol == 3)
|
if (profile->usb_intf.bInterfaceSubClass == 1 && profile->usb_intf.bInterfaceProtocol == 3)
|
||||||
return SOFTWARE_ECM_RNDIS_NCM;
|
return SOFTWARE_ECM_RNDIS_NCM;
|
||||||
}
|
}
|
||||||
@ -559,12 +529,14 @@ int get_driver_type(PROFILE_T *profile) {
|
|||||||
return DRV_INVALID;
|
return DRV_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct usbfs_getdriver {
|
struct usbfs_getdriver
|
||||||
|
{
|
||||||
unsigned int interface;
|
unsigned int interface;
|
||||||
char driver[255 + 1];
|
char driver[255 + 1];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct usbfs_ioctl {
|
struct usbfs_ioctl
|
||||||
|
{
|
||||||
int ifno; /* interface 0..N ; negative numbers reserved */
|
int ifno; /* interface 0..N ; negative numbers reserved */
|
||||||
int ioctl_code; /* MUST encode size + direction of data so the
|
int ioctl_code; /* MUST encode size + direction of data so the
|
||||||
* macros in <asm/ioctl.h> give correct values */
|
* macros in <asm/ioctl.h> give correct values */
|
||||||
@ -574,7 +546,8 @@ struct usbfs_ioctl {
|
|||||||
#define IOCTL_USBFS_DISCONNECT _IO('U', 22)
|
#define IOCTL_USBFS_DISCONNECT _IO('U', 22)
|
||||||
#define IOCTL_USBFS_CONNECT _IO('U', 23)
|
#define IOCTL_USBFS_CONNECT _IO('U', 23)
|
||||||
|
|
||||||
int usbfs_is_kernel_driver_alive(int fd, int ifnum) {
|
int usbfs_is_kernel_driver_alive(int fd, int ifnum)
|
||||||
|
{
|
||||||
struct usbfs_getdriver getdrv;
|
struct usbfs_getdriver getdrv;
|
||||||
getdrv.interface = ifnum;
|
getdrv.interface = ifnum;
|
||||||
if (ioctl(fd, USBDEVFS_GETDRIVER, &getdrv) < 0) {
|
if (ioctl(fd, USBDEVFS_GETDRIVER, &getdrv) < 0) {
|
||||||
@ -585,7 +558,8 @@ int usbfs_is_kernel_driver_alive(int fd, int ifnum) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbfs_detach_kernel_driver(int fd, int ifnum) {
|
void usbfs_detach_kernel_driver(int fd, int ifnum)
|
||||||
|
{
|
||||||
struct usbfs_ioctl operate;
|
struct usbfs_ioctl operate;
|
||||||
operate.data = NULL;
|
operate.data = NULL;
|
||||||
operate.ifno = ifnum;
|
operate.ifno = ifnum;
|
||||||
@ -597,7 +571,8 @@ void usbfs_detach_kernel_driver(int fd, int ifnum) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbfs_attach_kernel_driver(int fd, int ifnum) {
|
void usbfs_attach_kernel_driver(int fd, int ifnum)
|
||||||
|
{
|
||||||
struct usbfs_ioctl operate;
|
struct usbfs_ioctl operate;
|
||||||
operate.data = NULL;
|
operate.data = NULL;
|
||||||
operate.ifno = ifnum;
|
operate.ifno = ifnum;
|
||||||
@ -609,13 +584,15 @@ void usbfs_attach_kernel_driver(int fd, int ifnum) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int reattach_driver(PROFILE_T *profile) {
|
int reattach_driver(PROFILE_T *profile)
|
||||||
|
{
|
||||||
int ifnum = 4;
|
int ifnum = 4;
|
||||||
int fd;
|
int fd;
|
||||||
char devpath[128] = {'\0'};
|
char devpath[128] = {'\0'};
|
||||||
snprintf(devpath, sizeof(devpath), "/dev/bus/usb/%03d/%03d", profile->usb_dev.busnum, profile->usb_dev.devnum);
|
snprintf(devpath, sizeof(devpath), "/dev/bus/usb/%03d/%03d", profile->usb_dev.busnum, profile->usb_dev.devnum);
|
||||||
fd = open(devpath, O_RDWR | O_NOCTTY);
|
fd = open(devpath, O_RDWR | O_NOCTTY);
|
||||||
if (fd < 0) {
|
if (fd < 0)
|
||||||
|
{
|
||||||
dbg_time("%s fail to open %s", __func__, devpath);
|
dbg_time("%s fail to open %s", __func__, devpath);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -626,8 +603,8 @@ int reattach_driver(PROFILE_T *profile) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define SIOCETHTOOL 0x8946
|
#define SIOCETHTOOL 0x8946
|
||||||
|
int ql_get_netcard_driver_info(const char *devname)
|
||||||
int ql_get_netcard_driver_info(const char *devname) {
|
{
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
struct ethtool_drvinfo drvinfo;
|
struct ethtool_drvinfo drvinfo;
|
||||||
struct ifreq ifr; /* ifreq suitable for ethtool ioctl */
|
struct ifreq ifr; /* ifreq suitable for ethtool ioctl */
|
||||||
@ -642,7 +619,7 @@ int ql_get_netcard_driver_info(const char *devname) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
drvinfo.cmd = ETHTOOL_GDRVINFO;
|
drvinfo.cmd = ETHTOOL_GDRVINFO;
|
||||||
ifr.ifr_data = (void *) &drvinfo;
|
ifr.ifr_data = (void *)&drvinfo;
|
||||||
|
|
||||||
if (ioctl(fd, SIOCETHTOOL, &ifr) < 0) {
|
if (ioctl(fd, SIOCETHTOOL, &ifr) < 0) {
|
||||||
dbg_time("ioctl() error: errno(%d)(%s)", errno, strerror(errno));
|
dbg_time("ioctl() error: errno(%d)(%s)", errno, strerror(errno));
|
||||||
@ -657,7 +634,8 @@ int ql_get_netcard_driver_info(const char *devname) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ql_get_netcard_carrier_state(const char *devname) {
|
int ql_get_netcard_carrier_state(const char *devname)
|
||||||
|
{
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
struct ethtool_value edata;
|
struct ethtool_value edata;
|
||||||
struct ifreq ifr; /* ifreq suitable for ethtool ioctl */
|
struct ifreq ifr; /* ifreq suitable for ethtool ioctl */
|
||||||
@ -673,7 +651,7 @@ int ql_get_netcard_carrier_state(const char *devname) {
|
|||||||
|
|
||||||
edata.cmd = ETHTOOL_GLINK;
|
edata.cmd = ETHTOOL_GLINK;
|
||||||
edata.data = 0;
|
edata.data = 0;
|
||||||
ifr.ifr_data = (void *) &edata;
|
ifr.ifr_data = (void *)&edata;
|
||||||
|
|
||||||
if (ioctl(fd, SIOCETHTOOL, &ifr) < 0) {
|
if (ioctl(fd, SIOCETHTOOL, &ifr) < 0) {
|
||||||
dbg_time("ioctl('%s') error: errno(%d)(%s)", devname, errno, strerror(errno));
|
dbg_time("ioctl('%s') error: errno(%d)(%s)", devname, errno, strerror(errno));
|
||||||
@ -688,16 +666,17 @@ int ql_get_netcard_carrier_state(const char *devname) {
|
|||||||
return edata.data;
|
return edata.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *catch_log(void *arg) {
|
static void *catch_log(void *arg)
|
||||||
PROFILE_T *profile = (PROFILE_T *) arg;
|
{
|
||||||
|
PROFILE_T *profile = (PROFILE_T *)arg;
|
||||||
int nreads = 0;
|
int nreads = 0;
|
||||||
char tbuff[256 + 32];
|
char tbuff[256+32];
|
||||||
char filter[32];
|
char filter[32];
|
||||||
size_t tsize = strlen(get_time()) + 1;
|
size_t tsize = strlen(get_time()) + 1;
|
||||||
|
|
||||||
snprintf(filter, sizeof(filter), ":%d:%03d:", profile->usb_dev.busnum, profile->usb_dev.devnum);
|
snprintf(filter, sizeof(filter), ":%d:%03d:", profile->usb_dev.busnum, profile->usb_dev.devnum);
|
||||||
|
|
||||||
while (1) {
|
while(1) {
|
||||||
nreads = read(profile->usbmon_fd, tbuff + tsize, sizeof(tbuff) - tsize - 1);
|
nreads = read(profile->usbmon_fd, tbuff + tsize, sizeof(tbuff) - tsize - 1);
|
||||||
if (nreads <= 0) {
|
if (nreads <= 0) {
|
||||||
if (nreads == -1 && errno == EINTR)
|
if (nreads == -1 && errno == EINTR)
|
||||||
@ -705,13 +684,13 @@ static void *catch_log(void *arg) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
tbuff[tsize + nreads] = '\0'; // printf("%s", buff);
|
tbuff[tsize+nreads] = '\0'; // printf("%s", buff);
|
||||||
|
|
||||||
if (!strstr(tbuff + tsize, filter))
|
if (!strstr(tbuff+tsize, filter))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
snprintf(tbuff, sizeof(tbuff), "%s", get_time());
|
snprintf(tbuff, sizeof(tbuff), "%s", get_time());
|
||||||
tbuff[tsize - 1] = ' ';
|
tbuff[tsize-1] = ' ';
|
||||||
|
|
||||||
fwrite(tbuff, strlen(tbuff), 1, profile->usbmon_logfile_fp);
|
fwrite(tbuff, strlen(tbuff), 1, profile->usbmon_logfile_fp);
|
||||||
}
|
}
|
||||||
@ -719,7 +698,8 @@ static void *catch_log(void *arg) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ql_capture_usbmon_log(PROFILE_T *profile, const char *log_path) {
|
int ql_capture_usbmon_log(PROFILE_T *profile, const char *log_path)
|
||||||
|
{
|
||||||
char usbmon_path[256];
|
char usbmon_path[256];
|
||||||
pthread_t pt;
|
pthread_t pt;
|
||||||
pthread_attr_t attr;
|
pthread_attr_t attr;
|
||||||
@ -755,7 +735,7 @@ int ql_capture_usbmon_log(PROFILE_T *profile, const char *log_path) {
|
|||||||
pthread_attr_init(&attr);
|
pthread_attr_init(&attr);
|
||||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||||
|
|
||||||
pthread_create(&pt, &attr, catch_log, (void *) profile);
|
pthread_create(&pt, &attr, catch_log, (void *)profile);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -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.1");
|
||||||
|
|
||||||
ret = parse_user_input(argc, argv, ctx);
|
ret = parse_user_input(argc, argv, ctx);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
|
@ -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.
|
||||||
---------------------------------------------------------------------------
|
---------------------------------------------------------------------------
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
@ -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.
|
||||||
---------------------------------------------------------------------------
|
---------------------------------------------------------------------------
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
@ -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.
|
||||||
---------------------------------------------------------------------------
|
---------------------------------------------------------------------------
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
@ -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.
|
||||||
---------------------------------------------------------------------------
|
---------------------------------------------------------------------------
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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];
|
||||||
|
@ -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);
|
||||||
|
@ -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.
|
||||||
---------------------------------------------------------------------------
|
---------------------------------------------------------------------------
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
@ -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.
|
||||||
---------------------------------------------------------------------------
|
---------------------------------------------------------------------------
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user