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
PKG_NAME:=pcie_mhi
PKG_VERSION:=3.6
PKG_VERSION:=3.2
PKG_RELEASE:=1
include $(INCLUDE_DIR)/kernel.mk

View File

@ -1,20 +1,4 @@
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]
Date: 12/8/2022

View File

@ -15,36 +15,10 @@
#include <linux/uaccess.h>
#include <linux/msi.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_internal.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 (LINUX_VERSION_CODE < KERNEL_VERSION( 3,10,65 ))
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
ret = -EIO;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0))
if (!dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(64))) {
ret = dma_set_coherent_mask(&pci_dev->dev, DMA_BIT_MASK(64));
} else if (!dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(32))) {
ret = dma_set_coherent_mask(&pci_dev->dev, DMA_BIT_MASK(32));
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)
if((ret = dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(64))))
ret = dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(32));
#else
if (!pci_set_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);
}
#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,
void *priv,
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",
__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)) {
/*
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->powered_on = true;
mhi_arch_iommu_init(mhi_cntrl);
ret = mhi_arch_pcie_init(mhi_cntrl);
if (ret)
goto error_init_pci_arch;
return ret;
mhi_cntrl->dev = &pci_dev->dev;
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);
#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");
return 0;
@ -992,8 +912,6 @@ error_power_up:
error_init_pci:
mhi_arch_pcie_deinit(mhi_cntrl);
error_init_pci_arch:
mhi_arch_iommu_deinit(mhi_cntrl);
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);
#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);
/* 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_pcie_deinit(mhi_cntrl);
mhi_arch_iommu_deinit(mhi_cntrl);
pm_relax(&mhi_cntrl->mhi_dev->dev);
@ -1100,108 +1009,26 @@ void mhi_controller_qcom_exit(void)
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)
{
#ifdef QCOM_AP_SDM845_IOMMU_MAP
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);
#endif
mhi_cntrl->dev = &mhi_dev->pci_dev->dev;
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)
{
#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)
{
#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;
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);
return 0;
}
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)
@ -1216,91 +1043,11 @@ void mhi_arch_platform_deinit(struct mhi_dev *mhi_dev)
int mhi_arch_link_off(struct mhi_controller *mhi_cntrl,
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;
}
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;
}
#endif

View File

@ -4,14 +4,10 @@
#ifndef _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_IP_SW0
// #define ENABLE_ADPL
// #define ENABLE_QDSS
#include <linux/miscdevice.h>
typedef enum
{
@ -86,8 +82,7 @@ typedef enum
MHI_CLIENT_IP_HW_0_OUT = 100,
MHI_CLIENT_IP_HW_0_IN = 101,
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_MAX_CHANNELS = 128
}MHI_CLIENT_CHANNEL_TYPE;
@ -103,12 +98,7 @@ typedef enum
#endif
IPA_OUT_EVENT_RING,
IPA_IN_EVENT_RING,
#ifdef ENABLE_ADPL
ADPL_EVT_RING,
#endif
#ifdef ENABLE_QDSS
QDSS_EVT_RING,
#endif
MAX_EVT_RING_IDX
}MHI_EVT_RING_IDX;
@ -119,7 +109,7 @@ typedef enum
#define MAX_NUM_MHI_DEVICES 1
#define NUM_MHI_XFER_RINGS 128
#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_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
@ -127,14 +117,6 @@ typedef enum
#define NUM_MHI_DIAG_IN_RING_ELEMENTS 128
#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,
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));
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;
#else
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));
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;
#else
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));
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;
#else
mhi_cntrl->sequence_id = prandom_u32() & BHIE_TXVECSTATUS_SEQNUM_BMSK;
#endif
mhi_write_reg_field(mhi_cntrl, base, BHIE_TXVECDB_OFFS,
BHIE_TXVECDB_SEQNUM_BMSK, BHIE_TXVECDB_SEQNUM_SHFT,
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);
mhi_free_coherent(mhi_cntrl, size, buf, dma_addr);
/* error or in edl, we're done */
if (ret || mhi_cntrl->ee == MHI_EE_EDL) {
if (!mhi_cntrl->fbc_download || ret || mhi_cntrl->ee == MHI_EE_EDL)
release_firmware(firmware);
/* error or in edl, we're done */
if (ret || mhi_cntrl->ee == MHI_EE_EDL)
return;
}
write_lock_irq(&mhi_cntrl->pm_lock);
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_EXEC_STR(mhi_cntrl->ee), ret);
if (!mhi_cntrl->fbc_download) {
release_firmware(firmware);
if (!mhi_cntrl->fbc_download)
return;
}
if (ret) {
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);
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);
if (ret) {
MHI_ERR("IOCTL_BHI_WRITEIMAGE BhiWrite error, ret = %ld\n", ret);

View File

@ -12,7 +12,6 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/uaccess.h>
#include <asm/uaccess.h>
#include <linux/version.h>
#if (LINUX_VERSION_CODE > KERNEL_VERSION( 4,11,0 ))
@ -28,7 +27,6 @@ struct mhi_controller_map {
u32 domain;
u32 bus;
u32 slot;
struct mhi_controller *mhi_cntrl;
};
#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');
}
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;
@ -563,7 +561,7 @@ static ssize_t mon_text_read_u(struct file *file, char __user *buf,
ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt,
"%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]);
if (ep->len) {
@ -653,7 +651,7 @@ static const struct file_operations mon_fops_text_u = {
void mhi_init_debugfs(struct mhi_controller *mhi_cntrl)
{
struct dentry *dentry;
char node[64];
char node[32];
#ifdef ENABLE_MHI_MON
struct mhi_controller *mbus = mhi_cntrl;
@ -665,11 +663,11 @@ void mhi_init_debugfs(struct mhi_controller *mhi_cntrl)
#endif
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->slot);
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->slot);
@ -1011,7 +1009,7 @@ exit_timesync:
int mhi_init_mmio(struct mhi_controller *mhi_cntrl)
{
u32 val = 0;
u32 val;
int i, ret;
struct mhi_chan *mhi_chan;
struct mhi_event *mhi_event;
@ -1088,7 +1086,7 @@ int mhi_init_mmio(struct mhi_controller *mhi_cntrl)
MHIDATALIMIT_LOWER, U32_MAX, 0,
lower_32_bits(mhi_cntrl->iova_stop),
},
{ 0, 0, 0, 0 }
{ 0, 0, 0 }
};
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]);
}
#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) {
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]);
@ -1623,21 +1606,11 @@ static int of_parse_ev_cfg(struct mhi_controller *mhi_cntrl,
mhi_event->er_index = i;
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->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
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
@ -1650,16 +1623,6 @@ static int of_parse_ev_cfg(struct mhi_controller *mhi_cntrl,
mhi_event->intmod = 5;
#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
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)
mhi_event->chan = MHI_CLIENT_IP_SW_0_IN;
#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
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)
mhi_event->data_type = MHI_ER_DATA_ELEMENT_TYPE;
#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
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;
}
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
)
if (i == IPA_OUT_EVENT_RING || i == IPA_IN_EVENT_RING)
mhi_event->hw_ring = true;
else
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_IN, NUM_MHI_DIAG_IN_RING_ELEMENTS},
//"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_IN, 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},
//"Qualcomm PCIe EFS"
{"EFS", MHI_CLIENT_EFS_OUT, 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"
{"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},
#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);
@ -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;
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
#ifdef ENABLE_ADPL
|| chan == MHI_CLIENT_ADPL
#endif
#ifdef ENABLE_QDSS
|| chan == MHI_CLIENT_IP_HW_QDSS
#endif
) {
|| chan == MHI_CLIENT_IP_SW_0_OUT || chan == MHI_CLIENT_IP_SW_0_IN) {
mhi_chan->ring = 0;
}
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)
mhi_chan->er_index = SW_0_IN_EVT_RING;
#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
mhi_chan->er_index = PRIMARY_EVENT_RING;
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,
* 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;
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;
#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
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)
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))
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);
if (ret)
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
ret = of_property_read_u32(of_node, "mhi,timeout",
&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].bus = mhi_cntrl->bus;
mhi_controller_minors[i].slot = mhi_cntrl->slot;
mhi_controller_minors[i].mhi_cntrl = mhi_cntrl;
mhi_cntrl->cntrl_idx = i;
break;
}
@ -2672,11 +2548,7 @@ static int __init mhi_cntrl_init(void)
return 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);
#endif
if (IS_ERR(mhi_cntrl_drv.class)) {
unregister_chrdev(mhi_cntrl_drv.major, MHI_CNTRL_DRIVER_NAME);
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_out_chan_ring[NUM_MHI_SW_IP_RING_ELEMENTS] __packed __aligned(NUM_MHI_IPA_OUT_RING_ELEMENTS*16);
#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 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);

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->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->chan_name);
@ -1012,7 +1012,7 @@ void mhi_create_devices(struct mhi_controller *mhi_cntrl)
}
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->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));
else if (ee == MHI_EE_AMSS || ee == MHI_EE_SBL)
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)

View File

@ -30,16 +30,9 @@
#include <net/ipv6.h>
#include <net/tcp.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"
//#define MHI_NETDEV_ONE_CARD_MODE
//#define ANDROID_gki //some fuction not allow used in this TEST
#ifndef ETH_P_MAP
#define ETH_P_MAP 0xDA1A
@ -68,15 +61,13 @@ struct rmnet_nss_cb {
int (*nss_tx)(struct sk_buff *skb);
};
static struct rmnet_nss_cb __read_mostly *nss_cb = NULL;
#if defined(CONFIG_PINCTRL_IPQ807x) || defined(CONFIG_PINCTRL_IPQ5018) || defined(CONFIG_PINCTRL_IPQ8074)
//#ifdef CONFIG_RMNET_DATA //spf12.x have no macro defined, just for spf11.x
#if defined(CONFIG_PINCTRL_IPQ807x) || defined(CONFIG_PINCTRL_IPQ5018)
#ifdef CONFIG_RMNET_DATA
#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/datarmnet/core/rmnet_config.c */ //for spf12.x
/* define at qsdk/qca/src/linux-4.4/net/rmnet_data/rmnet_data_main.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;
//#endif
#endif
#endif
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;
u32 mru;
u32 max_mtu;
const char *interface_name;
struct napi_struct napi;
struct net_device *ndev;
@ -352,7 +342,7 @@ struct mhi_netdev {
uint use_rmnet_usb;
RMNET_INFO rmnet_info;
#if defined(CONFIG_IPQ5018_RATE_CONTROL)
#if defined(CONFIG_PINCTRL_IPQ5018)
u64 first_jiffy;
u64 bytes_received_1;
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),
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
#ifndef ANDROID_gki
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);
#endif
if (reply) {
skb_reset_mac_header(reply);
__skb_pull(reply, skb_network_offset(reply));
reply->ip_summed = CHECKSUM_UNNECESSARY;
reply->pkt_type = PACKET_HOST;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0))
netif_rx(reply);
#else
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0)
netif_rx_ni(reply);
#else
netif_rx(reply);
#endif
}
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);
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_bytes += rx_bytes;
#else
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
u64_stats_update_end(&stats64->syncp);
#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);
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_bytes += tx_bytes;
#else
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
u64_stats_update_end(&stats64->syncp);
#else
@ -891,44 +879,13 @@ static void rmnet_vnd_upate_tx_stats(struct net_device *net,
}
#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)
{
struct qmap_priv *dev = netdev_priv(net);
unsigned int start;
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
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) {
struct pcpu_sw_netstats *stats64;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0))
u64 rx_packets, rx_bytes;
u64 tx_packets, tx_bytes;
@ -945,35 +901,23 @@ static struct rtnl_link_stats64 *_rmnet_vnd_get_stats64(struct net_device *net,
do {
start = u64_stats_fetch_begin_irq(&stats64->syncp);
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0)
rx_packets = stats64->rx_packets;
rx_bytes = stats64->rx_bytes;
tx_packets = stats64->tx_packets;
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));
stats->rx_packets += rx_packets;
stats->rx_bytes += rx_bytes;
stats->tx_packets += tx_packets;
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;
@ -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)
{
struct mhi_netdev *mhi_netdev;
mhi_netdev = (struct mhi_netdev *)ndev_to_mhi(rmnet_dev);
if (mhi_netdev == NULL) {
printk("warning, mhi_netdev == null\n");
if (new_mtu < 0 || new_mtu > 1500)
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;
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);
goto error;
}
tci = abs(tci);
qmap_net = pQmapDev->mpQmapNetDev[qmap_mode == 1 ? 0 : tci - 1];
dpe16 = ndp16->dpe16;
@ -1407,21 +1337,8 @@ static void rmnet_qmi_rx_handler(void *dev, struct sk_buff *skb_in)
}
#endif
skb_len -= dl_minimum_padding;
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;
}
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);
if (skb_len > 1500) {
netdev_info(ndev, "drop skb_len=%x larger than 1500\n", skb_len);
goto error_pkt;
}
@ -1463,6 +1380,19 @@ static void rmnet_qmi_rx_handler(void *dev, struct sk_buff *skb_in)
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 NSS, do not use skb_clone(), or NSS 's performace is very bad.
qmap_skb = netdev_alloc_skb(qmap_net, skb_len);
@ -1575,8 +1505,7 @@ static struct net_device * rmnet_vnd_register_device(struct mhi_netdev *pQmapDev
struct qmap_priv *priv;
int err;
int use_qca_nss = !!nss_cb;
unsigned char temp_addr[ETH_ALEN];
u8 maddr[ETH_ALEN];
qmap_net = alloc_etherdev(sizeof(*priv));
if (!qmap_net)
return NULL;
@ -1589,21 +1518,11 @@ static struct net_device * rmnet_vnd_register_device(struct mhi_netdev *pQmapDev
priv->pQmapDev = pQmapDev;
priv->qmap_version = pQmapDev->qmap_version;
priv->mux_id = mux_id;
sprintf(qmap_net->name, "%.12s.%d", real_dev->name, offset_id + 1);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0))
__dev_addr_set(qmap_net, real_dev->dev_addr, ETH_ALEN);
#else
memcpy (qmap_net->dev_addr, real_dev->dev_addr, ETH_ALEN);
#endif
//qmap_net->dev_addr[5] = offset_id + 1;
sprintf(qmap_net->name, "%s.%d", real_dev->name, offset_id + 1);
ether_addr_copy(maddr, real_dev->dev_addr);
maddr[5]= offset_id + 1;
ether_addr_copy((u8*)qmap_net->dev_addr, maddr);
//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)
priv->stats64 = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats);
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->flags |= IFF_NOARP;
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) {
rmnet_vnd_rawip_setup(qmap_net);
}
#ifdef CONFIG_PINCTRL_IPQ9574
rmnet_vnd_rawip_setup(qmap_net);
#endif
if (pQmapDev->net_type == MHI_NET_MBIM) {
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);
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_bytes += rx_bytes;
#else
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
u64_stats_update_begin(&stats64->syncp);
#else
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);
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_bytes += tx_bytes;
#else
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
u64_stats_update_begin(&stats64->syncp);
#else
mhi_netdev->ndev->stats.tx_packets += tx_packets;
@ -2090,8 +2006,6 @@ static netdev_tx_t mhi_netdev_xmit(struct sk_buff *skb, struct net_device *dev)
//qmap_hex_dump(__func__, skb->data, 32);
#ifdef MHI_NETDEV_ONE_CARD_MODE
//printk("%s dev->type=%d\n", __func__, dev->type);
if (dev->type == ARPHRD_ETHER) {
skb_reset_mac_header(skb);
@ -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,
MHI_EOT);
//printk("%s transfer res=%d\n", __func__, res);
if (unlikely(res)) {
dev_kfree_skb_any(skb);
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) {
struct pcpu_sw_netstats *stats64;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0))
u64 rx_packets, rx_bytes;
u64 tx_packets, tx_bytes;
@ -2186,35 +2097,23 @@ static struct rtnl_link_stats64 * _mhi_netdev_get_stats64(struct net_device *nde
do {
start = u64_stats_fetch_begin_irq(&stats64->syncp);
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0)
rx_packets = stats64->rx_packets;
rx_bytes = stats64->rx_bytes;
tx_packets = stats64->tx_packets;
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));
stats->rx_packets += rx_packets;
stats->rx_bytes += rx_bytes;
stats->tx_packets += tx_packets;
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;
@ -2323,11 +2222,7 @@ static void mhi_netdev_setup(struct net_device *dev)
ether_setup(dev);
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);
#endif
/* set this after calling ether_setup */
dev->header_ops = 0; /* No header */
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;
}
rtnl_unlock();
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)
mhi_netdev->ndev->max_mtu = mhi_netdev->max_mtu; //first net card
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0))
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0)
netif_napi_add_weight(mhi_netdev->ndev, &mhi_netdev->napi, mhi_netdev_poll, poll_weight);
#else
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;
}
#if defined(CONFIG_IPQ5018_RATE_CONTROL)
#if defined(CONFIG_PINCTRL_IPQ5018)
if (likely(mhi_netdev->mhi_rate_control)) {
u32 time_interval = 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;
if (mhi_netdev->first_jiffy) {
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,2,0)
second_jiffy = arch_counter_get_cntvct();
#else
second_jiffy = __arch_counter_get_cntvct();
#endif
bytes_received_2 = mhi_netdev->bytes_received_2;
if ((second_jiffy > mhi_netdev->first_jiffy) &&
(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;
}
} else {
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,2,0)
mhi_netdev->first_jiffy = arch_counter_get_cntvct();
#else
mhi_netdev->first_jiffy = __arch_counter_get_cntvct();
#endif
cntfrq = arch_timer_get_cntfrq();
mhi_netdev->cntfrq_per_msec = cntfrq / 1000;
}
@ -2829,11 +2711,7 @@ static void mhi_netdev_remove(struct mhi_device *mhi_dev)
}
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))
#endif
netdev_rx_handler_unregister(mhi_netdev->ndev);
rtnl_unlock();
#endif
@ -2891,16 +2769,13 @@ static int mhi_netdev_probe(struct mhi_device *mhi_dev,
mhi_netdev->mhi_dev = mhi_dev;
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->max_mtu = mhi_netdev->mru - (sizeof(struct rmnet_map_v5_csum_header) + sizeof(struct rmnet_map_header));
mhi_netdev->mru = 15360; ///etc/data/qnicorn_config.xml dataformat_agg_dl_size 15*1024
if (mhi_netdev->net_type == MHI_NET_MBIM) {
mhi_netdev->mru = ncmNTBParams.dwNtbInMaxSize;
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) {
mhi_netdev->mru = 8*1024;
mhi_netdev->max_mtu = 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
}
#if defined(CONFIG_IPQ5018_RATE_CONTROL)
#if defined(CONFIG_PINCTRL_IPQ5018)
mhi_netdev->mhi_rate_control = 1;
#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[] = {
{ .chan = "IP_HW0" },
{ .chan = "IP_SW0" },
// ADPL do not register as a netcard. xingduo.du 2023-02-20
// { .chan = "IP_HW_ADPL" },
{ .chan = "IP_HW_ADPL" },
{ },
};

View File

@ -9,6 +9,7 @@
#include <linux/mm.h>
#include <linux/delay.h>
#include <linux/version.h>
#if 1
static inline void *ipc_log_context_create(int max_num_pages,
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 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 struct mhi_uci_drv mhi_uci_drv;
@ -197,7 +160,20 @@ static int mhi_queue_inbound(struct uci_dev *uci_dev)
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,
unsigned int cmd,
unsigned long arg)
@ -295,8 +271,7 @@ static unsigned int mhi_uci_poll(struct file *file, poll_table *wait)
unsigned int mask = 0;
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;
spin_lock_bh(&uci_chan->lock);
@ -308,9 +283,6 @@ static unsigned int mhi_uci_poll(struct file *file, poll_table *wait)
}
spin_unlock_bh(&uci_chan->lock);
// ADPL and QDSS are single channel, ul_chan not be initilized. xingduo.du 2023-02-27
if (mhi_dev->ul_chan) {
poll_wait(file, &uci_dev->ul_chan.wq, wait);
uci_chan = &uci_dev->ul_chan;
spin_lock_bh(&uci_chan->lock);
if (!uci_dev->enabled) {
@ -326,7 +298,6 @@ static unsigned int mhi_uci_poll(struct file *file, poll_table *wait)
mask |= POLLERR;
spin_unlock_bh(&uci_chan->lock);
}
MSG_LOG("Client attempted to poll, returning mask 0x%x\n", mask);
@ -822,10 +793,6 @@ static void mhi_dl_xfer_cb(struct mhi_device *mhi_dev,
unsigned nr_trb = uci_dev->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)
{
uci_dev->rx_error++;
@ -908,8 +875,7 @@ static void mhi_dl_xfer_cb(struct mhi_device *mhi_dev,
wake_up(&uci_chan->wq);
}
// repaire sdx6x module can not read qdb file. xingduo.du 2023-01-18
#define DIAG_MAX_PCIE_PKT_SZ 8192 //define by module
#define DIAG_MAX_PCIE_PKT_SZ 2048 //define by module
/* .driver_data stores max mtu */
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 = "QMI1", .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;
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);
#endif
if (IS_ERR(mhi_uci_drv.class)) {
unregister_chrdev(mhi_uci_drv.major, MHI_UCI_DRIVER_NAME);
return -ENODEV;

View File

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

View File

@ -9,7 +9,7 @@
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.
---------------------------------------------------------------------------
******************************************************************************/

View File

@ -9,7 +9,7 @@ CC:=$(CROSS-COMPILE)gcc
endif
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+=qrtr.c rmnetctl.c
ifeq (1,1)
@ -21,26 +21,25 @@ QL_CM_DHCP=udhcpc_netlink.c
QL_CM_DHCP+=${LIBMNL}
endif
CFLAGS += -Wall -Wextra -Werror -O1 #-s
LDFLAGS += -lpthread -ldl -lrt
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
$(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:
$(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:
$(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:
$(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:
$(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:
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.
---------------------------------------------------------------------------
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.
---------------------------------------------------------------------------
******************************************************************************/
@ -255,11 +255,11 @@ static USHORT WdsStartNwInterfaceReq(PQMUX_MSG pMUXMsg, void *arg) {
TLVLength += (le16_to_cpu(pIpFamily->TLVLength) + sizeof(QCQMICTL_TLV_HDR));
//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);
pProfileIndex->TLVLength = cpu_to_le16(0x01);
pProfileIndex->TLVType = 0x31;
pProfileIndex->ProfileIndex = profile->profile_index;
pProfileIndex->ProfileIndex = profile->pdp;
if (s_is_cdma && s_hdr_personality == 0x02) {
pProfileIndex->TLVType = 0x32; //profile_index_3gpp2
pProfileIndex->ProfileIndex = 101;
@ -478,13 +478,6 @@ static USHORT UimReadTransparentIMSIReqSend(PQMUX_MSG pMUXMsg, void *arg) {
#endif
#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) {
PROFILE_T *profile = (PROFILE_T *)arg;
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.TLVLength = cpu_to_le16(0x02);
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);
}
@ -517,7 +510,7 @@ static USHORT WdsModifyProfileSettingsReq(PQMUX_MSG pMUXMsg, void *arg) {
pMUXMsg->ModifyProfileSettingsReq.TLVType = 0x01;
pMUXMsg->ModifyProfileSettingsReq.TLVLength = cpu_to_le16(0x02);
pMUXMsg->ModifyProfileSettingsReq.ProfileType = 0x00; // 0 ~ 3GPP, 1 ~ 3GPP2
pMUXMsg->ModifyProfileSettingsReq.ProfileIndex = profile->profile_index;
pMUXMsg->ModifyProfileSettingsReq.ProfileIndex = profile->pdp;
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.ep_type = DATA_EP_TYPE_HSUSB;
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
@ -1867,9 +1858,8 @@ static int requestSetupDataCall(PROFILE_T *profile, int curIpFamily) {
dbg_time("call_end_reason_verbose is %d", verbose_call_end_reason);
}
err = le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXError);
free(pResponse);
return err;
return le16_to_cpu(pMUXMsg->QMUXMsgHdrResp.QMUXError);
}
if (curIpFamily == IpFamilyV4) {
@ -2036,8 +2026,8 @@ static int requestSetProfile(PROFILE_T *profile) {
const char *new_password = profile->password ? profile->password : "";
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]);
if (!profile->profile_index)
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->pdp)
return -1;
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_AUTH_PREFERENCE pAuthPref;
PQMIWDS_IPTYPE pIpType;
PQMIWDS_PDPCONTEXT pPdpContext;
PQMIWDS_PROFILELIST pProfileList;
const char *ipStr[] = {"IPV4", "NULL", "IPV6", "IPV4V6"};
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;
_re_check:
pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS, QMIWDS_GET_PROFILE_LIST_REQ, WdsGetProfileListReqSend, profile);
err = QmiThreadSendQMI(pRequest, &pResponse);s_pResponse = malloc(le16_to_cpu(pResponse->QMIHdr.Length) + 1);
qmi_rsp_check_and_return();
pProfileList = (PQMIWDS_PROFILELIST)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x01);
uint8 profile_indexs[42] = {0};
uint8 profile_num = pProfileList->ProfileList[0];
if(profile_num >= 1)
{
uint8 j = 0;
uint8 k = 2;
for(int i=0; i<profile_num; i++)
{
profile_indexs[j++] = pProfileList->ProfileList[k];
if(pProfileList->ProfileList[++k] == 0)
k+=2;
else
k+=2+pProfileList->ProfileList[k];
}
}
free(pResponse);
for(int i=0; i<profile_num; i++)
{
profile->profile_index = profile_indexs[i];
pRequest = ComposeQMUXMsg(QMUX_TYPE_WDS, QMIWDS_GET_PROFILE_SETTINGS_REQ, WdsGetProfileSettingsReqSend, profile);
err = QmiThreadSendQMI(pRequest, &pResponse);
qmi_rsp_check_and_return();
pPdpContext = (PQMIWDS_PDPCONTEXT)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x25);
if(pPdpContext->pdp_context == profile->pdp)
break;
else
free(pResponse);
if(i == profile_num-1)
if (err == 0 && pResponse && le16_to_cpu(pResponse->MUXMsg.QMUXMsgHdrResp.QMUXResult)
&& le16_to_cpu(pResponse->MUXMsg.QMUXMsgHdrResp.QMUXError) == QMI_ERR_EXTENDED_INTERNAL)
{
free(pResponse);
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);
pUserName = (PQMIWDS_USERNAME)GetTLV(&pResponse->MUXMsg.QMUXMsgHdr, 0x1B);
@ -2152,7 +2106,7 @@ _re_check:
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);
return 0;

View File

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

View File

@ -9,7 +9,7 @@
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.
---------------------------------------------------------------------------
******************************************************************************/
@ -264,7 +264,7 @@ static int QmiWwanDeInit(void) {
{
if (qmiclientId[i] != 0)
{
QmiWwanReleaseClientID((QMUX_TYPE_WDS_IPV6 == i ? QMUX_TYPE_WDS : i), qmiclientId[i]);
QmiWwanReleaseClientID(i, qmiclientId[i]);
qmiclientId[i] = 0;
}
}

View File

@ -1,26 +1,5 @@
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]
Date: 9/7/2022
enhancement:

View File

@ -9,7 +9,7 @@
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.
---------------------------------------------------------------------------
******************************************************************************/
@ -45,18 +45,6 @@ static int s_pdp;
#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;}}
int check_mcu_endian()
{
union
{
int a;
char b;
}u;
u.a = 1;
return u.b;
}
#define at_response_error(err, p_response) \
(err \
|| p_response == NULL \
@ -515,7 +503,6 @@ AT< OK
safe_at_response_free(p_response);
switch (cops_act) {
case 2: //UTRAN
case 3: //GSM W/EGPRS
case 4: //UTRAN W/HSDPA
case 5: //UTRAN W/HSUPA
case 6: //UTRAN W/HSDPA and HSUPA
@ -712,11 +699,7 @@ static int at_netdevstatus(int pdp, unsigned int *pV4Addr) {
else {
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);
}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};
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);
}else{
v4Addr = (addr[0])<< 24 | (addr[1]<<16) | (addr[2]<<8) | (addr[3]);
}
break;
}
}

View File

@ -9,7 +9,7 @@
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.
---------------------------------------------------------------------------
******************************************************************************/
@ -43,10 +43,10 @@
#define CM_MAX_PATHLEN 256
#define CM_INVALID_VAL (~((int)0))
/* get first line from file 'fname'
* 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;
long num;
char buff[32 + 1] = {'\0'};
@ -58,7 +58,7 @@ static int file_get_value(const char *fname, int base)
goto error;
fclose(fp);
num = (int)strtol(buff, &endptr, base);
num = (int) strtol(buff, &endptr, base);
if (errno == ERANGE && (num == LONG_MAX || num == LONG_MIN))
goto error;
/* if there is no digit in buff */
@ -67,9 +67,9 @@ static int file_get_value(const char *fname, int base)
if (debug_qmi)
dbg_time("(%s) = %lx", fname, num);
return (int)num;
return (int) num;
error:
error:
if (fp) fclose(fp);
return CM_INVALID_VAL;
}
@ -78,8 +78,7 @@ error:
* This function will search the directory 'dirname' and return the first child.
* '.' 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;
DIR *dirptr;
@ -102,14 +101,13 @@ static int dir_get_child(const char *dirname, char *buff, unsigned bufsize, cons
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'};
FILE *fp = fopen(fname, "r");
if (!fp)
return CM_INVALID_VAL;
while (fgets(buff, sizeof(buff)-1, fp)) {
while (fgets(buff, sizeof(buff) - 1, fp)) {
char prefix[128] = {'\0'};
char tail[128] = {'\0'};
/* To eliminate cppcheck warnning: Assume string length is no more than 15 */
@ -190,14 +188,13 @@ static void query_usb_interface_info(char *path, struct usb_interface_info *p) {
break;
n--;
}
strncpy(p->driver, &driver[n+1], sizeof(p->driver) - 1);
strncpy(p->driver, &driver[n + 1], sizeof(p->driver) - 1);
}
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);
char tmp[32];
@ -223,7 +220,7 @@ static int detect_path_cdc_wdm_or_qcqmi(char *path, char *devname, size_t bufsiz
return -1;
step_1:
step_1:
/* get device(qcqmiX|cdc-wdmX) */
if (debug_qmi) dbg_time("%s", path);
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! */
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;
dbg_time("access %s failed, errno: %d (%s)", devname, errno, strerror(errno));
@ -243,9 +239,9 @@ step_1:
major = conf_get_val(path, "MAJOR");
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");
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);
}
@ -258,11 +254,11 @@ step_1:
* TRUE -> ok
*/
BOOL qmidevice_detect(char *qmichannel, char *usbnet_adapter, unsigned bufsize, PROFILE_T *profile) {
struct dirent* ent = NULL;
struct dirent *ent = NULL;
DIR *pDir;
const char *rootdir = "/sys/bus/usb/devices";
struct {
char path[255*2];
char path[255 * 2];
} *pl;
pl = (typeof(pl)) malloc(sizeof(*pl));
memset(pl, 0x00, sizeof(*pl));
@ -274,8 +270,8 @@ BOOL qmidevice_detect(char *qmichannel, char *usbnet_adapter, unsigned bufsize,
}
while ((ent = readdir(pDir)) != NULL) {
char netcard[32+1] = {'\0'};
char devname[32+5] = {'\0'}; //+strlen("/dev/")
char netcard[32 + 1] = {'\0'};
char devname[32 + 5] = {'\0'}; //+strlen("/dev/")
int netIntf;
int driver_type;
@ -305,7 +301,7 @@ BOOL qmidevice_detect(char *qmichannel, char *usbnet_adapter, unsigned bufsize,
}
if (netcard[0] == '\0') { //for centos 2.6.x
const char *n= "usb0";
const char *n = "usb0";
const char *c = "qcqmi0";
snprintf(pl->path, sizeof(pl->path), "%s/%s:1.4/net:%s", rootdir, ent->d_name, n);
@ -334,15 +330,12 @@ BOOL qmidevice_detect(char *qmichannel, char *usbnet_adapter, unsigned bufsize,
if (driver_type == SOFTWARE_QMI || driver_type == SOFTWARE_MBIM) {
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;
if (profile->usb_dev.idVendor == 0x2c7c) { //Quectel
switch (profile->usb_dev.idProduct) { //EC200U
case 0x0901: //EC200U
case 0x0904: //EC200G
case 0x8101: //RG801H
atIntf = 2;
break;
@ -353,7 +346,6 @@ BOOL qmidevice_detect(char *qmichannel, char *usbnet_adapter, unsigned bufsize,
case 0x6005: //EC200A
case 0x6002: //EC200S
case 0x6001: //EC100Y
case 0x6007: //EG915Q-NA in ECM mode, it also could set atIntf to 4
atIntf = 3;
break;
default:
@ -391,49 +383,74 @@ BOOL qmidevice_detect(char *qmichannel, char *usbnet_adapter, unsigned bufsize,
}
free(pl);
return TRUE;
error:
error:
free(pl);
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) {
struct dirent* ent = NULL;
struct dirent *ent = NULL;
DIR *pDir;
const char *rootdir_mhi[] = {"/sys/bus/mhi_q/devices", "/sys/bus/mhi/devices", NULL};
int i = 0;
char path[256];
int find = 0;
while (rootdir_mhi[i]) {
const char *rootdir = rootdir_mhi[i++];
dbg_time("rootdir : %s ", rootdir);
pDir = opendir(rootdir);
if (!pDir) {
if (errno != ENOENT)
if (errno != ENOENT) {
dbg_time("opendir %s failed: %s", rootdir, strerror(errno));
}
continue;
}
while ((ent = readdir(pDir)) != NULL) {
char netcard[32] = {'\0'};
char devname[32] = {'\0'};
int software_interface = SOFTWARE_QMI;
char *pNode = NULL;
pNode = strstr(ent->d_name, "_IP_HW0"); //0306_00.01.00_IP_HW0
if (!pNode)
if (!pNode) {
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);
dir_get_child(path, netcard, sizeof(netcard), NULL);
if (!netcard[0])
if (!netcard[0]) {
continue;
if (usbnet_adapter[0] && strcmp(netcard, usbnet_adapter)) //not '-i x'
}
if (usbnet_adapter[0] && strcmp(netcard, usbnet_adapter)) { //not '-i x
continue;
}
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)) {
/* 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' */
@ -446,33 +463,51 @@ int mhidevice_detect(char *qmichannel, char *usbnet_adapter, PROFILE_T *profile)
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)) {
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)) {
snprintf(path, sizeof(path), "%s/%.13s_MBIM", rootdir, ent->d_name);
if (!access(path, F_OK))
snprintf(path, sizeof(path), "%s/%s_MBIM", rootdir, d_name);
if (!access(path, F_OK)) {
software_interface = SOFTWARE_MBIM;
}
}
if (access(path, F_OK))
continue;
}
strncat(path, "/mhi_uci_q", sizeof(path)-1);
//原
// 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;
}
strncat(path, "/mhi_uci_q", sizeof(path) - 1);
dir_get_child(path, devname, sizeof(devname), NULL);
if (!devname[0])
if (!devname[0]) {
continue;
}
dbg_time("while -> path_final_sub : %s ,dev_name: %s ", path, devname);
sprintf(usbnet_adapter, "%s", netcard);
sprintf(qmichannel, "/dev/%s", devname);
profile->software_interface = software_interface;
find = 1;
break;
}
closedir(pDir);
}
return find;
}
@ -480,8 +515,7 @@ int atdevice_detect(char *atchannel, char *usbnet_adapter, PROFILE_T *profile) {
if (!access("/sys/class/net/sipa_dummy0", F_OK)) {
strcpy(usbnet_adapter, "sipa_dummy0");
snprintf(profile->qmapnet_adapter, sizeof(profile->qmapnet_adapter), "%s%d", "pcie", profile->pdp - 1);
}
else {
} else {
dbg_time("atdevice_detect failed");
goto error;
}
@ -489,24 +523,21 @@ int atdevice_detect(char *atchannel, char *usbnet_adapter, PROFILE_T *profile) {
if (!access("/dev/stty_nr31", F_OK)) {
strcpy(atchannel, "/dev/stty_nr31");
profile->software_interface = SOFTWARE_ECM_RNDIS_NCM;
}
else {
} else {
goto error;
}
return 1;
error:
error:
return 0;
}
int get_driver_type(PROFILE_T *profile)
{
int get_driver_type(PROFILE_T *profile) {
/* QMI_WWAN */
if (profile->usb_intf.bInterfaceClass == USB_CLASS_VENDOR_SPEC) {
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) {
case USB_CDC_SUBCLASS_MBIM:
return SOFTWARE_MBIM;
@ -518,8 +549,7 @@ int get_driver_type(PROFILE_T *profile)
default:
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)
return SOFTWARE_ECM_RNDIS_NCM;
}
@ -529,14 +559,12 @@ int get_driver_type(PROFILE_T *profile)
return DRV_INVALID;
}
struct usbfs_getdriver
{
struct usbfs_getdriver {
unsigned int interface;
char driver[255 + 1];
};
struct usbfs_ioctl
{
struct usbfs_ioctl {
int ifno; /* interface 0..N ; negative numbers reserved */
int ioctl_code; /* MUST encode size + direction of data so the
* macros in <asm/ioctl.h> give correct values */
@ -546,8 +574,7 @@ struct usbfs_ioctl
#define IOCTL_USBFS_DISCONNECT _IO('U', 22)
#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;
getdrv.interface = ifnum;
if (ioctl(fd, USBDEVFS_GETDRIVER, &getdrv) < 0) {
@ -558,8 +585,7 @@ int usbfs_is_kernel_driver_alive(int fd, int ifnum)
return 1;
}
void usbfs_detach_kernel_driver(int fd, int ifnum)
{
void usbfs_detach_kernel_driver(int fd, int ifnum) {
struct usbfs_ioctl operate;
operate.data = NULL;
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;
operate.data = NULL;
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 fd;
char devpath[128] = {'\0'};
snprintf(devpath, sizeof(devpath), "/dev/bus/usb/%03d/%03d", profile->usb_dev.busnum, profile->usb_dev.devnum);
fd = open(devpath, O_RDWR | O_NOCTTY);
if (fd < 0)
{
if (fd < 0) {
dbg_time("%s fail to open %s", __func__, devpath);
return -1;
}
@ -603,8 +626,8 @@ int reattach_driver(PROFILE_T *profile)
}
#define SIOCETHTOOL 0x8946
int ql_get_netcard_driver_info(const char *devname)
{
int ql_get_netcard_driver_info(const char *devname) {
int fd = -1;
struct ethtool_drvinfo drvinfo;
struct ifreq ifr; /* ifreq suitable for ethtool ioctl */
@ -619,7 +642,7 @@ int ql_get_netcard_driver_info(const char *devname)
}
drvinfo.cmd = ETHTOOL_GDRVINFO;
ifr.ifr_data = (void *)&drvinfo;
ifr.ifr_data = (void *) &drvinfo;
if (ioctl(fd, SIOCETHTOOL, &ifr) < 0) {
dbg_time("ioctl() error: errno(%d)(%s)", errno, strerror(errno));
@ -634,8 +657,7 @@ int ql_get_netcard_driver_info(const char *devname)
return 0;
}
int ql_get_netcard_carrier_state(const char *devname)
{
int ql_get_netcard_carrier_state(const char *devname) {
int fd = -1;
struct ethtool_value edata;
struct ifreq ifr; /* ifreq suitable for ethtool ioctl */
@ -651,7 +673,7 @@ int ql_get_netcard_carrier_state(const char *devname)
edata.cmd = ETHTOOL_GLINK;
edata.data = 0;
ifr.ifr_data = (void *)&edata;
ifr.ifr_data = (void *) &edata;
if (ioctl(fd, SIOCETHTOOL, &ifr) < 0) {
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;
}
static void *catch_log(void *arg)
{
PROFILE_T *profile = (PROFILE_T *)arg;
static void *catch_log(void *arg) {
PROFILE_T *profile = (PROFILE_T *) arg;
int nreads = 0;
char tbuff[256+32];
char tbuff[256 + 32];
char filter[32];
size_t tsize = strlen(get_time()) + 1;
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);
if (nreads <= 0) {
if (nreads == -1 && errno == EINTR)
@ -684,13 +705,13 @@ static void *catch_log(void *arg)
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;
snprintf(tbuff, sizeof(tbuff), "%s", get_time());
tbuff[tsize-1] = ' ';
tbuff[tsize - 1] = ' ';
fwrite(tbuff, strlen(tbuff), 1, profile->usbmon_logfile_fp);
}
@ -698,8 +719,7 @@ static void *catch_log(void *arg)
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];
pthread_t pt;
pthread_attr_t attr;
@ -735,7 +755,7 @@ int ql_capture_usbmon_log(PROFILE_T *profile, const char *log_path)
pthread_attr_init(&attr);
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;
}

View File

@ -9,7 +9,7 @@
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.
---------------------------------------------------------------------------
******************************************************************************/
@ -58,10 +58,8 @@ static int check_ipv4_address(PROFILE_T *profile) {
if (profile->request_ops == &mbim_request_ops)
return 1; //we will get a new ipv6 address per requestGetIPAddress()
if (profile->request_ops == &atc_request_ops) {
if (!profile->udhcpc_ip) return 1;
oldAddress = profile->udhcpc_ip;
}
if (profile->request_ops == &atc_request_ops)
return 1; //TODO
if (profile->request_ops->requestGetIPAddress(profile, IpFamilyV4) == 0) {
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("-b Enable network interface bridge function (default 0)");
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("Example 1: %s ", progname);
dbg_time("Example 2: %s -s 3gnet ", progname);
@ -370,15 +367,6 @@ static int qmi_main(PROFILE_T *profile)
request_ops->requestRegisterQos(profile);
#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);
while (1)
@ -728,11 +716,6 @@ static int quectel_CM(PROFILE_T *profile)
dbg_time("Modem works in MBIM mode");
profile->request_ops = &mbim_request_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);
}
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;
profile->pdp = CONFIG_DEFAULT_PDP;
profile->profile_index = CONFIG_DEFAULT_PDP;
if (!strcmp(argv[argc-1], "&"))
argc--;
@ -883,10 +865,6 @@ static int parse_user_input(int argc, char **argv, PROFILE_T *profile) {
profile->enable_ipv6 = 1;
break;
case 'd':
profile->no_dhcp = 1;
break;
case 'u':
if (has_more_argv()) {
profile->usblogfile = argv[opt++];
@ -921,7 +899,7 @@ int main(int argc, char *argv[])
int ret;
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);
if (!ret)

View File

@ -9,7 +9,7 @@
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.
---------------------------------------------------------------------------
******************************************************************************/

View File

@ -9,7 +9,7 @@
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.
---------------------------------------------------------------------------
******************************************************************************/

View File

@ -10,7 +10,7 @@
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.
---------------------------------------------------------------------------
******************************************************************************/

View File

@ -9,7 +9,7 @@
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.
---------------------------------------------------------------------------
******************************************************************************/

View File

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

View File

@ -9,7 +9,7 @@
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.
---------------------------------------------------------------------------
******************************************************************************/
@ -36,9 +36,9 @@
#include "qendian.h"
#include "qlist.h"
#include "QCQMI.h"
#include "QCQCTL.h"
#include "QCQMUX.h"
#include "MPQMI.h"
#include "MPQCTL.h"
#include "MPQMUX.h"
static const char * get_time(void) {
static char time_buf[128];

View File

@ -9,7 +9,7 @@
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.
---------------------------------------------------------------------------
******************************************************************************/
@ -105,17 +105,6 @@ static short ifc_get_flags(const char *ifname)
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) {
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) {
int fd;
char raw_ip[128];
char shell_cmd[128];
char mode[2] = "X";
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 (mode[0] == '0' || mode[0] == 'N') {
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);
mode[0] = 'Y';
if (write(fd, mode, 2) == -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);
@ -219,7 +211,8 @@ void ql_set_driver_link_state(PROFILE_T *profile, int link_state) {
lseek(fd, 0, SEEK_SET);
rc = read(fd, link_file, sizeof(link_file));
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) {
char *ifname = profile->usbnet_adapter;
char shell_cmd[128];
ql_set_driver_link_state(profile, 1);
@ -489,13 +483,17 @@ void udhcpc_start(PROFILE_T *profile) {
}
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) {
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->PCSCFIpv4Addr1)
dbg_time("pcscf1: %s", ipv4Str(profile->PCSCFIpv4Addr1));
@ -530,7 +528,7 @@ void udhcpc_start(PROFILE_T *profile) {
if (profile->ipv4.Address == 0)
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);
}
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_join(udhcpc_thread_id, NULL);
if (profile->request_ops == &atc_request_ops) {
profile->udhcpc_ip = 0;
ifc_get_addr(ifname, &profile->udhcpc_ip);
if (profile->udhcpc_ip != profile->ipv4.Address) {
unsigned char *l = (unsigned char *)&profile->udhcpc_ip;
unsigned char *r = (unsigned char *)&profile->ipv4.Address;
dbg_time("ERROR: IP from udhcpc (%d.%d.%d.%d) is different to IP from ATC (%d.%d.%d.%d)!",
l[0], l[1], l[2], l[3], r[0], r[1], r[2], r[3]);
ql_get_netcard_carrier_state(ifname); //miss udhcpc default.script or modem not report usb-net-cdc-linkup
}
if (profile->request_ops == &atc_request_ops
&& !ql_netcard_ipv4_address_check(ifname, qmi2addr(profile->ipv4.Address))) {
ql_get_netcard_carrier_state(ifname);
}
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;
}
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()
if (!access("/sbin/ip", X_OK))
snprintf(shell_cmd, sizeof(shell_cmd), "ip addr flush dev %s", ifname);
else
snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s 0.0.0.0", ifname);
ql_system(shell_cmd);
ifc_set_state(ifname, 0);
snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s down", ifname);
ql_system(shell_cmd);
#ifdef QL_OPENWER_NETWORK_SETUP
ql_openwrt_setup_wan(ifname, NULL);

View File

@ -9,7 +9,7 @@
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.
---------------------------------------------------------------------------
******************************************************************************/

View File

@ -9,7 +9,7 @@
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.
---------------------------------------------------------------------------
******************************************************************************/