This commit is contained in:
ling 2024-03-21 21:19:27 +08:00
parent cce722cf5f
commit e8394c927d
34 changed files with 478 additions and 6691 deletions

View File

@ -8,7 +8,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=pcie_mhi PKG_NAME:=pcie_mhi
PKG_VERSION:=3.6 PKG_VERSION:=3.2
PKG_RELEASE:=1 PKG_RELEASE:=1
include $(INCLUDE_DIR)/kernel.mk include $(INCLUDE_DIR)/kernel.mk

View File

@ -1,20 +1,4 @@
Release Notes Release Notes
[V1.3.6]
Date: 01/08/2023
enhancement:
1. support Linux Kernel V6.4
2. support change mtu
fix:
1. fix compile error on ipq's spf12.x
Release Notes
[V1.3.5]
Date: 25/02/2023
enhancement:
1. support efuse SDX sleep
2. support IPQ9574 SFE
fix:
1. fix cannot find the node when dialing. Nodes in the /sys/bus/mhi_q/devices directory named hex
[V1.3.4] [V1.3.4]
Date: 12/8/2022 Date: 12/8/2022

View File

@ -15,36 +15,10 @@
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/msi.h> #include <linux/msi.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#define MAX_MHI 8
#ifdef CONFIG_PCI_MSM
#define QCOM_AP_AND_EFUSE_PCIE_SLEEP
#ifdef QCOM_AP_AND_EFUSE_PCIE_SLEEP
#include <linux/platform_device.h>
#include <linux/msm_pcie.h>
#endif
#endif
//#define QCOM_AP_SDM845_IOMMU_MAP
#ifdef QCOM_AP_SDM845_IOMMU_MAP
#include <linux/dma-mapping.h>
#include <asm/dma-iommu.h>
#include <linux/iommu.h>
#endif
#include "../core/mhi.h" #include "../core/mhi.h"
#include "../core/mhi_internal.h" #include "../core/mhi_internal.h"
#include "mhi_qti.h" #include "mhi_qti.h"
#ifdef QCOM_AP_AND_EFUSE_PCIE_SLEEP
extern int pci_write_config_byte(const struct pci_dev *dev, int where, u8 val);
struct arch_info {
struct mhi_dev *mhi_dev;
struct msm_bus_scale_pdata *msm_bus_pdata;
u32 bus_client;
struct pci_saved_state *pcie_state;
struct pci_saved_state *ref_pcie_state;
struct dma_iommu_mapping *mapping;
};
#endif
#if 1 #if 1
#if (LINUX_VERSION_CODE < KERNEL_VERSION( 3,10,65 )) #if (LINUX_VERSION_CODE < KERNEL_VERSION( 3,10,65 ))
static inline int dma_set_mask_and_coherent(struct device *dev, u64 mask) static inline int dma_set_mask_and_coherent(struct device *dev, u64 mask)
@ -203,12 +177,9 @@ static int mhi_init_pci_dev(struct mhi_controller *mhi_cntrl)
#if 1 //some SOC like rpi_4b need next codes #if 1 //some SOC like rpi_4b need next codes
ret = -EIO; ret = -EIO;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0)) #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)
if (!dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(64))) { if((ret = dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(64))))
ret = dma_set_coherent_mask(&pci_dev->dev, DMA_BIT_MASK(64)); ret = dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(32));
} else if (!dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(32))) {
ret = dma_set_coherent_mask(&pci_dev->dev, DMA_BIT_MASK(32));
}
#else #else
if (!pci_set_dma_mask(pci_dev, DMA_BIT_MASK(64))) { if (!pci_set_dma_mask(pci_dev, DMA_BIT_MASK(64))) {
ret = pci_set_consistent_dma_mask(pci_dev, DMA_BIT_MASK(64)); ret = pci_set_consistent_dma_mask(pci_dev, DMA_BIT_MASK(64));
@ -618,28 +589,6 @@ static void mhi_runtime_mark_last_busy(struct mhi_controller *mhi_cntrl, void *p
pm_runtime_mark_last_busy(dev); pm_runtime_mark_last_busy(dev);
} }
#ifdef QCOM_AP_AND_EFUSE_PCIE_SLEEP
static void mhi_pci_event_cb(struct msm_pcie_notify *notify)
{
struct pci_dev *pci_dev = notify->user;
struct device *dev = &pci_dev->dev;
dev_info(&pci_dev->dev, "Received PCIe event %d", notify->event);
switch (notify->event) {
case MSM_PCIE_EVENT_WAKEUP:
if (dev && pm_runtime_status_suspended(dev)) {
pm_request_resume(dev);
pm_runtime_mark_last_busy(dev);
}
break;
default:
break;
}
}
static struct msm_pcie_register_event mhi_pcie_events[MAX_MHI];
#endif
static void mhi_status_cb(struct mhi_controller *mhi_cntrl, static void mhi_status_cb(struct mhi_controller *mhi_cntrl,
void *priv, void *priv,
enum MHI_CB reason) enum MHI_CB reason)
@ -910,11 +859,6 @@ int mhi_pci_probe(struct pci_dev *pci_dev,
pr_info("%s pci_dev->name = %s, domain=%d, bus=%d, slot=%d, vendor=%04X, device=%04X\n", pr_info("%s pci_dev->name = %s, domain=%d, bus=%d, slot=%d, vendor=%04X, device=%04X\n",
__func__, dev_name(&pci_dev->dev), domain, bus, slot, pci_dev->vendor, pci_dev->device); __func__, dev_name(&pci_dev->dev), domain, bus, slot, pci_dev->vendor, pci_dev->device);
#if !defined(CONFIG_PCI_MSI)
/* MT7621 RTL8198D EcoNet-EN7565 */
#error "pcie msi is not support by this soc! and i donot support INTx (SW1SDX55-2688)"
#endif
if (!mhi_pci_is_alive(pci_dev)) { if (!mhi_pci_is_alive(pci_dev)) {
/* /*
root@OpenWrt:~# hexdump /sys/bus/pci/devices/0000:01:00.0/config root@OpenWrt:~# hexdump /sys/bus/pci/devices/0000:01:00.0/config
@ -938,11 +882,9 @@ int mhi_pci_probe(struct pci_dev *pci_dev,
mhi_dev = mhi_controller_get_devdata(mhi_cntrl); mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
mhi_dev->powered_on = true; mhi_dev->powered_on = true;
mhi_arch_iommu_init(mhi_cntrl);
ret = mhi_arch_pcie_init(mhi_cntrl); ret = mhi_arch_pcie_init(mhi_cntrl);
if (ret) if (ret)
goto error_init_pci_arch; return ret;
mhi_cntrl->dev = &pci_dev->dev; mhi_cntrl->dev = &pci_dev->dev;
ret = mhi_init_pci_dev(mhi_cntrl); ret = mhi_init_pci_dev(mhi_cntrl);
@ -960,28 +902,6 @@ int mhi_pci_probe(struct pci_dev *pci_dev,
mhi_pci_show_link(mhi_cntrl, pci_dev); mhi_pci_show_link(mhi_cntrl, pci_dev);
#ifdef QCOM_AP_AND_EFUSE_PCIE_SLEEP
{
struct msm_pcie_register_event *pcie_event = &mhi_pcie_events[mhi_cntrl->cntrl_idx];
pcie_event->events = MSM_PCIE_EVENT_WAKEUP;
#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,14,117 ))
pcie_event->pcie_event.user = pci_dev;
pcie_event->pcie_event.mode = MSM_PCIE_TRIGGER_CALLBACK;
pcie_event->pcie_event.callback = mhi_pci_event_cb;
#else
pcie_event->user = pci_dev;
pcie_event->mode = MSM_PCIE_TRIGGER_CALLBACK;
pcie_event->callback = mhi_pci_event_cb;
#endif
ret = msm_pcie_register_event(pcie_event);
if (ret) {
MHI_LOG("Failed to register for PCIe event");
}
}
#endif
MHI_LOG("Return successful\n"); MHI_LOG("Return successful\n");
return 0; return 0;
@ -992,8 +912,6 @@ error_power_up:
error_init_pci: error_init_pci:
mhi_arch_pcie_deinit(mhi_cntrl); mhi_arch_pcie_deinit(mhi_cntrl);
error_init_pci_arch:
mhi_arch_iommu_deinit(mhi_cntrl);
return ret; return ret;
} }
@ -1012,14 +930,6 @@ void mhi_pci_device_removed(struct pci_dev *pci_dev)
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
#ifdef QCOM_AP_AND_EFUSE_PCIE_SLEEP
{
struct msm_pcie_register_event *pcie_event = &mhi_pcie_events[mhi_cntrl->cntrl_idx];
msm_pcie_deregister_event(pcie_event);
}
#endif
pm_stay_awake(&mhi_cntrl->mhi_dev->dev); pm_stay_awake(&mhi_cntrl->mhi_dev->dev);
/* if link is in drv suspend, wake it up */ /* if link is in drv suspend, wake it up */
@ -1045,7 +955,6 @@ void mhi_pci_device_removed(struct pci_dev *pci_dev)
mhi_arch_link_off(mhi_cntrl, false); mhi_arch_link_off(mhi_cntrl, false);
mhi_arch_pcie_deinit(mhi_cntrl); mhi_arch_pcie_deinit(mhi_cntrl);
mhi_arch_iommu_deinit(mhi_cntrl);
pm_relax(&mhi_cntrl->mhi_dev->dev); pm_relax(&mhi_cntrl->mhi_dev->dev);
@ -1100,108 +1009,26 @@ void mhi_controller_qcom_exit(void)
pr_info("%s exit\n", __func__); pr_info("%s exit\n", __func__);
} }
#ifdef QCOM_AP_SDM845_IOMMU_MAP
struct dma_iommu_mapping *mhi_smmu_mapping[MAX_MHI];
#define SMMU_BASE 0x10000000
#define SMMU_SIZE 0x40000000
static struct dma_iommu_mapping * sdm845_smmu_init(struct pci_dev *pdev) {
int ret = 0;
int atomic_ctx = 1;
int s1_bypass = 1;
struct dma_iommu_mapping *mapping;
mapping = arm_iommu_create_mapping(&platform_bus_type, SMMU_BASE, SMMU_SIZE);
if (IS_ERR(mapping)) {
ret = PTR_ERR(mapping);
dev_err(&pdev->dev, "Create mapping failed, err = %d\n", ret);
return NULL;
}
ret = iommu_domain_set_attr(mapping->domain, DOMAIN_ATTR_ATOMIC, &atomic_ctx);
if (ret < 0) {
dev_err(&pdev->dev, "Set atomic_ctx attribute failed, err = %d\n", ret);
goto set_attr_fail;
}
ret = iommu_domain_set_attr(mapping->domain, DOMAIN_ATTR_S1_BYPASS, &s1_bypass);
if (ret < 0) {
dev_err(&pdev->dev, "Set s1_bypass attribute failed, err = %d\n", ret);
arm_iommu_release_mapping(mapping);
goto set_attr_fail;
}
ret = arm_iommu_attach_device(&pdev->dev, mapping);
if (ret < 0) {
dev_err(&pdev->dev, "Attach device failed, err = %d\n", ret);
goto attach_fail;
}
return mapping;
attach_fail:
set_attr_fail:
arm_iommu_release_mapping(mapping);
return NULL;
}
#endif
int mhi_arch_iommu_init(struct mhi_controller *mhi_cntrl) int mhi_arch_iommu_init(struct mhi_controller *mhi_cntrl)
{ {
#ifdef QCOM_AP_SDM845_IOMMU_MAP
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl); struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
mhi_smmu_mapping[mhi_cntrl->cntrl_idx] = sdm845_smmu_init(mhi_dev->pci_dev); mhi_cntrl->dev = &mhi_dev->pci_dev->dev;
#endif
return 0; return dma_set_mask_and_coherent(mhi_cntrl->dev, DMA_BIT_MASK(64));
} }
void mhi_arch_iommu_deinit(struct mhi_controller *mhi_cntrl) void mhi_arch_iommu_deinit(struct mhi_controller *mhi_cntrl)
{ {
#ifdef QCOM_AP_SDM845_IOMMU_MAP
if (mhi_smmu_mapping[mhi_cntrl->cntrl_idx]) {
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
arm_iommu_detach_device(&mhi_dev->pci_dev->dev);
arm_iommu_release_mapping(mhi_smmu_mapping[mhi_cntrl->cntrl_idx]);
mhi_smmu_mapping[mhi_cntrl->cntrl_idx] = NULL;
}
#endif
}
static int mhi_arch_set_bus_request(struct mhi_controller *mhi_cntrl, int index)
{
MHI_LOG("Setting bus request to index %d\n", index);
return 0;
} }
int mhi_arch_pcie_init(struct mhi_controller *mhi_cntrl) int mhi_arch_pcie_init(struct mhi_controller *mhi_cntrl)
{ {
#ifdef QCOM_AP_AND_EFUSE_PCIE_SLEEP return 0;
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
struct arch_info *arch_info = mhi_dev->arch_info;
if (!arch_info) {
arch_info = devm_kzalloc(&mhi_dev->pci_dev->dev,
sizeof(*arch_info), GFP_KERNEL);
if (!arch_info)
return -ENOMEM;
mhi_dev->arch_info = arch_info;
/* save reference state for pcie config space */
arch_info->ref_pcie_state = pci_store_saved_state(
mhi_dev->pci_dev);
}
#endif
return mhi_arch_set_bus_request(mhi_cntrl, 1);
} }
void mhi_arch_pcie_deinit(struct mhi_controller *mhi_cntrl) void mhi_arch_pcie_deinit(struct mhi_controller *mhi_cntrl)
{ {
mhi_arch_set_bus_request(mhi_cntrl, 0);
} }
int mhi_arch_platform_init(struct mhi_dev *mhi_dev) int mhi_arch_platform_init(struct mhi_dev *mhi_dev)
@ -1216,91 +1043,11 @@ void mhi_arch_platform_deinit(struct mhi_dev *mhi_dev)
int mhi_arch_link_off(struct mhi_controller *mhi_cntrl, int mhi_arch_link_off(struct mhi_controller *mhi_cntrl,
bool graceful) bool graceful)
{ {
#ifdef QCOM_AP_AND_EFUSE_PCIE_SLEEP
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
struct arch_info *arch_info = mhi_dev->arch_info;
struct pci_dev *pci_dev = mhi_dev->pci_dev;
int ret;
MHI_LOG("Entered\n");
if (graceful) {
pci_clear_master(pci_dev);
ret = pci_save_state(mhi_dev->pci_dev);
if (ret) {
MHI_ERR("Failed with pci_save_state, ret:%d\n", ret);
return ret;
}
arch_info->pcie_state = pci_store_saved_state(pci_dev);
pci_disable_device(pci_dev);
}
/*
* We will always attempt to put link into D3hot, however
* link down may have happened due to error fatal, so
* ignoring the return code
*/
pci_set_power_state(pci_dev, PCI_D3hot);
ret = msm_pcie_pm_control(MSM_PCIE_SUSPEND, mhi_cntrl->bus, pci_dev,
NULL, 0);
MHI_ERR("msm_pcie_pm_control(MSM_PCIE_SUSPEND), ret:%d\n", ret);
/* release the resources */
mhi_arch_set_bus_request(mhi_cntrl, 0);
MHI_LOG("Exited\n");
#endif
return 0; return 0;
} }
int mhi_arch_link_on(struct mhi_controller *mhi_cntrl) int mhi_arch_link_on(struct mhi_controller *mhi_cntrl)
{ {
#ifdef QCOM_AP_AND_EFUSE_PCIE_SLEEP
struct mhi_dev *mhi_dev = mhi_controller_get_devdata(mhi_cntrl);
struct arch_info *arch_info = mhi_dev->arch_info;
struct pci_dev *pci_dev = mhi_dev->pci_dev;
int ret;
MHI_LOG("Entered\n");
/* request resources and establish link trainning */
ret = mhi_arch_set_bus_request(mhi_cntrl, 1);
if (ret)
MHI_LOG("Could not set bus frequency, ret:%d\n", ret);
ret = msm_pcie_pm_control(MSM_PCIE_RESUME, mhi_cntrl->bus, pci_dev,
NULL, 0);
MHI_LOG("msm_pcie_pm_control(MSM_PCIE_RESUME), ret:%d\n", ret);
if (ret) {
MHI_ERR("Link training failed, ret:%d\n", ret);
return ret;
}
ret = pci_set_power_state(pci_dev, PCI_D0);
if (ret) {
MHI_ERR("Failed to set PCI_D0 state, ret:%d\n", ret);
return ret;
}
ret = pci_enable_device(pci_dev);
if (ret) {
MHI_ERR("Failed to enable device, ret:%d\n", ret);
return ret;
}
ret = pci_load_and_free_saved_state(pci_dev, &arch_info->pcie_state);
if (ret)
MHI_LOG("Failed to load saved cfg state\n");
pci_restore_state(pci_dev);
pci_set_master(pci_dev);
MHI_LOG("Exited\n");
#endif
return 0; return 0;
} }
#endif #endif

View File

@ -4,14 +4,10 @@
#ifndef _MHI_H_ #ifndef _MHI_H_
#define _MHI_H_ #define _MHI_H_
#define PCIE_MHI_DRIVER_VERSION "V1.3.6" #define PCIE_MHI_DRIVER_VERSION "V1.3.4"
#define ENABLE_MHI_MON #define ENABLE_MHI_MON
//#define ENABLE_IP_SW0 //#define ENABLE_IP_SW0
// #define ENABLE_ADPL
// #define ENABLE_QDSS
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
typedef enum typedef enum
{ {
@ -86,8 +82,7 @@ typedef enum
MHI_CLIENT_IP_HW_0_OUT = 100, MHI_CLIENT_IP_HW_0_OUT = 100,
MHI_CLIENT_IP_HW_0_IN = 101, MHI_CLIENT_IP_HW_0_IN = 101,
MHI_CLIENT_ADPL = 102, MHI_CLIENT_ADPL = 102,
MHI_CLIENT_IP_HW_QDSS = 103, MHI_CLIENT_RESERVED_5_LOWER = 103,
// MHI_CLIENT_RESERVED_5_LOWER = 103,
MHI_CLIENT_RESERVED_5_UPPER = 127, MHI_CLIENT_RESERVED_5_UPPER = 127,
MHI_MAX_CHANNELS = 128 MHI_MAX_CHANNELS = 128
}MHI_CLIENT_CHANNEL_TYPE; }MHI_CLIENT_CHANNEL_TYPE;
@ -103,12 +98,7 @@ typedef enum
#endif #endif
IPA_OUT_EVENT_RING, IPA_OUT_EVENT_RING,
IPA_IN_EVENT_RING, IPA_IN_EVENT_RING,
#ifdef ENABLE_ADPL
ADPL_EVT_RING, ADPL_EVT_RING,
#endif
#ifdef ENABLE_QDSS
QDSS_EVT_RING,
#endif
MAX_EVT_RING_IDX MAX_EVT_RING_IDX
}MHI_EVT_RING_IDX; }MHI_EVT_RING_IDX;
@ -119,7 +109,7 @@ typedef enum
#define MAX_NUM_MHI_DEVICES 1 #define MAX_NUM_MHI_DEVICES 1
#define NUM_MHI_XFER_RINGS 128 #define NUM_MHI_XFER_RINGS 128
#define NUM_MHI_EVT_RINGS MAX_EVT_RING_IDX #define NUM_MHI_EVT_RINGS MAX_EVT_RING_IDX
#define NUM_MHI_HW_EVT_RINGS 4 #define NUM_MHI_HW_EVT_RINGS 3
#define NUM_MHI_XFER_RING_ELEMENTS 16 #define NUM_MHI_XFER_RING_ELEMENTS 16
#define NUM_MHI_EVT_RING_ELEMENTS (NUM_MHI_IPA_IN_RING_ELEMENTS*2) //must *2, event ring full will make x55 dump #define NUM_MHI_EVT_RING_ELEMENTS (NUM_MHI_IPA_IN_RING_ELEMENTS*2) //must *2, event ring full will make x55 dump
#define NUM_MHI_IPA_IN_RING_ELEMENTS 512 #define NUM_MHI_IPA_IN_RING_ELEMENTS 512
@ -127,14 +117,6 @@ typedef enum
#define NUM_MHI_DIAG_IN_RING_ELEMENTS 128 #define NUM_MHI_DIAG_IN_RING_ELEMENTS 128
#define NUM_MHI_SW_IP_RING_ELEMENTS 512 #define NUM_MHI_SW_IP_RING_ELEMENTS 512
#ifdef ENABLE_ADPL
#define NUM_MHI_ADPL_RING_ELEMENTS 256
#endif
#ifdef ENABLE_QDSS
#define NUM_MHI_QDSS_RING_ELEMENTS 256
#endif
/* /*
* for if set Interrupt moderation time as 1ms, * for if set Interrupt moderation time as 1ms,
and transfer more than NUM_MHI_CHAN_RING_ELEMENTS data are sent to the modem in 1ms. and transfer more than NUM_MHI_CHAN_RING_ELEMENTS data are sent to the modem in 1ms.

View File

@ -200,7 +200,7 @@ static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl)
lower_32_bits(mhi_buf->dma_addr)); lower_32_bits(mhi_buf->dma_addr));
mhi_write_reg(mhi_cntrl, base, BHIE_RXVECSIZE_OFFS, mhi_buf->len); mhi_write_reg(mhi_cntrl, base, BHIE_RXVECSIZE_OFFS, mhi_buf->len);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)) #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)
sequence_id = get_random_u32() & BHIE_RXVECSTATUS_SEQNUM_BMSK; sequence_id = get_random_u32() & BHIE_RXVECSTATUS_SEQNUM_BMSK;
#else #else
sequence_id = prandom_u32() & BHIE_RXVECSTATUS_SEQNUM_BMSK; sequence_id = prandom_u32() & BHIE_RXVECSTATUS_SEQNUM_BMSK;
@ -315,8 +315,7 @@ int mhi_download_rddm_img(struct mhi_controller *mhi_cntrl, bool in_panic)
lower_32_bits(mhi_buf->dma_addr)); lower_32_bits(mhi_buf->dma_addr));
mhi_write_reg(mhi_cntrl, base, BHIE_RXVECSIZE_OFFS, mhi_buf->len); mhi_write_reg(mhi_cntrl, base, BHIE_RXVECSIZE_OFFS, mhi_buf->len);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0))
sequence_id = get_random_u32() & BHIE_RXVECSTATUS_SEQNUM_BMSK; sequence_id = get_random_u32() & BHIE_RXVECSTATUS_SEQNUM_BMSK;
#else #else
sequence_id = prandom_u32() & BHIE_RXVECSTATUS_SEQNUM_BMSK; sequence_id = prandom_u32() & BHIE_RXVECSTATUS_SEQNUM_BMSK;
@ -371,11 +370,12 @@ static int mhi_fw_load_amss(struct mhi_controller *mhi_cntrl,
lower_32_bits(mhi_buf->dma_addr)); lower_32_bits(mhi_buf->dma_addr));
mhi_write_reg(mhi_cntrl, base, BHIE_TXVECSIZE_OFFS, mhi_buf->len); mhi_write_reg(mhi_cntrl, base, BHIE_TXVECSIZE_OFFS, mhi_buf->len);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)) #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)
mhi_cntrl->sequence_id = get_random_u32() & BHIE_TXVECSTATUS_SEQNUM_BMSK; mhi_cntrl->sequence_id = get_random_u32() & BHIE_TXVECSTATUS_SEQNUM_BMSK;
#else #else
mhi_cntrl->sequence_id = prandom_u32() & BHIE_TXVECSTATUS_SEQNUM_BMSK; mhi_cntrl->sequence_id = prandom_u32() & BHIE_TXVECSTATUS_SEQNUM_BMSK;
#endif #endif
mhi_write_reg_field(mhi_cntrl, base, BHIE_TXVECDB_OFFS, mhi_write_reg_field(mhi_cntrl, base, BHIE_TXVECDB_OFFS,
BHIE_TXVECDB_SEQNUM_BMSK, BHIE_TXVECDB_SEQNUM_SHFT, BHIE_TXVECDB_SEQNUM_BMSK, BHIE_TXVECDB_SEQNUM_SHFT,
mhi_cntrl->sequence_id); mhi_cntrl->sequence_id);
@ -651,11 +651,12 @@ void mhi_fw_load_worker(struct work_struct *work)
ret = mhi_fw_load_sbl(mhi_cntrl, dma_addr, size); ret = mhi_fw_load_sbl(mhi_cntrl, dma_addr, size);
mhi_free_coherent(mhi_cntrl, size, buf, dma_addr); mhi_free_coherent(mhi_cntrl, size, buf, dma_addr);
/* error or in edl, we're done */ if (!mhi_cntrl->fbc_download || ret || mhi_cntrl->ee == MHI_EE_EDL)
if (ret || mhi_cntrl->ee == MHI_EE_EDL) {
release_firmware(firmware); release_firmware(firmware);
/* error or in edl, we're done */
if (ret || mhi_cntrl->ee == MHI_EE_EDL)
return; return;
}
write_lock_irq(&mhi_cntrl->pm_lock); write_lock_irq(&mhi_cntrl->pm_lock);
mhi_cntrl->dev_state = MHI_STATE_RESET; mhi_cntrl->dev_state = MHI_STATE_RESET;
@ -687,10 +688,8 @@ void mhi_fw_load_worker(struct work_struct *work)
TO_MHI_STATE_STR(mhi_cntrl->dev_state), TO_MHI_STATE_STR(mhi_cntrl->dev_state),
TO_MHI_EXEC_STR(mhi_cntrl->ee), ret); TO_MHI_EXEC_STR(mhi_cntrl->ee), ret);
if (!mhi_cntrl->fbc_download) { if (!mhi_cntrl->fbc_download)
release_firmware(firmware); return;
return;
}
if (ret) { if (ret) {
MHI_ERR("Did not transition to READY state\n"); MHI_ERR("Did not transition to READY state\n");
@ -847,10 +846,7 @@ long bhi_write_image(struct mhi_controller *mhi_cntrl, void __user *ubuf)
MHI_ERR("IOCTL_BHI_WRITEIMAGE copy size error, ret = %ld\n", ret); MHI_ERR("IOCTL_BHI_WRITEIMAGE copy size error, ret = %ld\n", ret);
return ret; return ret;
} }
if (size <= 0) {
MHI_ERR("IOCTL_BHI_WRITEIMAGE copy size error, size\n");
return -EINVAL;
}
ret = BhiWrite(mhi_cntrl, ubuf+sizeof(size), size); ret = BhiWrite(mhi_cntrl, ubuf+sizeof(size), size);
if (ret) { if (ret) {
MHI_ERR("IOCTL_BHI_WRITEIMAGE BhiWrite error, ret = %ld\n", ret); MHI_ERR("IOCTL_BHI_WRITEIMAGE BhiWrite error, ret = %ld\n", ret);

View File

@ -12,7 +12,6 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/uaccess.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/version.h> #include <linux/version.h>
#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,11,0 )) #if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,11,0 ))
@ -28,7 +27,6 @@ struct mhi_controller_map {
u32 domain; u32 domain;
u32 bus; u32 bus;
u32 slot; u32 slot;
struct mhi_controller *mhi_cntrl;
}; };
#define MAX_MHI_CONTROLLER 16 #define MAX_MHI_CONTROLLER 16
@ -390,7 +388,7 @@ static void mon_text_complete(void *data, u32 chan, dma_addr_t wp, struct mhi_tr
mon_text_event(rp, chan, wp, mhi_tre, NULL, 0, 'E'); mon_text_event(rp, chan, wp, mhi_tre, NULL, 0, 'E');
} }
static void mon_reader_add(struct mhi_controller *mbus, struct mon_reader *r) void mon_reader_add(struct mhi_controller *mbus, struct mon_reader *r)
{ {
unsigned long flags; unsigned long flags;
@ -562,9 +560,9 @@ static ssize_t mon_text_read_u(struct file *file, char __user *buf,
ptr.limit = rp->printf_size; ptr.limit = rp->printf_size;
ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt, ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt,
"%u %c %03d WP:%llx TRE: %llx %08x %08x", "%u %c %03d WP:%llx TRE: %llx %08x %08x",
ep->tstamp, ep->type, ep->chan, (long long unsigned int)ep->wp, ep->tstamp, ep->type, ep->chan, ep->wp,
ep->mhi_tre.ptr, ep->mhi_tre.dword[0], ep->mhi_tre.dword[1]); ep->mhi_tre.ptr, ep->mhi_tre.dword[0], ep->mhi_tre.dword[1]);
if (ep->len) { if (ep->len) {
struct mon_text_ptr *p = &ptr; struct mon_text_ptr *p = &ptr;
@ -653,7 +651,7 @@ static const struct file_operations mon_fops_text_u = {
void mhi_init_debugfs(struct mhi_controller *mhi_cntrl) void mhi_init_debugfs(struct mhi_controller *mhi_cntrl)
{ {
struct dentry *dentry; struct dentry *dentry;
char node[64]; char node[32];
#ifdef ENABLE_MHI_MON #ifdef ENABLE_MHI_MON
struct mhi_controller *mbus = mhi_cntrl; struct mhi_controller *mbus = mhi_cntrl;
@ -665,11 +663,11 @@ void mhi_init_debugfs(struct mhi_controller *mhi_cntrl)
#endif #endif
if (!mhi_cntrl->parent) if (!mhi_cntrl->parent)
snprintf(node, sizeof(node), "mhi_%04x_%02x:%02x.%02x", snprintf(node, sizeof(node), "mhi_%04x_%02u:%02u.%02u",
mhi_cntrl->dev_id, mhi_cntrl->domain, mhi_cntrl->bus, mhi_cntrl->dev_id, mhi_cntrl->domain, mhi_cntrl->bus,
mhi_cntrl->slot); mhi_cntrl->slot);
else else
snprintf(node, sizeof(node), "%04x_%02x:%02x.%02x", snprintf(node, sizeof(node), "%04x_%02u:%02u.%02u",
mhi_cntrl->dev_id, mhi_cntrl->domain, mhi_cntrl->bus, mhi_cntrl->dev_id, mhi_cntrl->domain, mhi_cntrl->bus,
mhi_cntrl->slot); mhi_cntrl->slot);
@ -1011,7 +1009,7 @@ exit_timesync:
int mhi_init_mmio(struct mhi_controller *mhi_cntrl) int mhi_init_mmio(struct mhi_controller *mhi_cntrl)
{ {
u32 val = 0; u32 val;
int i, ret; int i, ret;
struct mhi_chan *mhi_chan; struct mhi_chan *mhi_chan;
struct mhi_event *mhi_event; struct mhi_event *mhi_event;
@ -1088,7 +1086,7 @@ int mhi_init_mmio(struct mhi_controller *mhi_cntrl)
MHIDATALIMIT_LOWER, U32_MAX, 0, MHIDATALIMIT_LOWER, U32_MAX, 0,
lower_32_bits(mhi_cntrl->iova_stop), lower_32_bits(mhi_cntrl->iova_stop),
}, },
{ 0, 0, 0, 0 } { 0, 0, 0 }
}; };
MHI_LOG("Initializing MMIO\n"); MHI_LOG("Initializing MMIO\n");
@ -1196,21 +1194,6 @@ int mhi_init_chan_ctxt(struct mhi_controller *mhi_cntrl,
tre_ring->dma_handle = mhi_cntrl->mhi_ctxt->ctrl_seg_addr + offsetof(struct mhi_ctrl_seg, sw_out_chan_ring[mhi_chan->ring]); tre_ring->dma_handle = mhi_cntrl->mhi_ctxt->ctrl_seg_addr + offsetof(struct mhi_ctrl_seg, sw_out_chan_ring[mhi_chan->ring]);
} }
#endif #endif
#ifdef ENABLE_ADPL
else if (MHI_CLIENT_ADPL == mhi_chan->chan) {
tre_ring->pre_aligned = &mhi_cntrl->mhi_ctxt->ctrl_seg->adpl_in_chan_ring[mhi_chan->ring];
tre_ring->dma_handle = mhi_cntrl->mhi_ctxt->ctrl_seg_addr + offsetof(struct mhi_ctrl_seg, adpl_in_chan_ring[mhi_chan->ring]);
}
#endif
#ifdef ENABLE_QDSS
else if (MHI_CLIENT_IP_HW_QDSS == mhi_chan->chan) {
tre_ring->pre_aligned = &mhi_cntrl->mhi_ctxt->ctrl_seg->qdss_in_chan_ring[mhi_chan->ring];
tre_ring->dma_handle = mhi_cntrl->mhi_ctxt->ctrl_seg_addr + offsetof(struct mhi_ctrl_seg, qdss_in_chan_ring[mhi_chan->ring]);
}
#endif
else if (MHI_CLIENT_DIAG_IN == mhi_chan->chan) { else if (MHI_CLIENT_DIAG_IN == mhi_chan->chan) {
tre_ring->pre_aligned = &mhi_cntrl->mhi_ctxt->ctrl_seg->diag_in_chan_ring[mhi_chan->ring]; tre_ring->pre_aligned = &mhi_cntrl->mhi_ctxt->ctrl_seg->diag_in_chan_ring[mhi_chan->ring];
tre_ring->dma_handle = mhi_cntrl->mhi_ctxt->ctrl_seg_addr + offsetof(struct mhi_ctrl_seg, diag_in_chan_ring[mhi_chan->ring]); tre_ring->dma_handle = mhi_cntrl->mhi_ctxt->ctrl_seg_addr + offsetof(struct mhi_ctrl_seg, diag_in_chan_ring[mhi_chan->ring]);
@ -1623,21 +1606,11 @@ static int of_parse_ev_cfg(struct mhi_controller *mhi_cntrl,
mhi_event->er_index = i; mhi_event->er_index = i;
mhi_event->ring.elements = NUM_MHI_EVT_RING_ELEMENTS; //Event ring length in elements mhi_event->ring.elements = NUM_MHI_EVT_RING_ELEMENTS; //Event ring length in elements
if (i == PRIMARY_EVENT_RING) if (i == PRIMARY_EVENT_RING || i == ADPL_EVT_RING)
mhi_event->ring.elements = 256; //256 is enough, and 1024 some times make driver fail to open channel (reason is x6x fail to malloc) mhi_event->ring.elements = 256; //256 is enough, and 1024 some times make driver fail to open channel (reason is x6x fail to malloc)
mhi_event->intmod = 1; //Interrupt moderation time in ms mhi_event->intmod = 1; //Interrupt moderation time in ms
#ifdef ENABLE_ADPL
if (i == ADPL_EVT_RING)
mhi_event->ring.elements = 256;
#endif
#ifdef ENABLE_QDSS
if (i == QDSS_EVT_RING)
mhi_event->ring.elements = 512;
#endif
/* see mhi_netdev_status_cb(), when interrupt come, the napi_poll maybe scheduled, so can reduce interrupts /* see mhi_netdev_status_cb(), when interrupt come, the napi_poll maybe scheduled, so can reduce interrupts
root@OpenWrt:/# cat /proc/interrupts | grep mhi root@OpenWrt:/# cat /proc/interrupts | grep mhi
root@OpenWrt:/# cat /sys/kernel/debug/mhi_q/mhi_netdev/pcie_mhi_0306_00.01.00_0/rx_int root@OpenWrt:/# cat /sys/kernel/debug/mhi_q/mhi_netdev/pcie_mhi_0306_00.01.00_0/rx_int
@ -1650,16 +1623,6 @@ static int of_parse_ev_cfg(struct mhi_controller *mhi_cntrl,
mhi_event->intmod = 5; mhi_event->intmod = 5;
#endif #endif
#ifdef ENABLE_ADPL
if (i == ADPL_EVT_RING)
mhi_event->intmod = 0;
#endif
#ifdef ENABLE_QDSS
if (i == QDSS_EVT_RING)
mhi_event->intmod = 0;
#endif
mhi_event->msi = 1 + i + mhi_cntrl->msi_irq_base; //MSI associated with this event ring mhi_event->msi = 1 + i + mhi_cntrl->msi_irq_base; //MSI associated with this event ring
if (i == IPA_OUT_EVENT_RING) if (i == IPA_OUT_EVENT_RING)
@ -1672,16 +1635,6 @@ static int of_parse_ev_cfg(struct mhi_controller *mhi_cntrl,
else if (i == SW_0_IN_EVT_RING) else if (i == SW_0_IN_EVT_RING)
mhi_event->chan = MHI_CLIENT_IP_SW_0_IN; mhi_event->chan = MHI_CLIENT_IP_SW_0_IN;
#endif #endif
#ifdef ENABLE_ADPL
else if (i == ADPL_EVT_RING)
mhi_event->chan = MHI_CLIENT_ADPL;
#endif
#ifdef ENABLE_QDSS
else if (i == QDSS_EVT_RING)
mhi_event->chan = MHI_CLIENT_IP_HW_QDSS;
#endif
else else
mhi_event->chan = 0; mhi_event->chan = 0;
@ -1706,16 +1659,6 @@ static int of_parse_ev_cfg(struct mhi_controller *mhi_cntrl,
else if (i == SW_0_OUT_EVT_RING || i == SW_0_IN_EVT_RING) else if (i == SW_0_OUT_EVT_RING || i == SW_0_IN_EVT_RING)
mhi_event->data_type = MHI_ER_DATA_ELEMENT_TYPE; mhi_event->data_type = MHI_ER_DATA_ELEMENT_TYPE;
#endif #endif
#ifdef ENABLE_ADPL
else if (i == ADPL_EVT_RING)
mhi_event->data_type = MHI_ER_DATA_ELEMENT_TYPE;
#endif
#ifdef ENABLE_QDSS
else if (i == QDSS_EVT_RING)
mhi_event->data_type = MHI_ER_DATA_ELEMENT_TYPE;
#endif
else else
mhi_event->data_type = MHI_ER_CTRL_ELEMENT_TYPE; mhi_event->data_type = MHI_ER_CTRL_ELEMENT_TYPE;
@ -1731,14 +1674,7 @@ static int of_parse_ev_cfg(struct mhi_controller *mhi_cntrl,
break; break;
} }
if (i == IPA_OUT_EVENT_RING || i == IPA_IN_EVENT_RING if (i == IPA_OUT_EVENT_RING || i == IPA_IN_EVENT_RING)
#ifdef ENABLE_ADPL
|| i == ADPL_EVT_RING
#endif
#ifdef ENABLE_QDSS
|| i == QDSS_EVT_RING
#endif
)
mhi_event->hw_ring = true; mhi_event->hw_ring = true;
else else
mhi_event->hw_ring = false; mhi_event->hw_ring = false;
@ -1778,9 +1714,8 @@ static struct chan_cfg_t chan_cfg[] = {
{"DIAG", MHI_CLIENT_DIAG_OUT, NUM_MHI_CHAN_RING_ELEMENTS}, {"DIAG", MHI_CLIENT_DIAG_OUT, NUM_MHI_CHAN_RING_ELEMENTS},
{"DIAG", MHI_CLIENT_DIAG_IN, NUM_MHI_DIAG_IN_RING_ELEMENTS}, {"DIAG", MHI_CLIENT_DIAG_IN, NUM_MHI_DIAG_IN_RING_ELEMENTS},
//"Qualcomm PCIe QDSS Data" //"Qualcomm PCIe QDSS Data"
//"Do not use this QDSS. xingduo.du 2023-02-16" {"QDSS", MHI_CLIENT_QDSS_OUT, NUM_MHI_CHAN_RING_ELEMENTS},
// {"QDSS", MHI_CLIENT_QDSS_OUT, NUM_MHI_CHAN_RING_ELEMENTS}, {"QDSS", MHI_CLIENT_QDSS_IN, NUM_MHI_CHAN_RING_ELEMENTS},
// {"QDSS", MHI_CLIENT_QDSS_IN, NUM_MHI_CHAN_RING_ELEMENTS},
//"Qualcomm PCIe EFS" //"Qualcomm PCIe EFS"
{"EFS", MHI_CLIENT_EFS_OUT, NUM_MHI_CHAN_RING_ELEMENTS}, {"EFS", MHI_CLIENT_EFS_OUT, NUM_MHI_CHAN_RING_ELEMENTS},
{"EFS", MHI_CLIENT_EFS_IN, NUM_MHI_CHAN_RING_ELEMENTS}, {"EFS", MHI_CLIENT_EFS_IN, NUM_MHI_CHAN_RING_ELEMENTS},
@ -1818,13 +1753,6 @@ static struct chan_cfg_t chan_cfg[] = {
//"Qualcomm PCIe WWAN Adapter" //"Qualcomm PCIe WWAN Adapter"
{"IP_HW0", MHI_CLIENT_IP_HW_0_OUT, NUM_MHI_IPA_OUT_RING_ELEMENTS}, {"IP_HW0", MHI_CLIENT_IP_HW_0_OUT, NUM_MHI_IPA_OUT_RING_ELEMENTS},
{"IP_HW0", MHI_CLIENT_IP_HW_0_IN, NUM_MHI_IPA_IN_RING_ELEMENTS}, {"IP_HW0", MHI_CLIENT_IP_HW_0_IN, NUM_MHI_IPA_IN_RING_ELEMENTS},
#ifdef ENABLE_ADPL
{"ADPL", MHI_CLIENT_ADPL, NUM_MHI_ADPL_RING_ELEMENTS},
#endif
#ifdef ENABLE_QDSS
{"QDSS", MHI_CLIENT_IP_HW_QDSS, NUM_MHI_QDSS_RING_ELEMENTS},
#endif
}; };
extern int mhi_netdev_mbin_enabled(void); extern int mhi_netdev_mbin_enabled(void);
@ -1878,14 +1806,7 @@ static int of_parse_ch_cfg(struct mhi_controller *mhi_cntrl,
mhi_chan->buf_ring.elements = mhi_chan->tre_ring.elements; mhi_chan->buf_ring.elements = mhi_chan->tre_ring.elements;
if (chan == MHI_CLIENT_IP_HW_0_OUT || chan == MHI_CLIENT_IP_HW_0_IN || chan == MHI_CLIENT_DIAG_IN if (chan == MHI_CLIENT_IP_HW_0_OUT || chan == MHI_CLIENT_IP_HW_0_IN || chan == MHI_CLIENT_DIAG_IN
|| chan == MHI_CLIENT_IP_SW_0_OUT || chan == MHI_CLIENT_IP_SW_0_IN || chan == MHI_CLIENT_IP_SW_0_OUT || chan == MHI_CLIENT_IP_SW_0_IN) {
#ifdef ENABLE_ADPL
|| chan == MHI_CLIENT_ADPL
#endif
#ifdef ENABLE_QDSS
|| chan == MHI_CLIENT_IP_HW_QDSS
#endif
) {
mhi_chan->ring = 0; mhi_chan->ring = 0;
} }
else { else {
@ -1903,29 +1824,11 @@ static int of_parse_ch_cfg(struct mhi_controller *mhi_cntrl,
else if (chan == MHI_CLIENT_IP_SW_0_IN) else if (chan == MHI_CLIENT_IP_SW_0_IN)
mhi_chan->er_index = SW_0_IN_EVT_RING; mhi_chan->er_index = SW_0_IN_EVT_RING;
#endif #endif
#ifdef ENABLE_ADPL
else if (chan == MHI_CLIENT_ADPL)
mhi_chan->er_index = ADPL_EVT_RING;
#endif
#ifdef ENABLE_QDSS
else if (chan == MHI_CLIENT_IP_HW_QDSS)
mhi_chan->er_index = QDSS_EVT_RING;
#endif
else else
mhi_chan->er_index = PRIMARY_EVENT_RING; mhi_chan->er_index = PRIMARY_EVENT_RING;
mhi_chan->dir = CHAN_INBOUND(chan) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; mhi_chan->dir = CHAN_INBOUND(chan) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
#ifdef ENABLE_ADPL
if (chan == MHI_CLIENT_ADPL)
mhi_chan->dir = DMA_FROM_DEVICE;
#endif
#ifdef ENABLE_QDSS
if (chan == MHI_CLIENT_IP_HW_QDSS)
mhi_chan->dir = DMA_FROM_DEVICE;
#endif
/* /*
* For most channels, chtype is identical to channel directions, * For most channels, chtype is identical to channel directions,
* if not defined, assign ch direction to chtype * if not defined, assign ch direction to chtype
@ -1944,14 +1847,6 @@ static int of_parse_ch_cfg(struct mhi_controller *mhi_cntrl,
mhi_chan->xfer_type = MHI_XFER_SKB; mhi_chan->xfer_type = MHI_XFER_SKB;
else if (chan == MHI_CLIENT_IP_HW_0_IN || chan == MHI_CLIENT_IP_SW_0_IN) else if (chan == MHI_CLIENT_IP_HW_0_IN || chan == MHI_CLIENT_IP_SW_0_IN)
mhi_chan->xfer_type = MHI_XFER_SKB; //MHI_XFER_DMA; mhi_chan->xfer_type = MHI_XFER_SKB; //MHI_XFER_DMA;
#ifdef ENABLE_ADPL
else if (chan == MHI_CLIENT_ADPL)
mhi_chan->xfer_type = MHI_XFER_BUFFER;
#endif
#ifdef ENABLE_QDSS
else if (chan == MHI_CLIENT_IP_HW_QDSS)
mhi_chan->xfer_type = MHI_XFER_BUFFER;
#endif
else else
mhi_chan->xfer_type = MHI_XFER_BUFFER; mhi_chan->xfer_type = MHI_XFER_BUFFER;
@ -2009,14 +1904,6 @@ static int of_parse_ch_cfg(struct mhi_controller *mhi_cntrl,
if (chan == MHI_CLIENT_IP_HW_0_OUT || chan == MHI_CLIENT_IP_HW_0_IN) if (chan == MHI_CLIENT_IP_HW_0_OUT || chan == MHI_CLIENT_IP_HW_0_IN)
mhi_chan->db_cfg.brstmode = MHI_BRSTMODE_ENABLE; mhi_chan->db_cfg.brstmode = MHI_BRSTMODE_ENABLE;
#ifdef ENABLE_ADPL
if (chan == MHI_CLIENT_ADPL)
mhi_chan->db_cfg.brstmode = MHI_BRSTMODE_DISABLE;
#endif
#ifdef ENABLE_QDSS
if (chan == MHI_CLIENT_IP_HW_QDSS)
mhi_chan->db_cfg.brstmode = MHI_BRSTMODE_DISABLE;
#endif
if (MHI_INVALID_BRSTMODE(mhi_chan->db_cfg.brstmode)) if (MHI_INVALID_BRSTMODE(mhi_chan->db_cfg.brstmode))
goto error_chan_cfg; goto error_chan_cfg;
@ -2055,17 +1942,7 @@ static int of_parse_dt(struct mhi_controller *mhi_cntrl,
ret = of_parse_ev_cfg(mhi_cntrl, of_node); ret = of_parse_ev_cfg(mhi_cntrl, of_node);
if (ret) if (ret)
goto error_ev_cfg; goto error_ev_cfg;
#if defined(QCOM_AP_QCA6490_DMA_IOMMU)
/* for QCS6490 iommu-dma is fastmap
for SG845 iommu-dma is set in driver
for ipq iommu-dma is disabled
*/
const char *str;
ret = of_property_read_string(of_node, "qcom,iommu-dma", &str);
if (ret)
MHI_ERR("mhi qcom,iommu-dma need set");
#endif
#if 0 #if 0
ret = of_property_read_u32(of_node, "mhi,timeout", ret = of_property_read_u32(of_node, "mhi,timeout",
&mhi_cntrl->timeout_ms); &mhi_cntrl->timeout_ms);
@ -2119,7 +1996,6 @@ int of_register_mhi_controller(struct mhi_controller *mhi_cntrl)
mhi_controller_minors[i].domain = mhi_cntrl->domain; mhi_controller_minors[i].domain = mhi_cntrl->domain;
mhi_controller_minors[i].bus = mhi_cntrl->bus; mhi_controller_minors[i].bus = mhi_cntrl->bus;
mhi_controller_minors[i].slot = mhi_cntrl->slot; mhi_controller_minors[i].slot = mhi_cntrl->slot;
mhi_controller_minors[i].mhi_cntrl = mhi_cntrl;
mhi_cntrl->cntrl_idx = i; mhi_cntrl->cntrl_idx = i;
break; break;
} }
@ -2672,11 +2548,7 @@ static int __init mhi_cntrl_init(void)
return ret; return ret;
mhi_cntrl_drv.major = ret; mhi_cntrl_drv.major = ret;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0))
mhi_cntrl_drv.class = class_create(MHI_CNTRL_DRIVER_NAME);
#else
mhi_cntrl_drv.class = class_create(THIS_MODULE, MHI_CNTRL_DRIVER_NAME); mhi_cntrl_drv.class = class_create(THIS_MODULE, MHI_CNTRL_DRIVER_NAME);
#endif
if (IS_ERR(mhi_cntrl_drv.class)) { if (IS_ERR(mhi_cntrl_drv.class)) {
unregister_chrdev(mhi_cntrl_drv.major, MHI_CNTRL_DRIVER_NAME); unregister_chrdev(mhi_cntrl_drv.major, MHI_CNTRL_DRIVER_NAME);
return -ENODEV; return -ENODEV;

View File

@ -860,15 +860,6 @@ struct mhi_ctrl_seg
struct mhi_tre sw_in_chan_ring[NUM_MHI_SW_IP_RING_ELEMENTS] __packed __aligned(NUM_MHI_IPA_IN_RING_ELEMENTS*16); struct mhi_tre sw_in_chan_ring[NUM_MHI_SW_IP_RING_ELEMENTS] __packed __aligned(NUM_MHI_IPA_IN_RING_ELEMENTS*16);
struct mhi_tre sw_out_chan_ring[NUM_MHI_SW_IP_RING_ELEMENTS] __packed __aligned(NUM_MHI_IPA_OUT_RING_ELEMENTS*16); struct mhi_tre sw_out_chan_ring[NUM_MHI_SW_IP_RING_ELEMENTS] __packed __aligned(NUM_MHI_IPA_OUT_RING_ELEMENTS*16);
#endif #endif
#ifdef ENABLE_ADPL
struct mhi_tre adpl_in_chan_ring[NUM_MHI_ADPL_RING_ELEMENTS] __packed __aligned(NUM_MHI_IPA_IN_RING_ELEMENTS*16);
#endif
#ifdef ENABLE_QDSS
struct mhi_tre qdss_in_chan_ring[NUM_MHI_QDSS_RING_ELEMENTS] __packed __aligned(NUM_MHI_IPA_IN_RING_ELEMENTS*16);
#endif
struct mhi_tre diag_in_chan_ring[NUM_MHI_DIAG_IN_RING_ELEMENTS] __packed __aligned(NUM_MHI_IPA_OUT_RING_ELEMENTS*16); struct mhi_tre diag_in_chan_ring[NUM_MHI_DIAG_IN_RING_ELEMENTS] __packed __aligned(NUM_MHI_IPA_OUT_RING_ELEMENTS*16);
struct mhi_tre chan_ring[NUM_MHI_CHAN_RING_ELEMENTS*2*12] __packed __aligned(NUM_MHI_CHAN_RING_ELEMENTS*16); struct mhi_tre chan_ring[NUM_MHI_CHAN_RING_ELEMENTS*2*12] __packed __aligned(NUM_MHI_CHAN_RING_ELEMENTS*16);
struct mhi_tre event_ring[NUM_MHI_EVT_RINGS][NUM_MHI_EVT_RING_ELEMENTS] __packed __aligned(NUM_MHI_EVT_RING_ELEMENTS*16); struct mhi_tre event_ring[NUM_MHI_EVT_RINGS][NUM_MHI_EVT_RING_ELEMENTS] __packed __aligned(NUM_MHI_EVT_RING_ELEMENTS*16);

View File

@ -919,7 +919,7 @@ static void mhi_create_time_sync_dev(struct mhi_controller *mhi_cntrl)
mhi_dev->dev_type = MHI_TIMESYNC_TYPE; mhi_dev->dev_type = MHI_TIMESYNC_TYPE;
mhi_dev->chan_name = "TIME_SYNC"; mhi_dev->chan_name = "TIME_SYNC";
dev_set_name(&mhi_dev->dev, "%04x_%02x.%02x.%02x_%s", mhi_dev->dev_id, dev_set_name(&mhi_dev->dev, "%04x_%02u.%02u.%02u_%s", mhi_dev->dev_id,
mhi_dev->domain, mhi_dev->bus, mhi_dev->slot, mhi_dev->domain, mhi_dev->bus, mhi_dev->slot,
mhi_dev->chan_name); mhi_dev->chan_name);
@ -1012,7 +1012,7 @@ void mhi_create_devices(struct mhi_controller *mhi_cntrl)
} }
mhi_dev->chan_name = mhi_chan->name; mhi_dev->chan_name = mhi_chan->name;
dev_set_name(&mhi_dev->dev, "%04x_%02x.%02x.%02x_%s", dev_set_name(&mhi_dev->dev, "%04x_%02u.%02u.%02u_%s",
mhi_dev->dev_id, mhi_dev->domain, mhi_dev->bus, mhi_dev->dev_id, mhi_dev->domain, mhi_dev->bus,
mhi_dev->slot, mhi_dev->chan_name); mhi_dev->slot, mhi_dev->chan_name);

View File

@ -748,8 +748,6 @@ void mhi_pm_ready_worker(struct work_struct *work)
schedule_delayed_work(&mhi_cntrl->ready_worker, msecs_to_jiffies(10)); schedule_delayed_work(&mhi_cntrl->ready_worker, msecs_to_jiffies(10));
else if (ee == MHI_EE_AMSS || ee == MHI_EE_SBL) else if (ee == MHI_EE_AMSS || ee == MHI_EE_SBL)
mhi_queue_state_transition(mhi_cntrl, MHI_ST_TRANSITION_READY); mhi_queue_state_transition(mhi_cntrl, MHI_ST_TRANSITION_READY);
else if (ee == MHI_EE_EDL)
mhi_queue_state_transition(mhi_cntrl, MHI_ST_TRANSITION_PBL);
} }
void mhi_pm_st_worker(struct work_struct *work) void mhi_pm_st_worker(struct work_struct *work)

View File

@ -30,16 +30,9 @@
#include <net/ipv6.h> #include <net/ipv6.h>
#include <net/tcp.h> #include <net/tcp.h>
#include <linux/usb/cdc.h> #include <linux/usb/cdc.h>
//#define CONFIG_IPQ5018_RATE_CONTROL //Only used with spf11.5 for IPQ5018
#if defined(CONFIG_IPQ5018_RATE_CONTROL)
//#include <linux/jiffies.h>
#include <asm/arch_timer.h>
#endif
#include "../core/mhi.h" #include "../core/mhi.h"
//#define MHI_NETDEV_ONE_CARD_MODE //#define MHI_NETDEV_ONE_CARD_MODE
//#define ANDROID_gki //some fuction not allow used in this TEST
#ifndef ETH_P_MAP #ifndef ETH_P_MAP
#define ETH_P_MAP 0xDA1A #define ETH_P_MAP 0xDA1A
@ -68,15 +61,13 @@ struct rmnet_nss_cb {
int (*nss_tx)(struct sk_buff *skb); int (*nss_tx)(struct sk_buff *skb);
}; };
static struct rmnet_nss_cb __read_mostly *nss_cb = NULL; static struct rmnet_nss_cb __read_mostly *nss_cb = NULL;
#if defined(CONFIG_PINCTRL_IPQ807x) || defined(CONFIG_PINCTRL_IPQ5018) || defined(CONFIG_PINCTRL_IPQ8074) #if defined(CONFIG_PINCTRL_IPQ807x) || defined(CONFIG_PINCTRL_IPQ5018)
//#ifdef CONFIG_RMNET_DATA //spf12.x have no macro defined, just for spf11.x #ifdef CONFIG_RMNET_DATA
#define CONFIG_QCA_NSS_DRV #define CONFIG_QCA_NSS_DRV
/* define at qsdk/qca/src/linux-4.4/net/rmnet_data/rmnet_data_main.c */ //for spf11.x /* define at qsdk/qca/src/linux-4.4/net/rmnet_data/rmnet_data_main.c */
/* define at qsdk/qca/src/datarmnet/core/rmnet_config.c */ //for spf12.x
/* set at qsdk/qca/src/data-kernel/drivers/rmnet-nss/rmnet_nss.c */ /* set at qsdk/qca/src/data-kernel/drivers/rmnet-nss/rmnet_nss.c */
/* need add DEPENDS:= kmod-rmnet-core in feeds/makefile */
extern struct rmnet_nss_cb *rmnet_nss_callbacks __rcu __read_mostly; extern struct rmnet_nss_cb *rmnet_nss_callbacks __rcu __read_mostly;
//#endif #endif
#endif #endif
static const unsigned char node_id[ETH_ALEN] = {0x02, 0x50, 0xf4, 0x00, 0x00, 0x00}; static const unsigned char node_id[ETH_ALEN] = {0x02, 0x50, 0xf4, 0x00, 0x00, 0x00};
@ -320,7 +311,6 @@ struct mhi_netdev {
MHI_MBIM_CTX mbim_ctx; MHI_MBIM_CTX mbim_ctx;
u32 mru; u32 mru;
u32 max_mtu;
const char *interface_name; const char *interface_name;
struct napi_struct napi; struct napi_struct napi;
struct net_device *ndev; struct net_device *ndev;
@ -352,7 +342,7 @@ struct mhi_netdev {
uint use_rmnet_usb; uint use_rmnet_usb;
RMNET_INFO rmnet_info; RMNET_INFO rmnet_info;
#if defined(CONFIG_IPQ5018_RATE_CONTROL) #if defined(CONFIG_PINCTRL_IPQ5018)
u64 first_jiffy; u64 first_jiffy;
u64 bytes_received_1; u64 bytes_received_1;
u64 bytes_received_2; u64 bytes_received_2;
@ -451,20 +441,18 @@ static int bridge_arp_reply(struct net_device *net, struct sk_buff *skb, uint br
pr_info("%s sip = %d.%d.%d.%d, tip=%d.%d.%d.%d, ipv4=%d.%d.%d.%d\n", netdev_name(net), pr_info("%s sip = %d.%d.%d.%d, tip=%d.%d.%d.%d, ipv4=%d.%d.%d.%d\n", netdev_name(net),
sip[0], sip[1], sip[2], sip[3], tip[0], tip[1], tip[2], tip[3], ipv4[0], ipv4[1], ipv4[2], ipv4[3]); sip[0], sip[1], sip[2], sip[3], tip[0], tip[1], tip[2], tip[3], ipv4[0], ipv4[1], ipv4[2], ipv4[3]);
//wwan0 sip = 10.151.137.255, tip=10.151.138.0, ipv4=10.151.137.255 //wwan0 sip = 10.151.137.255, tip=10.151.138.0, ipv4=10.151.137.255
#ifndef ANDROID_gki
if (tip[0] == ipv4[0] && tip[1] == ipv4[1] && (tip[2]&0xFC) == (ipv4[2]&0xFC) && tip[3] != ipv4[3]) if (tip[0] == ipv4[0] && tip[1] == ipv4[1] && (tip[2]&0xFC) == (ipv4[2]&0xFC) && tip[3] != ipv4[3])
reply = arp_create(ARPOP_REPLY, ETH_P_ARP, *((__be32 *)sip), net, *((__be32 *)tip), sha, default_modem_addr, sha); reply = arp_create(ARPOP_REPLY, ETH_P_ARP, *((__be32 *)sip), net, *((__be32 *)tip), sha, default_modem_addr, sha);
#endif
if (reply) { if (reply) {
skb_reset_mac_header(reply); skb_reset_mac_header(reply);
__skb_pull(reply, skb_network_offset(reply)); __skb_pull(reply, skb_network_offset(reply));
reply->ip_summed = CHECKSUM_UNNECESSARY; reply->ip_summed = CHECKSUM_UNNECESSARY;
reply->pkt_type = PACKET_HOST; reply->pkt_type = PACKET_HOST;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0)) #if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0)
netif_rx(reply);
#else
netif_rx_ni(reply); netif_rx_ni(reply);
#else
netif_rx(reply);
#endif #endif
} }
return 1; return 1;
@ -855,12 +843,12 @@ static void rmnet_vnd_upate_rx_stats(struct net_device *net,
struct pcpu_sw_netstats *stats64 = this_cpu_ptr(dev->stats64); struct pcpu_sw_netstats *stats64 = this_cpu_ptr(dev->stats64);
u64_stats_update_begin(&stats64->syncp); u64_stats_update_begin(&stats64->syncp);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) #if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0)
stats64->rx_packets += rx_packets; stats64->rx_packets += rx_packets;
stats64->rx_bytes += rx_bytes; stats64->rx_bytes += rx_bytes;
#else #else
u64_stats_add(&stats64->rx_packets, rx_packets); u64_stats_add(&stats64->rx_packets, rx_packets);
u64_stats_add(&stats64->rx_bytes, rx_bytes); u64_stats_add(&stats64->rx_bytes,rx_bytes);
#endif #endif
u64_stats_update_end(&stats64->syncp); u64_stats_update_end(&stats64->syncp);
#else #else
@ -876,12 +864,12 @@ static void rmnet_vnd_upate_tx_stats(struct net_device *net,
struct pcpu_sw_netstats *stats64 = this_cpu_ptr(dev->stats64); struct pcpu_sw_netstats *stats64 = this_cpu_ptr(dev->stats64);
u64_stats_update_begin(&stats64->syncp); u64_stats_update_begin(&stats64->syncp);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) #if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0)
stats64->tx_packets += tx_packets; stats64->tx_packets += tx_packets;
stats64->tx_bytes += tx_bytes; stats64->tx_bytes += tx_bytes;
#else #else
u64_stats_add(&stats64->tx_packets, tx_packets); u64_stats_add(&stats64->tx_packets, tx_packets);
u64_stats_add(&stats64->tx_bytes, tx_bytes); u64_stats_add(&stats64->tx_bytes,tx_bytes);
#endif #endif
u64_stats_update_end(&stats64->syncp); u64_stats_update_end(&stats64->syncp);
#else #else
@ -891,44 +879,13 @@ static void rmnet_vnd_upate_tx_stats(struct net_device *net,
} }
#if defined(MHI_NETDEV_STATUS64) #if defined(MHI_NETDEV_STATUS64)
#ifdef ANDROID_gki
static void _netdev_stats_to_stats64(struct rtnl_link_stats64 *stats64,
const struct net_device_stats *netdev_stats)
{
#if BITS_PER_LONG == 64
BUILD_BUG_ON(sizeof(*stats64) < sizeof(*netdev_stats));
memcpy(stats64, netdev_stats, sizeof(*netdev_stats));
/* zero out counters that only exist in rtnl_link_stats64 */
memset((char *)stats64 + sizeof(*netdev_stats), 0,
sizeof(*stats64) - sizeof(*netdev_stats));
#else
size_t i, n = sizeof(*netdev_stats) / sizeof(unsigned long);
const unsigned long *src = (const unsigned long *)netdev_stats;
u64 *dst = (u64 *)stats64;
BUILD_BUG_ON(n > sizeof(*stats64) / sizeof(u64));
for (i = 0; i < n; i++)
dst[i] = src[i];
/* zero out counters that only exist in rtnl_link_stats64 */
memset((char *)stats64 + n * sizeof(u64), 0,
sizeof(*stats64) - n * sizeof(u64));
#endif
}
#else
static void my_netdev_stats_to_stats64(struct rtnl_link_stats64 *stats64,
const struct net_device_stats *netdev_stats)
{
netdev_stats_to_stats64(stats64, netdev_stats);
}
#endif
static struct rtnl_link_stats64 *_rmnet_vnd_get_stats64(struct net_device *net, struct rtnl_link_stats64 *stats) static struct rtnl_link_stats64 *_rmnet_vnd_get_stats64(struct net_device *net, struct rtnl_link_stats64 *stats)
{ {
struct qmap_priv *dev = netdev_priv(net); struct qmap_priv *dev = netdev_priv(net);
unsigned int start; unsigned int start;
int cpu; int cpu;
my_netdev_stats_to_stats64(stats, &net->stats); netdev_stats_to_stats64(stats, &net->stats);
if (nss_cb && dev->use_qca_nss) { // rmnet_nss.c:rmnet_nss_tx() will update rx stats if (nss_cb && dev->use_qca_nss) { // rmnet_nss.c:rmnet_nss_tx() will update rx stats
stats->rx_packets = 0; stats->rx_packets = 0;
@ -937,7 +894,6 @@ static struct rtnl_link_stats64 *_rmnet_vnd_get_stats64(struct net_device *net,
for_each_possible_cpu(cpu) { for_each_possible_cpu(cpu) {
struct pcpu_sw_netstats *stats64; struct pcpu_sw_netstats *stats64;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0))
u64 rx_packets, rx_bytes; u64 rx_packets, rx_bytes;
u64 tx_packets, tx_bytes; u64 tx_packets, tx_bytes;
@ -945,35 +901,23 @@ static struct rtnl_link_stats64 *_rmnet_vnd_get_stats64(struct net_device *net,
do { do {
start = u64_stats_fetch_begin_irq(&stats64->syncp); start = u64_stats_fetch_begin_irq(&stats64->syncp);
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0)
rx_packets = stats64->rx_packets; rx_packets = stats64->rx_packets;
rx_bytes = stats64->rx_bytes; rx_bytes = stats64->rx_bytes;
tx_packets = stats64->tx_packets; tx_packets = stats64->tx_packets;
tx_bytes = stats64->tx_bytes; tx_bytes = stats64->tx_bytes;
#else
rx_packets = u64_stats_read(&stats64->rx_packets);
rx_bytes = u64_stats_read(&stats64->rx_bytes);
tx_packets = u64_stats_read(&stats64->tx_packets);
tx_bytes = u64_stats_read(&stats64->tx_bytes);
#endif
} while (u64_stats_fetch_retry_irq(&stats64->syncp, start)); } while (u64_stats_fetch_retry_irq(&stats64->syncp, start));
stats->rx_packets += rx_packets; stats->rx_packets += rx_packets;
stats->rx_bytes += rx_bytes; stats->rx_bytes += rx_bytes;
stats->tx_packets += tx_packets; stats->tx_packets += tx_packets;
stats->tx_bytes += tx_bytes; stats->tx_bytes += tx_bytes;
#else
u64_stats_t rx_packets, rx_bytes;
u64_stats_t tx_packets, tx_bytes;
stats64 = per_cpu_ptr(dev->stats64, cpu);
do {
start = u64_stats_fetch_begin(&stats64->syncp);
rx_packets = stats64->rx_packets;
rx_bytes = stats64->rx_bytes;
tx_packets = stats64->tx_packets;
tx_bytes = stats64->tx_bytes;
} while (u64_stats_fetch_retry(&stats64->syncp, start));
stats->rx_packets += u64_stats_read(&rx_packets);
stats->rx_bytes += u64_stats_read(&rx_bytes);
stats->tx_packets += u64_stats_read(&tx_packets);
stats->tx_bytes += u64_stats_read(&tx_bytes);
#endif
} }
return stats; return stats;
@ -1111,22 +1055,8 @@ static netdev_tx_t rmnet_vnd_start_xmit(struct sk_buff *skb,
static int rmnet_vnd_change_mtu(struct net_device *rmnet_dev, int new_mtu) static int rmnet_vnd_change_mtu(struct net_device *rmnet_dev, int new_mtu)
{ {
struct mhi_netdev *mhi_netdev; if (new_mtu < 0 || new_mtu > 1500)
mhi_netdev = (struct mhi_netdev *)ndev_to_mhi(rmnet_dev);
if (mhi_netdev == NULL) {
printk("warning, mhi_netdev == null\n");
return -EINVAL; return -EINVAL;
}
if (new_mtu < 0 )
return -EINVAL;
if (new_mtu > mhi_netdev->max_mtu) {
printk("warning, set mtu=%d greater than max mtu=%d\n", new_mtu, mhi_netdev->max_mtu);
return -EINVAL;
}
rmnet_dev->mtu = new_mtu; rmnet_dev->mtu = new_mtu;
return 0; return 0;
@ -1278,7 +1208,7 @@ static void rmnet_mbim_rx_handler(void *dev, struct sk_buff *skb_in)
MSG_ERR("unsupported tci %d by now\n", tci); MSG_ERR("unsupported tci %d by now\n", tci);
goto error; goto error;
} }
tci = abs(tci);
qmap_net = pQmapDev->mpQmapNetDev[qmap_mode == 1 ? 0 : tci - 1]; qmap_net = pQmapDev->mpQmapNetDev[qmap_mode == 1 ? 0 : tci - 1];
dpe16 = ndp16->dpe16; dpe16 = ndp16->dpe16;
@ -1407,21 +1337,8 @@ static void rmnet_qmi_rx_handler(void *dev, struct sk_buff *skb_in)
} }
#endif #endif
skb_len -= dl_minimum_padding; skb_len -= dl_minimum_padding;
if (skb_len > 1500) {
mux_id = map_header->mux_id - QUECTEL_QMAP_MUX_ID; netdev_info(ndev, "drop skb_len=%x larger than 1500\n", skb_len);
if (mux_id >= pQmapDev->qmap_mode) {
netdev_info(ndev, "drop qmap unknow mux_id %x\n", map_header->mux_id);
goto error_pkt;
}
mux_id = abs(mux_id);
qmap_net = pQmapDev->mpQmapNetDev[mux_id];
if (qmap_net == NULL) {
netdev_info(ndev, "drop qmap unknow mux_id %x\n", map_header->mux_id);
goto skip_pkt;
}
if (skb_len > qmap_net->mtu) {
netdev_info(ndev, "drop skb_len=%x larger than qmap mtu=%d\n", skb_len, qmap_net->mtu);
goto error_pkt; goto error_pkt;
} }
@ -1462,6 +1379,19 @@ static void rmnet_qmi_rx_handler(void *dev, struct sk_buff *skb_in)
netdev_info(ndev, "unknow skb->protocol %02x\n", skb_in->data[hdr_size]); netdev_info(ndev, "unknow skb->protocol %02x\n", skb_in->data[hdr_size]);
goto error_pkt; goto error_pkt;
} }
mux_id = map_header->mux_id - QUECTEL_QMAP_MUX_ID;
if (mux_id >= pQmapDev->qmap_mode) {
netdev_info(ndev, "drop qmap unknow mux_id %x\n", map_header->mux_id);
goto error_pkt;
}
qmap_net = pQmapDev->mpQmapNetDev[mux_id];
if (qmap_net == NULL) {
netdev_info(ndev, "drop qmap unknow mux_id %x\n", map_header->mux_id);
goto skip_pkt;
}
//for Qualcomm's SFE, do not use skb_clone(), or SFE 's performace is very bad. //for Qualcomm's SFE, do not use skb_clone(), or SFE 's performace is very bad.
//for Qualcomm's NSS, do not use skb_clone(), or NSS 's performace is very bad. //for Qualcomm's NSS, do not use skb_clone(), or NSS 's performace is very bad.
@ -1575,8 +1505,7 @@ static struct net_device * rmnet_vnd_register_device(struct mhi_netdev *pQmapDev
struct qmap_priv *priv; struct qmap_priv *priv;
int err; int err;
int use_qca_nss = !!nss_cb; int use_qca_nss = !!nss_cb;
unsigned char temp_addr[ETH_ALEN]; u8 maddr[ETH_ALEN];
qmap_net = alloc_etherdev(sizeof(*priv)); qmap_net = alloc_etherdev(sizeof(*priv));
if (!qmap_net) if (!qmap_net)
return NULL; return NULL;
@ -1589,21 +1518,11 @@ static struct net_device * rmnet_vnd_register_device(struct mhi_netdev *pQmapDev
priv->pQmapDev = pQmapDev; priv->pQmapDev = pQmapDev;
priv->qmap_version = pQmapDev->qmap_version; priv->qmap_version = pQmapDev->qmap_version;
priv->mux_id = mux_id; priv->mux_id = mux_id;
sprintf(qmap_net->name, "%.12s.%d", real_dev->name, offset_id + 1); sprintf(qmap_net->name, "%s.%d", real_dev->name, offset_id + 1);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)) ether_addr_copy(maddr, real_dev->dev_addr);
__dev_addr_set(qmap_net, real_dev->dev_addr, ETH_ALEN); maddr[5]= offset_id + 1;
#else ether_addr_copy((u8*)qmap_net->dev_addr, maddr);
memcpy (qmap_net->dev_addr, real_dev->dev_addr, ETH_ALEN); //eth_random_addr(qmap_net->dev_addr);
#endif
//qmap_net->dev_addr[5] = offset_id + 1;
//eth_random_addr(qmap_net->dev_addr);
memcpy(temp_addr, qmap_net->dev_addr, ETH_ALEN);
temp_addr[5] = offset_id + 1;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0))
__dev_addr_set(qmap_net, temp_addr, ETH_ALEN);
#else
memcpy(qmap_net->dev_addr, temp_addr, ETH_ALEN);
#endif
#if defined(MHI_NETDEV_STATUS64) #if defined(MHI_NETDEV_STATUS64)
priv->stats64 = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); priv->stats64 = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
if (!priv->stats64) if (!priv->stats64)
@ -1630,16 +1549,11 @@ static struct net_device * rmnet_vnd_register_device(struct mhi_netdev *pQmapDev
qmap_net->netdev_ops = &rmnet_vnd_ops; qmap_net->netdev_ops = &rmnet_vnd_ops;
qmap_net->flags |= IFF_NOARP; qmap_net->flags |= IFF_NOARP;
qmap_net->flags &= ~(IFF_BROADCAST | IFF_MULTICAST); qmap_net->flags &= ~(IFF_BROADCAST | IFF_MULTICAST);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)
qmap_net->max_mtu = pQmapDev->max_mtu;
#endif
if (nss_cb && use_qca_nss) { if (nss_cb && use_qca_nss) {
rmnet_vnd_rawip_setup(qmap_net); rmnet_vnd_rawip_setup(qmap_net);
} }
#ifdef CONFIG_PINCTRL_IPQ9574
rmnet_vnd_rawip_setup(qmap_net);
#endif
if (pQmapDev->net_type == MHI_NET_MBIM) { if (pQmapDev->net_type == MHI_NET_MBIM) {
qmap_net->needed_headroom = sizeof(struct mhi_mbim_hdr); qmap_net->needed_headroom = sizeof(struct mhi_mbim_hdr);
} }
@ -1812,13 +1726,14 @@ static void mhi_netdev_upate_rx_stats(struct mhi_netdev *mhi_netdev,
struct pcpu_sw_netstats *stats64 = this_cpu_ptr(mhi_netdev->stats64); struct pcpu_sw_netstats *stats64 = this_cpu_ptr(mhi_netdev->stats64);
u64_stats_update_begin(&stats64->syncp); u64_stats_update_begin(&stats64->syncp);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) #if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0)
stats64->rx_packets += rx_packets; stats64->rx_packets += rx_packets;
stats64->rx_bytes += rx_bytes; stats64->rx_bytes += rx_bytes;
#else #else
u64_stats_add(&stats64->rx_packets, rx_packets); u64_stats_add(&stats64->rx_packets, rx_packets);
u64_stats_add(&stats64->rx_bytes, rx_bytes); u64_stats_add(&stats64->rx_bytes,rx_bytes);
#endif #endif
u64_stats_update_begin(&stats64->syncp); u64_stats_update_begin(&stats64->syncp);
#else #else
mhi_netdev->ndev->stats.rx_packets += rx_packets; mhi_netdev->ndev->stats.rx_packets += rx_packets;
@ -1832,13 +1747,14 @@ static void mhi_netdev_upate_tx_stats(struct mhi_netdev *mhi_netdev,
struct pcpu_sw_netstats *stats64 = this_cpu_ptr(mhi_netdev->stats64); struct pcpu_sw_netstats *stats64 = this_cpu_ptr(mhi_netdev->stats64);
u64_stats_update_begin(&stats64->syncp); u64_stats_update_begin(&stats64->syncp);
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0)) #if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0)
stats64->tx_packets += tx_packets; stats64->tx_packets += tx_packets;
stats64->tx_bytes += tx_bytes; stats64->tx_bytes += tx_bytes;
#else #else
u64_stats_add(&stats64->tx_packets, tx_packets); u64_stats_add(&stats64->tx_packets, tx_packets);
u64_stats_add(&stats64->tx_bytes, tx_bytes); u64_stats_add(&stats64->tx_bytes,tx_bytes);
#endif #endif
u64_stats_update_begin(&stats64->syncp); u64_stats_update_begin(&stats64->syncp);
#else #else
mhi_netdev->ndev->stats.tx_packets += tx_packets; mhi_netdev->ndev->stats.tx_packets += tx_packets;
@ -2090,9 +2006,7 @@ static netdev_tx_t mhi_netdev_xmit(struct sk_buff *skb, struct net_device *dev)
//qmap_hex_dump(__func__, skb->data, 32); //qmap_hex_dump(__func__, skb->data, 32);
#ifdef MHI_NETDEV_ONE_CARD_MODE #ifdef MHI_NETDEV_ONE_CARD_MODE
//printk("%s dev->type=%d\n", __func__, dev->type); if (dev->type == ARPHRD_ETHER) {
if (dev->type == ARPHRD_ETHER) {
skb_reset_mac_header(skb); skb_reset_mac_header(skb);
#ifdef QUECTEL_BRIDGE_MODE #ifdef QUECTEL_BRIDGE_MODE
@ -2154,8 +2068,6 @@ static netdev_tx_t mhi_netdev_xmit(struct sk_buff *skb, struct net_device *dev)
res = mhi_queue_transfer(mhi_dev, DMA_TO_DEVICE, skb, skb->len, res = mhi_queue_transfer(mhi_dev, DMA_TO_DEVICE, skb, skb->len,
MHI_EOT); MHI_EOT);
//printk("%s transfer res=%d\n", __func__, res);
if (unlikely(res)) { if (unlikely(res)) {
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
dev->stats.tx_errors++; dev->stats.tx_errors++;
@ -2178,7 +2090,6 @@ static struct rtnl_link_stats64 * _mhi_netdev_get_stats64(struct net_device *nde
for_each_possible_cpu(cpu) { for_each_possible_cpu(cpu) {
struct pcpu_sw_netstats *stats64; struct pcpu_sw_netstats *stats64;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0))
u64 rx_packets, rx_bytes; u64 rx_packets, rx_bytes;
u64 tx_packets, tx_bytes; u64 tx_packets, tx_bytes;
@ -2186,35 +2097,23 @@ static struct rtnl_link_stats64 * _mhi_netdev_get_stats64(struct net_device *nde
do { do {
start = u64_stats_fetch_begin_irq(&stats64->syncp); start = u64_stats_fetch_begin_irq(&stats64->syncp);
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0)
rx_packets = stats64->rx_packets; rx_packets = stats64->rx_packets;
rx_bytes = stats64->rx_bytes; rx_bytes = stats64->rx_bytes;
tx_packets = stats64->tx_packets; tx_packets = stats64->tx_packets;
tx_bytes = stats64->tx_bytes; tx_bytes = stats64->tx_bytes;
#else
rx_packets = u64_stats_read(&stats64->rx_packets);
rx_bytes = u64_stats_read(&stats64->rx_bytes);
tx_packets = u64_stats_read(&stats64->tx_packets);
tx_bytes = u64_stats_read(&stats64->tx_bytes);
#endif
} while (u64_stats_fetch_retry_irq(&stats64->syncp, start)); } while (u64_stats_fetch_retry_irq(&stats64->syncp, start));
stats->rx_packets += rx_packets; stats->rx_packets += rx_packets;
stats->rx_bytes += rx_bytes; stats->rx_bytes += rx_bytes;
stats->tx_packets += tx_packets; stats->tx_packets += tx_packets;
stats->tx_bytes += tx_bytes; stats->tx_bytes += tx_bytes;
#else
u64_stats_t rx_packets, rx_bytes;
u64_stats_t tx_packets, tx_bytes;
stats64 = per_cpu_ptr(mhi_netdev->stats64, cpu);
do {
start = u64_stats_fetch_begin(&stats64->syncp);
rx_packets = stats64->rx_packets;
rx_bytes = stats64->rx_bytes;
tx_packets = stats64->tx_packets;
tx_bytes = stats64->tx_bytes;
} while (u64_stats_fetch_retry(&stats64->syncp, start));
stats->rx_packets += u64_stats_read(&rx_packets);
stats->rx_bytes += u64_stats_read(&rx_bytes);
stats->tx_packets += u64_stats_read(&tx_packets);
stats->tx_bytes += u64_stats_read(&tx_bytes);
#endif
} }
return stats; return stats;
@ -2323,11 +2222,7 @@ static void mhi_netdev_setup(struct net_device *dev)
ether_setup(dev); ether_setup(dev);
dev->ethtool_ops = &mhi_netdev_ethtool_ops; dev->ethtool_ops = &mhi_netdev_ethtool_ops;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0))
__dev_addr_set (dev, node_id, sizeof node_id);
#else
memcpy (dev->dev_addr, node_id, sizeof node_id); memcpy (dev->dev_addr, node_id, sizeof node_id);
#endif
/* set this after calling ether_setup */ /* set this after calling ether_setup */
dev->header_ops = 0; /* No header */ dev->header_ops = 0; /* No header */
dev->hard_header_len = 0; dev->hard_header_len = 0;
@ -2414,11 +2309,7 @@ static int mhi_netdev_enable_iface(struct mhi_netdev *mhi_netdev)
mhi_netdev->ndev->mtu = mhi_netdev->mru; mhi_netdev->ndev->mtu = mhi_netdev->mru;
} }
rtnl_unlock(); rtnl_unlock();
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)
mhi_netdev->ndev->max_mtu = mhi_netdev->max_mtu; //first net card
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0))
netif_napi_add_weight(mhi_netdev->ndev, &mhi_netdev->napi, mhi_netdev_poll, poll_weight); netif_napi_add_weight(mhi_netdev->ndev, &mhi_netdev->napi, mhi_netdev_poll, poll_weight);
#else #else
netif_napi_add(mhi_netdev->ndev, &mhi_netdev->napi, mhi_netdev_poll, poll_weight); netif_napi_add(mhi_netdev->ndev, &mhi_netdev->napi, mhi_netdev_poll, poll_weight);
@ -2519,7 +2410,7 @@ static void mhi_netdev_xfer_dl_cb(struct mhi_device *mhi_dev,
return; return;
} }
#if defined(CONFIG_IPQ5018_RATE_CONTROL) #if defined(CONFIG_PINCTRL_IPQ5018)
if (likely(mhi_netdev->mhi_rate_control)) { if (likely(mhi_netdev->mhi_rate_control)) {
u32 time_interval = 0; u32 time_interval = 0;
u32 time_difference = 0; u32 time_difference = 0;
@ -2529,11 +2420,7 @@ static void mhi_netdev_xfer_dl_cb(struct mhi_device *mhi_dev,
struct net_device *ndev = mhi_netdev->ndev; struct net_device *ndev = mhi_netdev->ndev;
if (mhi_netdev->first_jiffy) { if (mhi_netdev->first_jiffy) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,2,0)
second_jiffy = arch_counter_get_cntvct(); second_jiffy = arch_counter_get_cntvct();
#else
second_jiffy = __arch_counter_get_cntvct();
#endif
bytes_received_2 = mhi_netdev->bytes_received_2; bytes_received_2 = mhi_netdev->bytes_received_2;
if ((second_jiffy > mhi_netdev->first_jiffy) && if ((second_jiffy > mhi_netdev->first_jiffy) &&
(bytes_received_2 > mhi_netdev->bytes_received_1)) { (bytes_received_2 > mhi_netdev->bytes_received_1)) {
@ -2574,12 +2461,7 @@ static void mhi_netdev_xfer_dl_cb(struct mhi_device *mhi_dev,
mhi_netdev->bytes_received_1 = bytes_received_2; mhi_netdev->bytes_received_1 = bytes_received_2;
} }
} else { } else {
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,2,0)
mhi_netdev->first_jiffy = arch_counter_get_cntvct(); mhi_netdev->first_jiffy = arch_counter_get_cntvct();
#else
mhi_netdev->first_jiffy = __arch_counter_get_cntvct();
#endif
cntfrq = arch_timer_get_cntfrq(); cntfrq = arch_timer_get_cntfrq();
mhi_netdev->cntfrq_per_msec = cntfrq / 1000; mhi_netdev->cntfrq_per_msec = cntfrq / 1000;
} }
@ -2829,11 +2711,7 @@ static void mhi_netdev_remove(struct mhi_device *mhi_dev)
} }
rtnl_lock(); rtnl_lock();
#ifdef ANDROID_gki
if (mhi_netdev->ndev && rtnl_dereference(mhi_netdev->ndev->rx_handler))
#else
if (netdev_is_rx_handler_busy(mhi_netdev->ndev)) if (netdev_is_rx_handler_busy(mhi_netdev->ndev))
#endif
netdev_rx_handler_unregister(mhi_netdev->ndev); netdev_rx_handler_unregister(mhi_netdev->ndev);
rtnl_unlock(); rtnl_unlock();
#endif #endif
@ -2891,16 +2769,13 @@ static int mhi_netdev_probe(struct mhi_device *mhi_dev,
mhi_netdev->mhi_dev = mhi_dev; mhi_netdev->mhi_dev = mhi_dev;
mhi_device_set_devdata(mhi_dev, mhi_netdev); mhi_device_set_devdata(mhi_dev, mhi_netdev);
mhi_netdev->mru = (15*1024); ///etc/data/qnicorn_config.xml dataformat_agg_dl_size 15*1024 mhi_netdev->mru = 15360; ///etc/data/qnicorn_config.xml dataformat_agg_dl_size 15*1024
mhi_netdev->max_mtu = mhi_netdev->mru - (sizeof(struct rmnet_map_v5_csum_header) + sizeof(struct rmnet_map_header));
if (mhi_netdev->net_type == MHI_NET_MBIM) { if (mhi_netdev->net_type == MHI_NET_MBIM) {
mhi_netdev->mru = ncmNTBParams.dwNtbInMaxSize; mhi_netdev->mru = ncmNTBParams.dwNtbInMaxSize;
mhi_netdev->mbim_ctx.rx_max = mhi_netdev->mru; mhi_netdev->mbim_ctx.rx_max = mhi_netdev->mru;
mhi_netdev->max_mtu = mhi_netdev->mru - sizeof(struct mhi_mbim_hdr);
} }
else if (mhi_netdev->net_type == MHI_NET_ETHER) { else if (mhi_netdev->net_type == MHI_NET_ETHER) {
mhi_netdev->mru = 8*1024; mhi_netdev->mru = 8*1024;
mhi_netdev->max_mtu = mhi_netdev->mru;
} }
mhi_netdev->qmap_size = mhi_netdev->mru; mhi_netdev->qmap_size = mhi_netdev->mru;
@ -2983,7 +2858,7 @@ static int mhi_netdev_probe(struct mhi_device *mhi_dev,
#endif #endif
} }
#if defined(CONFIG_IPQ5018_RATE_CONTROL) #if defined(CONFIG_PINCTRL_IPQ5018)
mhi_netdev->mhi_rate_control = 1; mhi_netdev->mhi_rate_control = 1;
#endif #endif
@ -2993,8 +2868,7 @@ static int mhi_netdev_probe(struct mhi_device *mhi_dev,
static const struct mhi_device_id mhi_netdev_match_table[] = { static const struct mhi_device_id mhi_netdev_match_table[] = {
{ .chan = "IP_HW0" }, { .chan = "IP_HW0" },
{ .chan = "IP_SW0" }, { .chan = "IP_SW0" },
// ADPL do not register as a netcard. xingduo.du 2023-02-20 { .chan = "IP_HW_ADPL" },
// { .chan = "IP_HW_ADPL" },
{ }, { },
}; };
@ -3019,7 +2893,7 @@ int __init mhi_device_netdev_init(struct dentry *parent)
printk(KERN_ERR "mhi_device_netdev_init: driver load must after '/etc/modules.d/42-rmnet-nss'\n"); printk(KERN_ERR "mhi_device_netdev_init: driver load must after '/etc/modules.d/42-rmnet-nss'\n");
} }
#endif #endif
mhi_netdev_create_debugfs_dir(parent); mhi_netdev_create_debugfs_dir(parent);
return mhi_driver_register(&mhi_netdev_driver); return mhi_driver_register(&mhi_netdev_driver);

View File

@ -8,7 +8,8 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/version.h> #include <linux/version.h>
#if 1 #if 1
static inline void *ipc_log_context_create(int max_num_pages, static inline void *ipc_log_context_create(int max_num_pages,
const char *modname, uint16_t user_version) const char *modname, uint16_t user_version)
@ -98,44 +99,6 @@ module_param( uci_msg_lvl, uint, S_IRUGO | S_IWUSR);
#define MAX_UCI_DEVICES (64) #define MAX_UCI_DEVICES (64)
#define QUEC_MHI_UCI_ALWAYS_OPEN //by now, sdx20 can not handle "start-reset-start" operation, so the simply solution is keep start state #define QUEC_MHI_UCI_ALWAYS_OPEN //by now, sdx20 can not handle "start-reset-start" operation, so the simply solution is keep start state
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0))
#ifdef TCGETS2
__weak int user_termios_to_kernel_termios(struct ktermios *k,
struct termios2 __user *u)
{
return copy_from_user(k, u, sizeof(struct termios2));
}
__weak int kernel_termios_to_user_termios(struct termios2 __user *u,
struct ktermios *k)
{
return copy_to_user(u, k, sizeof(struct termios2));
}
__weak int user_termios_to_kernel_termios_1(struct ktermios *k,
struct termios __user *u)
{
return copy_from_user(k, u, sizeof(struct termios));
}
__weak int kernel_termios_to_user_termios_1(struct termios __user *u,
struct ktermios *k)
{
return copy_to_user(u, k, sizeof(struct termios));
}
#else
__weak int user_termios_to_kernel_termios(struct ktermios *k,
struct termios __user *u)
{
return copy_from_user(k, u, sizeof(struct termios));
}
__weak int kernel_termios_to_user_termios(struct termios __user *u,
struct ktermios *k)
{
return copy_to_user(u, k, sizeof(struct termios));
}
#endif /* TCGETS2 */
#endif
static DECLARE_BITMAP(uci_minors, MAX_UCI_DEVICES); static DECLARE_BITMAP(uci_minors, MAX_UCI_DEVICES);
static struct mhi_uci_drv mhi_uci_drv; static struct mhi_uci_drv mhi_uci_drv;
@ -197,7 +160,20 @@ static int mhi_queue_inbound(struct uci_dev *uci_dev)
return ret; return ret;
} }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)
#ifdef TCGETS2
static int kernel_termios_to_user_termios_1(struct termios __user *u,
struct ktermios *k)
{
return copy_to_user(u, k, sizeof(struct termios));
}
static int user_termios_to_kernel_termios_1(struct ktermios *k,
struct termios __user *u)
{
return copy_from_user(k, u, sizeof(struct termios));
}
#endif
#endif
static long mhi_uci_ioctl(struct file *file, static long mhi_uci_ioctl(struct file *file,
unsigned int cmd, unsigned int cmd,
unsigned long arg) unsigned long arg)
@ -295,8 +271,7 @@ static unsigned int mhi_uci_poll(struct file *file, poll_table *wait)
unsigned int mask = 0; unsigned int mask = 0;
poll_wait(file, &uci_dev->dl_chan.wq, wait); poll_wait(file, &uci_dev->dl_chan.wq, wait);
// ADPL and QDSS do not need poll write. xingduo.du 2023-02-16 poll_wait(file, &uci_dev->ul_chan.wq, wait);
// poll_wait(file, &uci_dev->ul_chan.wq, wait);
uci_chan = &uci_dev->dl_chan; uci_chan = &uci_dev->dl_chan;
spin_lock_bh(&uci_chan->lock); spin_lock_bh(&uci_chan->lock);
@ -308,26 +283,22 @@ static unsigned int mhi_uci_poll(struct file *file, poll_table *wait)
} }
spin_unlock_bh(&uci_chan->lock); spin_unlock_bh(&uci_chan->lock);
// ADPL and QDSS are single channel, ul_chan not be initilized. xingduo.du 2023-02-27 uci_chan = &uci_dev->ul_chan;
if (mhi_dev->ul_chan) { spin_lock_bh(&uci_chan->lock);
poll_wait(file, &uci_dev->ul_chan.wq, wait); if (!uci_dev->enabled) {
uci_chan = &uci_dev->ul_chan; mask |= POLLERR;
spin_lock_bh(&uci_chan->lock); } else if (mhi_get_no_free_descriptors(mhi_dev, DMA_TO_DEVICE) > 0) {
if (!uci_dev->enabled) { MSG_VERB("Client can write to node\n");
mask |= POLLERR; mask |= POLLOUT | POLLWRNORM;
} else if (mhi_get_no_free_descriptors(mhi_dev, DMA_TO_DEVICE) > 0) {
MSG_VERB("Client can write to node\n");
mask |= POLLOUT | POLLWRNORM;
}
if (!uci_dev->enabled)
mask |= POLLHUP;
if (uci_dev->rx_error)
mask |= POLLERR;
spin_unlock_bh(&uci_chan->lock);
} }
if (!uci_dev->enabled)
mask |= POLLHUP;
if (uci_dev->rx_error)
mask |= POLLERR;
spin_unlock_bh(&uci_chan->lock);
MSG_LOG("Client attempted to poll, returning mask 0x%x\n", mask); MSG_LOG("Client attempted to poll, returning mask 0x%x\n", mask);
return mask; return mask;
@ -822,10 +793,6 @@ static void mhi_dl_xfer_cb(struct mhi_device *mhi_dev,
unsigned nr_trb = uci_dev->nr_trb; unsigned nr_trb = uci_dev->nr_trb;
buf = &uci_dev->uci_buf[nr_trb]; buf = &uci_dev->uci_buf[nr_trb];
if (buf == NULL) {
MSG_ERR("buf = NULL");
return;
}
if (buf->nr_trb != nr_trb || buf->data != mhi_result->buf_addr) if (buf->nr_trb != nr_trb || buf->data != mhi_result->buf_addr)
{ {
uci_dev->rx_error++; uci_dev->rx_error++;
@ -908,8 +875,7 @@ static void mhi_dl_xfer_cb(struct mhi_device *mhi_dev,
wake_up(&uci_chan->wq); wake_up(&uci_chan->wq);
} }
// repaire sdx6x module can not read qdb file. xingduo.du 2023-01-18 #define DIAG_MAX_PCIE_PKT_SZ 2048 //define by module
#define DIAG_MAX_PCIE_PKT_SZ 8192 //define by module
/* .driver_data stores max mtu */ /* .driver_data stores max mtu */
static const struct mhi_device_id mhi_uci_match_table[] = { static const struct mhi_device_id mhi_uci_match_table[] = {
@ -921,12 +887,6 @@ static const struct mhi_device_id mhi_uci_match_table[] = {
{ .chan = "QMI0", .driver_data = 0x1000 }, { .chan = "QMI0", .driver_data = 0x1000 },
{ .chan = "QMI1", .driver_data = 0x1000 }, { .chan = "QMI1", .driver_data = 0x1000 },
{ .chan = "DUN", .driver_data = 0x1000 }, { .chan = "DUN", .driver_data = 0x1000 },
#ifdef ENABLE_ADPL
{ .chan = "ADPL", .driver_data = 0x1000 },
#endif
#ifdef ENABLE_QDSS
{ .chan = "QDSS", .driver_data = 0x1000 },
#endif
{}, {},
}; };
@ -951,11 +911,7 @@ int mhi_device_uci_init(void)
return ret; return ret;
mhi_uci_drv.major = ret; mhi_uci_drv.major = ret;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0))
mhi_uci_drv.class = class_create(MHI_UCI_DRIVER_NAME);
#else
mhi_uci_drv.class = class_create(THIS_MODULE, MHI_UCI_DRIVER_NAME); mhi_uci_drv.class = class_create(THIS_MODULE, MHI_UCI_DRIVER_NAME);
#endif
if (IS_ERR(mhi_uci_drv.class)) { if (IS_ERR(mhi_uci_drv.class)) {
unregister_chrdev(mhi_uci_drv.major, MHI_UCI_DRIVER_NAME); unregister_chrdev(mhi_uci_drv.major, MHI_UCI_DRIVER_NAME);
return -ENODEV; return -ENODEV;

View File

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

View File

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

View File

@ -9,7 +9,7 @@ CC:=$(CROSS-COMPILE)gcc
endif endif
LD:=$(CROSS-COMPILE)ld LD:=$(CROSS-COMPILE)ld
QL_CM_SRC=QmiWwanCM.c GobiNetCM.c main.c QCQMUX.c QMIThread.c util.c qmap_bridge_mode.c mbim-cm.c device.c 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+=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,26 +21,25 @@ 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 out/quectel-CM ${LDFLAGS} $(CC) ${CFLAGS} ${QL_CM_SRC} ${QL_CM_DHCP} -o quectel-CM ${LDFLAGS}
debug: clean debug: clean
$(CC) ${CFLAGS} -g -DCM_DEBUG ${QL_CM_SRC} ${QL_CM_DHCP} -o out/quectel-CM -lpthread -ldl -lrt $(CC) ${CFLAGS} -g -DCM_DEBUG ${QL_CM_SRC} ${QL_CM_DHCP} -o quectel-CM -lpthread -ldl -lrt
qmi-proxy: qmi-proxy:
$(CC) ${CFLAGS} quectel-qmi-proxy.c -o out/quectel-qmi-proxy ${LDFLAGS} $(CC) ${CFLAGS} quectel-qmi-proxy.c -o quectel-qmi-proxy ${LDFLAGS}
mbim-proxy: mbim-proxy:
$(CC) ${CFLAGS} quectel-mbim-proxy.c -o out/quectel-mbim-proxy ${LDFLAGS} $(CC) ${CFLAGS} quectel-mbim-proxy.c -o quectel-mbim-proxy ${LDFLAGS}
qrtr-proxy: qrtr-proxy:
$(CC) ${CFLAGS} quectel-qrtr-proxy.c -o out/quectel-qrtr-proxy ${LDFLAGS} $(CC) ${CFLAGS} quectel-qrtr-proxy.c -o quectel-qrtr-proxy ${LDFLAGS}
atc-proxy: atc-proxy:
$(CC) ${CFLAGS} quectel-atc-proxy.c atchannel.c at_tok.c util.c -o out/quectel-atc-proxy ${LDFLAGS} $(CC) ${CFLAGS} quectel-atc-proxy.c atchannel.c at_tok.c util.c -o quectel-atc-proxy ${LDFLAGS}
clean: clean:
cd out/; rm -rf *.o libmnl/*.o quectel-CM quectel-qmi-proxy quectel-mbim-proxy quectel-atc-proxy rm -rf *.o libmnl/*.o quectel-CM quectel-qmi-proxy quectel-mbim-proxy quectel-atc-proxy

View File

@ -1,394 +0,0 @@
/******************************************************************************
@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

View File

@ -1,320 +0,0 @@
/******************************************************************************
@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

View File

@ -1,477 +0,0 @@
/******************************************************************************
@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);
}

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,7 @@
None. None.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2016 - 2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. Copyright (c) 2016 - 2020 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->profile_index && !s_is_cdma) { //cdma only support one pdp, so no need to set profile index if (profile->pdp && !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->profile_index; pProfileIndex->ProfileIndex = profile->pdp;
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,13 +478,6 @@ 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);
@ -503,7 +496,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->profile_index; pMUXMsg->GetProfileSettingsReq.ProfileIndex = profile->pdp;
return sizeof(QMIWDS_GET_PROFILE_SETTINGS_REQ_MSG); return sizeof(QMIWDS_GET_PROFILE_SETTINGS_REQ_MSG);
} }
@ -517,7 +510,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->profile_index; pMUXMsg->ModifyProfileSettingsReq.ProfileIndex = profile->pdp;
pTLV = (UCHAR *)(&pMUXMsg->ModifyProfileSettingsReq + 1); pTLV = (UCHAR *)(&pMUXMsg->ModifyProfileSettingsReq + 1);
@ -766,8 +759,6 @@ 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
@ -1867,9 +1858,8 @@ 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 err; return le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXError);
} }
if (curIpFamily == IpFamilyV4) { if (curIpFamily == IpFamilyV4) {
@ -2036,8 +2026,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[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]); dbg_time("%s[%d] %s/%s/%s/%d/%s", __func__, profile->pdp, profile->apn, profile->user, profile->password, profile->auth,ipStr[profile->iptype]);
if (!profile->profile_index) if (!profile->pdp)
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)
@ -2067,9 +2057,6 @@ 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';
@ -2086,52 +2073,19 @@ 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); pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS, QMIWDS_GET_PROFILE_SETTINGS_REQ, WdsGetProfileSettingsReqSend, profile);
err = QmiThreadSendQMI(pRequest, &pResponse);s_pResponse = malloc(le16_to_cpu(pResponse->QMIHdr.Length) + 1); err = QmiThreadSendQMI(pRequest, &pResponse);
qmi_rsp_check_and_return(); if (err == 0 && pResponse && le16_to_cpu(pResponse->MUXMsg.QMUXMsgHdrResp.QMUXResult)
&& le16_to_cpu(pResponse->MUXMsg.QMUXMsgHdrResp.QMUXError) == QMI_ERR_EXTENDED_INTERNAL)
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; free(pResponse);
uint8 k = 2; pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS, QMIWDS_CREATE_PROFILE_REQ, WdsCreateProfileSettingsReqSend, profile);
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);
err = QmiThreadSendQMI(pRequest, &pResponse); err = QmiThreadSendQMI(pRequest, &pResponse);
qmi_rsp_check_and_return(); qmi_rsp_check_and_return();
free(pResponse);
pPdpContext = (PQMIWDS_PDPCONTEXT)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x25); goto _re_check;
if(pPdpContext->pdp_context == profile->pdp)
break;
else
free(pResponse);
if(i == profile_num-1)
{
pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS, QMIWDS_CREATE_PROFILE_REQ, WdsCreateProfileSettingsReqSend, profile);
err = QmiThreadSendQMI(pRequest, &pResponse);
qmi_rsp_check_and_return();
free(pResponse);
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);
@ -2152,7 +2106,7 @@ _re_check:
profile->old_iptype = pIpType->IPType; profile->old_iptype = pIpType->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]); 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]);
free(pResponse); free(pResponse);
return 0; return 0;

View File

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

View File

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

View File

@ -1,26 +1,5 @@
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:

View File

@ -9,7 +9,7 @@
None. None.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2016 - 2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
Quectel Wireless Solution Proprietary and Confidential. Quectel Wireless Solution Proprietary and Confidential.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
******************************************************************************/ ******************************************************************************/
@ -45,18 +45,6 @@ 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 \
@ -515,7 +503,6 @@ 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
@ -712,11 +699,7 @@ 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);
}
} }
} }
@ -842,11 +825,7 @@ 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;
} }
} }

View File

@ -9,7 +9,7 @@
None. None.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2016 - 2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
Quectel Wireless Solution Proprietary and Confidential. Quectel Wireless Solution Proprietary and Confidential.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
******************************************************************************/ ******************************************************************************/
@ -32,21 +32,21 @@
#include "QMIThread.h" #include "QMIThread.h"
#include "ethtool-copy.h" #include "ethtool-copy.h"
#define USB_CLASS_VENDOR_SPEC 0xff #define USB_CLASS_VENDOR_SPEC 0xff
#define USB_CLASS_COMM 2 #define USB_CLASS_COMM 2
#define USB_CDC_SUBCLASS_ACM 0x02 #define USB_CDC_SUBCLASS_ACM 0x02
#define USB_CDC_SUBCLASS_ETHERNET 0x06 #define USB_CDC_SUBCLASS_ETHERNET 0x06
#define USB_CDC_SUBCLASS_NCM 0x0d #define USB_CDC_SUBCLASS_NCM 0x0d
#define USB_CDC_SUBCLASS_MBIM 0x0e #define USB_CDC_SUBCLASS_MBIM 0x0e
#define USB_CLASS_WIRELESS_CONTROLLER 0xe0 #define USB_CLASS_WIRELESS_CONTROLLER 0xe0
#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,8 +78,7 @@ error:
* 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;
@ -102,14 +101,13 @@ 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 */
@ -190,17 +188,16 @@ 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];
devname[0] = 0; devname[0] = 0;
if (access(path, R_OK)) if (access(path, R_OK))
@ -223,7 +220,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);
@ -232,8 +229,7 @@ step_1:
/* 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));
@ -243,9 +239,9 @@ step_1:
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);
} }
@ -258,11 +254,11 @@ step_1:
* 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));
@ -273,9 +269,9 @@ BOOL qmidevice_detect(char *qmichannel, char *usbnet_adapter, unsigned bufsize,
goto error; goto error;
} }
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;
@ -289,15 +285,15 @@ BOOL qmidevice_detect(char *qmichannel, char *usbnet_adapter, unsigned bufsize,
if (profile->usb_dev.idVendor == 0x2c7c || profile->usb_dev.idVendor == 0x05c6) { if (profile->usb_dev.idVendor == 0x2c7c || profile->usb_dev.idVendor == 0x05c6) {
dbg_time("Find %s/%s idVendor=0x%x idProduct=0x%x, bus=0x%03x, dev=0x%03x", dbg_time("Find %s/%s idVendor=0x%x idProduct=0x%x, bus=0x%03x, dev=0x%03x",
rootdir, ent->d_name, profile->usb_dev.idVendor, profile->usb_dev.idProduct, rootdir, ent->d_name, profile->usb_dev.idVendor, profile->usb_dev.idProduct,
profile->usb_dev.busnum, profile->usb_dev.devnum); profile->usb_dev.busnum, profile->usb_dev.devnum);
} }
/* get network interface */ /* get network interface */
/* NOTICE: there is a case that, bNumberInterface=6, but the net interface is 8 */ /* NOTICE: there is a case that, bNumberInterface=6, but the net interface is 8 */
/* toolchain-mips_24kc_gcc-5.4.0_musl donot support GLOB_BRACE */ /* toolchain-mips_24kc_gcc-5.4.0_musl donot support GLOB_BRACE */
/* RG500U's MBIM is at inteface 0 */ /* RG500U's MBIM is at inteface 0 */
for (netIntf = 0; netIntf < (profile->usb_dev.bNumInterfaces + 8); netIntf++) { for (netIntf = 0; netIntf < (profile->usb_dev.bNumInterfaces + 8); netIntf++) {
snprintf(pl->path, sizeof(pl->path), "%s/%s:1.%d/net", rootdir, ent->d_name, netIntf); snprintf(pl->path, sizeof(pl->path), "%s/%s:1.%d/net", rootdir, ent->d_name, netIntf);
dir_get_child(pl->path, netcard, sizeof(netcard), NULL); dir_get_child(pl->path, netcard, sizeof(netcard), NULL);
if (netcard[0]) if (netcard[0])
@ -305,7 +301,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);
@ -334,31 +330,27 @@ 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; case 0x0900: //RG500U
case 0x0900: //RG500U atIntf = 4;
atIntf = 4; break;
break; case 0x6026: //EC200T
case 0x6026: //EC200T case 0x6005: //EC200A
case 0x6005: //EC200A case 0x6002: //EC200S
case 0x6002: //EC200S case 0x6001: //EC100Y
case 0x6001: //EC100Y atIntf = 3;
case 0x6007: //EG915Q-NA in ECM mode, it also could set atIntf to 4 break;
atIntf = 3; default:
break; dbg_time("unknow at interface for USB idProduct:%04x\n", profile->usb_dev.idProduct);
default: break;
dbg_time("unknow at interface for USB idProduct:%04x\n", profile->usb_dev.idProduct);
break;
} }
} }
@ -371,7 +363,7 @@ BOOL qmidevice_detect(char *qmichannel, char *usbnet_adapter, unsigned bufsize,
} }
} }
} }
if (netcard[0] && devname[0]) { if (netcard[0] && devname[0]) {
if (devname[0] == '/') if (devname[0] == '/')
snprintf(qmichannel, bufsize, "%s", devname); snprintf(qmichannel, bufsize, "%s", devname);
@ -391,51 +383,76 @@ 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 pNode = strstr(ent->d_name, "_IP_HW0"); //0306_00.01.00_IP_HW0
if (!pNode) if (!pNode) {
continue; continue;
}
char *d_name[32];
strcpy(d_name, ent->d_name);
replaceStr(d_name, "_IP_HW0", "");
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' */
sprintf(usbnet_adapter, "%s", netcard); sprintf(usbnet_adapter, "%s", netcard);
sprintf(qmichannel, "qrtr-%d", 3); // 3 is sdx modem's node id sprintf(qmichannel, "qrtr-%d", 3); // 3 is sdx modem's node id
@ -446,42 +463,59 @@ int mhidevice_detect(char *qmichannel, char *usbnet_adapter, PROFILE_T *profile)
continue; continue;
} }
snprintf(path, sizeof(path), "%s/%.13s_IPCR", rootdir, ent->d_name); //解决PCIE硬编码导致不兼容hv问题
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/%.13s_QMI0", rootdir, ent->d_name); snprintf(path, sizeof(path), "%s/%s_QMI0", rootdir, d_name);
if (access(path, F_OK)) { if (access(path, F_OK)) {
snprintf(path, sizeof(path), "%s/%.13s_MBIM", rootdir, ent->d_name); snprintf(path, sizeof(path), "%s/%s_MBIM", rootdir, 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;
} }
int atdevice_detect(char *atchannel, char *usbnet_adapter, PROFILE_T *profile) { 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;
} }
@ -489,65 +523,58 @@ 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;
break; break;
case USB_CDC_SUBCLASS_ETHERNET: case USB_CDC_SUBCLASS_ETHERNET:
case USB_CDC_SUBCLASS_NCM: case USB_CDC_SUBCLASS_NCM:
return SOFTWARE_ECM_RNDIS_NCM; return SOFTWARE_ECM_RNDIS_NCM;
break; break;
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;
} }
dbg_time("%s unknow bInterfaceClass=%d, bInterfaceSubClass=%d", __func__, dbg_time("%s unknow bInterfaceClass=%d, bInterfaceSubClass=%d", __func__,
profile->usb_intf.bInterfaceClass, profile->usb_intf.bInterfaceSubClass); profile->usb_intf.bInterfaceClass, profile->usb_intf.bInterfaceSubClass);
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 */
void *data; /* param buffer (in, or out) */ void *data; /* param buffer (in, or out) */
}; };
#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) {
@ -558,8 +585,7 @@ 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;
@ -571,8 +597,7 @@ 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;
@ -584,15 +609,13 @@ 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;
} }
@ -603,11 +626,11 @@ 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 */
memset(&ifr, 0, sizeof(ifr)); memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, devname); strcpy(ifr.ifr_name, devname);
@ -619,7 +642,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));
@ -634,11 +657,10 @@ 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 */
memset(&ifr, 0, sizeof(ifr)); memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, devname); strcpy(ifr.ifr_name, devname);
@ -651,7 +673,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));
@ -666,17 +688,16 @@ 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)
@ -684,13 +705,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);
} }
@ -698,8 +719,7 @@ 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;
@ -726,16 +746,16 @@ int ql_capture_usbmon_log(PROFILE_T *profile, const char *log_path)
profile->usbmon_logfile_fp = fopen(log_path, "wb"); profile->usbmon_logfile_fp = fopen(log_path, "wb");
if (!profile->usbmon_logfile_fp) { if (!profile->usbmon_logfile_fp) {
dbg_time("open %s error(%d) (%s)", log_path, errno, strerror(errno)); dbg_time("open %s error(%d) (%s)", log_path, errno, strerror(errno));
close(profile->usbmon_fd); close(profile->usbmon_fd);
profile->usbmon_fd = -1; profile->usbmon_fd = -1;
return -1; return -1;
} }
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;
} }

View File

@ -9,7 +9,7 @@
None. None.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2016 -2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. Copyright (c) 2016 -2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
Quectel Wireless Solution Proprietary and Confidential. Quectel Wireless Solution Proprietary and Confidential.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
******************************************************************************/ ******************************************************************************/
@ -58,10 +58,8 @@ 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)
if (!profile->udhcpc_ip) return 1; return 1; //TODO
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) {
@ -250,7 +248,6 @@ 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);
@ -370,15 +367,6 @@ 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)
@ -728,11 +716,6 @@ 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) {
@ -774,7 +757,6 @@ 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--;
@ -883,10 +865,6 @@ 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++];
@ -921,7 +899,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.5.1"); dbg_time("QConnectManager_Linux_V1.6.4");
ret = parse_user_input(argc, argv, ctx); ret = parse_user_input(argc, argv, ctx);
if (!ret) if (!ret)

View File

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

View File

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

View File

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

View File

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

View File

@ -9,7 +9,7 @@
None. None.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2016 - 2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. Copyright (c) 2016 - 2020 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 "QCQMI.h" #include "MPQMI.h"
#include "QCQCTL.h" #include "MPQCTL.h"
#include "QCQMUX.h" #include "MPQMUX.h"
#ifndef MIN #ifndef MIN
#define MIN(a, b) ((a) < (b)? (a): (b)) #define MIN(a, b) ((a) < (b)? (a): (b))
@ -117,8 +117,6 @@ 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;
@ -170,8 +168,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) {
dprintf("bind %s errno: %d (%s)\n", name, errno, strerror(errno));
close(sockfd); close(sockfd);
dprintf("bind %s errno: %d (%s)\n", name, errno, strerror(errno));
return -1; return -1;
} }
@ -203,7 +201,7 @@ static void accept_qmi_connection(int serverfd) {
cfmakenoblock(clientfd); cfmakenoblock(clientfd);
} }
static void cleanup_qmi_connection(int clientfd, int clientDisconnect) { static void cleanup_qmi_connection(int clientfd) {
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) {
@ -213,33 +211,8 @@ static void cleanup_qmi_connection(int clientfd, int clientDisconnect) {
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) { dprintf("xxx ClientFd=%d QMIType=%d ClientId=%d\n", qmi_con->ClientFd, qmi_client->QMIType, qmi_client->ClientId);
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);
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);
} }
@ -300,13 +273,12 @@ 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;
char buf[128]; printf("%c %d %u: ", flag, fd, size);
int cnt = 0; if (size > 16)
size = 16;
cnt += snprintf(buf + cnt, sizeof(buf) - cnt, "%c %d %u: ", flag, fd, size); for (i = 0; i < size; i++)
for (i = 0; i < size && i < 24; i++) printf("%02x ", ((uint8_t *)pQMI)[i]);
cnt += snprintf(buf + cnt, sizeof(buf) - cnt, "%02x ", ((uint8_t *)pQMI)[i]); printf("\n");
dprintf("%s\n", buf)
} }
} }
@ -355,51 +327,40 @@ 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 qlist_for_each(con_node, &qmi_proxy_connection) {
|| qmi_msg->qmi[0].CTLMsg.QMICTLMsgHdrRsp.QMICTLType != pQMI->CTLMsg.QMICTLMsgHdrRsp.QMICTLType) { QMI_PROXY_CONNECTION *qmi_con = qnode_to_item(con_node, QMI_PROXY_CONNECTION, qnode);
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) {
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) ||
else if (le16toh(pQMI->CTLMsg.QMICTLMsgHdrRsp.QMICTLType) == QMICTL_RELEASE_CLIENT_ID_RESP) { (le16toh(pQMI->CTLMsg.QMICTLMsgHdrRsp.QMICTLType) == QMICTL_REVOKE_CLIENT_ID_IND)) {
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)
else { modem_reset_flag = 1;
} }
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 {
@ -419,10 +380,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 == -1) if (qmi_proxy_server_fd <= 0) {
return -1; send_qmi_to_cdc_wdm(pQMI);
}
if (pQMI->QMIHdr.QMIType == QMUX_TYPE_CTL) { else 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) {
@ -430,13 +391,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 {
@ -446,7 +407,7 @@ static int recv_qmi_from_client(PQCQMIMSG pQMI, unsigned size, int clientfd) {
return 0; return 0;
} }
static int qmi_proxy_init(unsigned retry) { static int qmi_proxy_init(void) {
unsigned i; unsigned i;
QCQMIMSG _QMI; QCQMIMSG _QMI;
PQCQMIMSG pQMI = &_QMI; PQCQMIMSG pQMI = &_QMI;
@ -461,10 +422,10 @@ static int qmi_proxy_init(unsigned retry) {
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 < retry; i++) { for (i = 0; i < 10; i++) {
pQMI->CTLMsg.SyncReq.TransactionId = i+1; pQMI->CTLMsg.SyncReq.TransactionId = i+1;
pQMI->CTLMsg.SyncReq.QMICTLType = htole16(QMICTL_SYNC_REQ); pQMI->CTLMsg.SyncReq.QMICTLType = QMICTL_SYNC_REQ;
pQMI->CTLMsg.SyncReq.Length = htole16(0); pQMI->CTLMsg.SyncReq.Length = 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);
@ -481,6 +442,22 @@ static int qmi_proxy_init(unsigned retry) {
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;
@ -533,7 +510,7 @@ static void *qmi_proxy_loop(void *param)
do { do {
//ret = poll(pollfds, nevents, -1); //ret = poll(pollfds, nevents, -1);
ret = poll(pollfds, nevents, (qmi_proxy_server_fd > 0) ? -1 : 200); ret = poll(pollfds, nevents, (qmi_proxy_server_fd > 0) ? -1 : 200);
} while (ret == -1 && errno == EINTR && qmi_proxy_quit == 0); } while (ret == -1 && errno == EINTR && qmi_proxy_quit == 0);
if (ret < 0) { if (ret < 0) {
dprintf("%s poll=%d, errno: %d (%s)\n", __func__, ret, errno, strerror(errno)); dprintf("%s poll=%d, errno: %d (%s)\n", __func__, ret, errno, strerror(errno));
@ -551,7 +528,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, 1); cleanup_qmi_connection(fd);
} }
continue; continue;
@ -589,7 +566,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, 1); cleanup_qmi_connection(fd);
break; break;
} }
@ -608,7 +585,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, 0); cleanup_qmi_connection(qmi_con->ClientFd);
} }
dprintf("%s exit, thread_id %p\n", __func__, (void *)pthread_self()); dprintf("%s exit, thread_id %p\n", __func__, (void *)pthread_self());
@ -624,7 +601,8 @@ 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);
} }
@ -633,6 +611,7 @@ 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;
@ -653,47 +632,62 @@ 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) {
cdc_wdm_fd = open(cdc_wdm, O_RDWR | O_NONBLOCK | O_NOCTTY); if (access(cdc_wdm, R_OK | W_OK)) {
if (cdc_wdm_fd == -1) { dprintf("Fail to access %s, errno: %d (%s). continue\n", cdc_wdm, errno, strerror(errno));
dprintf("Failed to open %s, errno: %d (%s)\n", cdc_wdm, errno, strerror(errno)); // wait device
sleep(3); sleep(3);
continue; continue;
} }
cdc_wdm_fd = open(cdc_wdm, O_RDWR | O_NONBLOCK | O_NOCTTY);
if (cdc_wdm_fd == -1) {
dprintf("Failed to open %s, errno: %d (%s). break\n", cdc_wdm, errno, strerror(errno));
return -1;
}
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 */
if (qmi_proxy_init(60) == 0) { while (qmi_proxy_init() != 0) {
qmi_proxy_server_fd = create_local_server(servername); if (retry_times < 5) {
dprintf("qmi_proxy_server_fd = %d\n", qmi_proxy_server_fd); dprintf("fail to init proxy, try again in 2 seconds.\n");
if (qmi_proxy_server_fd == -1) { sleep(2);
dprintf("Failed to create %s, errno: %d (%s)\n", servername, errno, strerror(errno)); retry_times++;
pthread_cancel(thread_id); } 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;
} }
else { retry_times = 0;
pthread_cancel(thread_id); qmi_start_server(servername);
} if (qmi_proxy_server_fd == -1)
pthread_cancel(thread_id);
pthread_join(thread_id, NULL); pthread_join(thread_id, NULL);
thread_id = 0;
if (qmi_proxy_server_fd != -1) { /* close local server at last */
dprintf("close server %s\n", servername); qmi_close_server(servername);
close(qmi_proxy_server_fd);
qmi_proxy_server_fd = -1;
}
close(cdc_wdm_fd); close(cdc_wdm_fd);
cdc_wdm_fd = -1; /* DO RESTART IN 20s IF MODEM RESET ITSELF */
if (modem_reset_flag) {
if (qmi_proxy_quit == 0) unsigned int time_to_wait = 20;
sleep(modem_reset_flag ? 30 : 3); while (time_to_wait) {
modem_reset_flag = 0; time_to_wait = sleep(time_to_wait);
}
modem_reset_flag = 0;
}
} }
return 0; return 0;

View File

@ -9,7 +9,7 @@
None. None.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2016 - 2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. Copyright (c) 2016 - 2020 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 "QCQMI.h" #include "MPQMI.h"
#include "QCQCTL.h" #include "MPQCTL.h"
#include "QCQMUX.h" #include "MPQMUX.h"
static const char * get_time(void) { static const char * get_time(void) {
static char time_buf[128]; static char time_buf[128];

View File

@ -9,7 +9,7 @@
None. None.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2016 - 2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
Quectel Wireless Solution Proprietary and Confidential. Quectel Wireless Solution Proprietary and Confidential.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
******************************************************************************/ ******************************************************************************/
@ -105,17 +105,6 @@ 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;
@ -126,6 +115,7 @@ 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;
@ -145,12 +135,14 @@ 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__);
ifc_set_state(ifname, 0); snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s down", ifname);
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;
ifc_set_state(ifname, 1); snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s up", ifname);
ql_system(shell_cmd);
} }
close(fd); close(fd);
@ -219,7 +211,8 @@ 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))) {
ifc_set_state(profile->usbnet_adapter, 0); snprintf(link_file, sizeof(link_file), "ifconfig %s down", profile->usbnet_adapter);
ql_system(link_file);
} }
} }
@ -477,6 +470,7 @@ 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);
@ -489,13 +483,17 @@ void udhcpc_start(PROFILE_T *profile) {
} }
if (strcmp(ifname, profile->usbnet_adapter)) { if (strcmp(ifname, profile->usbnet_adapter)) {
ifc_set_state(profile->usbnet_adapter, 1); snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s up", profile->usbnet_adapter);
ql_system(shell_cmd);
if (ifc_get_flags(ifname)&IFF_UP) { if (ifc_get_flags(ifname)&IFF_UP) {
ifc_set_state(ifname, 0); snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s down", ifname);
ql_system(shell_cmd);
} }
} }
ifc_set_state(ifname, 1); snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s up", ifname);
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));
@ -530,7 +528,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->no_dhcp || profile->request_ops == &mbim_request_ops) { //lots of mbim modem do not support DHCP if (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
@ -581,16 +579,9 @@ 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
profile->udhcpc_ip = 0; && !ql_netcard_ipv4_address_check(ifname, qmi2addr(profile->ipv4.Address))) {
ifc_get_addr(ifname, &profile->udhcpc_ip); ql_get_netcard_carrier_state(ifname);
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!
@ -729,14 +720,11 @@ 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), "ifconfig %s 0.0.0.0", ifname);
snprintf(shell_cmd, sizeof(shell_cmd), "ip addr flush dev %s", ifname); ql_system(shell_cmd);
else snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s down", ifname);
snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s 0.0.0.0", ifname);
ql_system(shell_cmd); ql_system(shell_cmd);
ifc_set_state(ifname, 0);
#ifdef QL_OPENWER_NETWORK_SETUP #ifdef QL_OPENWER_NETWORK_SETUP
ql_openwrt_setup_wan(ifname, NULL); ql_openwrt_setup_wan(ifname, NULL);

View File

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

View File

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