diff --git a/wwan/app/luci-app-pcimodem/Makefile b/wwan/app/luci-app-pcimodem/Makefile index 1bcb748..de20f9d 100644 --- a/wwan/app/luci-app-pcimodem/Makefile +++ b/wwan/app/luci-app-pcimodem/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=PCI Modem Server -LUCI_DEPENDS:=+kmod-pcie_mhi +pciutils +quectel-CM-5G +LUCI_DEPENDS:=+kmod-pcie_mhi +pciutils +quectel-cm include $(TOPDIR)/feeds/luci/luci.mk diff --git a/wwan/app/luci-app-usbmodem/Makefile b/wwan/app/luci-app-usbmodem/Makefile index 447ca3c..7efe2ec 100644 --- a/wwan/app/luci-app-usbmodem/Makefile +++ b/wwan/app/luci-app-usbmodem/Makefile @@ -8,11 +8,11 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=Modem Server -LUCI_DEPENDS:=+luci-compat +quectel-CM-5G +kmod-usb-acm \ +LUCI_DEPENDS:=+luci-compat +quectel-cm +kmod-usb-acm \ +kmod-usb-net-cdc-ether +kmod-usb-net-cdc-mbim \ +kmod-usb-net-qmi-wwan +kmod-usb-net-rndis \ +kmod-usb-serial-option +kmod-usb-wdm \ - +kmod-qmi_wwan_f +kmod-qmi_wwan_q + +kmod-qmi_wwan_q include $(TOPDIR)/feeds/luci/luci.mk diff --git a/wwan/app/luci-proto-quectel/Makefile b/wwan/app/luci-proto-quectel/Makefile new file mode 100644 index 0000000..ee27c48 --- /dev/null +++ b/wwan/app/luci-proto-quectel/Makefile @@ -0,0 +1,8 @@ +include $(TOPDIR)/rules.mk + +LUCI_TITLE:=Support for Quectel WWAN modules +LUCI_DEPENDS:=+quectel-cm + +include $(TOPDIR)/feeds/luci/luci.mk + +# call BuildPackage - OpenWrt buildroot signature diff --git a/wwan/app/luci-proto-quectel/htdocs/luci-static/resources/protocol/quectel.js b/wwan/app/luci-proto-quectel/htdocs/luci-static/resources/protocol/quectel.js new file mode 100644 index 0000000..cce491a --- /dev/null +++ b/wwan/app/luci-proto-quectel/htdocs/luci-static/resources/protocol/quectel.js @@ -0,0 +1,124 @@ +'use strict'; +'require rpc'; +'require form'; +'require network'; + +var callFileList = rpc.declare({ + object: 'file', + method: 'list', + params: [ 'path' ], + expect: { entries: [] }, + filter: function(list, params) { + var rv = []; + for (var i = 0; i < list.length; i++) + if (list[i].name.match(/^cdc-wdm/)) + rv.push(params.path + list[i].name); + return rv.sort(); + } +}); + +network.registerPatternVirtual(/^quectel-.+$/); +network.registerErrorCode('CALL_FAILED', _('Call failed')); +network.registerErrorCode('NO_CID', _('Unable to obtain client ID')); +network.registerErrorCode('PLMN_FAILED', _('Setting PLMN failed')); + +return network.registerProtocol('quectel', { + getI18n: function() { + return _('Quectel Cellular'); + }, + + getIfname: function() { + return this._ubus('l3_device') || 'quectel-%s'.format(this.sid); + }, + + getOpkgPackage: function() { + return 'quectel-cm'; + }, + + isFloating: function() { + return true; + }, + + isVirtual: function() { + return true; + }, + + getDevices: function() { + return null; + }, + + containsDevice: function(ifname) { + return (network.getIfnameOf(ifname) == this.getIfname()); + }, + + renderFormOptions: function(s) { + var dev = this.getL3Device() || this.getDevice(), o; + + o = s.taboption('general', form.Value, '_modem_device', _('Modem device')); + o.ucioption = 'device'; + o.rmempty = false; + o.load = function(section_id) { + return callFileList('/dev/').then(L.bind(function(devices) { + for (var i = 0; i < devices.length; i++) + this.value(devices[i]); + return form.Value.prototype.load.apply(this, [section_id]); + }, this)); + }; + + o = s.taboption('general', form.Value, 'apn', _('APN')); + o.validate = function(section_id, value) { + if (value == null || value == '') + return true; + + if (!/^[a-zA-Z0-9\-.]*[a-zA-Z0-9]$/.test(value)) + return _('Invalid APN provided'); + + return true; + }; + + o = s.taboption('general', form.Value, 'pincode', _('PIN')); + o.datatype = 'and(uinteger,minlength(4),maxlength(8))'; + + o = s.taboption('general', form.ListValue, 'auth', _('Authentication Type')); + o.value('mschapv2', 'MsChapV2'); + o.value('pap', 'PAP'); + o.value('chap', 'CHAP'); + o.value('none', 'NONE'); + o.default = 'none'; + + o = s.taboption('general', form.Value, 'username', _('PAP/CHAP username')); + o.depends('auth', 'pap'); + o.depends('auth', 'chap'); + o.depends('auth', 'mschapv2'); + + o = s.taboption('general', form.Value, 'password', _('PAP/CHAP password')); + o.depends('auth', 'pap'); + o.depends('auth', 'chap'); + o.depends('auth', 'mschapv2'); + o.password = true; + + o = s.taboption('advanced', form.Value, 'delay', _('Modem init timeout'), + _('Maximum amount of seconds to wait for the modem to become ready')); + o.placeholder = '10'; + o.datatype = 'min(1)'; + + o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU')); + o.placeholder = dev ? (dev.getMTU() || '1500') : '1500'; + o.datatype = 'max(9200)'; + + o = s.taboption('general', form.ListValue, 'pdptype', _('PDP Type')); + o.value('ipv4v6', 'IPv4/IPv6'); + o.value('ipv4', 'IPv4'); + o.value('ipv6', 'IPv6'); + o.default = 'ipv4v6'; + + o = s.taboption('advanced', form.Flag, 'defaultroute', _('Use default gateway'), + _('If unchecked, no default route is configured')); + o.default = o.enabled; + + o = s.taboption('advanced', form.Value, 'metric', _('Use gateway metric')); + o.placeholder = '0'; + o.datatype = 'uinteger'; + o.depends('defaultroute', '1'); + } +}); diff --git a/wwan/app/quectel-cm/Makefile b/wwan/app/quectel-cm/Makefile new file mode 100644 index 0000000..c7a505f --- /dev/null +++ b/wwan/app/quectel-cm/Makefile @@ -0,0 +1,35 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=quectel-cm +PKG_VERSION:=1.6.5 +PKG_RELEASE:=2 + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/cmake.mk + +define Package/quectel-cm + SECTION:=net + CATEGORY:=Network + SUBMENU:=WWAN + TITLE:=Qconnector Manager for Quectel WWAN modules + DEPENDS:= \ + +kmod-usb-net-cdc-mbim \ + +kmod-usb-net-qmi-wwan \ + ++kmod-qmi_wwan_q \ + +kmod-usb-serial-option +endef + +define Package/quectel-cm/install + $(INSTALL_DIR) $(1)/usr/bin + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/quectel-CM $(1)/usr/bin/quectel-cm + $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/quectel-{mbim,qmi}-proxy $(1)/usr/bin/ + + $(INSTALL_DIR) $(1)/lib/netifd/proto + $(INSTALL_BIN) ./files/quectel.sh $(1)/lib/netifd/proto/ + + $(INSTALL_DIR) $(1)/etc/hotplug.d/net + $(INSTALL_BIN) ./files/smp-affinity-mhi-pcie.sh $(1)/etc/hotplug.d/net/21-smp-affinity-mhi-pcie + $(INSTALL_BIN) ./files/smp-affinity-qmi-usb.sh $(1)/etc/hotplug.d/net/22-smp-affinity-qmi-usb +endef + +$(eval $(call BuildPackage,quectel-cm)) diff --git a/wwan/app/quectel-cm/files/quectel.sh b/wwan/app/quectel-cm/files/quectel.sh new file mode 100644 index 0000000..056a150 --- /dev/null +++ b/wwan/app/quectel-cm/files/quectel.sh @@ -0,0 +1,138 @@ +#!/bin/sh + +[ -n "$INCLUDE_ONLY" ] || { + . /lib/functions.sh + . ../netifd-proto.sh + init_proto "$@" +} + +proto_quectel_init_config() { + available=1 + no_device=1 + proto_config_add_string "device:device" + proto_config_add_string "apn" + proto_config_add_string "auth" + proto_config_add_string "username" + proto_config_add_string "password" + proto_config_add_string "pincode" + proto_config_add_int "delay" + proto_config_add_string "pdptype" + proto_config_add_boolean "dhcp" + proto_config_add_boolean "dhcpv6" + proto_config_add_boolean "sourcefilter" + proto_config_add_boolean "delegate" + proto_config_add_int "mtu" + proto_config_add_defaults +} + +proto_quectel_setup() { + local interface="$1" + local device apn auth username password pincode delay pdptype + local dhcp dhcpv6 sourcefilter delegate mtu $PROTO_DEFAULT_OPTIONS + local ip4table ip6table + local pid zone + + json_get_vars device apn auth username password pincode delay + json_get_vars pdptype dhcp dhcpv6 sourcefilter delegate ip4table + json_get_vars ip6table mtu $PROTO_DEFAULT_OPTIONS + + [ -n "$delay" ] && sleep "$delay" + + [ -n "$metric" ] || metric="0" + [ -z "$ctl_device" ] || device="$ctl_device" + + [ -n "$device" ] || { + echo "No control device specified" + proto_notify_error "$interface" NO_DEVICE + proto_set_available "$interface" 0 + return 1 + } + + device="$(readlink -f "$device")" + [ -c "$device" ] || { + echo "The specified control device does not exist" + proto_notify_error "$interface" NO_DEVICE + proto_set_available "$interface" 0 + return 1 + } + + devname="$(basename "$device")" + devpath="$(readlink -f "/sys/class/usbmisc/$devname/device/")" + ifname="$(ls "$devpath/net" 2>"/dev/null")" + [ -n "$ifname" ] || { + echo "The interface could not be found." + proto_notify_error "$interface" NO_IFACE + proto_set_available "$interface" 0 + return 1 + } + + [ "$pdptype" = "ip" -o "$pdptype" = "ipv4v6" ] && ipv4opt="-4" + [ "$pdptype" = "ipv6" -o "$pdptype" = "ipv4v6" ] && ipv6opt="-6" + [ -n "$auth" ] || auth="none" + + eval "proto_run_command '$interface' /usr/bin/quectel-cm -i '$ifname' $ipv4opt $ipv6opt ${pincode:+-p $pincode} -s '$apn' '$username' '$password' '$auth'" + sleep 5 + + ifconfig "$ifname" up + ifconfig "${ifname}_1" &>"/dev/null" && ifname="${ifname}_1" + + if [ -n "$mtu" ]; then + echo "Setting MTU to $mtu" + /sbin/ip link set dev "$ifname" mtu "$mtu" + fi + + echo "Setting up $ifname" + proto_init_update "$ifname" 1 + proto_set_keep 1 + proto_send_update "$interface" + + zone="$(fw3 -q network "$interface" 2>/dev/null)" + + if [ "$pdptype" = "ipv6" ] || [ "$pdptype" = "ipv4v6" ]; then + json_init + json_add_string name "${interface}_6" + json_add_string ifname "@$interface" + [ "$pdptype" = "ipv4v6" ] && json_add_string iface_464xlat "0" + json_add_string proto "dhcpv6" + proto_add_dynamic_defaults + [ -z "$ip6table" ] || json_add_string ip6table "$ip6table" + # RFC 7278: Extend an IPv6 /64 Prefix to LAN + json_add_string extendprefix 1 + [ "$delegate" = "0" ] && json_add_boolean delegate "0" + [ "$sourcefilter" = "0" ] && json_add_boolean sourcefilter "0" + [ -z "$zone" ] || json_add_string zone "$zone" + json_close_object + ubus call network add_dynamic "$(json_dump)" + fi + + if [ "$pdptype" = "ip" ] || [ "$pdptype" = "ipv4v6" ]; then + json_init + json_add_string name "${interface}_4" + json_add_string ifname "@$interface" + json_add_string proto "dhcp" + [ -z "$ip4table" ] || json_add_string ip4table "$ip4table" + proto_add_dynamic_defaults + [ -z "$zone" ] || json_add_string zone "$zone" + json_close_object + ubus call network add_dynamic "$(json_dump)" + fi +} + +proto_quectel_teardown() { + local interface="$1" + + local device + json_get_vars device + [ -z "$ctl_device" ] || device="$ctl_device" + + echo "Stopping network $interface" + + proto_kill_command "$interface" + + proto_init_update "*" 0 + proto_send_update "$interface" +} + +[ -n "$INCLUDE_ONLY" ] || { + add_protocol quectel +} diff --git a/wwan/app/quectel-cm/files/smp-affinity-mhi-pcie.sh b/wwan/app/quectel-cm/files/smp-affinity-mhi-pcie.sh new file mode 100644 index 0000000..fed439b --- /dev/null +++ b/wwan/app/quectel-cm/files/smp-affinity-mhi-pcie.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +[ "$ACTION" = add ] || exit +echo "$INTERFACE" | grep -q "rmnet_mhi" || exit + +core_count="$(grep -c "processor" "/proc/cpuinfo")" +irq_path="/sys/class/net/$INTERFACE/queues" + +devnum="$(echo "${INTERFACE%.*}" | grep -Eo "[0-9]+")" +core="$(( devnum % (core_count - 1) + 1))" +if [ "$INTERFACE" != "${INTERFACE%.*}" ]; then + if [ "$core" -lt "$(( core_count - 1 ))" ]; then + let core++ + else + core="1" + fi +fi +irq="$(printf "%x" "$((1 << core))")" + +echo "$irq" > "$irq_path/rx-0/rps_cpus" +echo "4096" > "$irq_path/rx-0/rps_flow_cnt" +echo "2000" > "/proc/sys/net/core/netdev_max_backlog" + +exit 0 diff --git a/wwan/app/quectel-cm/files/smp-affinity-qmi-usb.sh b/wwan/app/quectel-cm/files/smp-affinity-qmi-usb.sh new file mode 100644 index 0000000..7ea5da3 --- /dev/null +++ b/wwan/app/quectel-cm/files/smp-affinity-qmi-usb.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +[ "$ACTION" = add ] || exit +echo "$INTERFACE" | grep -q "wwan" || exit + +core_count="$(grep -c "processor" "/proc/cpuinfo")" +irq_path="/sys/class/net/$INTERFACE/queues" + +devnum="$(echo "${INTERFACE%_*}" | grep -Eo "[0-9]+")" +core="$(( devnum % (core_count - 1) + 1))" +if [ "$INTERFACE" != "${INTERFACE%_*}" ]; then + if [ "$core" -lt "$(( core_count - 1 ))" ]; then + let core++ + else + core="1" + fi +fi +irq="$(printf "%x" "$((1 << core))")" + +echo "$irq" > "$irq_path/rx-0/rps_cpus" +echo "4096" > "$irq_path/rx-0/rps_flow_cnt" +echo "2000" > "/proc/sys/net/core/netdev_max_backlog" + +exit 0 diff --git a/wwan/app/quectel_cm_5G/src/CMakeLists.txt b/wwan/app/quectel-cm/src/CMakeLists.txt similarity index 62% rename from wwan/app/quectel_cm_5G/src/CMakeLists.txt rename to wwan/app/quectel-cm/src/CMakeLists.txt index 8ce3f5a..e9e7646 100644 --- a/wwan/app/quectel_cm_5G/src/CMakeLists.txt +++ b/wwan/app/quectel-cm/src/CMakeLists.txt @@ -1,36 +1,36 @@ -cmake_minimum_required(VERSION 2.4) +cmake_minimum_required(VERSION 2.4) -project(quectel-CM) +project(quectel-CM) add_definitions(-Wall -Wextra -Werror -O1) -option(USE_QRTR "Enable QRTR" OFF) +option(USE_QRTR "Enable QRTR" OFF) set( QL_CM_SRC - QmiWwanCM.c GobiNetCM.c main.c MPQMUX.c QMIThread.c util.c qmap_bridge_mode.c mbim-cm.c device.c + QmiWwanCM.c GobiNetCM.c main.c QCQMUX.c QMIThread.c util.c qmap_bridge_mode.c mbim-cm.c device.c atc.c atchannel.c at_tok.c udhcpc.c ) -if(USE_QRTR) +if(USE_QRTR) add_definitions(-DCONFIG_QRTR) set( QRTR_SRC qrtr.c rmnetctl.c) -endif() +endif() add_executable(quectel-CM ${QL_CM_SRC} ${QRTR_SRC}) -target_link_libraries(quectel-CM PUBLIC pthread) +target_link_libraries(quectel-CM PUBLIC pthread) install (TARGETS quectel-CM DESTINATION bin) add_executable(quectel-qmi-proxy quectel-qmi-proxy.c) -target_link_libraries(quectel-qmi-proxy PUBLIC pthread) +target_link_libraries(quectel-qmi-proxy PUBLIC pthread) install (TARGETS quectel-qmi-proxy DESTINATION bin) add_executable(quectel-mbim-proxy quectel-mbim-proxy.c) -target_link_libraries(quectel-mbim-proxy PUBLIC pthread) +target_link_libraries(quectel-mbim-proxy PUBLIC pthread) install (TARGETS quectel-mbim-proxy DESTINATION bin) add_executable(quectel-atc-proxy quectel-atc-proxy.c atchannel.c at_tok.c util.c) -target_link_libraries(quectel-atc-proxy PUBLIC pthread) +target_link_libraries(quectel-atc-proxy PUBLIC pthread) install (TARGETS quectel-atc-proxy DESTINATION bin) add_executable(quectel-qrtr-proxy quectel-qrtr-proxy.c) -target_link_libraries(quectel-qrtr-proxy PUBLIC pthread) +target_link_libraries(quectel-qrtr-proxy PUBLIC pthread) install (TARGETS quectel-qrtr-proxy DESTINATION bin) diff --git a/wwan/app/quectel_cm_5G/src/GobiNetCM.c b/wwan/app/quectel-cm/src/GobiNetCM.c similarity index 97% rename from wwan/app/quectel_cm_5G/src/GobiNetCM.c rename to wwan/app/quectel-cm/src/GobiNetCM.c index e9c4c81..a57249f 100644 --- a/wwan/app/quectel_cm_5G/src/GobiNetCM.c +++ b/wwan/app/quectel-cm/src/GobiNetCM.c @@ -1,246 +1,246 @@ -/****************************************************************************** - @file GobiNetCM.c - @brief GobiNet driver. - - 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 -#include -#include -#include -#include -#include "QMIThread.h" - -#ifdef CONFIG_GOBINET -static int qmiclientId[QMUX_TYPE_ALL]; - -// IOCTL to generate a client ID for this service type -#define IOCTL_QMI_GET_SERVICE_FILE 0x8BE0 + 1 - -// IOCTL to get the VIDPID of the device -#define IOCTL_QMI_GET_DEVICE_VIDPID 0x8BE0 + 2 - -// IOCTL to get the MEID of the device -#define IOCTL_QMI_GET_DEVICE_MEID 0x8BE0 + 3 - -static int GobiNetSendQMI(PQCQMIMSG pRequest) { - int ret, fd; - - fd = qmiclientId[pRequest->QMIHdr.QMIType]; - pRequest->QMIHdr.ClientId = (fd&0xFF) ? fd&0xFF : pRequest->QMIHdr.QMIType; - - if (fd <= 0) { - dbg_time("%s QMIType: %d has no clientID", __func__, pRequest->QMIHdr.QMIType); - return -ENODEV; - } - - // Always ready to write - if (1 == 1) { - ssize_t nwrites = le16_to_cpu(pRequest->QMIHdr.Length) + 1 - sizeof(QCQMI_HDR); - ret = write(fd, &pRequest->MUXMsg, nwrites); - if (ret == nwrites) { - ret = 0; - } else { - dbg_time("%s write=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno)); - } - } else { - dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno)); - } - - return ret; -} - -static int GobiNetGetClientID(const char *qcqmi, UCHAR QMIType) { - int ClientId; - ClientId = cm_open_dev(qcqmi); - if (ClientId == -1) { - dbg_time("failed to open %s, errno: %d (%s)", qcqmi, errno, strerror(errno)); - return -1; - } - - if (ioctl(ClientId, IOCTL_QMI_GET_SERVICE_FILE, QMIType) != 0) { - dbg_time("failed to get ClientID for 0x%02x errno: %d (%s)", QMIType, errno, strerror(errno)); - close(ClientId); - ClientId = 0; - } - - switch (QMIType) { - case QMUX_TYPE_WDS: dbg_time("Get clientWDS = %d", ClientId); break; - case QMUX_TYPE_DMS: dbg_time("Get clientDMS = %d", ClientId); break; - case QMUX_TYPE_NAS: dbg_time("Get clientNAS = %d", ClientId); break; - case QMUX_TYPE_QOS: dbg_time("Get clientQOS = %d", ClientId); break; - case QMUX_TYPE_WMS: dbg_time("Get clientWMS = %d", ClientId); break; - case QMUX_TYPE_PDS: dbg_time("Get clientPDS = %d", ClientId); break; - case QMUX_TYPE_UIM: dbg_time("Get clientUIM = %d", ClientId); break; - case QMUX_TYPE_COEX: dbg_time("Get clientCOEX = %d", ClientId); break; - case QMUX_TYPE_WDS_ADMIN: dbg_time("Get clientWDA = %d", ClientId); - break; - default: break; - } - - return ClientId; -} - -static int GobiNetDeInit(void) { - unsigned int i; - for (i = 0; i < sizeof(qmiclientId)/sizeof(qmiclientId[0]); i++) - { - if (qmiclientId[i] != 0) - { - close(qmiclientId[i]); - qmiclientId[i] = 0; - } - } - - return 0; -} - -static void * GobiNetThread(void *pData) { - PROFILE_T *profile = (PROFILE_T *)pData; - const char *qcqmi = (const char *)profile->qmichannel; - int wait_for_request_quit = 0; - - qmiclientId[QMUX_TYPE_WDS] = GobiNetGetClientID(qcqmi, QMUX_TYPE_WDS); - if (profile->enable_ipv6) - qmiclientId[QMUX_TYPE_WDS_IPV6] = GobiNetGetClientID(qcqmi, QMUX_TYPE_WDS); - qmiclientId[QMUX_TYPE_DMS] = GobiNetGetClientID(qcqmi, QMUX_TYPE_DMS); - qmiclientId[QMUX_TYPE_NAS] = GobiNetGetClientID(qcqmi, QMUX_TYPE_NAS); - qmiclientId[QMUX_TYPE_UIM] = GobiNetGetClientID(qcqmi, QMUX_TYPE_UIM); -#ifdef CONFIG_COEX_WWAN_STATE - qmiclientId[QMUX_TYPE_COEX] = GobiNetGetClientID(qcqmi, QMUX_TYPE_COEX); -#endif - if (profile->qmap_mode == 0 || profile->loopback_state) {//when QMAP enabled, set data format in GobiNet Driver - qmiclientId[QMUX_TYPE_WDS_ADMIN] = GobiNetGetClientID(qcqmi, QMUX_TYPE_WDS_ADMIN); - profile->wda_client = qmiclientId[QMUX_TYPE_WDS_ADMIN]; - } - - //donot check clientWDA, there is only one client for WDA, if quectel-CM is killed by SIGKILL, i cannot get client ID for WDA again! - if (qmiclientId[QMUX_TYPE_WDS] == 0) /*|| (clientWDA == -1)*/ { - GobiNetDeInit(); - dbg_time("%s Failed to open %s, errno: %d (%s)", __func__, qcqmi, errno, strerror(errno)); - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED); - pthread_exit(NULL); - return NULL; - } - - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_CONNECTED); - - while (1) { - struct pollfd pollfds[16] = {{qmidevice_control_fd[1], POLLIN, 0}}; - int ne, ret, nevents = 1; - unsigned int i; - - for (i = 0; i < sizeof(qmiclientId)/sizeof(qmiclientId[0]); i++) - { - if (qmiclientId[i] != 0) - { - pollfds[nevents].fd = qmiclientId[i]; - pollfds[nevents].events = POLLIN; - pollfds[nevents].revents = 0; - nevents++; - } - } - - do { - ret = poll(pollfds, nevents, wait_for_request_quit ? 1000: -1); - } while ((ret < 0) && (errno == EINTR)); - - if (ret == 0 && wait_for_request_quit) { - QmiThreadRecvQMI(NULL); //main thread may pending on QmiThreadSendQMI() - continue; - } - - if (ret <= 0) { - dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno)); - break; - } - - for (ne = 0; ne < nevents; ne++) { - int fd = pollfds[ne].fd; - short revents = pollfds[ne].revents; - - if (revents & (POLLERR | POLLHUP | POLLNVAL)) { - dbg_time("%s poll err/hup/inval", __func__); - dbg_time("epoll fd = %d, events = 0x%04x", fd, revents); - if (fd == qmidevice_control_fd[1]) { - } else { - } - if (revents & (POLLERR | POLLHUP | POLLNVAL)) - goto __GobiNetThread_quit; - } - - if ((revents & POLLIN) == 0) - continue; - - if (fd == qmidevice_control_fd[1]) { - int triger_event; - if (read(fd, &triger_event, sizeof(triger_event)) == sizeof(triger_event)) { - //DBG("triger_event = 0x%x", triger_event); - switch (triger_event) { - case RIL_REQUEST_QUIT: - goto __GobiNetThread_quit; - break; - case SIG_EVENT_STOP: - wait_for_request_quit = 1; - break; - default: - break; - } - } - continue; - } - - { - ssize_t nreads; - PQCQMIMSG pResponse = (PQCQMIMSG)cm_recv_buf; - - nreads = read(fd, &pResponse->MUXMsg, sizeof(cm_recv_buf) - sizeof(QCQMI_HDR)); - if (nreads <= 0) - { - dbg_time("%s read=%d errno: %d (%s)", __func__, (int)nreads, errno, strerror(errno)); - break; - } - - for (i = 0; i < sizeof(qmiclientId)/sizeof(qmiclientId[0]); i++) - { - if (qmiclientId[i] == fd) - { - pResponse->QMIHdr.QMIType = i; - } - } - - pResponse->QMIHdr.IFType = USB_CTL_MSG_TYPE_QMI; - pResponse->QMIHdr.Length = cpu_to_le16(nreads + sizeof(QCQMI_HDR) - 1); - pResponse->QMIHdr.CtlFlags = 0x00; - pResponse->QMIHdr.ClientId = (fd&0xFF) ? fd&0xFF : pResponse->QMIHdr.QMIType;; - - QmiThreadRecvQMI(pResponse); - } - } - } - -__GobiNetThread_quit: - GobiNetDeInit(); - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED); - QmiThreadRecvQMI(NULL); //main thread may pending on QmiThreadSendQMI() - dbg_time("%s exit", __func__); - pthread_exit(NULL); - return NULL; -} - -const struct qmi_device_ops gobi_qmidev_ops = { - .deinit = GobiNetDeInit, - .send = GobiNetSendQMI, - .read = GobiNetThread, -}; -#endif - +/****************************************************************************** + @file GobiNetCM.c + @brief GobiNet driver. + + 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 +#include +#include +#include +#include +#include "QMIThread.h" + +#ifdef CONFIG_GOBINET +static int qmiclientId[QMUX_TYPE_ALL]; + +// IOCTL to generate a client ID for this service type +#define IOCTL_QMI_GET_SERVICE_FILE 0x8BE0 + 1 + +// IOCTL to get the VIDPID of the device +#define IOCTL_QMI_GET_DEVICE_VIDPID 0x8BE0 + 2 + +// IOCTL to get the MEID of the device +#define IOCTL_QMI_GET_DEVICE_MEID 0x8BE0 + 3 + +static int GobiNetSendQMI(PQCQMIMSG pRequest) { + int ret, fd; + + fd = qmiclientId[pRequest->QMIHdr.QMIType]; + pRequest->QMIHdr.ClientId = (fd&0xFF) ? fd&0xFF : pRequest->QMIHdr.QMIType; + + if (fd <= 0) { + dbg_time("%s QMIType: %d has no clientID", __func__, pRequest->QMIHdr.QMIType); + return -ENODEV; + } + + // Always ready to write + if (1 == 1) { + ssize_t nwrites = le16_to_cpu(pRequest->QMIHdr.Length) + 1 - sizeof(QCQMI_HDR); + ret = write(fd, &pRequest->MUXMsg, nwrites); + if (ret == nwrites) { + ret = 0; + } else { + dbg_time("%s write=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno)); + } + } else { + dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno)); + } + + return ret; +} + +static int GobiNetGetClientID(const char *qcqmi, UCHAR QMIType) { + int ClientId; + ClientId = cm_open_dev(qcqmi); + if (ClientId == -1) { + dbg_time("failed to open %s, errno: %d (%s)", qcqmi, errno, strerror(errno)); + return -1; + } + + if (ioctl(ClientId, IOCTL_QMI_GET_SERVICE_FILE, QMIType) != 0) { + dbg_time("failed to get ClientID for 0x%02x errno: %d (%s)", QMIType, errno, strerror(errno)); + close(ClientId); + ClientId = 0; + } + + switch (QMIType) { + case QMUX_TYPE_WDS: dbg_time("Get clientWDS = %d", ClientId); break; + case QMUX_TYPE_DMS: dbg_time("Get clientDMS = %d", ClientId); break; + case QMUX_TYPE_NAS: dbg_time("Get clientNAS = %d", ClientId); break; + case QMUX_TYPE_QOS: dbg_time("Get clientQOS = %d", ClientId); break; + case QMUX_TYPE_WMS: dbg_time("Get clientWMS = %d", ClientId); break; + case QMUX_TYPE_PDS: dbg_time("Get clientPDS = %d", ClientId); break; + case QMUX_TYPE_UIM: dbg_time("Get clientUIM = %d", ClientId); break; + case QMUX_TYPE_COEX: dbg_time("Get clientCOEX = %d", ClientId); break; + case QMUX_TYPE_WDS_ADMIN: dbg_time("Get clientWDA = %d", ClientId); + break; + default: break; + } + + return ClientId; +} + +static int GobiNetDeInit(void) { + unsigned int i; + for (i = 0; i < sizeof(qmiclientId)/sizeof(qmiclientId[0]); i++) + { + if (qmiclientId[i] != 0) + { + close(qmiclientId[i]); + qmiclientId[i] = 0; + } + } + + return 0; +} + +static void * GobiNetThread(void *pData) { + PROFILE_T *profile = (PROFILE_T *)pData; + const char *qcqmi = (const char *)profile->qmichannel; + int wait_for_request_quit = 0; + + qmiclientId[QMUX_TYPE_WDS] = GobiNetGetClientID(qcqmi, QMUX_TYPE_WDS); + if (profile->enable_ipv6) + qmiclientId[QMUX_TYPE_WDS_IPV6] = GobiNetGetClientID(qcqmi, QMUX_TYPE_WDS); + qmiclientId[QMUX_TYPE_DMS] = GobiNetGetClientID(qcqmi, QMUX_TYPE_DMS); + qmiclientId[QMUX_TYPE_NAS] = GobiNetGetClientID(qcqmi, QMUX_TYPE_NAS); + qmiclientId[QMUX_TYPE_UIM] = GobiNetGetClientID(qcqmi, QMUX_TYPE_UIM); +#ifdef CONFIG_COEX_WWAN_STATE + qmiclientId[QMUX_TYPE_COEX] = GobiNetGetClientID(qcqmi, QMUX_TYPE_COEX); +#endif + if (profile->qmap_mode == 0 || profile->loopback_state) {//when QMAP enabled, set data format in GobiNet Driver + qmiclientId[QMUX_TYPE_WDS_ADMIN] = GobiNetGetClientID(qcqmi, QMUX_TYPE_WDS_ADMIN); + profile->wda_client = qmiclientId[QMUX_TYPE_WDS_ADMIN]; + } + + //donot check clientWDA, there is only one client for WDA, if quectel-CM is killed by SIGKILL, i cannot get client ID for WDA again! + if (qmiclientId[QMUX_TYPE_WDS] == 0) /*|| (clientWDA == -1)*/ { + GobiNetDeInit(); + dbg_time("%s Failed to open %s, errno: %d (%s)", __func__, qcqmi, errno, strerror(errno)); + qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED); + pthread_exit(NULL); + return NULL; + } + + qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_CONNECTED); + + while (1) { + struct pollfd pollfds[16] = {{qmidevice_control_fd[1], POLLIN, 0}}; + int ne, ret, nevents = 1; + unsigned int i; + + for (i = 0; i < sizeof(qmiclientId)/sizeof(qmiclientId[0]); i++) + { + if (qmiclientId[i] != 0) + { + pollfds[nevents].fd = qmiclientId[i]; + pollfds[nevents].events = POLLIN; + pollfds[nevents].revents = 0; + nevents++; + } + } + + do { + ret = poll(pollfds, nevents, wait_for_request_quit ? 1000: -1); + } while ((ret < 0) && (errno == EINTR)); + + if (ret == 0 && wait_for_request_quit) { + QmiThreadRecvQMI(NULL); //main thread may pending on QmiThreadSendQMI() + continue; + } + + if (ret <= 0) { + dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno)); + break; + } + + for (ne = 0; ne < nevents; ne++) { + int fd = pollfds[ne].fd; + short revents = pollfds[ne].revents; + + if (revents & (POLLERR | POLLHUP | POLLNVAL)) { + dbg_time("%s poll err/hup/inval", __func__); + dbg_time("epoll fd = %d, events = 0x%04x", fd, revents); + if (fd == qmidevice_control_fd[1]) { + } else { + } + if (revents & (POLLERR | POLLHUP | POLLNVAL)) + goto __GobiNetThread_quit; + } + + if ((revents & POLLIN) == 0) + continue; + + if (fd == qmidevice_control_fd[1]) { + int triger_event; + if (read(fd, &triger_event, sizeof(triger_event)) == sizeof(triger_event)) { + //DBG("triger_event = 0x%x", triger_event); + switch (triger_event) { + case RIL_REQUEST_QUIT: + goto __GobiNetThread_quit; + break; + case SIG_EVENT_STOP: + wait_for_request_quit = 1; + break; + default: + break; + } + } + continue; + } + + { + ssize_t nreads; + PQCQMIMSG pResponse = (PQCQMIMSG)cm_recv_buf; + + nreads = read(fd, &pResponse->MUXMsg, sizeof(cm_recv_buf) - sizeof(QCQMI_HDR)); + if (nreads <= 0) + { + dbg_time("%s read=%d errno: %d (%s)", __func__, (int)nreads, errno, strerror(errno)); + break; + } + + for (i = 0; i < sizeof(qmiclientId)/sizeof(qmiclientId[0]); i++) + { + if (qmiclientId[i] == fd) + { + pResponse->QMIHdr.QMIType = i; + } + } + + pResponse->QMIHdr.IFType = USB_CTL_MSG_TYPE_QMI; + pResponse->QMIHdr.Length = cpu_to_le16(nreads + sizeof(QCQMI_HDR) - 1); + pResponse->QMIHdr.CtlFlags = 0x00; + pResponse->QMIHdr.ClientId = (fd&0xFF) ? fd&0xFF : pResponse->QMIHdr.QMIType;; + + QmiThreadRecvQMI(pResponse); + } + } + } + +__GobiNetThread_quit: + GobiNetDeInit(); + qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED); + QmiThreadRecvQMI(NULL); //main thread may pending on QmiThreadSendQMI() + dbg_time("%s exit", __func__); + pthread_exit(NULL); + return NULL; +} + +const struct qmi_device_ops gobi_qmidev_ops = { + .deinit = GobiNetDeInit, + .send = GobiNetSendQMI, + .read = GobiNetThread, +}; +#endif + diff --git a/wwan/app/quectel_cm_5G/src/Makefile b/wwan/app/quectel-cm/src/Makefile similarity index 94% rename from wwan/app/quectel_cm_5G/src/Makefile rename to wwan/app/quectel-cm/src/Makefile index 5219a21..9ffb503 100644 --- a/wwan/app/quectel_cm_5G/src/Makefile +++ b/wwan/app/quectel-cm/src/Makefile @@ -1,46 +1,46 @@ -ifneq ($(CROSS_COMPILE),) -CROSS-COMPILE:=$(CROSS_COMPILE) -endif -#CROSS-COMPILE:=/workspace/buildroot/buildroot-qemu_mips_malta_defconfig/output/host/usr/bin/mips-buildroot-linux-uclibc- -#CROSS-COMPILE:=/workspace/buildroot/buildroot-qemu_arm_vexpress_defconfig/output/host/usr/bin/arm-buildroot-linux-uclibcgnueabi- -#CROSS-COMPILE:=/workspace/buildroot-git/qemu_mips64_malta/output/host/usr/bin/mips-gnu-linux- -ifeq ($(CC),cc) -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+=atc.c atchannel.c at_tok.c -#QL_CM_SRC+=qrtr.c rmnetctl.c -ifeq (1,1) -QL_CM_DHCP=udhcpc.c -else -LIBMNL=libmnl/ifutils.c libmnl/attr.c libmnl/callback.c libmnl/nlmsg.c libmnl/socket.c -DHCP=libmnl/dhcp/dhcpclient.c libmnl/dhcp/dhcpmsg.c libmnl/dhcp/packet.c -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 quectel-CM ${LDFLAGS} - -debug: clean - $(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 quectel-qmi-proxy ${LDFLAGS} - -mbim-proxy: - $(CC) ${CFLAGS} quectel-mbim-proxy.c -o quectel-mbim-proxy ${LDFLAGS} - -qrtr-proxy: - $(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 quectel-atc-proxy ${LDFLAGS} - -clean: - rm -rf *.o libmnl/*.o quectel-CM quectel-qmi-proxy quectel-mbim-proxy quectel-atc-proxy +ifneq ($(CROSS_COMPILE),) +CROSS-COMPILE:=$(CROSS_COMPILE) +endif +#CROSS-COMPILE:=/workspace/buildroot/buildroot-qemu_mips_malta_defconfig/output/host/usr/bin/mips-buildroot-linux-uclibc- +#CROSS-COMPILE:=/workspace/buildroot/buildroot-qemu_arm_vexpress_defconfig/output/host/usr/bin/arm-buildroot-linux-uclibcgnueabi- +#CROSS-COMPILE:=/workspace/buildroot-git/qemu_mips64_malta/output/host/usr/bin/mips-gnu-linux- +ifeq ($(CC),cc) +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+=atc.c atchannel.c at_tok.c +#QL_CM_SRC+=qrtr.c rmnetctl.c +ifeq (1,1) +QL_CM_DHCP=udhcpc.c +else +LIBMNL=libmnl/ifutils.c libmnl/attr.c libmnl/callback.c libmnl/nlmsg.c libmnl/socket.c +DHCP=libmnl/dhcp/dhcpclient.c libmnl/dhcp/dhcpmsg.c libmnl/dhcp/packet.c +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 quectel-CM ${LDFLAGS} + +debug: clean + $(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 quectel-qmi-proxy ${LDFLAGS} + +mbim-proxy: + $(CC) ${CFLAGS} quectel-mbim-proxy.c -o quectel-mbim-proxy ${LDFLAGS} + +qrtr-proxy: + $(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 quectel-atc-proxy ${LDFLAGS} + +clean: + rm -rf *.o libmnl/*.o quectel-CM quectel-qmi-proxy quectel-mbim-proxy quectel-atc-proxy diff --git a/wwan/app/quectel_cm_5G/src/Makefile.am b/wwan/app/quectel-cm/src/Makefile.am similarity index 76% rename from wwan/app/quectel_cm_5G/src/Makefile.am rename to wwan/app/quectel-cm/src/Makefile.am index 87e5266..23c49fb 100644 --- a/wwan/app/quectel_cm_5G/src/Makefile.am +++ b/wwan/app/quectel-cm/src/Makefile.am @@ -1,17 +1,17 @@ bin_PROGRAMS = quectel-CM -QL_CM_SRC=QmiWwanCM.c GobiNetCM.c main.c MPQMUX.c QMIThread.c util.c qmap_bridge_mode.c mbim-cm.c device.c +QL_CM_SRC=QmiWwanCM.c GobiNetCM.c main.c QCQMUX.c QMIThread.c util.c qmap_bridge_mode.c mbim-cm.c device.c QL_CM_SRC+=atc.c atchannel.c at_tok.c #QL_CM_SRC+=qrtr.c rmnetctl.c QL_CM_DHCP=udhcpc.c if USE_QRTR -quectel_CM_CFLAGS = -DCONFIG_QRTR +quectel_CM_CFLAGS = -DCONFIG_QRTR QL_CM_SRC += qrtr.c rmnetctl.c if USE_MSM_IPC quectel_CM_CFLAGS += -DUSE_LINUX_MSM_IPC endif endif -quectel_CM_SOURCES = ${QL_CM_SRC} ${QL_CM_DHCP} +quectel_CM_SOURCES = ${QL_CM_SRC} ${QL_CM_DHCP} bin_PROGRAMS += quectel-qmi-proxy quectel_qmi_proxy_SOURCES = quectel-qmi-proxy.c diff --git a/wwan/app/quectel_cm_5G/src/NOTICE b/wwan/app/quectel-cm/src/NOTICE similarity index 98% rename from wwan/app/quectel_cm_5G/src/NOTICE rename to wwan/app/quectel-cm/src/NOTICE index 0a062cf..898aac4 100644 --- a/wwan/app/quectel_cm_5G/src/NOTICE +++ b/wwan/app/quectel-cm/src/NOTICE @@ -1,7 +1,7 @@ -This program is totally open souce code, and public domain software for customers of Quectel company. - -The APIs of QMI WWAMN interfaces are defined by Qualcomm. And this program complies with Qualcomm QMI WWAN interfaces specification. - -Customers are free to modify the source codes and redistribute them. - -For those who is not Quectel's customer, all rights are closed, and any copying and commercial development over this progrma is not allowed. +This program is totally open souce code, and public domain software for customers of Quectel company. + +The APIs of QMI WWAMN interfaces are defined by Qualcomm. And this program complies with Qualcomm QMI WWAN interfaces specification. + +Customers are free to modify the source codes and redistribute them. + +For those who is not Quectel's customer, all rights are closed, and any copying and commercial development over this progrma is not allowed. diff --git a/wwan/app/quectel_cm_5G/src/QCQCTL.h b/wwan/app/quectel-cm/src/QCQCTL.h similarity index 97% rename from wwan/app/quectel_cm_5G/src/QCQCTL.h rename to wwan/app/quectel-cm/src/QCQCTL.h index eaf2ad6..6111614 100644 --- a/wwan/app/quectel_cm_5G/src/QCQCTL.h +++ b/wwan/app/quectel-cm/src/QCQCTL.h @@ -1,394 +1,394 @@ -/****************************************************************************** - @file QCQCTL.h - - DESCRIPTION - This module contains QMI QCTL module. - - INITIALIZATION AND SEQUENCING REQUIREMENTS - None. - - --------------------------------------------------------------------------- - Copyright (c) 2016 - 2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. - Quectel Wireless Solution Proprietary and Confidential. - --------------------------------------------------------------------------- -******************************************************************************/ - - -#ifndef QCQCTL_H -#define QCQCTL_H - -#include "QCQMI.h" - -#pragma pack(push, 1) - -// ================= QMICTL ================== - -// QMICTL Control Flags -#define QMICTL_CTL_FLAG_CMD 0x00 -#define QMICTL_CTL_FLAG_RSP 0x01 -#define QMICTL_CTL_FLAG_IND 0x02 - -#if 0 -typedef struct _QMICTL_TRANSACTION_ITEM -{ - LIST_ENTRY List; - UCHAR TransactionId; // QMICTL transaction id - PVOID Context; // Adapter or IocDev - PIRP Irp; -} QMICTL_TRANSACTION_ITEM, *PQMICTL_TRANSACTION_ITEM; -#endif - -typedef struct _QCQMICTL_MSG_HDR -{ - UCHAR CtlFlags; // 00-cmd, 01-rsp, 10-ind - UCHAR TransactionId; - USHORT QMICTLType; - USHORT Length; -} __attribute__ ((packed)) QCQMICTL_MSG_HDR, *PQCQMICTL_MSG_HDR; - -#define QCQMICTL_MSG_HDR_SIZE sizeof(QCQMICTL_MSG_HDR) - -typedef struct _QCQMICTL_MSG_HDR_RESP -{ - UCHAR CtlFlags; // 00-cmd, 01-rsp, 10-ind - UCHAR TransactionId; - USHORT QMICTLType; - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} __attribute__ ((packed)) QCQMICTL_MSG_HDR_RESP, *PQCQMICTL_MSG_HDR_RESP; - -typedef struct _QCQMICTL_MSG -{ - UCHAR CtlFlags; // 00-cmd, 01-rsp, 10-ind - UCHAR TransactionId; - USHORT QMICTLType; - USHORT Length; - UCHAR Payload; -} __attribute__ ((packed)) QCQMICTL_MSG, *PQCQMICTL_MSG; - -// TLV Header -typedef struct _QCQMICTL_TLV_HDR -{ - UCHAR TLVType; - USHORT TLVLength; -} __attribute__ ((packed)) QCQMICTL_TLV_HDR, *PQCQMICTL_TLV_HDR; - -#define QCQMICTL_TLV_HDR_SIZE sizeof(QCQMICTL_TLV_HDR) - -// QMICTL Type -#define QMICTL_SET_INSTANCE_ID_REQ 0x0020 -#define QMICTL_SET_INSTANCE_ID_RESP 0x0020 -#define QMICTL_GET_VERSION_REQ 0x0021 -#define QMICTL_GET_VERSION_RESP 0x0021 -#define QMICTL_GET_CLIENT_ID_REQ 0x0022 -#define QMICTL_GET_CLIENT_ID_RESP 0x0022 -#define QMICTL_RELEASE_CLIENT_ID_REQ 0x0023 -#define QMICTL_RELEASE_CLIENT_ID_RESP 0x0023 -#define QMICTL_REVOKE_CLIENT_ID_IND 0x0024 -#define QMICTL_INVALID_CLIENT_ID_IND 0x0025 -#define QMICTL_SET_DATA_FORMAT_REQ 0x0026 -#define QMICTL_SET_DATA_FORMAT_RESP 0x0026 -#define QMICTL_SYNC_REQ 0x0027 -#define QMICTL_SYNC_RESP 0x0027 -#define QMICTL_SYNC_IND 0x0027 -#define QMI_MESSAGE_CTL_INTERNAL_PROXY_OPEN 0xFF00 - -#define QMICTL_FLAG_REQUEST 0x00 -#define QMICTL_FLAG_RESPONSE 0x01 -#define QMICTL_FLAG_INDICATION 0x02 - -// QMICTL Message Definitions - -typedef struct _QMICTL_SET_INSTANCE_ID_REQ_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_REQUEST - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_SET_INSTANCE_ID_REQ - USHORT Length; // 4 - UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLVLength; // 1 - UCHAR Value; // Host-unique QMI instance for this device driver -} __attribute__ ((packed)) QMICTL_SET_INSTANCE_ID_REQ_MSG, *PQMICTL_SET_INSTANCE_ID_REQ_MSG; - -typedef struct _QMICTL_SET_INSTANCE_ID_RESP_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_SET_INSTANCE_ID_RESP - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE - USHORT TLVLength; // 0x0004 - USHORT QMIResult; - USHORT QMIError; - UCHAR TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLV2Length; // 0x0002 - USHORT QMI_ID; // Upper byte is assigned by MSM, - // lower assigned by host -} __attribute__ ((packed)) QMICTL_SET_INSTANCE_ID_RESP_MSG, *PQMICTL_SET_INSTANCE_ID_RESP_MSG; - -typedef struct _QMICTL_GET_VERSION_REQ_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_REQUEST - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_GET_VERSION_REQ - USHORT Length; // 0 - UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLVLength; // var - UCHAR QMUXTypes; // List of one byte QMUX_TYPE values - // 0xFF returns a list of versions for all - // QMUX_TYPEs implemented on the device -} __attribute__ ((packed)) QMICTL_GET_VERSION_REQ_MSG, *PQMICTL_GET_VERSION_REQ_MSG; - -typedef struct _QMUX_TYPE_VERSION_STRUCT -{ - UCHAR QMUXType; - USHORT MajorVersion; - USHORT MinorVersion; -} __attribute__ ((packed)) QMUX_TYPE_VERSION_STRUCT, *PQMUX_TYPE_VERSION_STRUCT; - -typedef struct _ADDENDUM_VERSION_PREAMBLE -{ - UCHAR LabelLength; - UCHAR Label; -} __attribute__ ((packed)) ADDENDUM_VERSION_PREAMBLE, *PADDENDUM_VERSION_PREAMBLE; - -#define QMICTL_GET_VERSION_RSP_TLV_TYPE_VERSION 0x01 -#define QMICTL_GET_VERSION_RSP_TLV_TYPE_ADD_VERSION 0x10 - -typedef struct _QMICTL_GET_VERSION_RESP_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_GET_VERSION_RESP - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE - USHORT TLVLength; // 0x0004 - USHORT QMIResult; - USHORT QMIError; - UCHAR TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLV2Length; // var - UCHAR NumElements; // Num of QMUX_TYPE_VERSION_STRUCT - QMUX_TYPE_VERSION_STRUCT TypeVersion[0]; -} __attribute__ ((packed)) QMICTL_GET_VERSION_RESP_MSG, *PQMICTL_GET_VERSION_RESP_MSG; - -typedef struct _QMICTL_GET_CLIENT_ID_REQ_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_REQUEST - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_GET_CLIENT_ID_REQ - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLVLength; // 1 - UCHAR QMIType; // QMUX type -} __attribute__ ((packed)) QMICTL_GET_CLIENT_ID_REQ_MSG, *PQMICTL_GET_CLIENT_ID_REQ_MSG; - -typedef struct _QMICTL_GET_CLIENT_ID_RESP_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_GET_CLIENT_ID_RESP - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE - USHORT TLVLength; // 0x0004 - USHORT QMIResult; // result code - USHORT QMIError; // error code - UCHAR TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLV2Length; // 2 - UCHAR QMIType; - UCHAR ClientId; -} __attribute__ ((packed)) QMICTL_GET_CLIENT_ID_RESP_MSG, *PQMICTL_GET_CLIENT_ID_RESP_MSG; - -typedef struct _QMICTL_RELEASE_CLIENT_ID_REQ_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_REQUEST - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_RELEASE_CLIENT_ID_REQ - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLVLength; // 0x0002 - UCHAR QMIType; - UCHAR ClientId; -} __attribute__ ((packed)) QMICTL_RELEASE_CLIENT_ID_REQ_MSG, *PQMICTL_RELEASE_CLIENT_ID_REQ_MSG; - -typedef struct _QMICTL_RELEASE_CLIENT_ID_RESP_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_RELEASE_CLIENT_ID_RESP - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE - USHORT TLVLength; // 0x0004 - USHORT QMIResult; // result code - USHORT QMIError; // error code - UCHAR TLV2Type; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLV2Length; // 2 - UCHAR QMIType; - UCHAR ClientId; -} __attribute__ ((packed)) QMICTL_RELEASE_CLIENT_ID_RESP_MSG, *PQMICTL_RELEASE_CLIENT_ID_RESP_MSG; - -typedef struct _QMICTL_REVOKE_CLIENT_ID_IND_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_INDICATION - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_REVOKE_CLIENT_ID_IND - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLVLength; // 0x0002 - UCHAR QMIType; - UCHAR ClientId; -} __attribute__ ((packed)) QMICTL_REVOKE_CLIENT_ID_IND_MSG, *PQMICTL_REVOKE_CLIENT_ID_IND_MSG; - -typedef struct _QMICTL_INVALID_CLIENT_ID_IND_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_INDICATION - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_REVOKE_CLIENT_ID_IND - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLVLength; // 0x0002 - UCHAR QMIType; - UCHAR ClientId; -} __attribute__ ((packed)) QMICTL_INVALID_CLIENT_ID_IND_MSG, *PQMICTL_INVALID_CLIENT_ID_IND_MSG; - -typedef struct _QMICTL_SET_DATA_FORMAT_REQ_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_REQUEST - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_SET_DATA_FORMAT_REQ - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_REQUIRED_PARAMETER - USHORT TLVLength; // 1 - UCHAR DataFormat; // 0-default; 1-QoS hdr present -} __attribute__ ((packed)) QMICTL_SET_DATA_FORMAT_REQ_MSG, *PQMICTL_SET_DATA_FORMAT_REQ_MSG; - -#ifdef QC_IP_MODE -#define SET_DATA_FORMAT_TLV_TYPE_LINK_PROTO 0x10 -#define SET_DATA_FORMAT_LINK_PROTO_ETH 0x0001 -#define SET_DATA_FORMAT_LINK_PROTO_IP 0x0002 -typedef struct _QMICTL_SET_DATA_FORMAT_TLV_LINK_PROT -{ - UCHAR TLVType; // Link-Layer Protocol - USHORT TLVLength; // 2 - USHORT LinkProt; // 0x1: ETH; 0x2: IP -} QMICTL_SET_DATA_FORMAT_TLV_LINK_PROT, *PQMICTL_SET_DATA_FORMAT_TLV_LINK_PROT; - -#ifdef QCMP_UL_TLP -#define SET_DATA_FORMAT_TLV_TYPE_UL_TLP 0x11 -typedef struct _QMICTL_SET_DATA_FORMAT_TLV_UL_TLP -{ - UCHAR TLVType; // 0x11, Uplink TLP Setting - USHORT TLVLength; // 1 - UCHAR UlTlpSetting; // 0x0: Disable; 0x01: Enable -} QMICTL_SET_DATA_FORMAT_TLV_UL_TLP, *PQMICTL_SET_DATA_FORMAT_TLV_UL_TLP; -#endif // QCMP_UL_TLP - -#ifdef QCMP_DL_TLP -#define SET_DATA_FORMAT_TLV_TYPE_DL_TLP 0x13 -typedef struct _QMICTL_SET_DATA_FORMAT_TLV_DL_TLP -{ - UCHAR TLVType; // 0x11, Uplink TLP Setting - USHORT TLVLength; // 1 - UCHAR DlTlpSetting; // 0x0: Disable; 0x01: Enable -} QMICTL_SET_DATA_FORMAT_TLV_DL_TLP, *PQMICTL_SET_DATA_FORMAT_TLV_DL_TLP; -#endif // QCMP_DL_TLP - -#endif // QC_IP_MODE - -#ifdef MP_QCQOS_ENABLED -#define SET_DATA_FORMAT_TLV_TYPE_QOS_SETTING 0x12 -typedef struct _QMICTL_SET_DATA_FORMAT_TLV_QOS_SETTING -{ - UCHAR TLVType; // 0x12, QoS setting - USHORT TLVLength; // 1 - UCHAR QosSetting; // 0x0: Disable; 0x01: Enable -} QMICTL_SET_DATA_FORMAT_TLV_QOS_SETTING, *PQMICTL_SET_DATA_FORMAT_TLV_QOS_SETTING; -#endif // MP_QCQOS_ENABLED - -typedef struct _QMICTL_SET_DATA_FORMAT_RESP_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_SET_DATA_FORMAT_RESP - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE - USHORT TLVLength; // 0x0004 - USHORT QMIResult; // result code - USHORT QMIError; // error code -} __attribute__ ((packed)) QMICTL_SET_DATA_FORMAT_RESP_MSG, *PQMICTL_SET_DATA_FORMAT_RESP_MSG; - -typedef struct _QMICTL_SYNC_REQ_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_REQUEST - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_CTL_SYNC_REQ - USHORT Length; // 0 -} __attribute__ ((packed)) QMICTL_SYNC_REQ_MSG, *PQMICTL_SYNC_REQ_MSG; - -typedef struct _QMICTL_SYNC_RESP_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_CTL_SYNC_RESP - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE - USHORT TLVLength; // 0x0004 - USHORT QMIResult; - USHORT QMIError; -} __attribute__ ((packed)) QMICTL_SYNC_RESP_MSG, *PQMICTL_SYNC_RESP_MSG; - -typedef struct _QMICTL_SYNC_IND_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_INDICATION - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_REVOKE_CLIENT_ID_IND - USHORT Length; -} __attribute__ ((packed)) QMICTL_SYNC_IND_MSG, *PQMICTL_SYNC_IND_MSG; - -typedef struct _QMICTL_LIBQMI_PROXY_OPEN_MSG -{ - UCHAR CtlFlags; // QMICTL_FLAG_RESPONSE - UCHAR TransactionId; - USHORT QMICTLType; // QMICTL_SET_DATA_FORMAT_RESP - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE - USHORT TLVLength; // 0x0004 - char device_path[0]; // result code -} __attribute__ ((packed)) QMICTL_LIBQMI_PROXY_OPEN_MSG, *PQMICTL_LIBQMI_PROXY_OPEN_MSG; - -typedef struct _QMICTL_MSG -{ - union - { - // Message Header - QCQMICTL_MSG_HDR QMICTLMsgHdr; - QCQMICTL_MSG_HDR_RESP QMICTLMsgHdrRsp; - - // QMICTL Message - QMICTL_SET_INSTANCE_ID_REQ_MSG SetInstanceIdReq; - QMICTL_SET_INSTANCE_ID_RESP_MSG SetInstanceIdRsp; - QMICTL_GET_VERSION_REQ_MSG GetVersionReq; - QMICTL_GET_VERSION_RESP_MSG GetVersionRsp; - QMICTL_GET_CLIENT_ID_REQ_MSG GetClientIdReq; - QMICTL_GET_CLIENT_ID_RESP_MSG GetClientIdRsp; - QMICTL_RELEASE_CLIENT_ID_REQ_MSG ReleaseClientIdReq; - QMICTL_RELEASE_CLIENT_ID_RESP_MSG ReleaseClientIdRsp; - QMICTL_REVOKE_CLIENT_ID_IND_MSG RevokeClientIdInd; - QMICTL_INVALID_CLIENT_ID_IND_MSG InvalidClientIdInd; - QMICTL_SET_DATA_FORMAT_REQ_MSG SetDataFormatReq; - QMICTL_SET_DATA_FORMAT_RESP_MSG SetDataFormatRsp; - QMICTL_SYNC_REQ_MSG SyncReq; - QMICTL_SYNC_RESP_MSG SyncRsp; - QMICTL_SYNC_IND_MSG SyncInd; - QMICTL_LIBQMI_PROXY_OPEN_MSG LibQmiProxyOpenReq; - }; -} __attribute__ ((packed)) QMICTL_MSG, *PQMICTL_MSG; -#pragma pack(pop) - +/****************************************************************************** + @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 \ No newline at end of file diff --git a/wwan/app/quectel_cm_5G/src/QCQMI.h b/wwan/app/quectel-cm/src/QCQMI.h similarity index 96% rename from wwan/app/quectel_cm_5G/src/QCQMI.h rename to wwan/app/quectel-cm/src/QCQMI.h index 2b2a260..e9cab6b 100644 --- a/wwan/app/quectel_cm_5G/src/QCQMI.h +++ b/wwan/app/quectel-cm/src/QCQMI.h @@ -1,320 +1,320 @@ -/****************************************************************************** - @file QCQMI.h - - DESCRIPTION - This module contains QMI module. - - INITIALIZATION AND SEQUENCING REQUIREMENTS - None. - - --------------------------------------------------------------------------- - Copyright (c) 2016 - 2023 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. - Quectel Wireless Solution Proprietary and Confidential. - --------------------------------------------------------------------------- -******************************************************************************/ - - -#ifndef USBQMI_H -#define USBQMI_H - -typedef uint8_t uint8; -typedef int8_t int8; -typedef uint16_t uint16; -typedef int16_t int16; -typedef uint32_t uint32; -typedef uint64_t uint64; - -typedef signed char CHAR; -typedef unsigned char UCHAR; -typedef short SHORT; -typedef unsigned short USHORT; -typedef int INT; -typedef unsigned int UINT; -typedef long LONG; -typedef unsigned int ULONG; -typedef unsigned long long ULONG64; -typedef signed char *PCHAR; -typedef unsigned char *PUCHAR; -typedef int *PINT; -typedef int BOOL; - -#define TRUE (1 == 1) -#define FALSE (1 != 1) - -#define QMICTL_SUPPORTED_MAJOR_VERSION 1 -#define QMICTL_SUPPORTED_MINOR_VERSION 0 - -#pragma pack(push, 1) - -// ========= USB Control Message ========== - -#define USB_CTL_MSG_TYPE_QMI 0x01 - -// USB Control Message -typedef struct _QCUSB_CTL_MSG_HDR -{ - UCHAR IFType; -} __attribute__ ((packed)) QCUSB_CTL_MSG_HDR, *PQCUSB_CTL_MSG_HDR; - -#define QCUSB_CTL_MSG_HDR_SIZE sizeof(QCUSB_CTL_MSG_HDR) - -typedef struct _QCUSB_CTL_MSG -{ - UCHAR IFType; - UCHAR Message; -} __attribute__ ((packed)) QCUSB_CTL_MSG, *PQCUSB_CTL_MSG; - -#define QCTLV_TYPE_REQUIRED_PARAMETER 0x01 -#define QCTLV_TYPE_RESULT_CODE 0x02 - -// ================= QMI ================== - -// Define QMI Type -typedef enum _QMI_SERVICE_TYPE -{ - QMUX_TYPE_CTL = 0x00, - QMUX_TYPE_WDS = 0x01, - QMUX_TYPE_DMS = 0x02, - QMUX_TYPE_NAS = 0x03, - QMUX_TYPE_QOS = 0x04, - QMUX_TYPE_WMS = 0x05, - QMUX_TYPE_PDS = 0x06, - QMUX_TYPE_UIM = 0x0B, - QMUX_TYPE_WDS_IPV6 = 0x11, - QMUX_TYPE_WDS_ADMIN = 0x1A, - QMUX_TYPE_COEX = 0x22, - QMUX_TYPE_MAX = 0xFF, - QMUX_TYPE_ALL = 0xFF -} QMI_SERVICE_TYPE; - -typedef enum _QMI_RESULT_CODE_TYPE -{ - QMI_RESULT_SUCCESS = 0x0000, - QMI_RESULT_FAILURE = 0x0001 -} QMI_RESULT_CODE_TYPE; - -typedef enum _QMI_ERROR_CODE_TYPE -{ - QMI_ERR_NONE = 0x0000 - ,QMI_ERR_MALFORMED_MSG = 0x0001 - ,QMI_ERR_NO_MEMORY = 0x0002 - ,QMI_ERR_INTERNAL = 0x0003 - ,QMI_ERR_ABORTED = 0x0004 - ,QMI_ERR_CLIENT_IDS_EXHAUSTED = 0x0005 - ,QMI_ERR_UNABORTABLE_TRANSACTION = 0x0006 - ,QMI_ERR_INVALID_CLIENT_ID = 0x0007 - ,QMI_ERR_NO_THRESHOLDS = 0x0008 - ,QMI_ERR_INVALID_HANDLE = 0x0009 - ,QMI_ERR_INVALID_PROFILE = 0x000A - ,QMI_ERR_INVALID_PINID = 0x000B - ,QMI_ERR_INCORRECT_PIN = 0x000C - ,QMI_ERR_NO_NETWORK_FOUND = 0x000D - ,QMI_ERR_CALL_FAILED = 0x000E - ,QMI_ERR_OUT_OF_CALL = 0x000F - ,QMI_ERR_NOT_PROVISIONED = 0x0010 - ,QMI_ERR_MISSING_ARG = 0x0011 - ,QMI_ERR_ARG_TOO_LONG = 0x0013 - ,QMI_ERR_INVALID_TX_ID = 0x0016 - ,QMI_ERR_DEVICE_IN_USE = 0x0017 - ,QMI_ERR_OP_NETWORK_UNSUPPORTED = 0x0018 - ,QMI_ERR_OP_DEVICE_UNSUPPORTED = 0x0019 - ,QMI_ERR_NO_EFFECT = 0x001A - ,QMI_ERR_NO_FREE_PROFILE = 0x001B - ,QMI_ERR_INVALID_PDP_TYPE = 0x001C - ,QMI_ERR_INVALID_TECH_PREF = 0x001D - ,QMI_ERR_INVALID_PROFILE_TYPE = 0x001E - ,QMI_ERR_INVALID_SERVICE_TYPE = 0x001F - ,QMI_ERR_INVALID_REGISTER_ACTION = 0x0020 - ,QMI_ERR_INVALID_PS_ATTACH_ACTION = 0x0021 - ,QMI_ERR_AUTHENTICATION_FAILED = 0x0022 - ,QMI_ERR_PIN_BLOCKED = 0x0023 - ,QMI_ERR_PIN_PERM_BLOCKED = 0x0024 - ,QMI_ERR_SIM_NOT_INITIALIZED = 0x0025 - ,QMI_ERR_MAX_QOS_REQUESTS_IN_USE = 0x0026 - ,QMI_ERR_INCORRECT_FLOW_FILTER = 0x0027 - ,QMI_ERR_NETWORK_QOS_UNAWARE = 0x0028 - ,QMI_ERR_INVALID_QOS_ID = 0x0029 - ,QMI_ERR_INVALID_ID = 0x0029 - ,QMI_ERR_REQUESTED_NUM_UNSUPPORTED = 0x002A - ,QMI_ERR_INTERFACE_NOT_FOUND = 0x002B - ,QMI_ERR_FLOW_SUSPENDED = 0x002C - ,QMI_ERR_INVALID_DATA_FORMAT = 0x002D - ,QMI_ERR_GENERAL = 0x002E - ,QMI_ERR_UNKNOWN = 0x002F - ,QMI_ERR_INVALID_ARG = 0x0030 - ,QMI_ERR_INVALID_INDEX = 0x0031 - ,QMI_ERR_NO_ENTRY = 0x0032 - ,QMI_ERR_DEVICE_STORAGE_FULL = 0x0033 - ,QMI_ERR_DEVICE_NOT_READY = 0x0034 - ,QMI_ERR_NETWORK_NOT_READY = 0x0035 - ,QMI_ERR_CAUSE_CODE = 0x0036 - ,QMI_ERR_MESSAGE_NOT_SENT = 0x0037 - ,QMI_ERR_MESSAGE_DELIVERY_FAILURE = 0x0038 - ,QMI_ERR_INVALID_MESSAGE_ID = 0x0039 - ,QMI_ERR_ENCODING = 0x003A - ,QMI_ERR_AUTHENTICATION_LOCK = 0x003B - ,QMI_ERR_INVALID_TRANSITION = 0x003C - ,QMI_ERR_NOT_A_MCAST_IFACE = 0x003D - ,QMI_ERR_MAX_MCAST_REQUESTS_IN_USE = 0x003E - ,QMI_ERR_INVALID_MCAST_HANDLE = 0x003F - ,QMI_ERR_INVALID_IP_FAMILY_PREF = 0x0040 - ,QMI_ERR_SESSION_INACTIVE = 0x0041 - ,QMI_ERR_SESSION_INVALID = 0x0042 - ,QMI_ERR_SESSION_OWNERSHIP = 0x0043 - ,QMI_ERR_INSUFFICIENT_RESOURCES = 0x0044 - ,QMI_ERR_DISABLED = 0x0045 - ,QMI_ERR_INVALID_OPERATION = 0x0046 - ,QMI_ERR_INVALID_QMI_CMD = 0x0047 - ,QMI_ERR_TPDU_TYPE = 0x0048 - ,QMI_ERR_SMSC_ADDR = 0x0049 - ,QMI_ERR_INFO_UNAVAILABLE = 0x004A - ,QMI_ERR_SEGMENT_TOO_LONG = 0x004B - ,QMI_ERR_SEGMENT_ORDER = 0x004C - ,QMI_ERR_BUNDLING_NOT_SUPPORTED = 0x004D - ,QMI_ERR_OP_PARTIAL_FAILURE = 0x004E - ,QMI_ERR_POLICY_MISMATCH = 0x004F - ,QMI_ERR_SIM_FILE_NOT_FOUND = 0x0050 - ,QMI_ERR_EXTENDED_INTERNAL = 0x0051 - ,QMI_ERR_ACCESS_DENIED = 0x0052 - ,QMI_ERR_HARDWARE_RESTRICTED = 0x0053 - ,QMI_ERR_ACK_NOT_SENT = 0x0054 - ,QMI_ERR_INJECT_TIMEOUT = 0x0055 - ,QMI_ERR_INCOMPATIBLE_STATE = 0x005A - ,QMI_ERR_FDN_RESTRICT = 0x005B - ,QMI_ERR_SUPS_FAILURE_CAUSE = 0x005C - ,QMI_ERR_NO_RADIO = 0x005D - ,QMI_ERR_NOT_SUPPORTED = 0x005E - ,QMI_ERR_NO_SUBSCRIPTION = 0x005F - ,QMI_ERR_CARD_CALL_CONTROL_FAILED = 0x0060 - ,QMI_ERR_NETWORK_ABORTED = 0x0061 - ,QMI_ERR_MSG_BLOCKED = 0x0062 - ,QMI_ERR_INVALID_SESSION_TYPE = 0x0064 - ,QMI_ERR_INVALID_PB_TYPE = 0x0065 - ,QMI_ERR_NO_SIM = 0x0066 - ,QMI_ERR_PB_NOT_READY = 0x0067 - ,QMI_ERR_PIN_RESTRICTION = 0x0068 - ,QMI_ERR_PIN2_RESTRICTION = 0x0069 - ,QMI_ERR_PUK_RESTRICTION = 0x006A - ,QMI_ERR_PUK2_RESTRICTION = 0x006B - ,QMI_ERR_PB_ACCESS_RESTRICTED = 0x006C - ,QMI_ERR_PB_DELETE_IN_PROG = 0x006D - ,QMI_ERR_PB_TEXT_TOO_LONG = 0x006E - ,QMI_ERR_PB_NUMBER_TOO_LONG = 0x006F - ,QMI_ERR_PB_HIDDEN_KEY_RESTRICTION = 0x0070 -} QMI_ERROR_CODE_TYPE; - -#define QCQMI_CTL_FLAG_SERVICE 0x80 -#define QCQMI_CTL_FLAG_CTL_POINT 0x00 - -typedef struct _QCQMI_HDR -{ - UCHAR IFType; - USHORT Length; - UCHAR CtlFlags; // reserved - UCHAR QMIType; - UCHAR ClientId; -} __attribute__ ((packed)) QCQMI_HDR, *PQCQMI_HDR; - -#define QCQMI_HDR_SIZE (sizeof(QCQMI_HDR)-1) - -typedef struct _QCQMI -{ - UCHAR IFType; - USHORT Length; - UCHAR CtlFlags; // reserved - UCHAR QMIType; - UCHAR ClientId; - UCHAR SDU; -} __attribute__ ((packed)) QCQMI, *PQCQMI; - -typedef struct _QMI_SERVICE_VERSION -{ - USHORT Major; - USHORT Minor; - USHORT AddendumMajor; - USHORT AddendumMinor; -} __attribute__ ((packed)) QMI_SERVICE_VERSION, *PQMI_SERVICE_VERSION; - -// ================= QMUX ================== - -#define QMUX_MSG_OVERHEAD_BYTES 4 // Type(USHORT) Length(USHORT) -- header - -#define QMUX_BROADCAST_CID 0xFF - -typedef struct _QCQMUX_HDR -{ - UCHAR CtlFlags; // 0: single QMUX Msg; 1: - USHORT TransactionId; -} __attribute__ ((packed)) QCQMUX_HDR, *PQCQMUX_HDR; - -typedef struct _QCQMUX -{ - UCHAR CtlFlags; // 0: single QMUX Msg; 1: - USHORT TransactionId; - UCHAR Message; // Type(2), Length(2), Value -} __attribute__ ((packed)) QCQMUX, *PQCQMUX; - -#define QCQMUX_HDR_SIZE sizeof(QCQMUX_HDR) - -typedef struct _QCQMUX_MSG_HDR -{ - USHORT Type; - USHORT Length; -} __attribute__ ((packed)) QCQMUX_MSG_HDR, *PQCQMUX_MSG_HDR; - -#define QCQMUX_MSG_HDR_SIZE sizeof(QCQMUX_MSG_HDR) - -typedef struct _QCQMUX_MSG_HDR_RESP -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG - // QMI_ERR_NO_MEMORY - // QMI_ERR_INTERNAL - // QMI_ERR_FAULT -} __attribute__ ((packed)) QCQMUX_MSG_HDR_RESP, *PQCQMUX_MSG_HDR_RESP; - -typedef struct _QCQMUX_TLV -{ - UCHAR Type; - USHORT Length; - UCHAR Value; -} __attribute__ ((packed)) QCQMUX_TLV, *PQCQMUX_TLV; - -typedef struct _QMI_TLV_HDR -{ - UCHAR TLVType; - USHORT TLVLength; -} __attribute__ ((packed)) QMI_TLV_HDR, *PQMI_TLV_HDR; - -typedef struct _QMI_TLV -{ - UCHAR TLVType; - USHORT TLVLength; - union { - int8_t s8; - uint8_t u8; - int16_t s16; - uint16_t u16; - int32_t s32; - uint32_t u32; - uint64_t u64; - }; -} __attribute__ ((packed)) QMI_TLV, *PQMI_TLV; - -// QMUX Message Definitions -- QMI SDU -#define QMUX_CTL_FLAG_SINGLE_MSG 0x00 -#define QMUX_CTL_FLAG_COMPOUND_MSG 0x01 -#define QMUX_CTL_FLAG_TYPE_CMD 0x00 -#define QMUX_CTL_FLAG_TYPE_RSP 0x02 -#define QMUX_CTL_FLAG_TYPE_IND 0x04 -#define QMUX_CTL_FLAG_MASK_COMPOUND 0x01 -#define QMUX_CTL_FLAG_MASK_TYPE 0x06 // 00-cmd, 01-rsp, 10-ind - -#pragma pack(pop) - -#endif // USBQMI_H +/****************************************************************************** + @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 diff --git a/wwan/app/quectel_cm_5G/src/QCQMUX.c b/wwan/app/quectel-cm/src/QCQMUX.c similarity index 100% rename from wwan/app/quectel_cm_5G/src/QCQMUX.c rename to wwan/app/quectel-cm/src/QCQMUX.c diff --git a/wwan/app/quectel_cm_5G/src/QCQMUX.h b/wwan/app/quectel-cm/src/QCQMUX.h similarity index 97% rename from wwan/app/quectel_cm_5G/src/QCQMUX.h rename to wwan/app/quectel-cm/src/QCQMUX.h index b1feb1d..eb42dd8 100644 --- a/wwan/app/quectel_cm_5G/src/QCQMUX.h +++ b/wwan/app/quectel-cm/src/QCQMUX.h @@ -1,4310 +1,4310 @@ -/****************************************************************************** - @file QCQMUX.h - - DESCRIPTION - This module contains QMI QMUX 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 QCQMUX_H -#define QCQMUX_H - -#include "QCQMI.h" - -#pragma pack(push, 1) - -#define QMIWDS_SET_EVENT_REPORT_REQ 0x0001 -#define QMIWDS_SET_EVENT_REPORT_RESP 0x0001 -#define QMIWDS_EVENT_REPORT_IND 0x0001 -#define QMIWDS_START_NETWORK_INTERFACE_REQ 0x0020 -#define QMIWDS_START_NETWORK_INTERFACE_RESP 0x0020 -#define QMIWDS_STOP_NETWORK_INTERFACE_REQ 0x0021 -#define QMIWDS_STOP_NETWORK_INTERFACE_RESP 0x0021 -#define QMIWDS_GET_PKT_SRVC_STATUS_REQ 0x0022 -#define QMIWDS_GET_PKT_SRVC_STATUS_RESP 0x0022 -#define QMIWDS_GET_PKT_SRVC_STATUS_IND 0x0022 -#define QMIWDS_GET_CURRENT_CHANNEL_RATE_REQ 0x0023 -#define QMIWDS_GET_CURRENT_CHANNEL_RATE_RESP 0x0023 -#define QMIWDS_GET_PKT_STATISTICS_REQ 0x0024 -#define QMIWDS_GET_PKT_STATISTICS_RESP 0x0024 -#define QMIWDS_CREATE_PROFILE_REQ 0x0027 -#define QMIWDS_CREATE_PROFILE_RESP 0x0027 -#define QMIWDS_MODIFY_PROFILE_SETTINGS_REQ 0x0028 -#define QMIWDS_MODIFY_PROFILE_SETTINGS_RESP 0x0028 -#define QMIWDS_GET_PROFILE_LIST_REQ 0x002A -#define QMIWDS_GET_PROFILE_LIST_RESP 0x002A -#define QMIWDS_GET_PROFILE_SETTINGS_REQ 0x002B -#define QMIWDS_GET_PROFILE_SETTINGS_RESP 0x002B -#define QMIWDS_GET_DEFAULT_SETTINGS_REQ 0x002C -#define QMIWDS_GET_DEFAULT_SETTINGS_RESP 0x002C -#define QMIWDS_GET_RUNTIME_SETTINGS_REQ 0x002D -#define QMIWDS_GET_RUNTIME_SETTINGS_RESP 0x002D -#define QMIWDS_GET_MIP_MODE_REQ 0x002F -#define QMIWDS_GET_MIP_MODE_RESP 0x002F -#define QMIWDS_GET_DATA_BEARER_REQ 0x0037 -#define QMIWDS_GET_DATA_BEARER_RESP 0x0037 -#define QMIWDS_DUN_CALL_INFO_REQ 0x0038 -#define QMIWDS_DUN_CALL_INFO_RESP 0x0038 -#define QMIWDS_DUN_CALL_INFO_IND 0x0038 -#define QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ 0x004D -#define QMIWDS_SET_CLIENT_IP_FAMILY_PREF_RESP 0x004D -#define QMIWDS_SET_AUTO_CONNECT_REQ 0x0051 -#define QMIWDS_SET_AUTO_CONNECT_RESP 0x0051 -#define QMIWDS_BIND_MUX_DATA_PORT_REQ 0x00A2 -#define QMIWDS_BIND_MUX_DATA_PORT_RESP 0x00A2 - - -// Stats masks -#define QWDS_STAT_MASK_TX_PKT_OK 0x00000001 -#define QWDS_STAT_MASK_RX_PKT_OK 0x00000002 -#define QWDS_STAT_MASK_TX_PKT_ER 0x00000004 -#define QWDS_STAT_MASK_RX_PKT_ER 0x00000008 -#define QWDS_STAT_MASK_TX_PKT_OF 0x00000010 -#define QWDS_STAT_MASK_RX_PKT_OF 0x00000020 - -// TLV Types for xfer statistics -#define TLV_WDS_TX_GOOD_PKTS 0x10 -#define TLV_WDS_RX_GOOD_PKTS 0x11 -#define TLV_WDS_TX_ERROR 0x12 -#define TLV_WDS_RX_ERROR 0x13 -#define TLV_WDS_TX_OVERFLOW 0x14 -#define TLV_WDS_RX_OVERFLOW 0x15 -#define TLV_WDS_CHANNEL_RATE 0x16 -#define TLV_WDS_DATA_BEARER 0x17 -#define TLV_WDS_DORMANCY_STATUS 0x18 - -#define QWDS_PKT_DATA_UNKNOW 0x00 -#define QWDS_PKT_DATA_DISCONNECTED 0x01 -#define QWDS_PKT_DATA_CONNECTED 0x02 -#define QWDS_PKT_DATA_SUSPENDED 0x03 -#define QWDS_PKT_DATA_AUTHENTICATING 0x04 - -#define QMIWDS_ADMIN_SET_DATA_FORMAT_REQ 0x0020 -#define QMIWDS_ADMIN_SET_DATA_FORMAT_RESP 0x0020 -#define QMIWDS_ADMIN_GET_DATA_FORMAT_REQ 0x0021 -#define QMIWDS_ADMIN_GET_DATA_FORMAT_RESP 0x0021 -#define QMIWDS_ADMIN_SET_QMAP_SETTINGS_REQ 0x002B -#define QMIWDS_ADMIN_SET_QMAP_SETTINGS_RESP 0x002B -#define QMIWDS_ADMIN_GET_QMAP_SETTINGS_REQ 0x002C -#define QMIWDS_ADMIN_GET_QMAP_SETTINGS_RESP 0x002C -#define QMI_WDA_SET_LOOPBACK_CONFIG_REQ 0x002F -#define QMI_WDA_SET_LOOPBACK_CONFIG_RESP 0x002F -#define QMI_WDA_SET_LOOPBACK_CONFIG_IND 0x002F - -#define NETWORK_DESC_ENCODING_OCTET 0x00 -#define NETWORK_DESC_ENCODING_EXTPROTOCOL 0x01 -#define NETWORK_DESC_ENCODING_7BITASCII 0x02 -#define NETWORK_DESC_ENCODING_IA5 0x03 -#define NETWORK_DESC_ENCODING_UNICODE 0x04 -#define NETWORK_DESC_ENCODING_SHIFTJIS 0x05 -#define NETWORK_DESC_ENCODING_KOREAN 0x06 -#define NETWORK_DESC_ENCODING_LATINH 0x07 -#define NETWORK_DESC_ENCODING_LATIN 0x08 -#define NETWORK_DESC_ENCODING_GSM7BIT 0x09 -#define NETWORK_DESC_ENCODING_GSMDATA 0x0A -#define NETWORK_DESC_ENCODING_UNKNOWN 0xFF - -typedef struct _QMIWDS_ADMIN_SET_DATA_FORMAT -{ - USHORT Type; // QMUX type 0x0000 - USHORT Length; -} __attribute__ ((packed)) QMIWDS_ADMIN_SET_DATA_FORMAT, *PQMIWDS_ADMIN_SET_DATA_FORMAT; - -typedef struct _QMIWDS_ADMIN_SET_DATA_FORMAT_TLV_QOS -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR QOSSetting; -} __attribute__ ((packed)) QMIWDS_ADMIN_SET_DATA_FORMAT_TLV_QOS, *PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV_QOS; - -typedef struct _QMIWDS_ADMIN_SET_DATA_FORMAT_TLV -{ - UCHAR TLVType; - USHORT TLVLength; - ULONG Value; -} __attribute__ ((packed)) QMIWDS_ADMIN_SET_DATA_FORMAT_TLV, *PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV; - -typedef struct _QMIWDS_ENDPOINT_TLV -{ - UCHAR TLVType; - USHORT TLVLength; - ULONG ep_type; - ULONG iface_id; -} __attribute__ ((packed)) QMIWDS_ENDPOINT_TLV, *PQMIWDS_ENDPOINT_TLV; - -typedef struct _QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG -{ - USHORT Type; - USHORT Length; - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV_QOS QosDataFormatTlv; - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV UnderlyingLinkLayerProtocolTlv; - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV UplinkDataAggregationProtocolTlv; - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV DownlinkDataAggregationProtocolTlv; - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV DownlinkDataAggregationMaxDatagramsTlv; - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV DownlinkDataAggregationMaxSizeTlv; - QMIWDS_ENDPOINT_TLV epTlv; -#ifdef QUECTEL_UL_DATA_AGG - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV DlMinimumPassingTlv; - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV UplinkDataAggregationMaxDatagramsTlv; - QMIWDS_ADMIN_SET_DATA_FORMAT_TLV UplinkDataAggregationMaxSizeTlv; -#endif -} __attribute__ ((packed)) QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG, *PQMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG; - -typedef struct _QMI_U8_TLV -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR TLVVaule; -} __attribute__ ((packed)) QMI_U8_TLV, *PQMI_U8_TLV; - -typedef struct _QMI_U32_TLV -{ - UCHAR TLVType; - USHORT TLVLength; - ULONG TLVVaule; -} __attribute__ ((packed)) QMI_U32_TLV, *PQMI_U32_TLV; - -typedef struct _QMI_WDA_SET_LOOPBACK_CONFIG_REQ_MSG { - USHORT Type; - USHORT Length; - QMI_U8_TLV loopback_state; //0x01 - QMI_U32_TLV replication_factor; //0x10 -} __attribute__ ((packed)) QMI_WDA_SET_LOOPBACK_CONFIG_REQ_MSG, *PQMI_WDA_SET_LOOPBACK_CONFIG_REQ_MSG; - -typedef struct _QMI_WDA_SET_LOOPBACK_CONFIG_IND_MSG -{ - USHORT Type; - USHORT Length; - QMI_U8_TLV loopback_state; //0x01 - QMI_U32_TLV replication_factor; //0x10 -} __attribute__ ((packed)) QMI_WDA_SET_LOOPBACK_CONFIG_IND_MSG, *PQMI_WDA_SET_LOOPBACK_CONFIG_IND_MSG; - -#if 0 -typedef enum _QMI_RETURN_CODES { - QMI_SUCCESS = 0, - QMI_SUCCESS_NOT_COMPLETE, - QMI_FAILURE -}QMI_RETURN_CODES; - -typedef struct _QMIWDS_GET_PKT_SRVC_STATUS_REQ_MSG -{ - USHORT Type; // 0x0022 - USHORT Length; // 0x0000 -} QMIWDS_GET_PKT_SRVC_STATUS_REQ_MSG, *PQMIWDS_GET_PKT_SRVC_STATUS_REQ_MSG; - -typedef struct _QMIWDS_GET_PKT_SRVC_STATUS_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR TLVType2; - USHORT TLVLength2; - UCHAR ConnectionStatus; // 0x01: QWDS_PKT_DATAC_DISCONNECTED - // 0x02: QWDS_PKT_DATA_CONNECTED - // 0x03: QWDS_PKT_DATA_SUSPENDED - // 0x04: QWDS_PKT_DATA_AUTHENTICATING -} QMIWDS_GET_PKT_SRVC_STATUS_RESP_MSG, *PQMIWDS_GET_PKT_SRVC_STATUS_RESP_MSG; - -typedef struct _QMIWDS_GET_PKT_SRVC_STATUS_IND_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR ConnectionStatus; // 0x01: QWDS_PKT_DATAC_DISCONNECTED - // 0x02: QWDS_PKT_DATA_CONNECTED - // 0x03: QWDS_PKT_DATA_SUSPENDED - UCHAR ReconfigRequired; // 0x00: No need to reconfigure - // 0x01: Reconfiguration required -} QMIWDS_GET_PKT_SRVC_STATUS_IND_MSG, *PQMIWDS_GET_PKT_SRVC_STATUS_IND_MSG; - -typedef struct _WDS_PKT_SRVC_IP_FAMILY_TLV -{ - UCHAR TLVType; // 0x12 - USHORT TLVLength; // 1 - UCHAR IpFamily; // IPV4-0x04, IPV6-0x06 -} WDS_PKT_SRVC_IP_FAMILY_TLV, *PWDS_PKT_SRVC_IP_FAMILY_TLV; - -typedef struct _QMIWDS_DUN_CALL_INFO_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - ULONG Mask; - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR ReportConnectionStatus; -} QMIWDS_DUN_CALL_INFO_REQ_MSG, *PQMIWDS_DUN_CALL_INFO_REQ_MSG; - -typedef struct _QMIWDS_DUN_CALL_INFO_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} QMIWDS_DUN_CALL_INFO_RESP_MSG, *PQMIWDS_DUN_CALL_INFO_RESP_MSG; - -typedef struct _QMIWDS_DUN_CALL_INFO_IND_MSG -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR ConnectionStatus; -} QMIWDS_DUN_CALL_INFO_IND_MSG, *PQMIWDS_DUN_CALL_INFO_IND_MSG; - -typedef struct _QMIWDS_GET_CURRENT_CHANNEL_RATE_REQ_MSG -{ - USHORT Type; // QMUX type 0x0040 - USHORT Length; -} QMIWDS_GET_CURRENT_CHANNEL_RATE_REQ_MSG, *PQMIWDS_GET_CURRENT_CHANNEL_RATE_REQ_MSG; - -typedef struct _QMIWDS_GET_CURRENT_CHANNEL_RATE_RESP_MSG -{ - USHORT Type; // QMUX type 0x0040 - USHORT Length; - UCHAR TLVType; // 0x02 - 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 - - UCHAR TLV2Type; // 0x01 - USHORT TLV2Length; // 16 - //ULONG CallHandle; // Context corresponding to reported channel - ULONG CurrentTxRate; // bps - ULONG CurrentRxRate; // bps - ULONG ServingSystemTxRate; // bps - ULONG ServingSystemRxRate; // bps - -} QMIWDS_GET_CURRENT_CHANNEL_RATE_RESP_MSG, *PQMIWDS_GET_CURRENT_CHANNEL_RATE_RESP; - -#define QWDS_EVENT_REPORT_MASK_RATES 0x01 -#define QWDS_EVENT_REPORT_MASK_STATS 0x02 - -#ifdef QCUSB_MUX_PROTOCOL -#error code not present -#endif // QCUSB_MUX_PROTOCOL - -typedef struct _QMIWDS_SET_EVENT_REPORT_REQ_MSG -{ - USHORT Type; // QMUX type 0x0042 - USHORT Length; - - UCHAR TLVType; // 0x10 -- current channel rate indicator - USHORT TLVLength; // 1 - UCHAR Mode; // 0-do not report; 1-report when rate changes - - UCHAR TLV2Type; // 0x11 - USHORT TLV2Length; // 5 - UCHAR StatsPeriod; // seconds between reports; 0-do not report - ULONG StatsMask; // - - UCHAR TLV3Type; // 0x12 -- current data bearer indicator - USHORT TLV3Length; // 1 - UCHAR Mode3; // 0-do not report; 1-report when changes - - UCHAR TLV4Type; // 0x13 -- dormancy status indicator - USHORT TLV4Length; // 1 - UCHAR DormancyStatus; // 0-do not report; 1-report when changes -} QMIWDS_SET_EVENT_REPORT_REQ_MSG, *PQMIWDS_SET_EVENT_REPORT_REQ_MSG; - -typedef struct _QMIWDS_SET_EVENT_REPORT_RESP_MSG -{ - USHORT Type; // QMUX type 0x0042 - 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_NO_BATTERY - // QMI_ERR_FAULT -} QMIWDS_SET_EVENT_REPORT_RESP_MSG, *PQMIWDS_SET_EVENT_REPORT_RESP_MSG; - -typedef struct _QMIWDS_EVENT_REPORT_IND_MSG -{ - USHORT Type; // QMUX type 0x0001 - USHORT Length; -} QMIWDS_EVENT_REPORT_IND_MSG, *PQMIWDS_EVENT_REPORT_IND_MSG; - -// PQCTLV_PKT_STATISTICS - -typedef struct _QMIWDS_EVENT_REPORT_IND_CHAN_RATE_TLV -{ - UCHAR Type; - USHORT Length; // 8 - ULONG TxRate; - ULONG RxRate; -} QMIWDS_EVENT_REPORT_IND_CHAN_RATE_TLV, *PQMIWDS_EVENT_REPORT_IND_CHAN_RATE_TLV; - -#ifdef QCUSB_MUX_PROTOCOL -#error code not present -#endif // QCUSB_MUX_PROTOCOL - -typedef struct _QMIWDS_GET_PKT_STATISTICS_REQ_MSG -{ - USHORT Type; // QMUX type 0x0041 - USHORT Length; - UCHAR TLVType; // 0x01 - USHORT TLVLength; // 4 - ULONG StateMask; // 0x00000001 tx success packets - // 0x00000002 rx success packets - // 0x00000004 rx packet errors (checksum) - // 0x00000008 rx packets dropped (memory) - -} QMIWDS_GET_PKT_STATISTICS_REQ_MSG, *PQMIWDS_GET_PKT_STATISTICS_REQ_MSG; - -typedef struct _QMIWDS_GET_PKT_STATISTICS_RESP_MSG -{ - USHORT Type; // QMUX type 0x0041 - USHORT Length; - UCHAR TLVType; // 0x02 - 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 -} QMIWDS_GET_PKT_STATISTICS_RESP_MSG, *PQMIWDS_GET_PKT_STATISTICS_RESP_MSG; - -// optional TLV for stats -typedef struct _QCTLV_PKT_STATISTICS -{ - UCHAR TLVType; // see above definitions for TLV types - USHORT TLVLength; // 4 - ULONG Count; -} QCTLV_PKT_STATISTICS, *PQCTLV_PKT_STATISTICS; -#endif - -//#ifdef QC_IP_MODE - -/* - �Bit 0 �Profile identifier - �Bit 1 �Profile name - �Bit 2 �PDP type - �Bit 3 �APN name - �Bit 4 �DNS address - �Bit 5 �UMTS/GPRS granted QoS - �Bit 6 �Username - �Bit 7 �Authentication Protocol - �Bit 8 �IP address - �Bit 9 �Gateway information (address and subnet mask) - �Bit 10 �PCSCF address using a PCO flag - �Bit 11 �PCSCF server address list - �Bit 12 �PCSCF domain name list - �Bit 13 �MTU - �Bit 14 �Domain name list - �Bit 15 �IP family - �Bit 16 �IM_CM flag - �Bit 17 �Technology name - �Bit 18 �Operator reserved PCO -*/ -#define QMIWDS_GET_RUNTIME_SETTINGS_MASK_IPV4DNS_ADDR (1 << 4) -#define QMIWDS_GET_RUNTIME_SETTINGS_MASK_IPV4_ADDR (1 << 8) -#define QMIWDS_GET_RUNTIME_SETTINGS_MASK_IPV4GATEWAY_ADDR (1 << 9) -#define QMIWDS_GET_RUNTIME_SETTINGS_MASK_MTU (1 << 13) -#define QMIWDS_GET_RUNTIME_SETTINGS_MASK_PCSCF_SV_ADDR (1 << 11) -#define QMIWDS_GET_RUNTIME_SETTINGS_MASK_PCSCF_DOM_NAME (1 << 14) - -typedef struct _QMIWDS_GET_RUNTIME_SETTINGS_REQ_MSG -{ - USHORT Type; // QMIWDS_GET_RUNTIME_SETTINGS_REQ - USHORT Length; - UCHAR TLVType; // 0x10 - USHORT TLVLength; // 0x0004 - ULONG Mask; // mask, bit 8: IP addr -- 0x0100 -} __attribute__ ((packed)) QMIWDS_GET_RUNTIME_SETTINGS_REQ_MSG, *PQMIWDS_GET_RUNTIME_SETTINGS_REQ_MSG; - -typedef struct _QMIWDS_BIND_MUX_DATA_PORT_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - ULONG ep_type; - ULONG iface_id; - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR MuxId; - UCHAR TLV3Type; - USHORT TLV3Length; - ULONG client_type; -} __attribute__ ((packed)) QMIWDS_BIND_MUX_DATA_PORT_REQ_MSG, *PQMIWDS_BIND_MUX_DATA_PORT_REQ_MSG; - -#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4PRIMARYDNS 0x15 -#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4SECONDARYDNS 0x16 -#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4 0x1E -#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4GATEWAY 0x20 -#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4SUBNET 0x21 - -#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6 0x25 -#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6GATEWAY 0x26 -#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6PRIMARYDNS 0x27 -#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6SECONDARYDNS 0x28 -#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_MTU 0x29 - -typedef struct _QMIWDS_GET_RUNTIME_SETTINGS_TLV_MTU -{ - UCHAR TLVType; // QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_MTU - USHORT TLVLength; // 4 - ULONG Mtu; // MTU -} __attribute__ ((packed)) QMIWDS_GET_RUNTIME_SETTINGS_TLV_MTU, *PQMIWDS_GET_RUNTIME_SETTINGS_TLV_MTU; - -typedef struct _QMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR -{ - UCHAR TLVType; // QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4 - USHORT TLVLength; // 4 - ULONG IPV4Address; // address -} __attribute__ ((packed)) QMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR, *PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR; - -typedef struct _QMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_ADDR -{ - UCHAR TLVType; // QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6 - USHORT TLVLength; // 16 - UCHAR IPV6Address[16]; // address - UCHAR PrefixLength; // prefix length -} __attribute__ ((packed)) QMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_ADDR, *PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_ADDR; - -typedef struct _QMIWDS_GET_RUNNING_SETTINGS_PCSCF_IPV6_ADDR -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR PCSCFNumber; -} __attribute__ ((packed)) QMIWDS_GET_RUNNING_SETTINGS_PCSCF_IPV6_ADDR, *PQMIWDS_GET_RUNNING_SETTINGS_PCSCF_IPV6_ADDR; - -typedef struct _QMIWDS_GET_RUNNING_SETTINGS_PCSCF_IPV4_ADDR -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR PCSCFNumber; -} __attribute__ ((packed)) QMIWDS_GET_RUNNING_SETTINGS_PCSCF_IPV4_ADDR, *PQMIWDS_GET_RUNNING_SETTINGS_PCSCF_IPV4_ADDR; - -typedef struct _QMIWDS_GET_RUNTIME_SETTINGS_RESP_MSG -{ - USHORT Type; // QMIWDS_GET_RUNTIME_SETTINGS_RESP - USHORT Length; - UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE - USHORT TLVLength; // 0x0004 - USHORT QMUXResult; // result code - USHORT QMUXError; // error code -} __attribute__ ((packed)) QMIWDS_GET_RUNTIME_SETTINGS_RESP_MSG, *PQMIWDS_GET_RUNTIME_SETTINGS_RESP_MSG; - -//#endif // QC_IP_MODE - -typedef struct _QMIWDS_IP_FAMILY_TLV -{ - UCHAR TLVType; // 0x12 - USHORT TLVLength; // 1 - UCHAR IpFamily; // IPV4-0x04, IPV6-0x06 -} __attribute__ ((packed)) QMIWDS_IP_FAMILY_TLV, *PQMIWDS_IP_FAMILY_TLV; - -typedef struct _QMIWDS_PKT_SRVC_TLV -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR ConnectionStatus; - UCHAR ReconfigReqd; -} __attribute__ ((packed)) QMIWDS_PKT_SRVC_TLV, *PQMIWDS_PKT_SRVC_TLV; - -typedef struct _QMIWDS_CALL_END_REASON_TLV -{ - UCHAR TLVType; - USHORT TLVLength; - USHORT CallEndReason; -} __attribute__ ((packed)) QMIWDS_CALL_END_REASON_TLV, *PQMIWDS_CALL_END_REASON_TLV; - -typedef struct _QMIWDS_CALL_END_REASON_V_TLV -{ - UCHAR TLVType; - USHORT TLVLength; - USHORT CallEndReasonType; - USHORT CallEndReason; -} __attribute__ ((packed)) QMIWDS_CALL_END_REASON_V_TLV, *PQMIWDS_CALL_END_REASON_V_TLV; - -typedef struct _QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ_MSG -{ - USHORT Type; // QMUX type 0x004D - USHORT Length; - UCHAR TLVType; // 0x01 - USHORT TLVLength; // 1 - UCHAR IpPreference; // IPV4-0x04, IPV6-0x06 -} __attribute__ ((packed)) QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ_MSG, *PQMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ_MSG; - -typedef struct _QMIWDS_SET_CLIENT_IP_FAMILY_PREF_RESP_MSG -{ - USHORT Type; // QMUX type 0x0037 - USHORT Length; - UCHAR TLVType; // 0x02 - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS, QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INTERNAL, QMI_ERR_MALFORMED_MSG, QMI_ERR_INVALID_ARG -} __attribute__ ((packed)) QMIWDS_SET_CLIENT_IP_FAMILY_PREF_RESP_MSG, *PQMIWDS_SET_CLIENT_IP_FAMILY_PREF_RESP_MSG; - -typedef struct _QMIWDS_SET_AUTO_CONNECT_REQ_MSG -{ - USHORT Type; // QMUX type 0x0051 - USHORT Length; - UCHAR TLVType; // 0x01 - USHORT TLVLength; // 1 - UCHAR autoconnect_setting; // 0x00 ?C Disabled, 0x01 ?C Enabled, 0x02 ?C Paused (resume on power cycle) -} __attribute__ ((packed)) QMIWDS_SET_AUTO_CONNECT_REQ_MSG, *PQMIWDS_SET_AUTO_CONNECT_REQ_MSG; - -#if 0 -typedef struct _QMIWDS_GET_MIP_MODE_REQ_MSG -{ - USHORT Type; // QMUX type 0x0040 - USHORT Length; -} QMIWDS_GET_MIP_MODE_REQ_MSG, *PQMIWDS_GET_MIP_MODE_REQ_MSG; - -typedef struct _QMIWDS_GET_MIP_MODE_RESP_MSG -{ - USHORT Type; // QMUX type 0x0040 - USHORT Length; - UCHAR TLVType; // 0x02 - 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 - - UCHAR TLV2Type; // 0x01 - USHORT TLV2Length; // 20 - UCHAR MipMode; // -} QMIWDS_GET_MIP_MODE_RESP_MSG, *PQMIWDS_GET_MIP_MODE_RESP_MSG; -#endif - -typedef struct _QMIWDS_TECHNOLOGY_PREFERECE -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR TechPreference; -} __attribute__ ((packed)) QMIWDS_TECHNOLOGY_PREFERECE, *PQMIWDS_TECHNOLOGY_PREFERECE; - -typedef struct _QMIWDS_PROFILE_IDENTIFIER -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR ProfileIndex; -} __attribute__ ((packed)) QMIWDS_PROFILE_IDENTIFIER, *PQMIWDS_PROFILE_IDENTIFIER; - -#if 0 -typedef struct _QMIWDS_IPADDRESS -{ - UCHAR TLVType; - USHORT TLVLength; - ULONG IPv4Address; -}QMIWDS_IPADDRESS, *PQMIWDS_IPADDRESS; - -/* -typedef struct _QMIWDS_UMTS_QOS -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR TrafficClass; - ULONG MaxUplinkBitRate; - ULONG MaxDownlinkBitRate; - ULONG GuarUplinkBitRate; - ULONG GuarDownlinkBitRate; - UCHAR QOSDevOrder; - ULONG MAXSDUSize; - UCHAR SDUErrorRatio; - UCHAR ResidualBerRatio; - UCHAR DeliveryErrorSDUs; - ULONG TransferDelay; - ULONG TrafficHndPri; -}QMIWDS_UMTS_QOS, *PQMIWDS_UMTS_QOS; - -typedef struct _QMIWDS_GPRS_QOS -{ - UCHAR TLVType; - USHORT TLVLength; - ULONG PrecedenceClass; - ULONG DelayClass; - ULONG ReliabilityClass; - ULONG PeekThroClass; - ULONG MeanThroClass; -}QMIWDS_GPRS_QOS, *PQMIWDS_GPRS_QOS; -*/ -#endif - -typedef struct _QMIWDS_PDPCONTEXT -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR pdp_context; -} __attribute__ ((packed)) QMIWDS_PDPCONTEXT, *PQMIWDS_PDPCONTEXT; - -typedef struct _QMIWDS_PROFILELIST -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR ProfileList[1024]; -} __attribute__ ((packed)) QMIWDS_PROFILELIST, *PQMIWDS_PROFILELIST; - -typedef struct _QMIWDS_PROFILENAME -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR ProfileName; -} __attribute__ ((packed)) QMIWDS_PROFILENAME, *PQMIWDS_PROFILENAME; - -typedef struct _QMIWDS_PDPTYPE -{ - UCHAR TLVType; - USHORT TLVLength; -// 0 ?C PDP-IP (IPv4) -// 1 ?C PDP-PPP -// 2 ?C PDP-IPv6 -// 3 ?C PDP-IPv4v6 - UCHAR PdpType; -} __attribute__ ((packed)) QMIWDS_PDPTYPE, *PQMIWDS_PDPTYPE; - -typedef struct _QMIWDS_USERNAME -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR UserName; -} __attribute__ ((packed)) QMIWDS_USERNAME, *PQMIWDS_USERNAME; - -typedef struct _QMIWDS_PASSWD -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR Passwd; -} __attribute__ ((packed)) QMIWDS_PASSWD, *PQMIWDS_PASSWD; - -typedef struct _QMIWDS_AUTH_PREFERENCE -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR AuthPreference; -} __attribute__ ((packed)) QMIWDS_AUTH_PREFERENCE, *PQMIWDS_AUTH_PREFERENCE; - -typedef struct _QMIWDS_IPTYPE -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR IPType; -} __attribute__ ((packed)) QMIWDS_IPTYPE, *PQMIWDS_IPTYPE; - -typedef struct _QMIWDS_APNNAME -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR ApnName; -} __attribute__ ((packed)) QMIWDS_APNNAME, *PQMIWDS_APNNAME; - -typedef struct _QMIWDS_AUTOCONNECT -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR AutoConnect; -} __attribute__ ((packed)) QMIWDS_AUTOCONNECT, *PQMIWDS_AUTOCONNECT; - -typedef struct _QMIWDS_START_NETWORK_INTERFACE_REQ_MSG -{ - USHORT Type; - USHORT Length; -} __attribute__ ((packed)) QMIWDS_START_NETWORK_INTERFACE_REQ_MSG, *PQMIWDS_START_NETWORK_INTERFACE_REQ_MSG; - -typedef struct _QMIWDS_CALLENDREASON -{ - UCHAR TLVType; - USHORT TLVLength; - USHORT Reason; -}__attribute__ ((packed)) QMIWDS_CALLENDREASON, *PQMIWDS_CALLENDREASON; - -typedef struct _QMIWDS_START_NETWORK_INTERFACE_RESP_MSG -{ - USHORT Type; // QMUX type 0x0040 - USHORT Length; - UCHAR TLVType; // 0x02 - 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 - - UCHAR TLV2Type; // 0x01 - USHORT TLV2Length; // 20 - ULONG Handle; // -} __attribute__ ((packed)) QMIWDS_START_NETWORK_INTERFACE_RESP_MSG, *PQMIWDS_START_NETWORK_INTERFACE_RESP_MSG; - -typedef struct _QMIWDS_STOP_NETWORK_INTERFACE_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - ULONG Handle; -} __attribute__ ((packed)) QMIWDS_STOP_NETWORK_INTERFACE_REQ_MSG, *PQMIWDS_STOP_NETWORK_INTERFACE_REQ_MSG; - -typedef struct _QMIWDS_STOP_NETWORK_INTERFACE_RESP_MSG -{ - USHORT Type; // QMUX type 0x0040 - USHORT Length; - UCHAR TLVType; // 0x02 - 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)) QMIWDS_STOP_NETWORK_INTERFACE_RESP_MSG, *PQMIWDS_STOP_NETWORK_INTERFACE_RESP_MSG; - -typedef struct _QMIWDS_GET_DEFAULT_SETTINGS_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR ProfileType; -} __attribute__ ((packed)) QMIWDS_GET_DEFAULT_SETTINGS_REQ_MSG, *PQMIWDS_GET_DEFAULT_SETTINGS_REQ_MSG; - -typedef struct _QMIWDS_GET_DEFAULT_SETTINGS_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} __attribute__ ((packed)) QMIWDS_GET_DEFAULT_SETTINGS_RESP_MSG, *PQMIWDS_GET_DEFAULT_SETTINGS_RESP_MSG; - -typedef struct _QMIWDS_MODIFY_PROFILE_SETTINGS_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR ProfileType; - UCHAR ProfileIndex; -} __attribute__ ((packed)) QMIWDS_MODIFY_PROFILE_SETTINGS_REQ_MSG, *PQMIWDS_MODIFY_PROFILE_SETTINGS_REQ_MSG; - -typedef struct _QMIWDS_MODIFY_PROFILE_SETTINGS_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} __attribute__ ((packed)) QMIWDS_MODIFY_PROFILE_SETTINGS_RESP_MSG, *PQMIWDS_MODIFY_PROFILE_SETTINGS_RESP_MSG; - -typedef struct _QMIWDS_GET_PROFILE_SETTINGS_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR ProfileType; - UCHAR ProfileIndex; -} __attribute__ ((packed)) QMIWDS_GET_PROFILE_SETTINGS_REQ_MSG, *PQMIWDS_GET_PROFILE_SETTINGS_REQ_MSG; - -typedef struct _QMIWDS_CREATE_PROFILE_SETTINGS_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR ProfileType; - UCHAR TLV2Type; //0x25 - USHORT TLV2Length; - UCHAR pdp_context; -} __attribute__ ((packed)) QMIWDS_CREATE_PROFILE_SETTINGS_REQ_MSG, *PQMIWDS_CREATE_PROFILE_SETTINGS_REQ_MSG; - -typedef struct _QMIWDS_GET_PROFILE_LIST_REQ_MSG -{ - USHORT Type; - USHORT Length; -} __attribute__ ((packed)) QMIWDS_GET_PROFILE_LIST_REQ_MSG, *PQMIWDS_GET_PROFILE_LIST_REQ_MSG; - -typedef struct _QMIWDS_GET_PROFILE_LIST_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR ProfileList[1024]; -} __attribute__ ((packed)) QMIWDS_GET_PROFILE_LIST_RESP_MSG, *PQMIWDS_GET_PROFILE_LIST_RESP_MSG; - -#if 0 -typedef struct _QMIWDS_EVENT_REPORT_IND_DATA_BEARER_TLV -{ - UCHAR Type; - USHORT Length; - UCHAR DataBearer; -} QMIWDS_EVENT_REPORT_IND_DATA_BEARER_TLV, *PQMIWDS_EVENT_REPORT_IND_DATA_BEARER_TLV; - -typedef struct _QMIWDS_EVENT_REPORT_IND_DORMANCY_STATUS_TLV -{ - UCHAR Type; - USHORT Length; - UCHAR DormancyStatus; -} QMIWDS_EVENT_REPORT_IND_DORMANCY_STATUS_TLV, *PQMIWDS_EVENT_REPORT_IND_DORMANCY_STATUS_TLV; - - -typedef struct _QMIWDS_GET_DATA_BEARER_REQ_MSG -{ - USHORT Type; // QMUX type 0x0037 - USHORT Length; -} QMIWDS_GET_DATA_BEARER_REQ_MSG, *PQMIWDS_GET_DATA_BEARER_REQ_MSG; - -typedef struct _QMIWDS_GET_DATA_BEARER_RESP_MSG -{ - USHORT Type; // QMUX type 0x0037 - USHORT Length; - UCHAR TLVType; // 0x02 - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INTERNAL - // QMI_ERR_MALFORMED_MSG - // QMI_ERR_NO_MEMORY - // QMI_ERR_OUT_OF_CALL - // QMI_ERR_INFO_UNAVAILABLE - UCHAR TLV2Type; // 0x01 - USHORT TLV2Length; // - UCHAR Technology; // -} QMIWDS_GET_DATA_BEARER_RESP_MSG, *PQMIWDS_GET_DATA_BEARER_RESP_MSG; -#endif - -// ======================= DMS ============================== -#define QMIDMS_SET_EVENT_REPORT_REQ 0x0001 -#define QMIDMS_SET_EVENT_REPORT_RESP 0x0001 -#define QMIDMS_EVENT_REPORT_IND 0x0001 -#define QMIDMS_GET_DEVICE_CAP_REQ 0x0020 -#define QMIDMS_GET_DEVICE_CAP_RESP 0x0020 -#define QMIDMS_GET_DEVICE_MFR_REQ 0x0021 -#define QMIDMS_GET_DEVICE_MFR_RESP 0x0021 -#define QMIDMS_GET_DEVICE_MODEL_ID_REQ 0x0022 -#define QMIDMS_GET_DEVICE_MODEL_ID_RESP 0x0022 -#define QMIDMS_GET_DEVICE_REV_ID_REQ 0x0023 -#define QMIDMS_GET_DEVICE_REV_ID_RESP 0x0023 -#define QMIDMS_GET_MSISDN_REQ 0x0024 -#define QMIDMS_GET_MSISDN_RESP 0x0024 -#define QMIDMS_GET_DEVICE_SERIAL_NUMBERS_REQ 0x0025 -#define QMIDMS_GET_DEVICE_SERIAL_NUMBERS_RESP 0x0025 -#define QMIDMS_UIM_SET_PIN_PROTECTION_REQ 0x0027 -#define QMIDMS_UIM_SET_PIN_PROTECTION_RESP 0x0027 -#define QMIDMS_UIM_VERIFY_PIN_REQ 0x0028 -#define QMIDMS_UIM_VERIFY_PIN_RESP 0x0028 -#define QMIDMS_UIM_UNBLOCK_PIN_REQ 0x0029 -#define QMIDMS_UIM_UNBLOCK_PIN_RESP 0x0029 -#define QMIDMS_UIM_CHANGE_PIN_REQ 0x002A -#define QMIDMS_UIM_CHANGE_PIN_RESP 0x002A -#define QMIDMS_UIM_GET_PIN_STATUS_REQ 0x002B -#define QMIDMS_UIM_GET_PIN_STATUS_RESP 0x002B -#define QMIDMS_GET_DEVICE_HARDWARE_REV_REQ 0x002C -#define QMIDMS_GET_DEVICE_HARDWARE_REV_RESP 0x002C -#define QMIDMS_GET_OPERATING_MODE_REQ 0x002D -#define QMIDMS_GET_OPERATING_MODE_RESP 0x002D -#define QMIDMS_SET_OPERATING_MODE_REQ 0x002E -#define QMIDMS_SET_OPERATING_MODE_RESP 0x002E -#define QMIDMS_GET_ACTIVATED_STATUS_REQ 0x0031 -#define QMIDMS_GET_ACTIVATED_STATUS_RESP 0x0031 -#define QMIDMS_ACTIVATE_AUTOMATIC_REQ 0x0032 -#define QMIDMS_ACTIVATE_AUTOMATIC_RESP 0x0032 -#define QMIDMS_ACTIVATE_MANUAL_REQ 0x0033 -#define QMIDMS_ACTIVATE_MANUAL_RESP 0x0033 -#define QMIDMS_UIM_GET_ICCID_REQ 0x003C -#define QMIDMS_UIM_GET_ICCID_RESP 0x003C -#define QMIDMS_UIM_GET_CK_STATUS_REQ 0x0040 -#define QMIDMS_UIM_GET_CK_STATUS_RESP 0x0040 -#define QMIDMS_UIM_SET_CK_PROTECTION_REQ 0x0041 -#define QMIDMS_UIM_SET_CK_PROTECTION_RESP 0x0041 -#define QMIDMS_UIM_UNBLOCK_CK_REQ 0x0042 -#define QMIDMS_UIM_UNBLOCK_CK_RESP 0x0042 -#define QMIDMS_UIM_GET_IMSI_REQ 0x0043 -#define QMIDMS_UIM_GET_IMSI_RESP 0x0043 -#define QMIDMS_UIM_GET_STATE_REQ 0x0044 -#define QMIDMS_UIM_GET_STATE_RESP 0x0044 -#define QMIDMS_GET_BAND_CAP_REQ 0x0045 -#define QMIDMS_GET_BAND_CAP_RESP 0x0045 - -#if 0 -typedef struct _QMIDMS_GET_DEVICE_MFR_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; -} QMIDMS_GET_DEVICE_MFR_REQ_MSG, *PQMIDMS_GET_DEVICE_MFR_REQ_MSG; - -typedef struct _QMIDMS_GET_DEVICE_MFR_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - 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 - UCHAR TLV2Type; // 0x01 - required parameter - USHORT TLV2Length; // length of the mfr string - UCHAR DeviceManufacturer; // first byte of string -} QMIDMS_GET_DEVICE_MFR_RESP_MSG, *PQMIDMS_GET_DEVICE_MFR_RESP_MSG; - -typedef struct _QMIDMS_GET_DEVICE_MODEL_ID_REQ_MSG -{ - USHORT Type; // QMUX type 0x0004 - USHORT Length; -} QMIDMS_GET_DEVICE_MODEL_ID_REQ_MSG, *PQMIDMS_GET_DEVICE_MODEL_ID_REQ_MSG; - -typedef struct _QMIDMS_GET_DEVICE_MODEL_ID_RESP_MSG -{ - USHORT Type; // QMUX type 0x0004 - 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 - UCHAR TLV2Type; // 0x01 - required parameter - USHORT TLV2Length; // length of the modem id string - UCHAR DeviceModelID; // device model id -} QMIDMS_GET_DEVICE_MODEL_ID_RESP_MSG, *PQMIDMS_GET_DEVICE_MODEL_ID_RESP_MSG; -#endif - -typedef struct _QMIDMS_GET_DEVICE_REV_ID_REQ_MSG -{ - USHORT Type; // QMUX type 0x0005 - USHORT Length; -} __attribute__ ((packed)) QMIDMS_GET_DEVICE_REV_ID_REQ_MSG, *PQMIDMS_GET_DEVICE_REV_ID_REQ_MSG; - -typedef struct _DEVICE_REV_ID -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR RevisionID; -} __attribute__ ((packed)) DEVICE_REV_ID, *PDEVICE_REV_ID; - -#if 0 -typedef struct _QMIDMS_GET_DEVICE_REV_ID_RESP_MSG -{ - USHORT Type; // QMUX type 0x0023 - 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 -} QMIDMS_GET_DEVICE_REV_ID_RESP_MSG, *PQMIDMS_GET_DEVICE_REV_ID_RESP_MSG; - -typedef struct _QMIDMS_GET_MSISDN_REQ_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; -} QMIDMS_GET_MSISDN_REQ_MSG, *PQMIDMS_GET_MSISDN_REQ_MSG; - -typedef struct _QCTLV_DEVICE_VOICE_NUMBERS -{ - UCHAR TLVType; // as defined above - USHORT TLVLength; // 4/7/7 - UCHAR VoideNumberString; // ESN, IMEI, or MEID - -} QCTLV_DEVICE_VOICE_NUMBERS, *PQCTLV_DEVICE_VOICE_NUMBERS; - - -typedef struct _QMIDMS_GET_MSISDN_RESP_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG -} QMIDMS_GET_MSISDN_RESP_MSG, *PQMIDMS_GET_MSISDN_RESP_MSG; -#endif - -typedef struct _QMIDMS_UIM_GET_IMSI_REQ_MSG -{ - USHORT Type; - USHORT Length; -} __attribute__ ((packed)) QMIDMS_UIM_GET_IMSI_REQ_MSG, *PQMIDMS_UIM_GET_IMSI_REQ_MSG; - -typedef struct _QMIDMS_UIM_GET_IMSI_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR IMSI; -} __attribute__ ((packed)) QMIDMS_UIM_GET_IMSI_RESP_MSG, *PQMIDMS_UIM_GET_IMSI_RESP_MSG; - -#if 0 -typedef struct _QMIDMS_GET_DEVICE_SERIAL_NUMBERS_REQ_MSG -{ - USHORT Type; // QMUX type 0x0007 - USHORT Length; -} QMIDMS_GET_DEVICE_SERIAL_NUMBERS_REQ_MSG, *PQMIDMS_GET_DEVICE_SERIAL_NUMBERS_REQ_MSG; - -#define QCTLV_TYPE_SER_NUM_ESN 0x10 -#define QCTLV_TYPE_SER_NUM_IMEI 0x11 -#define QCTLV_TYPE_SER_NUM_MEID 0x12 - -typedef struct _QCTLV_DEVICE_SERIAL_NUMBER -{ - UCHAR TLVType; // as defined above - USHORT TLVLength; // 4/7/7 - UCHAR SerialNumberString; // ESN, IMEI, or MEID - -} QCTLV_DEVICE_SERIAL_NUMBER, *PQCTLV_DEVICE_SERIAL_NUMBER; - -typedef struct _QMIDMS_GET_DEVICE_SERIAL_NUMBERS_RESP_MSG -{ - USHORT Type; // QMUX type 0x0007 - 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 - // followed by optional TLV -} QMIDMS_GET_DEVICE_SERIAL_NUMBERS_RESP_MSG, *PQMIDMS_GET_DEVICE_SERIAL_NUMBERS_RESP; - -typedef struct _QMIDMS_GET_DMS_BAND_CAP -{ - USHORT Type; - USHORT Length; -} QMIDMS_GET_BAND_CAP_REQ_MSG, *PQMIDMS_GET_BAND_CAP_REQ_MSG; - -typedef struct _QMIDMS_GET_BAND_CAP_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_NONE - // QMI_ERR_INTERNAL - // QMI_ERR_MALFORMED_MSG - // QMI_ERR_NO_MEMORY - - UCHAR TLV2Type; // 0x01 - USHORT TLV2Length; // 2 - ULONG64 BandCap; -} QMIDMS_GET_BAND_CAP_RESP_MSG, *PQMIDMS_GET_BAND_CAP_RESP; - -typedef struct _QMIDMS_GET_DEVICE_CAP_REQ_MSG -{ - USHORT Type; // QMUX type 0x0002 - USHORT Length; -} QMIDMS_GET_DEVICE_CAP_REQ_MSG, *PQMIDMS_GET_DEVICE_CAP_REQ_MSG; - -typedef struct _QMIDMS_GET_DEVICE_CAP_RESP_MSG -{ - USHORT Type; // QMUX type 0x0002 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMUX_RESULT_SUCCESS - // QMUX_RESULT_FAILURE - USHORT QMUXError; // QMUX_ERR_INVALID_ARG - // QMUX_ERR_NO_MEMORY - // QMUX_ERR_INTERNAL - // QMUX_ERR_FAULT - UCHAR TLV2Type; // 0x01 - USHORT TLV2Length; // 2 - - ULONG MaxTxChannelRate; - ULONG MaxRxChannelRate; - UCHAR VoiceCap; - UCHAR SimCap; - - UCHAR RadioIfListCnt; // #elements in radio interface list - UCHAR RadioIfList; // N 1-byte elements -} QMIDMS_GET_DEVICE_CAP_RESP_MSG, *PQMIDMS_GET_DEVICE_CAP_RESP_MSG; - -typedef struct _QMIDMS_GET_ACTIVATED_STATUS_REQ_MSG -{ - USHORT Type; // QMUX type 0x0002 - USHORT Length; -} QMIDMS_GET_ACTIVATED_STATUS_REQ_MSG, *PQMIDMS_GET_ACTIVATES_STATUD_REQ_MSG; - -typedef struct _QMIDMS_GET_ACTIVATED_STATUS_RESP_MSG -{ - USHORT Type; // QMUX type 0x0002 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMUX_RESULT_SUCCESS - // QMUX_RESULT_FAILURE - USHORT QMUXError; // QMUX_ERR_INVALID_ARG - // QMUX_ERR_NO_MEMORY - // QMUX_ERR_INTERNAL - // QMUX_ERR_FAULT - UCHAR TLV2Type; // 0x01 - USHORT TLV2Length; // 2 - - USHORT ActivatedStatus; -} QMIDMS_GET_ACTIVATED_STATUS_RESP_MSG, *PQMIDMS_GET_ACTIVATED_STATUS_RESP_MSG; - -typedef struct _QMIDMS_GET_OPERATING_MODE_REQ_MSG -{ - USHORT Type; // QMUX type 0x0002 - USHORT Length; -} QMIDMS_GET_OPERATING_MODE_REQ_MSG, *PQMIDMS_GET_OPERATING_MODE_REQ_MSG; - -typedef struct _OFFLINE_REASON -{ - UCHAR TLVType; - USHORT TLVLength; - USHORT OfflineReason; -} OFFLINE_REASON, *POFFLINE_REASON; - -typedef struct _HARDWARE_RESTRICTED_MODE -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR HardwareControlledMode; -} HARDWARE_RESTRICTED_MODE, *PHARDWARE_RESTRICTED_MODE; - -typedef struct _QMIDMS_GET_OPERATING_MODE_RESP_MSG -{ - USHORT Type; // QMUX type 0x0002 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMUX_RESULT_SUCCESS - // QMUX_RESULT_FAILURE - USHORT QMUXError; // QMUX_ERR_INVALID_ARG - // QMUX_ERR_NO_MEMORY - // QMUX_ERR_INTERNAL - // QMUX_ERR_FAULT - UCHAR TLV2Type; // 0x01 - USHORT TLV2Length; // 2 - - UCHAR OperatingMode; -} QMIDMS_GET_OPERATING_MODE_RESP_MSG, *PQMIDMS_GET_OPERATING_MODE_RESP_MSG; - -typedef struct _QMIDMS_UIM_GET_ICCID_REQ_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; -} QMIDMS_UIM_GET_ICCID_REQ_MSG, *PQMIDMS_UIM_GET_ICCID_REQ_MSG; - -typedef struct _QMIDMS_UIM_GET_ICCID_RESP_MSG -{ - USHORT Type; // QMUX type 0x0024 - 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 - UCHAR TLV2Type; // 0x01 - required parameter - USHORT TLV2Length; // var - UCHAR ICCID; // String of voice number -} QMIDMS_UIM_GET_ICCID_RESP_MSG, *PQMIDMS_UIM_GET_ICCID_RESP_MSG; -#endif - -typedef struct _QMIDMS_SET_OPERATING_MODE_REQ_MSG -{ - USHORT Type; // QMUX type 0x0002 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - UCHAR OperatingMode; -} __attribute__ ((packed)) QMIDMS_SET_OPERATING_MODE_REQ_MSG, *PQMIDMS_SET_OPERATING_MODE_REQ_MSG; - -typedef struct _QMIDMS_SET_OPERATING_MODE_RESP_MSG -{ - USHORT Type; // QMUX type 0x0002 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMUX_RESULT_SUCCESS - // QMUX_RESULT_FAILURE - USHORT QMUXError; // QMUX_ERR_INVALID_ARG - // QMUX_ERR_NO_MEMORY - // QMUX_ERR_INTERNAL - // QMUX_ERR_FAULT -} __attribute__ ((packed)) QMIDMS_SET_OPERATING_MODE_RESP_MSG, *PQMIDMS_SET_OPERATING_MODE_RESP_MSG; - -#if 0 -typedef struct _QMIDMS_ACTIVATE_AUTOMATIC_REQ_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // - UCHAR ActivateCodelen; - UCHAR ActivateCode; -} QMIDMS_ACTIVATE_AUTOMATIC_REQ_MSG, *PQMIDMS_ACTIVATE_AUTOMATIC_REQ_MSG; - -typedef struct _QMIDMS_ACTIVATE_AUTOMATIC_RESP_MSG -{ - USHORT Type; // QMUX type 0x0024 - 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 -} QMIDMS_ACTIVATE_AUTOMATIC_RESP_MSG, *PQMIDMS_ACTIVATE_AUTOMATIC_RESP_MSG; - - -typedef struct _SPC_MSG -{ - UCHAR SPC[6]; - USHORT SID; -} SPC_MSG, *PSPC_MSG; - -typedef struct _MDN_MSG -{ - UCHAR MDNLEN; - UCHAR MDN; -} MDN_MSG, *PMDN_MSG; - -typedef struct _MIN_MSG -{ - UCHAR MINLEN; - UCHAR MIN; -} MIN_MSG, *PMIN_MSG; - -typedef struct _PRL_MSG -{ - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // - USHORT PRLLEN; - UCHAR PRL; -} PRL_MSG, *PPRL_MSG; - -typedef struct _MN_HA_KEY_MSG -{ - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // - UCHAR MN_HA_KEY_LEN; - UCHAR MN_HA_KEY; -} MN_HA_KEY_MSG, *PMN_HA_KEY_MSG; - -typedef struct _MN_AAA_KEY_MSG -{ - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // - UCHAR MN_AAA_KEY_LEN; - UCHAR MN_AAA_KEY; -} MN_AAA_KEY_MSG, *PMN_AAA_KEY_MSG; - -typedef struct _QMIDMS_ACTIVATE_MANUAL_REQ_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // - UCHAR Value; -} QMIDMS_ACTIVATE_MANUAL_REQ_MSG, *PQMIDMS_ACTIVATE_MANUAL_REQ_MSG; - -typedef struct _QMIDMS_ACTIVATE_MANUAL_RESP_MSG -{ - USHORT Type; // QMUX type 0x0024 - 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 -} QMIDMS_ACTIVATE_MANUAL_RESP_MSG, *PQMIDMS_ACTIVATE_MANUAL_RESP_MSG; -#endif - -typedef struct _QMIDMS_UIM_GET_STATE_REQ_MSG -{ - USHORT Type; - USHORT Length; -} __attribute__ ((packed)) QMIDMS_UIM_GET_STATE_REQ_MSG, *PQMIDMS_UIM_GET_STATE_REQ_MSG; - -typedef struct _QMIDMS_UIM_GET_STATE_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR UIMState; -} __attribute__ ((packed)) QMIDMS_UIM_GET_STATE_RESP_MSG, *PQMIDMS_UIM_GET_STATE_RESP_MSG; - -typedef struct _QMIDMS_UIM_GET_PIN_STATUS_REQ_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; -} __attribute__ ((packed)) QMIDMS_UIM_GET_PIN_STATUS_REQ_MSG, *PQMIDMS_UIM_GET_PIN_STATUS_REQ_MSG; - -typedef struct _QMIDMS_UIM_PIN_STATUS -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR PINStatus; - UCHAR PINVerifyRetriesLeft; - UCHAR PINUnblockRetriesLeft; -} __attribute__ ((packed)) QMIDMS_UIM_PIN_STATUS, *PQMIDMS_UIM_PIN_STATUS; - -#define QMI_PIN_STATUS_NOT_INIT 0 -#define QMI_PIN_STATUS_NOT_VERIF 1 -#define QMI_PIN_STATUS_VERIFIED 2 -#define QMI_PIN_STATUS_DISABLED 3 -#define QMI_PIN_STATUS_BLOCKED 4 -#define QMI_PIN_STATUS_PERM_BLOCKED 5 -#define QMI_PIN_STATUS_UNBLOCKED 6 -#define QMI_PIN_STATUS_CHANGED 7 - - -typedef struct _QMIDMS_UIM_GET_PIN_STATUS_RESP_MSG -{ - USHORT Type; // QMUX type 0x0024 - 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 - UCHAR PinStatus; -} __attribute__ ((packed)) QMIDMS_UIM_GET_PIN_STATUS_RESP_MSG, *PQMIDMS_UIM_GET_PIN_STATUS_RESP_MSG; - -#if 0 -typedef struct _QMIDMS_UIM_GET_CK_STATUS_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR Facility; -} QMIDMS_UIM_GET_CK_STATUS_REQ_MSG, *PQMIDMS_UIM_GET_CK_STATUS_REQ_MSG; - - -typedef struct _QMIDMS_UIM_CK_STATUS -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR FacilityStatus; - UCHAR FacilityVerifyRetriesLeft; - UCHAR FacilityUnblockRetriesLeft; -} QMIDMS_UIM_CK_STATUS, *PQMIDMS_UIM_CK_STATUS; - -typedef struct _QMIDMS_UIM_CK_OPERATION_STATUS -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR OperationBlocking; -} QMIDMS_UIM_CK_OPERATION_STATUS, *PQMIDMS_UIM_CK_OPERATION_STATUS; - -typedef struct _QMIDMS_UIM_GET_CK_STATUS_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR CkStatus; -} QMIDMS_UIM_GET_CK_STATUS_RESP_MSG, *PQMIDMS_UIM_GET_CK_STATUS_RESP_MSG; -#endif - -typedef struct _QMIDMS_UIM_VERIFY_PIN_REQ_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - UCHAR PINID; - UCHAR PINLen; - UCHAR PINValue; -} __attribute__ ((packed)) QMIDMS_UIM_VERIFY_PIN_REQ_MSG, *PQMIDMS_UIM_VERIFY_PIN_REQ_MSG; - -typedef struct _QMIDMS_UIM_VERIFY_PIN_RESP_MSG -{ - USHORT Type; // QMUX type 0x0024 - 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 - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR PINVerifyRetriesLeft; - UCHAR PINUnblockRetriesLeft; -} __attribute__ ((packed)) QMIDMS_UIM_VERIFY_PIN_RESP_MSG, *PQMIDMS_UIM_VERIFY_PIN_RESP_MSG; - -#if 0 -typedef struct _QMIDMS_UIM_SET_PIN_PROTECTION_REQ_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - UCHAR PINID; - UCHAR ProtectionSetting; - UCHAR PINLen; - UCHAR PINValue; -} QMIDMS_UIM_SET_PIN_PROTECTION_REQ_MSG, *PQMIDMS_UIM_SET_PIN_PROTECTION_REQ_MSG; - -typedef struct _QMIDMS_UIM_SET_PIN_PROTECTION_RESP_MSG -{ - USHORT Type; // QMUX type 0x0024 - 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 - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR PINVerifyRetriesLeft; - UCHAR PINUnblockRetriesLeft; -} QMIDMS_UIM_SET_PIN_PROTECTION_RESP_MSG, *PQMIDMS_UIM_SET_PIN_PROTECTION_RESP_MSG; - -typedef struct _QMIDMS_UIM_SET_CK_PROTECTION_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR Facility; - UCHAR FacilityState; - UCHAR FacliltyLen; - UCHAR FacliltyValue; -} QMIDMS_UIM_SET_CK_PROTECTION_REQ_MSG, *PQMIDMS_UIM_SET_CK_PROTECTION_REQ_MSG; - -typedef struct _QMIDMS_UIM_SET_CK_PROTECTION_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR FacilityRetriesLeft; -} QMIDMS_UIM_SET_CK_PROTECTION_RESP_MSG, *PQMIDMS_UIM_SET_CK_PROTECTION_RESP_MSG; - - -typedef struct _UIM_PIN -{ - UCHAR PinLength; - UCHAR PinValue; -} UIM_PIN, *PUIM_PIN; - -typedef struct _QMIDMS_UIM_CHANGE_PIN_REQ_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - UCHAR PINID; - UCHAR PinDetails; -} QMIDMS_UIM_CHANGE_PIN_REQ_MSG, *PQMIDMS_UIM_CHANGE_PIN_REQ_MSG; - -typedef struct QMIDMS_UIM_CHANGE_PIN_RESP_MSG -{ - USHORT Type; // QMUX type 0x0024 - 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 - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR PINVerifyRetriesLeft; - UCHAR PINUnblockRetriesLeft; -} QMIDMS_UIM_CHANGE_PIN_RESP_MSG, *PQMIDMS_UIM_CHANGE_PIN_RESP_MSG; - -typedef struct _UIM_PUK -{ - UCHAR PukLength; - UCHAR PukValue; -} UIM_PUK, *PUIM_PUK; - -typedef struct _QMIDMS_UIM_UNBLOCK_PIN_REQ_MSG -{ - USHORT Type; // QMUX type 0x0024 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - UCHAR PINID; - UCHAR PinDetails; -} QMIDMS_UIM_UNBLOCK_PIN_REQ_MSG, *PQMIDMS_UIM_BLOCK_PIN_REQ_MSG; - -typedef struct QMIDMS_UIM_UNBLOCK_PIN_RESP_MSG -{ - USHORT Type; // QMUX type 0x0024 - 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 - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR PINVerifyRetriesLeft; - UCHAR PINUnblockRetriesLeft; -} QMIDMS_UIM_UNBLOCK_PIN_RESP_MSG, *PQMIDMS_UIM_UNBLOCK_PIN_RESP_MSG; - -typedef struct _QMIDMS_UIM_UNBLOCK_CK_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR Facility; - UCHAR FacliltyUnblockLen; - UCHAR FacliltyUnblockValue; -} QMIDMS_UIM_UNBLOCK_CK_REQ_MSG, *PQMIDMS_UIM_BLOCK_CK_REQ_MSG; - -typedef struct QMIDMS_UIM_UNBLOCK_CK_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR FacilityUnblockRetriesLeft; -} QMIDMS_UIM_UNBLOCK_CK_RESP_MSG, *PQMIDMS_UIM_UNBLOCK_CK_RESP_MSG; - -typedef struct _QMIDMS_SET_EVENT_REPORT_REQ_MSG -{ - USHORT Type; - USHORT Length; -} QMIDMS_SET_EVENT_REPORT_REQ_MSG, *PQMIDMS_SET_EVENT_REPORT_REQ_MSG; - -typedef struct _QMIDMS_SET_EVENT_REPORT_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMI_RESULT_SUCCESS - // QMI_RESULT_FAILURE - USHORT QMUXError; // QMI_ERR_INVALID_ARG -} QMIDMS_SET_EVENT_REPORT_RESP_MSG, *PQMIDMS_SET_EVENT_REPORT_RESP_MSG; - -typedef struct _PIN_STATUS -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR ReportPinState; -} PIN_STATUS, *PPIN_STATUS; - -typedef struct _POWER_STATUS -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR PowerStatus; - UCHAR BatteryLvl; -} POWER_STATUS, *PPOWER_STATUS; - -typedef struct _ACTIVATION_STATE -{ - UCHAR TLVType; - USHORT TLVLength; - USHORT ActivationState; -} ACTIVATION_STATE, *PACTIVATION_STATE; - -typedef struct _ACTIVATION_STATE_REQ -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR ActivationState; -} ACTIVATION_STATE_REQ, *PACTIVATION_STATE_REQ; - -typedef struct _OPERATING_MODE -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR OperatingMode; -} OPERATING_MODE, *POPERATING_MODE; - -typedef struct _UIM_STATE -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR UIMState; -} UIM_STATE, *PUIM_STATE; - -typedef struct _WIRELESS_DISABLE_STATE -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR WirelessDisableState; -} WIRELESS_DISABLE_STATE, *PWIRELESS_DISABLE_STATE; - -typedef struct _QMIDMS_EVENT_REPORT_IND_MSG -{ - USHORT Type; - USHORT Length; -} QMIDMS_EVENT_REPORT_IND_MSG, *PQMIDMS_EVENT_REPORT_IND_MSG; -#endif - -// ============================ END OF DMS =============================== - -// ======================= QOS ============================== -typedef struct _MPIOC_DEV_INFO MPIOC_DEV_INFO, *PMPIOC_DEV_INFO; - -#define QMI_QOS_SET_EVENT_REPORT_REQ 0x0001 -#define QMI_QOS_SET_EVENT_REPORT_RESP 0x0001 -#define QMI_QOS_SET_EVENT_REPORT_IND 0x0001 -#define QMI_QOS_BIND_DATA_PORT_REQ 0x002B -#define QMI_QOS_BIND_DATA_PORT_RESP 0x002B -#define QMI_QOS_INDICATION_REGISTER_REQ 0x002F -#define QMI_QOS_INDICATION_REGISTER_RESP 0x002F -#define QMI_QOS_GLOBAL_QOS_FLOW_IND 0x0031 -#define QMI_QOS_GET_QOS_INFO_REQ 0x0033 -#define QMI_QOS_GET_QOS_INFO_RESP 0x0033 - - -#if 1 -typedef struct _QMI_QOS_SET_EVENT_REPORT_REQ_MSG -{ - USHORT Type; // QMUX type 0x0001 - USHORT Length; - // UCHAR TLVType; // 0x01 - physical link state - // USHORT TLVLength; // 1 - // UCHAR PhyLinkStatusRpt; // 0-enable; 1-disable - UCHAR TLVType2; // 0x02 = global flow reporting - USHORT TLVLength2; // 1 - UCHAR GlobalFlowRpt; // 1-enable; 0-disable -} QMI_QOS_SET_EVENT_REPORT_REQ_MSG, *PQMI_QOS_SET_EVENT_REPORT_REQ_MSG; - -typedef struct _QMI_QOS_SET_EVENT_REPORT_RESP_MSG -{ - USHORT Type; // QMUX type 0x0010 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT QMUXResult; // QMUX_RESULT_SUCCESS - // QMUX_RESULT_FAILURE - USHORT QMUXError; // QMUX_ERR_INVALID_ARG - // QMUX_ERR_NO_MEMORY - // QMUX_ERR_INTERNAL - // QMUX_ERR_FAULT -} QMI_QOS_SET_EVENT_REPORT_RESP_MSG, *PQMI_QOS_SET_EVENT_REPORT_RESP_MSG; - -typedef struct _QMI_QOS_SET_EVENT_REPORT_IND_MSG -{ - USHORT Type; // QMUX type 0x0001 - USHORT Length; - UCHAR TLVs; -} QMI_QOS_SET_EVENT_REPORT_IND_MSG, *PQMI_QOS_SET_EVENT_REPORT_IND_MSG; - - -typedef struct _QMI_QOS_BIND_DATA_PORT_TLV_EP_ID -{ - UCHAR TLVType; //0x10 - USHORT TLVLength; - ULONG ep_type; - ULONG iface_id; -} __attribute__ ((packed)) QMI_QOS_BIND_DATA_PORT_TLV_EP_ID, *PQMI_QOS_BIND_DATA_PORT_TLV_EP_ID; - -typedef struct _QMI_QOS_BIND_DATA_PORT_TLV_MUX_ID -{ - UCHAR TLVType; //0x11 - USHORT TLVLength; - UCHAR mux_id; -} __attribute__ ((packed)) QMI_QOS_BIND_DATA_PORT_TLV_MUX_ID, *PQMI_QOS_BIND_DATA_PORT_TLV_MUX_ID; - -typedef struct _QMI_QOS_BIND_DATA_PORT_TLV_DATA_PORT -{ - UCHAR TLVType; //0x12 - USHORT TLVLength; - USHORT data_port; -} __attribute__ ((packed)) QMI_QOS_BIND_DATA_PORT_TLV_DATA_PORT, *PQMI_QOS_BIND_DATA_PORT_TLV_DATA_PORT; - -typedef struct _QMI_QOS_BIND_DATA_PORT_REQ_MSG -{ - USHORT Type; - USHORT Length; - QMI_QOS_BIND_DATA_PORT_TLV_EP_ID EpIdTlv; - QMI_QOS_BIND_DATA_PORT_TLV_MUX_ID MuxIdTlv; - //QMI_QOS_BIND_DATA_PORT_TLV_DATA_PORT DataPortTlv; -} __attribute__ ((packed)) QMI_QOS_BIND_DATA_PORT_REQ_MSG, *PQMI_QOS_BIND_DATA_PORT_REQ_MSG; - -typedef struct _QMI_QOS_BIND_DATA_PORT_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; //0x02 - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} __attribute__ ((packed)) QMI_QOS_BIND_DATA_PORT_RESP_MSG, *PQMI_QOS_BIND_DATA_PORT_RESP_MSG; - -typedef struct _QMI_QOS_INDICATION_REGISTER_TLV_REPORT_GLOBAL_QOS_FLOW -{ - UCHAR TLVType; //0x10 - USHORT TLVLength; - UCHAR report_global_qos_flows; -} __attribute__ ((packed)) QMI_QOS_INDICATION_REGISTER_TLV_REPORT_GLOBAL_QOS_FLOW, *PQMI_QOS_INDICATION_REGISTER_TLV_REPORT_GLOBAL_QOS_FLOW; - -typedef struct _QMI_QOS_INDICATION_REGISTER_TLV_SUPPRESS_REPORT_FLOW_CTL -{ - UCHAR TLVType; //0x11 - USHORT TLVLength; - UCHAR suppress_report_flow_control; -} __attribute__ ((packed)) QMI_QOS_INDICATION_REGISTER_TLV_SUPPRESS_REPORT_FLOW_CTL, *PQMI_QOS_INDICATION_REGISTER_TLV_SUPPRESS_REPORT_FLOW_CTL; - -typedef struct _QMI_QOS_INDICATION_REGISTER_TLV_SUPPRESS_NW_STATUS_IND -{ - UCHAR TLVType; //0x12 - USHORT TLVLength; - UCHAR suppress_network_status_ind; -} __attribute__ ((packed)) QMI_QOS_INDICATION_REGISTER_TLV_SUPPRESS_NW_STATUS_IND, *PQMI_QOS_INDICATION_REGISTER_TLV_SUPPRESS_NW_STATUS_IND; - -typedef struct _QMI_QOS_INDICATION_REGISTER_REQ_MSG -{ - USHORT Type; - USHORT Length; - QMI_QOS_INDICATION_REGISTER_TLV_REPORT_GLOBAL_QOS_FLOW ReportGlobalQosFlowTlv; - //QMI_QOS_INDICATION_REGISTER_TLV_SUPPRESS_REPORT_FLOW_CTL SuppressReportFlowCtlTlv; - //QMI_QOS_INDICATION_REGISTER_TLV_SUPPRESS_NW_STATUS_IND SuppressNWStatusIndTlv; -} __attribute__ ((packed)) QMI_QOS_INDICATION_REGISTER_REQ_MSG, *PQMI_QOS_INDICATION_REGISTER_REQ_MSG; - -typedef struct _QMI_QOS_INDICATION_REGISTER_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; //0x02 - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} __attribute__ ((packed)) QMI_QOS_INDICATION_REGISTER_RESP_MSG, *PQMI_QOS_INDICATION_REGISTER_RESP_MSG; - -typedef struct _QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_STATE -{ - UCHAR TLVType; //0x01 - USHORT TLVLength; - ULONG qos_id; - UCHAR new_flow; - ULONG state_change; -} __attribute__ ((packed)) QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_STATE, *PQMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_STATE; - -typedef struct _QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_GRANTED -{ - UCHAR TLVType; //0x10 0x11 - USHORT TLVLength; - ULONG64 flow_valid_params; - ULONG ip_flow_trf_cls; - ULONG64 data_rate_max; - ULONG64 guaranteed_rate; - ULONG peak_rate; - ULONG token_rate; - ULONG bucket_size; - ULONG ip_flow_latency; - ULONG ip_flow_jitter; - USHORT ip_flow_pkt_error_rate_multiplier; - USHORT ip_flow_pkt_error_rate_exponent; - ULONG ip_flow_min_policed_packet_size; - ULONG ip_flow_max_allowed_packet_size; - ULONG ip_flow_3gpp_residual_bit_error_rate; - ULONG ip_flow_3gpp_traffic_handling_priority; - USHORT ip_flow_3gpp2_profile_id; - UCHAR ip_flow_3gpp2_flow_priority; - UCHAR ip_flow_3gpp_im_cn_flag; - UCHAR ip_flow_3gpp_sig_ind; - ULONG ip_flow_lte_qci; -} __attribute__ ((packed)) QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_GRANTED, *PQMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_GRANTED; - -typedef struct _QMI_QOS_GLOBAL_QOS_FLOW_TLV_FILTER -{ - UCHAR TLVType; //0x12 0x13 - USHORT TLVLength; - UCHAR tx_rx_qos_filter_len; - UCHAR ip_version; - ULONG64 valid_params0; - ULONG ipv4_addr0; - ULONG subnet_mask0; - ULONG ipv4_addr1; - ULONG subnet_mask1; - UCHAR val4; - UCHAR mask4; - ULONG64 valid_params01; - UCHAR ipv6_address00; - UCHAR ipv6_address01; - UCHAR ipv6_address02; - UCHAR ipv6_address03; - UCHAR ipv6_address04; - UCHAR ipv6_address05; - UCHAR ipv6_address06; - UCHAR ipv6_address07; - UCHAR ipv6_address08; - UCHAR ipv6_address09; - UCHAR ipv6_address010; - UCHAR ipv6_address011; - UCHAR ipv6_address012; - UCHAR ipv6_address013; - UCHAR ipv6_address014; - ULONG ipv6_address015; - UCHAR prefix_len0; - UCHAR ipv6_address10; - UCHAR ipv6_address11; - UCHAR ipv6_address12; - UCHAR ipv6_address13; - UCHAR ipv6_address14; - UCHAR ipv6_address15; - UCHAR ipv6_address16; - UCHAR ipv6_address17; - UCHAR ipv6_address18; - UCHAR ipv6_address19; - UCHAR ipv6_address110; - UCHAR ipv6_address111; - UCHAR ipv6_address112; - UCHAR ipv6_address113; - UCHAR ipv6_address114; - ULONG ipv6_address115; - UCHAR prefix_len1; - UCHAR val6; - UCHAR mask6; - ULONG flow_label; - ULONG xport_protocol; - ULONG64 valid_params2; - USHORT port0; - USHORT range0; - USHORT port1; - USHORT range1; - ULONG64 valid_params3; - USHORT port2; - USHORT range2; - USHORT port3; - USHORT range3; - ULONG64 valid_params4; - UCHAR type; - UCHAR code; - ULONG64 valid_params5; - ULONG spi0; - ULONG64 valid_params6; - ULONG spi1; - USHORT filter_id; - USHORT filter_precedence; -} __attribute__ ((packed)) QMI_QOS_GLOBAL_QOS_FLOW_TLV_FILTER, *PQMI_QOS_GLOBAL_QOS_FLOW_TLV_FILTER; - -typedef struct _QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_TYPE -{ - UCHAR TLVType; //0x14 - USHORT TLVLength; - ULONG flow_type; -} __attribute__ ((packed)) QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_TYPE, *PQMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_TYPE; - -typedef struct _QMI_QOS_GLOBAL_QOS_FLOW_TLV_BEARER_ID -{ - UCHAR TLVType; //0x15 - USHORT TLVLength; - UCHAR bearer_id; -} __attribute__ ((packed)) QMI_QOS_GLOBAL_QOS_FLOW_TLV_BEARER_ID, *PQMI_QOS_GLOBAL_QOS_FLOW_TLV_BEARER_ID; - -typedef struct _QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_CTL_SEQ_NUM -{ - UCHAR TLVType; //0x16 - USHORT TLVLength; - USHORT fc_seq_num; -} __attribute__ ((packed)) QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_CTL_SEQ_NUM, *PQMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_CTL_SEQ_NUM; - -typedef struct _QMI_QOS_GLOBAL_QOS_FLOW_TLV_5G_QCI -{ - UCHAR TLVType; //0x17 0x18 - USHORT TLVLength; - ULONG tx_rx_5g_qci; -} __attribute__ ((packed)) QMI_QOS_GLOBAL_QOS_FLOW_TLV_5G_QCI, *PQMI_QOS_GLOBAL_QOS_FLOW_TLV_5G_QCI; - -typedef struct _QMI_QOS_GLOBAL_QOS_FLOW_TLV_AVG_WINDOW -{ - UCHAR TLVType; //0x19 0x1A - USHORT TLVLength; - USHORT tx_rx_avg_window; -} __attribute__ ((packed)) QMI_QOS_GLOBAL_QOS_FLOW_TLV_AVG_WINDOW, *PQMI_QOS_GLOBAL_QOS_FLOW_TLV_AVG_WINDOW; - -typedef struct _QMI_QOS_GLOBAL_QOS_FLOW_TLV_TX_FILTER_MATCH_ALL -{ - UCHAR TLVType; //0x1B - USHORT TLVLength; - UCHAR tx_filter_match_all_len; - USHORT filter_id; -} __attribute__ ((packed)) QMI_QOS_GLOBAL_QOS_FLOW_TLV_TX_FILTER_MATCH_ALL, *PQMI_QOS_GLOBAL_QOS_FLOW_TLV_TX_FILTER_MATCH_ALL; - -typedef struct _QMI_QOS_GLOBAL_QOS_FLOW_IND_MSG -{ - USHORT Type; - USHORT Length; - QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_STATE FlowStateTlv; - //QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_GRANTED TxFlowGrantedTlv; - //QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_GRANTED RxFlowGrantedTlv; - //QMI_QOS_GLOBAL_QOS_FLOW_TLV_FILTER TxFilterTlv; - //QMI_QOS_GLOBAL_QOS_FLOW_TLV_FILTER RxFilterTlv; - //QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_TYPE FlowTypeTlv; - //QMI_QOS_GLOBAL_QOS_FLOW_TLV_BEARER_ID BearerIdTlv; - //QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_CTL_SEQ_NUM FlowCtlSeqNumTlv; - //QMI_QOS_GLOBAL_QOS_FLOW_TLV_5G_QCI Tx5GQciTlv; - //QMI_QOS_GLOBAL_QOS_FLOW_TLV_5G_QCI Rx5GQciTlv; - //QMI_QOS_GLOBAL_QOS_FLOW_TLV_AVG_WINDOW AvgWindowTlv; - //QMI_QOS_GLOBAL_QOS_FLOW_TLV_TX_FILTER_MATCH_ALL TxFilterMatchAllTlv; -} __attribute__ ((packed)) QMI_QOS_GLOBAL_QOS_FLOW_IND_MSG, *PQMI_QOS_GLOBAL_QOS_FLOW_IND_MSG; - -typedef struct _QMI_QOS_GET_QOS_INFO_TLV_QOS_ID -{ - UCHAR TLVType; //0x01 - USHORT TLVLength; - ULONG qos_id; -} __attribute__ ((packed)) QMI_QOS_GET_QOS_INFO_TLV_QOS_ID, *PQMI_QOS_GET_QOS_INFO_TLV_QOS_ID; - -typedef struct _QMI_QOS_GET_QOS_INFO_TLV_FLOW_STATUS -{ - UCHAR TLVType; //0x10 - USHORT TLVLength; - UCHAR flow_status; -} __attribute__ ((packed)) QMI_QOS_GET_QOS_INFO_TLV_FLOW_STATUS, *PQMI_QOS_GET_QOS_INFO_TLV_FLOW_STATUS; - -typedef struct _QMI_QOS_GET_QOS_INFO_TLV_GRANTED_FLOW -{ - UCHAR TLVType; //0x11 0x12 - USHORT TLVLength; - ULONG64 flow_valid_params; - ULONG ip_flow_trf_cls; - ULONG64 data_rate_max; - ULONG64 guaranteed_rate; - ULONG peak_rate; - ULONG token_rate; - ULONG bucket_size; - ULONG ip_flow_latency; - ULONG ip_flow_jitter; - USHORT ip_flow_pkt_error_rate_multiplier; - USHORT ip_flow_pkt_error_rate_exponent; - ULONG ip_flow_min_policed_packet_size; - ULONG ip_flow_max_allowed_packet_size; - ULONG ip_flow_3gpp_residual_bit_error_rate; - ULONG ip_flow_3gpp_traffic_handling_priority; - USHORT ip_flow_3gpp2_profile_id; - UCHAR ip_flow_3gpp2_flow_priority; - UCHAR ip_flow_3gpp_im_cn_flag; - UCHAR ip_flow_3gpp_sig_ind; - ULONG ip_flow_lte_qci; -} __attribute__ ((packed)) QMI_QOS_GET_QOS_INFO_TLV_GRANTED_FLOW, *PQMI_QOS_GET_QOS_INFO_TLV_GRANTED_FLOW; - -typedef struct _QMI_QOS_GET_QOS_INFO_TLV_FILTER_SPECS -{ - UCHAR TLVType; //0x13 0x14 - USHORT TLVLength; - UCHAR tx_rx_qos_filter_len; - UCHAR ip_version; - ULONG64 valid_params0; - ULONG ipv4_addr0; - ULONG subnet_mask0; - ULONG ipv4_addr1; - ULONG subnet_mask1; - UCHAR val4; - UCHAR mask4; - ULONG64 valid_params01; - UCHAR ipv6_address00; - UCHAR ipv6_address01; - UCHAR ipv6_address02; - UCHAR ipv6_address03; - UCHAR ipv6_address04; - UCHAR ipv6_address05; - UCHAR ipv6_address06; - UCHAR ipv6_address07; - UCHAR ipv6_address08; - UCHAR ipv6_address09; - UCHAR ipv6_address010; - UCHAR ipv6_address011; - UCHAR ipv6_address012; - UCHAR ipv6_address013; - UCHAR ipv6_address014; - ULONG ipv6_address015; - UCHAR prefix_len0; - UCHAR ipv6_address10; - UCHAR ipv6_address11; - UCHAR ipv6_address12; - UCHAR ipv6_address13; - UCHAR ipv6_address14; - UCHAR ipv6_address15; - UCHAR ipv6_address16; - UCHAR ipv6_address17; - UCHAR ipv6_address18; - UCHAR ipv6_address19; - UCHAR ipv6_address110; - UCHAR ipv6_address111; - UCHAR ipv6_address112; - UCHAR ipv6_address113; - UCHAR ipv6_address114; - ULONG ipv6_address115; - UCHAR prefix_len1; - UCHAR val6; - UCHAR mask6; - ULONG flow_label; - ULONG xport_protocol; - ULONG64 valid_params2; - USHORT port0; - USHORT range0; - USHORT port1; - USHORT range1; - ULONG64 valid_params3; - USHORT port2; - USHORT range2; - USHORT port3; - USHORT range3; - ULONG64 valid_params4; - UCHAR type; - UCHAR code; - ULONG64 valid_params5; - ULONG spi0; - ULONG64 valid_params6; - ULONG spi1; - USHORT filter_id; - USHORT filter_precedence; -} __attribute__ ((packed)) QMI_QOS_GET_QOS_INFO_TLV_FILTER_SPECS, *PQMI_QOS_GET_QOS_INFO_TLV_FILTER_SPECS; - -typedef struct _QMI_QOS_GET_QOS_INFO_TLV_EXT_ERROR_INFO -{ - UCHAR TLVType; //0x15 - USHORT TLVLength; - USHORT ext_error_info; -} __attribute__ ((packed)) QMI_QOS_GET_QOS_INFO_TLV_EXT_ERROR_INFO, *PQMI_QOS_GET_QOS_INFO_TLV_EXT_ERROR_INFO; - -typedef struct _QMI_QOS_GET_QOS_INFO_TLV_5G_QCI -{ - UCHAR TLVType; //0x16 0x17 - USHORT TLVLength; - ULONG tx_rx_5g_qci; -} __attribute__ ((packed)) QMI_QOS_GET_QOS_INFO_TLV_5G_QCI, *PQMI_QOS_GET_QOS_INFO_TLV_5G_QCI; - -typedef struct _QMI_QOS_GET_QOS_INFO_TLV_AVG_WINDOW -{ - UCHAR TLVType; //0x18 0x19 - USHORT TLVLength; - USHORT tx_rx_averaging_window; -} __attribute__ ((packed)) QMI_QOS_GET_QOS_INFO_TLV_AVG_WINDOW, *PQMI_QOS_GET_QOS_INFO_TLV_AVG_WINDOW; - -typedef struct _QMI_QOS_GET_QOS_INFO_TLV_TX_FILTER_MATCH_ALL -{ - UCHAR TLVType; //0x1A - USHORT TLVLength; - UCHAR tx_filter_match_all_len; - USHORT filter_id; -} __attribute__ ((packed)) QMI_QOS_GET_QOS_INFO_TLV_TX_FILTER_MATCH_ALL, *PQMI_QOS_GET_QOS_INFO_TLV_TX_FILTER_MATCH_ALL; - -typedef struct _QMI_QOS_GET_QOS_INFO_REQ_MSG -{ - USHORT Type; - USHORT Length; - QMI_QOS_GET_QOS_INFO_TLV_QOS_ID QosIdTlv; -} __attribute__ ((packed)) QMI_QOS_GET_QOS_INFO_REQ_MSG, *PQMI_QOS_GET_QOS_INFO_REQ_MSG; - -typedef struct _QMI_QOS_GET_QOS_INFO_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; //0x02 - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - //QMI_QOS_GET_QOS_INFO_TLV_FLOW_STATUS FlowStatusTlv; - //QMI_QOS_GET_QOS_INFO_TLV_GRANTED_FLOW TxGrantedFlowTlv; - //QMI_QOS_GET_QOS_INFO_TLV_GRANTED_FLOW RxGrantedFlowTlv; - //QMI_QOS_GET_QOS_INFO_TLV_FILTER_SPECS TxFilterSpecsTlv; - //QMI_QOS_GET_QOS_INFO_TLV_FILTER_SPECS RxFilterSpecsTlv; - //QMI_QOS_GET_QOS_INFO_TLV_EXT_ERROR_INFO ExtErrorInfoTlv; - //QMI_QOS_GET_QOS_INFO_TLV_5G_QCI Tx5GQciTlv; - //QMI_QOS_GET_QOS_INFO_TLV_5G_QCI Rx5GQciTlv; - //QMI_QOS_GET_QOS_INFO_TLV_AVG_WINDOW TxAvgWindowTlv; - //QMI_QOS_GET_QOS_INFO_TLV_AVG_WINDOW RxAvgWindowTlv; - //QMI_QOS_GET_QOS_INFO_TLV_TX_FILTER_MATCH_ALL TxFilterMatchAllTlv; -} __attribute__ ((packed)) QMI_QOS_GET_QOS_INFO_RESP_MSG, *PQMI_QOS_GET_QOS_INFO_RESP_MSG; - -#define QOS_IND_FLOW_STATE_ACTIVATED 0x00 -#define QOS_IND_FLOW_STATE_MODIFIED 0x01 -#define QOS_IND_FLOW_STATE_DELETED 0x02 -#define QOS_IND_FLOW_STATE_SUSPENDED 0x03 -#define QOS_IND_FLOW_STATE_ENABLED 0x04 -#define QOS_IND_FLOW_STATE_DISABLED 0x05 -#define QOS_IND_FLOW_STATE_INVALID 0x06 - -#define QOS_EVENT_RPT_IND_FLOW_ACTIVATED 0x01 -#define QOS_EVENT_RPT_IND_FLOW_MODIFIED 0x02 -#define QOS_EVENT_RPT_IND_FLOW_DELETED 0x03 -#define QOS_EVENT_RPT_IND_FLOW_SUSPENDED 0x04 -#define QOS_EVENT_RPT_IND_FLOW_ENABLED 0x05 -#define QOS_EVENT_RPT_IND_FLOW_DISABLED 0x06 - -#define QOS_EVENT_RPT_IND_TLV_PHY_LINK_STATE_TYPE 0x01 -#define QOS_EVENT_RPT_IND_TLV_GLOBAL_FL_RPT_STATE 0x10 -#define QOS_EVENT_RPT_IND_TLV_GLOBAL_FL_RPT_TYPE 0x10 -#define QOS_EVENT_RPT_IND_TLV_TX_FLOW_TYPE 0x11 -#define QOS_EVENT_RPT_IND_TLV_RX_FLOW_TYPE 0x12 -#define QOS_EVENT_RPT_IND_TLV_TX_FILTER_TYPE 0x13 -#define QOS_EVENT_RPT_IND_TLV_RX_FILTER_TYPE 0x14 -#define QOS_EVENT_RPT_IND_TLV_FLOW_SPEC 0x10 -#define QOS_EVENT_RPT_IND_TLV_FILTER_SPEC 0x10 - -typedef struct _QOS_EVENT_RPT_IND_TLV_PHY_LINK_STATE -{ - UCHAR TLVType; // 0x01 - USHORT TLVLength; // 1 - UCHAR PhyLinkState; // 0-dormant, 1-active -} QOS_EVENT_RPT_IND_TLV_PHY_LINK_STATE, *PQOS_EVENT_RPT_IND_TLV_PHY_LINK_STATE; - -typedef struct _QOS_EVENT_RPT_IND_TLV_GLOBAL_FL_RPT -{ - UCHAR TLVType; // 0x10 - USHORT TLVLength; // 6 - ULONG QosId; - UCHAR NewFlow; // 1: newly added flow; 0: existing flow - UCHAR StateChange; // 1: activated; 2: modified; 3: deleted; - // 4: suspended(delete); 5: enabled; 6: disabled -} QOS_EVENT_RPT_IND_TLV_GLOBAL_FL_RPT, *PQOS_EVENT_RPT_IND_TLV_GLOBAL_FL_RPT; - -// QOS Flow - -typedef struct _QOS_EVENT_RPT_IND_TLV_FLOW -{ - UCHAR TLVType; // 0x10-TX flow; 0x11-RX flow - USHORT TLVLength; // var - // embedded TLV's -} QOS_EVENT_RPT_IND_TLV_TX_FLOW, *PQOS_EVENT_RPT_IND_TLV_TX_FLOW; - -#define QOS_FLOW_TLV_IP_FLOW_IDX_TYPE 0x10 -#define QOS_FLOW_TLV_IP_FLOW_TRAFFIC_CLASS_TYPE 0x11 -#define QOS_FLOW_TLV_IP_FLOW_DATA_RATE_MIN_MAX_TYPE 0x12 -#define QOS_FLOW_TLV_IP_FLOW_DATA_RATE_TOKEN_BUCKET_TYPE 0x13 -#define QOS_FLOW_TLV_IP_FLOW_LATENCY_TYPE 0x14 -#define QOS_FLOW_TLV_IP_FLOW_JITTER_TYPE 0x15 -#define QOS_FLOW_TLV_IP_FLOW_PKT_ERR_RATE_TYPE 0x16 -#define QOS_FLOW_TLV_IP_FLOW_MIN_PKT_SIZE_TYPE 0x17 -#define QOS_FLOW_TLV_IP_FLOW_MAX_PKT_SIZE_TYPE 0x18 -#define QOS_FLOW_TLV_IP_FLOW_3GPP_BIT_ERR_RATE_TYPE 0x19 -#define QOS_FLOW_TLV_IP_FLOW_3GPP_TRAF_PRIORITY_TYPE 0x1A -#define QOS_FLOW_TLV_IP_FLOW_3GPP2_PROFILE_ID_TYPE 0x1B - -typedef struct _QOS_FLOW_TLV_IP_FLOW_IDX -{ - UCHAR TLVType; // 0x10 - USHORT TLVLength; // 1 - UCHAR IpFlowIndex; -} QOS_FLOW_TLV_IP_FLOW_IDX, *PQOS_FLOW_TLV_IP_FLOW_IDX; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_TRAFFIC_CLASS -{ - UCHAR TLVType; // 0x11 - USHORT TLVLength; // 1 - UCHAR TrafficClass; -} QOS_FLOW_TLV_IP_FLOW_TRAFFIC_CLASS, *PQOS_FLOW_TLV_IP_FLOW_TRAFFIC_CLASS; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_DATA_RATE_MIN_MAX -{ - UCHAR TLVType; // 0x12 - USHORT TLVLength; // 8 - ULONG DataRateMax; - ULONG GuaranteedRate; -} QOS_FLOW_TLV_IP_FLOW_DATA_RATE_MIN_MAX, *PQOS_FLOW_TLV_IP_FLOW_DATA_RATE_MIN_MAX; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_DATA_RATE_TOKEN_BUCKET -{ - UCHAR TLVType; // 0x13 - USHORT TLVLength; // 12 - ULONG PeakRate; - ULONG TokenRate; - ULONG BucketSize; -} QOS_FLOW_TLV_IP_FLOW_DATA_RATE_TOKEN_BUCKET, *PQOS_FLOW_TLV_IP_FLOW_DATA_RATE_TOKEN_BUCKET; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_LATENCY -{ - UCHAR TLVType; // 0x14 - USHORT TLVLength; // 4 - ULONG IpFlowLatency; -} QOS_FLOW_TLV_IP_FLOW_LATENCY, *PQOS_FLOW_TLV_IP_FLOW_LATENCY; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_JITTER -{ - UCHAR TLVType; // 0x15 - USHORT TLVLength; // 4 - ULONG IpFlowJitter; -} QOS_FLOW_TLV_IP_FLOW_JITTER, *PQOS_FLOW_TLV_IP_FLOW_JITTER; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_PKT_ERR_RATE -{ - UCHAR TLVType; // 0x16 - USHORT TLVLength; // 4 - USHORT ErrRateMultiplier; - USHORT ErrRateExponent; -} QOS_FLOW_TLV_IP_FLOW_PKT_ERR_RATE, *PQOS_FLOW_TLV_IP_FLOW_PKT_ERR_RATE; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_MIN_PKT_SIZE -{ - UCHAR TLVType; // 0x17 - USHORT TLVLength; // 4 - ULONG MinPolicedPktSize; -} QOS_FLOW_TLV_IP_FLOW_MIN_PKT_SIZE, *PQOS_FLOW_TLV_IP_FLOW_MIN_PKT_SIZE; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_MAX_PKT_SIZE -{ - UCHAR TLVType; // 0x18 - USHORT TLVLength; // 4 - ULONG MaxAllowedPktSize; -} QOS_FLOW_TLV_IP_FLOW_MAX_PKT_SIZE, *PQOS_FLOW_TLV_IP_FLOW_MAX_PKT_SIZE; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_3GPP_BIT_ERR_RATE -{ - UCHAR TLVType; // 0x19 - USHORT TLVLength; // 1 - UCHAR ResidualBitErrorRate; -} QOS_FLOW_TLV_IP_FLOW_3GPP_BIT_ERR_RATE, *PQOS_FLOW_TLV_IP_FLOW_3GPP_BIT_ERR_RATE; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_3GPP_TRAF_PRIORITY -{ - UCHAR TLVType; // 0x1A - USHORT TLVLength; // 1 - UCHAR TrafficHandlingPriority; -} QOS_FLOW_TLV_IP_FLOW_3GPP_TRAF_PRIORITY, *PQOS_FLOW_TLV_IP_FLOW_3GPP_TRAF_PRIORITY; - -typedef struct _QOS_FLOW_TLV_IP_FLOW_3GPP2_PROFILE_ID -{ - UCHAR TLVType; // 0x1B - USHORT TLVLength; // 2 - USHORT ProfileId; -} QOS_FLOW_TLV_IP_FLOW_3GPP2_PROFILE_ID, *PQOS_FLOW_TLV_IP_FLOW_3GPP2_PROFILE_ID; - -// QOS Filter - -#define QOS_FILTER_TLV_IP_FILTER_IDX_TYPE 0x10 -#define QOS_FILTER_TLV_IP_VERSION_TYPE 0x11 -#define QOS_FILTER_TLV_IPV4_SRC_ADDR_TYPE 0x12 -#define QOS_FILTER_TLV_IPV4_DEST_ADDR_TYPE 0x13 -#define QOS_FILTER_TLV_NEXT_HDR_PROTOCOL_TYPE 0x14 -#define QOS_FILTER_TLV_IPV4_TYPE_OF_SERVICE_TYPE 0x15 -#define QOS_FILTER_TLV_TCP_UDP_PORT_SRC_TCP_TYPE 0x1B -#define QOS_FILTER_TLV_TCP_UDP_PORT_DEST_TCP_TYPE 0x1C -#define QOS_FILTER_TLV_TCP_UDP_PORT_SRC_UDP_TYPE 0x1D -#define QOS_FILTER_TLV_TCP_UDP_PORT_DEST_UDP_TYPE 0x1E -#define QOS_FILTER_TLV_ICMP_FILTER_MSG_TYPE_TYPE 0x1F -#define QOS_FILTER_TLV_ICMP_FILTER_MSG_CODE_TYPE 0x20 -#define QOS_FILTER_TLV_TCP_UDP_PORT_SRC_TYPE 0x24 -#define QOS_FILTER_TLV_TCP_UDP_PORT_DEST_TYPE 0x25 - -typedef struct _QOS_EVENT_RPT_IND_TLV_FILTER -{ - UCHAR TLVType; // 0x12-TX filter; 0x13-RX filter - USHORT TLVLength; // var - // embedded TLV's -} QOS_EVENT_RPT_IND_TLV_RX_FILTER, *PQOS_EVENT_RPT_IND_TLV_RX_FILTER; - -typedef struct _QOS_FILTER_TLV_IP_FILTER_IDX -{ - UCHAR TLVType; // 0x10 - USHORT TLVLength; // 1 - UCHAR IpFilterIndex; -} QOS_FILTER_TLV_IP_FILTER_IDX, *PQOS_FILTER_TLV_IP_FILTER_IDX; - -typedef struct _QOS_FILTER_TLV_IP_VERSION -{ - UCHAR TLVType; // 0x11 - USHORT TLVLength; // 1 - UCHAR IpVersion; -} QOS_FILTER_TLV_IP_VERSION, *PQOS_FILTER_TLV_IP_VERSION; - -typedef struct _QOS_FILTER_TLV_IPV4_SRC_ADDR -{ - UCHAR TLVType; // 0x12 - USHORT TLVLength; // 8 - ULONG IpSrcAddr; - ULONG IpSrcSubnetMask; -} QOS_FILTER_TLV_IPV4_SRC_ADDR, *PQOS_FILTER_TLV_IPV4_SRC_ADDR; - -typedef struct _QOS_FILTER_TLV_IPV4_DEST_ADDR -{ - UCHAR TLVType; // 0x13 - USHORT TLVLength; // 8 - ULONG IpDestAddr; - ULONG IpDestSubnetMask; -} QOS_FILTER_TLV_IPV4_DEST_ADDR, *PQOS_FILTER_TLV_IPV4_DEST_ADDR; - -typedef struct _QOS_FILTER_TLV_NEXT_HDR_PROTOCOL -{ - UCHAR TLVType; // 0x14 - USHORT TLVLength; // 1 - UCHAR NextHdrProtocol; -} QOS_FILTER_TLV_NEXT_HDR_PROTOCOL, *PQOS_FILTER_TLV_NEXT_HDR_PROTOCOL; - -typedef struct _QOS_FILTER_TLV_IPV4_TYPE_OF_SERVICE -{ - UCHAR TLVType; // 0x15 - USHORT TLVLength; // 2 - UCHAR Ipv4TypeOfService; - UCHAR Ipv4TypeOfServiceMask; -} QOS_FILTER_TLV_IPV4_TYPE_OF_SERVICE, *PQOS_FILTER_TLV_IPV4_TYPE_OF_SERVICE; - -typedef struct _QOS_FILTER_TLV_TCP_UDP_PORT -{ - UCHAR TLVType; // source port: 0x1B-TCP; 0x1D-UDP - // dest port: 0x1C-TCP; 0x1E-UDP - USHORT TLVLength; // 4 - USHORT FilterPort; - USHORT FilterPortRange; -} QOS_FILTER_TLV_TCP_UDP_PORT, *PQOS_FILTER_TLV_TCP_UDP_PORT; - -typedef struct _QOS_FILTER_TLV_ICMP_FILTER_MSG_TYPE -{ - UCHAR TLVType; // 0x1F - USHORT TLVLength; // 1 - UCHAR IcmpFilterMsgType; -} QOS_FILTER_TLV_ICMP_FILTER_MSG_TYPE, *PQOS_FILTER_TLV_ICMP_FILTER_MSG_TYPE; - -typedef struct _QOS_FILTER_TLV_ICMP_FILTER_MSG_CODE -{ - UCHAR TLVType; // 0x20 - USHORT TLVLength; // 1 - UCHAR IcmpFilterMsgCode; -} QOS_FILTER_TLV_ICMP_FILTER_MSG_CODE, *PQOS_FILTER_TLV_ICMP_FILTER_MSG_CODE; - -#define QOS_FILTER_PRECEDENCE_INVALID 256 -#define QOS_FILTER_TLV_PRECEDENCE_TYPE 0x22 -#define QOS_FILTER_TLV_ID_TYPE 0x23 - -typedef struct _QOS_FILTER_TLV_PRECEDENCE -{ - UCHAR TLVType; // 0x22 - USHORT TLVLength; // 2 - USHORT Precedence; // precedence of the filter -} QOS_FILTER_TLV_PRECEDENCE, *PQOS_FILTER_TLV_PRECEDENCE; - -typedef struct _QOS_FILTER_TLV_ID -{ - UCHAR TLVType; // 0x23 - USHORT TLVLength; // 2 - USHORT FilterId; // filter ID -} QOS_FILTER_TLV_ID, *PQOS_FILTER_TLV_ID; - -#ifdef QCQOS_IPV6 - -#define QOS_FILTER_TLV_IPV6_SRC_ADDR_TYPE 0x16 -#define QOS_FILTER_TLV_IPV6_DEST_ADDR_TYPE 0x17 -#define QOS_FILTER_TLV_IPV6_NEXT_HDR_PROTOCOL_TYPE 0x14 // same as IPV4 -#define QOS_FILTER_TLV_IPV6_TRAFFIC_CLASS_TYPE 0x19 -#define QOS_FILTER_TLV_IPV6_FLOW_LABEL_TYPE 0x1A - -typedef struct _QOS_FILTER_TLV_IPV6_SRC_ADDR -{ - UCHAR TLVType; // 0x16 - USHORT TLVLength; // 17 - UCHAR IpSrcAddr[16]; - UCHAR IpSrcAddrPrefixLen; // [0..128] -} QOS_FILTER_TLV_IPV6_SRC_ADDR, *PQOS_FILTER_TLV_IPV6_SRC_ADDR; - -typedef struct _QOS_FILTER_TLV_IPV6_DEST_ADDR -{ - UCHAR TLVType; // 0x17 - USHORT TLVLength; // 17 - UCHAR IpDestAddr[16]; - UCHAR IpDestAddrPrefixLen; // [0..128] -} QOS_FILTER_TLV_IPV6_DEST_ADDR, *PQOS_FILTER_TLV_IPV6_DEST_ADDR; - -#define QOS_FILTER_IPV6_NEXT_HDR_PROTOCOL_TCP 0x06 -#define QOS_FILTER_IPV6_NEXT_HDR_PROTOCOL_UDP 0x11 - -typedef struct _QOS_FILTER_TLV_IPV6_TRAFFIC_CLASS -{ - UCHAR TLVType; // 0x19 - USHORT TLVLength; // 2 - UCHAR TrafficClass; - UCHAR TrafficClassMask; // compare the first 6 bits only -} QOS_FILTER_TLV_IPV6_TRAFFIC_CLASS, *PQOS_FILTER_TLV_IPV6_TRAFFIC_CLASS; - -typedef struct _QOS_FILTER_TLV_IPV6_FLOW_LABEL -{ - UCHAR TLVType; // 0x1A - USHORT TLVLength; // 4 - ULONG FlowLabel; -} QOS_FILTER_TLV_IPV6_FLOW_LABEL, *PQOS_FILTER_TLV_IPV6_FLOW_LABEL; - -#endif // QCQOS_IPV6 -#endif - -// ======================= WMS ============================== -#define QMIWMS_SET_EVENT_REPORT_REQ 0x0001 -#define QMIWMS_SET_EVENT_REPORT_RESP 0x0001 -#define QMIWMS_EVENT_REPORT_IND 0x0001 -#define QMIWMS_RAW_SEND_REQ 0x0020 -#define QMIWMS_RAW_SEND_RESP 0x0020 -#define QMIWMS_RAW_WRITE_REQ 0x0021 -#define QMIWMS_RAW_WRITE_RESP 0x0021 -#define QMIWMS_RAW_READ_REQ 0x0022 -#define QMIWMS_RAW_READ_RESP 0x0022 -#define QMIWMS_MODIFY_TAG_REQ 0x0023 -#define QMIWMS_MODIFY_TAG_RESP 0x0023 -#define QMIWMS_DELETE_REQ 0x0024 -#define QMIWMS_DELETE_RESP 0x0024 -#define QMIWMS_GET_MESSAGE_PROTOCOL_REQ 0x0030 -#define QMIWMS_GET_MESSAGE_PROTOCOL_RESP 0x0030 -#define QMIWMS_LIST_MESSAGES_REQ 0x0031 -#define QMIWMS_LIST_MESSAGES_RESP 0x0031 -#define QMIWMS_GET_SMSC_ADDRESS_REQ 0x0034 -#define QMIWMS_GET_SMSC_ADDRESS_RESP 0x0034 -#define QMIWMS_SET_SMSC_ADDRESS_REQ 0x0035 -#define QMIWMS_SET_SMSC_ADDRESS_RESP 0x0035 -#define QMIWMS_GET_STORE_MAX_SIZE_REQ 0x0036 -#define QMIWMS_GET_STORE_MAX_SIZE_RESP 0x0036 - - -#define WMS_MESSAGE_PROTOCOL_CDMA 0x00 -#define WMS_MESSAGE_PROTOCOL_WCDMA 0x01 - -#if 0 -typedef struct _QMIWMS_GET_MESSAGE_PROTOCOL_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; -} QMIWMS_GET_MESSAGE_PROTOCOL_REQ_MSG, *PQMIWMS_GET_MESSAGE_PROTOCOL_REQ_MSG; - -typedef struct _QMIWMS_GET_MESSAGE_PROTOCOL_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR MessageProtocol; -} QMIWMS_GET_MESSAGE_PROTOCOL_RESP_MSG, *PQMIWMS_GET_MESSAGE_PROTOCOL_RESP_MSG; - -typedef struct _QMIWMS_GET_STORE_MAX_SIZE_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR StorageType; -} QMIWMS_GET_STORE_MAX_SIZE_REQ_MSG, *PQMIWMS_GET_STORE_MAX_SIZE_REQ_MSG; - -typedef struct _QMIWMS_GET_STORE_MAX_SIZE_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR TLV2Type; - USHORT TLV2Length; - ULONG MemStoreMaxSize; -} QMIWMS_GET_STORE_MAX_SIZE_RESP_MSG, *PQMIWMS_GET_STORE_MAX_SIZE_RESP_MSG; - -typedef struct _REQUEST_TAG -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR TagType; -} REQUEST_TAG, *PREQUEST_TAG; - -typedef struct _QMIWMS_LIST_MESSAGES_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR StorageType; -} QMIWMS_LIST_MESSAGES_REQ_MSG, *PQMIWMS_LIST_MESSAGES_REQ_MSG; - -typedef struct _QMIWMS_MESSAGE -{ - ULONG MessageIndex; - UCHAR TagType; -} QMIWMS_MESSAGE, *PQMIWMS_MESSAGE; - -typedef struct _QMIWMS_LIST_MESSAGES_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR TLV2Type; - USHORT TLV2Length; - ULONG NumMessages; -} QMIWMS_LIST_MESSAGES_RESP_MSG, *PQMIWMS_LIST_MESSAGES_RESP_MSG; - -typedef struct _QMIWMS_RAW_READ_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR StorageType; - ULONG MemoryIndex; -} QMIWMS_RAW_READ_REQ_MSG, *PQMIWMS_RAW_READ_REQ_MSG; - -typedef struct _QMIWMS_RAW_READ_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR TagType; - UCHAR Format; - USHORT MessageLength; - UCHAR Message; -} QMIWMS_RAW_READ_RESP_MSG, *PQMIWMS_RAW_READ_RESP_MSG; - -typedef struct _QMIWMS_MODIFY_TAG_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR StorageType; - ULONG MemoryIndex; - UCHAR TagType; -} QMIWMS_MODIFY_TAG_REQ_MSG, *PQMIWMS_MODIFY_TAG_REQ_MSG; - -typedef struct _QMIWMS_MODIFY_TAG_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} QMIWMS_MODIFY_TAG_RESP_MSG, *PQMIWMS_MODIFY_TAG_RESP_MSG; - -typedef struct _QMIWMS_RAW_SEND_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR SmsFormat; - USHORT SmsLength; - UCHAR SmsMessage; -} QMIWMS_RAW_SEND_REQ_MSG, *PQMIWMS_RAW_SEND_REQ_MSG; - -typedef struct _RAW_SEND_CAUSE_CODE -{ - UCHAR TLVType; - USHORT TLVLength; - USHORT CauseCode; -} RAW_SEND_CAUSE_CODE, *PRAW_SEND_CAUSE_CODE; - - -typedef struct _QMIWMS_RAW_SEND_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} QMIWMS_RAW_SEND_RESP_MSG, *PQMIWMS_RAW_SEND_RESP_MSG; - - -typedef struct _WMS_DELETE_MESSAGE_INDEX -{ - UCHAR TLVType; - USHORT TLVLength; - ULONG MemoryIndex; -} WMS_DELETE_MESSAGE_INDEX, *PWMS_DELETE_MESSAGE_INDEX; - -typedef struct _WMS_DELETE_MESSAGE_TAG -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR MessageTag; -} WMS_DELETE_MESSAGE_TAG, *PWMS_DELETE_MESSAGE_TAG; - -typedef struct _QMIWMS_DELETE_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR StorageType; -} QMIWMS_DELETE_REQ_MSG, *PQMIWMS_DELETE_REQ_MSG; - -typedef struct _QMIWMS_DELETE_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} QMIWMS_DELETE_RESP_MSG, *PQMIWMS_DELETE_RESP_MSG; - - -typedef struct _QMIWMS_GET_SMSC_ADDRESS_REQ_MSG -{ - USHORT Type; - USHORT Length; -} QMIWMS_GET_SMSC_ADDRESS_REQ_MSG, *PQMIWMS_GET_SMSC_ADDRESS_REQ_MSG; - -typedef struct _QMIWMS_SMSC_ADDRESS -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR SMSCAddressType[3]; - UCHAR SMSCAddressLength; - UCHAR SMSCAddressDigits; -} QMIWMS_SMSC_ADDRESS, *PQMIWMS_SMSC_ADDRESS; - - -typedef struct _QMIWMS_GET_SMSC_ADDRESS_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR SMSCAddress; -} QMIWMS_GET_SMSC_ADDRESS_RESP_MSG, *PQMIWMS_GET_SMSC_ADDRESS_RESP_MSG; - -typedef struct _QMIWMS_SET_SMSC_ADDRESS_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR SMSCAddress; -} QMIWMS_SET_SMSC_ADDRESS_REQ_MSG, *PQMIWMS_SET_SMSC_ADDRESS_REQ_MSG; - -typedef struct _QMIWMS_SET_SMSC_ADDRESS_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} QMIWMS_SET_SMSC_ADDRESS_RESP_MSG, *PQMIWMS_SET_SMSC_ADDRESS_RESP_MSG; - -typedef struct _QMIWMS_SET_EVENT_REPORT_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR ReportNewMessage; -} QMIWMS_SET_EVENT_REPORT_REQ_MSG, *PQMIWMS_SET_EVENT_REPORT_REQ_MSG; - -typedef struct _QMIWMS_SET_EVENT_REPORT_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} QMIWMS_SET_EVENT_REPORT_RESP_MSG, *PQMIWMS_SET_EVENT_REPORT_RESP_MSG; - -typedef struct _QMIWMS_EVENT_REPORT_IND_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR StorageType; - ULONG StorageIndex; -} QMIWMS_EVENT_REPORT_IND_MSG, *PQMIWMS_EVENT_REPORT_IND_MSG; -#endif - -// ======================= End of WMS ============================== - - -// ======================= NAS ============================== -#define QMINAS_SET_EVENT_REPORT_REQ 0x0002 -#define QMINAS_SET_EVENT_REPORT_RESP 0x0002 -#define QMINAS_EVENT_REPORT_IND 0x0002 -#define QMINAS_GET_SIGNAL_STRENGTH_REQ 0x0020 -#define QMINAS_GET_SIGNAL_STRENGTH_RESP 0x0020 -#define QMINAS_PERFORM_NETWORK_SCAN_REQ 0x0021 -#define QMINAS_PERFORM_NETWORK_SCAN_RESP 0x0021 -#define QMINAS_INITIATE_NW_REGISTER_REQ 0x0022 -#define QMINAS_INITIATE_NW_REGISTER_RESP 0x0022 -#define QMINAS_INITIATE_ATTACH_REQ 0x0023 -#define QMINAS_INITIATE_ATTACH_RESP 0x0023 -#define QMINAS_GET_SERVING_SYSTEM_REQ 0x0024 -#define QMINAS_GET_SERVING_SYSTEM_RESP 0x0024 -#define QMINAS_SERVING_SYSTEM_IND 0x0024 -#define QMINAS_GET_HOME_NETWORK_REQ 0x0025 -#define QMINAS_GET_HOME_NETWORK_RESP 0x0025 -#define QMINAS_GET_PREFERRED_NETWORK_REQ 0x0026 -#define QMINAS_GET_PREFERRED_NETWORK_RESP 0x0026 -#define QMINAS_SET_PREFERRED_NETWORK_REQ 0x0027 -#define QMINAS_SET_PREFERRED_NETWORK_RESP 0x0027 -#define QMINAS_GET_FORBIDDEN_NETWORK_REQ 0x0028 -#define QMINAS_GET_FORBIDDEN_NETWORK_RESP 0x0028 -#define QMINAS_SET_FORBIDDEN_NETWORK_REQ 0x0029 -#define QMINAS_SET_FORBIDDEN_NETWORK_RESP 0x0029 -#define QMINAS_SET_TECHNOLOGY_PREF_REQ 0x002A -#define QMINAS_SET_TECHNOLOGY_PREF_RESP 0x002A -#define QMINAS_GET_RF_BAND_INFO_REQ 0x0031 -#define QMINAS_GET_RF_BAND_INFO_RESP 0x0031 -#define QMINAS_GET_CELL_LOCATION_INFO_REQ 0x0043 -#define QMINAS_GET_CELL_LOCATION_INFO_RESP 0x0043 -#define QMINAS_GET_PLMN_NAME_REQ 0x0044 -#define QMINAS_GET_PLMN_NAME_RESP 0x0044 -#define QUECTEL_PACKET_TRANSFER_START_IND 0X100 -#define QUECTEL_PACKET_TRANSFER_END_IND 0X101 -#define QMINAS_GET_SYS_INFO_REQ 0x004D -#define QMINAS_GET_SYS_INFO_RESP 0x004D -#define QMINAS_SYS_INFO_IND 0x004E -#define QMINAS_GET_SIG_INFO_REQ 0x004F -#define QMINAS_GET_SIG_INFO_RESP 0x004F - -typedef struct _QMINAS_GET_HOME_NETWORK_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; -} __attribute__ ((packed)) QMINAS_GET_HOME_NETWORK_REQ_MSG, *PQMINAS_GET_HOME_NETWORK_REQ_MSG; - -typedef struct _HOME_NETWORK_SYSTEMID -{ - UCHAR TLVType; - USHORT TLVLength; - USHORT SystemID; - USHORT NetworkID; -} __attribute__ ((packed)) HOME_NETWORK_SYSTEMID, *PHOME_NETWORK_SYSTEMID; - -typedef struct _HOME_NETWORK -{ - UCHAR TLVType; - USHORT TLVLength; - USHORT MobileCountryCode; - USHORT MobileNetworkCode; - UCHAR NetworkDesclen; - UCHAR NetworkDesc; -} __attribute__ ((packed)) HOME_NETWORK, *PHOME_NETWORK; - -#if 0 -typedef struct _HOME_NETWORK_EXT -{ - UCHAR TLVType; - USHORT TLVLength; - USHORT MobileCountryCode; - USHORT MobileNetworkCode; - UCHAR NetworkDescDisp; - UCHAR NetworkDescEncoding; - UCHAR NetworkDesclen; - UCHAR NetworkDesc; -} HOME_NETWORK_EXT, *PHOME_NETWORK_EXT; - -typedef struct _QMINAS_GET_HOME_NETWORK_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} QMINAS_GET_HOME_NETWORK_RESP_MSG, *PQMINAS_GET_HOME_NETWORK_RESP_MSG; - -typedef struct _QMINAS_GET_PREFERRED_NETWORK_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; -} QMINAS_GET_PREFERRED_NETWORK_REQ_MSG, *PQMINAS_GET_PREFERRED_NETWORK_REQ_MSG; - - -typedef struct _PREFERRED_NETWORK -{ - USHORT MobileCountryCode; - USHORT MobileNetworkCode; - USHORT RadioAccess; -} PREFERRED_NETWORK, *PPREFERRED_NETWORK; - -typedef struct _QMINAS_GET_PREFERRED_NETWORK_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - 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 - UCHAR TLV2Type; // 0x01 - required parameter - USHORT TLV2Length; // length of the mfr string - USHORT NumPreferredNetwork; -} QMINAS_GET_PREFERRED_NETWORK_RESP_MSG, *PQMINAS_GET_PREFERRED_NETWORK_RESP_MSG; - -typedef struct _QMINAS_GET_FORBIDDEN_NETWORK_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; -} QMINAS_GET_FORBIDDEN_NETWORK_REQ_MSG, *PQMINAS_GET_FORBIDDEN_NETWORK_REQ_MSG; - -typedef struct _FORBIDDEN_NETWORK -{ - USHORT MobileCountryCode; - USHORT MobileNetworkCode; -} FORBIDDEN_NETWORK, *PFORBIDDEN_NETWORK; - -typedef struct _QMINAS_GET_FORBIDDEN_NETWORK_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - 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 - UCHAR TLV2Type; // 0x01 - required parameter - USHORT TLV2Length; // length of the mfr string - USHORT NumForbiddenNetwork; -} QMINAS_GET_FORBIDDEN_NETWORK_RESP_MSG, *PQMINAS_GET_FORBIDDEN_NETWORK_RESP_MSG; - -typedef struct _QMINAS_GET_SERVING_SYSTEM_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; -} QMINAS_GET_SERVING_SYSTEM_REQ_MSG, *PQMINAS_GET_SERVING_SYSTEM_REQ_MSG; - -typedef struct _QMINAS_ROAMING_INDICATOR_MSG -{ - UCHAR TLVType; // 0x01 - required parameter - USHORT TLVLength; // length of the mfr string - UCHAR RoamingIndicator; -} QMINAS_ROAMING_INDICATOR_MSG, *PQMINAS_ROAMING_INDICATOR_MSG; -#endif - -typedef struct _QMINAS_DATA_CAP -{ - UCHAR TLVType; // 0x01 - required parameter - USHORT TLVLength; // length of the mfr string - UCHAR DataCapListLen; - UCHAR DataCap; -} __attribute__ ((packed)) QMINAS_DATA_CAP, *PQMINAS_DATA_CAP; - -typedef struct _QMINAS_CURRENT_PLMN_MSG -{ - UCHAR TLVType; // 0x01 - required parameter - USHORT TLVLength; // length of the mfr string - USHORT MobileCountryCode; - USHORT MobileNetworkCode; - UCHAR NetworkDesclen; - UCHAR NetworkDesc; -} __attribute__ ((packed)) QMINAS_CURRENT_PLMN_MSG, *PQMINAS_CURRENT_PLMN_MSG; - -typedef struct _QMINAS_GET_SERVING_SYSTEM_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} __attribute__ ((packed)) QMINAS_GET_SERVING_SYSTEM_RESP_MSG, *PQMINAS_GET_SERVING_SYSTEM_RESP_MSG; - -typedef struct _SERVING_SYSTEM -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR RegistrationState; - UCHAR CSAttachedState; - UCHAR PSAttachedState; - UCHAR RegistredNetwork; - UCHAR InUseRadioIF; - UCHAR RadioIF; -} __attribute__ ((packed)) SERVING_SYSTEM, *PSERVING_SYSTEM; - -typedef struct _QMINAS_GET_SYS_INFO_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} __attribute__ ((packed)) QMINAS_GET_SYS_INFO_RESP_MSG, *PQMINAS_GET_SYS_INFO_RESP_MSG; - -typedef struct _QMINAS_SYS_INFO_IND_MSG -{ - USHORT Type; - USHORT Length; -} __attribute__ ((packed)) QMINAS_SYS_INFO_IND_MSG, *PQMINAS_SYS_INFO_IND_MSG; - -typedef struct _SERVICE_STATUS_INFO -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR SrvStatus; - UCHAR true_srv_status; - UCHAR IsPrefDataPath; -} __attribute__ ((packed)) SERVICE_STATUS_INFO, *PSERVICE_STATUS_INFO; - -typedef struct _CDMA_SYSTEM_INFO -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR SrvDomainValid; - UCHAR SrvDomain; - UCHAR SrvCapabilityValid; - UCHAR SrvCapability; - UCHAR RoamStatusValid; - UCHAR RoamStatus; - UCHAR IsSysForbiddenValid; - UCHAR IsSysForbidden; - UCHAR IsSysPrlMatchValid; - UCHAR IsSysPrlMatch; - UCHAR PRevInUseValid; - UCHAR PRevInUse; - UCHAR BSPRevValid; - UCHAR BSPRev; - UCHAR CCSSupportedValid; - UCHAR CCSSupported; - UCHAR CDMASysIdValid; - USHORT SID; - USHORT NID; - UCHAR BSInfoValid; - USHORT BaseID; - ULONG BaseLAT; - ULONG BaseLONG; - UCHAR PacketZoneValid; - USHORT PacketZone; - UCHAR NetworkIdValid; - UCHAR MCC[3]; - UCHAR MNC[3]; -} __attribute__ ((packed)) CDMA_SYSTEM_INFO, *PCDMA_SYSTEM_INFO; - -typedef struct _HDR_SYSTEM_INFO -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR SrvDomainValid; - UCHAR SrvDomain; - UCHAR SrvCapabilityValid; - UCHAR SrvCapability; - UCHAR RoamStatusValid; - UCHAR RoamStatus; - UCHAR IsSysForbiddenValid; - UCHAR IsSysForbidden; - UCHAR IsSysPrlMatchValid; - UCHAR IsSysPrlMatch; - UCHAR HdrPersonalityValid; - UCHAR HdrPersonality; - UCHAR HdrActiveProtValid; - UCHAR HdrActiveProt; - UCHAR is856SysIdValid; - UCHAR is856SysId[16]; -} __attribute__ ((packed)) HDR_SYSTEM_INFO, *PHDR_SYSTEM_INFO; - -typedef struct _GSM_SYSTEM_INFO -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR SrvDomainValid; - UCHAR SrvDomain; - UCHAR SrvCapabilityValid; - UCHAR SrvCapability; - UCHAR RoamStatusValid; - UCHAR RoamStatus; - UCHAR IsSysForbiddenValid; - UCHAR IsSysForbidden; - UCHAR LacValid; - USHORT Lac; - UCHAR CellIdValid; - ULONG CellId; - UCHAR RegRejectInfoValid; - UCHAR RejectSrvDomain; - UCHAR RejCause; - UCHAR NetworkIdValid; - UCHAR MCC[3]; - UCHAR MNC[3]; - UCHAR EgprsSuppValid; - UCHAR EgprsSupp; - UCHAR DtmSuppValid; - UCHAR DtmSupp; -} __attribute__ ((packed)) GSM_SYSTEM_INFO, *PGSM_SYSTEM_INFO; - -typedef struct _WCDMA_SYSTEM_INFO -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR SrvDomainValid; - UCHAR SrvDomain; - UCHAR SrvCapabilityValid; - UCHAR SrvCapability; - UCHAR RoamStatusValid; - UCHAR RoamStatus; - UCHAR IsSysForbiddenValid; - UCHAR IsSysForbidden; - UCHAR LacValid; - USHORT Lac; - UCHAR CellIdValid; - ULONG CellId; - UCHAR RegRejectInfoValid; - UCHAR RejectSrvDomain; - UCHAR RejCause; - UCHAR NetworkIdValid; - UCHAR MCC[3]; - UCHAR MNC[3]; - UCHAR HsCallStatusValid; - UCHAR HsCallStatus; - UCHAR HsIndValid; - UCHAR HsInd; - UCHAR PscValid; - UCHAR Psc; -} __attribute__ ((packed)) WCDMA_SYSTEM_INFO, *PWCDMA_SYSTEM_INFO; - -typedef struct _LTE_SYSTEM_INFO -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR SrvDomainValid; - UCHAR SrvDomain; - UCHAR SrvCapabilityValid; - UCHAR SrvCapability; - UCHAR RoamStatusValid; - UCHAR RoamStatus; - UCHAR IsSysForbiddenValid; - UCHAR IsSysForbidden; - UCHAR LacValid; - USHORT Lac; - UCHAR CellIdValid; - ULONG CellId; - UCHAR RegRejectInfoValid; - UCHAR RejectSrvDomain; - UCHAR RejCause; - UCHAR NetworkIdValid; - UCHAR MCC[3]; - UCHAR MNC[3]; - UCHAR TacValid; - USHORT Tac; -} __attribute__ ((packed)) LTE_SYSTEM_INFO, *PLTE_SYSTEM_INFO; - -typedef struct _TDSCDMA_SYSTEM_INFO -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR SrvDomainValid; - UCHAR SrvDomain; - UCHAR SrvCapabilityValid; - UCHAR SrvCapability; - UCHAR RoamStatusValid; - UCHAR RoamStatus; - UCHAR IsSysForbiddenValid; - UCHAR IsSysForbidden; - UCHAR LacValid; - USHORT Lac; - UCHAR CellIdValid; - ULONG CellId; - UCHAR RegRejectInfoValid; - UCHAR RejectSrvDomain; - UCHAR RejCause; - UCHAR NetworkIdValid; - UCHAR MCC[3]; - UCHAR MNC[3]; - UCHAR HsCallStatusValid; - UCHAR HsCallStatus; - UCHAR HsIndValid; - UCHAR HsInd; - UCHAR CellParameterIdValid; - USHORT CellParameterId; - UCHAR CellBroadcastCapValid; - ULONG CellBroadcastCap; - UCHAR CsBarStatusValid; - ULONG CsBarStatus; - UCHAR PsBarStatusValid; - ULONG PsBarStatus; - UCHAR CipherDomainValid; - UCHAR CipherDomain; -} __attribute__ ((packed)) TDSCDMA_SYSTEM_INFO, *PTDSCDMA_SYSTEM_INFO; - -typedef enum { - NAS_SYS_SRV_STATUS_NO_SRV_V01 = 0, - NAS_SYS_SRV_STATUS_LIMITED_V01 = 1, - NAS_SYS_SRV_STATUS_SRV_V01 = 2, - NAS_SYS_SRV_STATUS_LIMITED_REGIONAL_V01 = 3, - NAS_SYS_SRV_STATUS_PWR_SAVE_V01 = 4, -}nas_service_status_enum_type_v01; - -typedef enum { - SYS_SRV_DOMAIN_NO_SRV_V01 = 0, - SYS_SRV_DOMAIN_CS_ONLY_V01 = 1, - SYS_SRV_DOMAIN_PS_ONLY_V01 = 2, - SYS_SRV_DOMAIN_CS_PS_V01 = 3, - SYS_SRV_DOMAIN_CAMPED_V01 = 4, -}nas_service_domain_enum_type_v01; - -typedef enum { - QMI_NAS_RADIO_INTERFACE_UNKNOWN = -1, - QMI_NAS_RADIO_INTERFACE_NONE = 0x00, - QMI_NAS_RADIO_INTERFACE_CDMA_1X = 0x01, - QMI_NAS_RADIO_INTERFACE_CDMA_1XEVDO = 0x02, - QMI_NAS_RADIO_INTERFACE_AMPS = 0x03, - QMI_NAS_RADIO_INTERFACE_GSM = 0x04, - QMI_NAS_RADIO_INTERFACE_UMTS = 0x05, - QMI_NAS_RADIO_INTERFACE_LTE = 0x08, - QMI_NAS_RADIO_INTERFACE_TD_SCDMA = 0x09, - QMI_NAS_RADIO_INTERFACE_5GNR = 0x0C, -} QMI_NAS_RADIO_INTERFACE_E; - -typedef enum { - QMI_NAS_ACTIVE_BAND_BC_0 = 0, - QMI_NAS_ACTIVE_BAND_BC_1 = 1, - QMI_NAS_ACTIVE_BAND_BC_2 = 2, - QMI_NAS_ACTIVE_BAND_BC_3 = 3, - QMI_NAS_ACTIVE_BAND_BC_4 = 4, - QMI_NAS_ACTIVE_BAND_BC_5 = 5, - QMI_NAS_ACTIVE_BAND_BC_6 = 6, - QMI_NAS_ACTIVE_BAND_BC_7 = 7, - QMI_NAS_ACTIVE_BAND_BC_8 = 8, - QMI_NAS_ACTIVE_BAND_BC_9 = 9, - QMI_NAS_ACTIVE_BAND_BC_10 = 10, - QMI_NAS_ACTIVE_BAND_BC_11 = 11, - QMI_NAS_ACTIVE_BAND_BC_12 = 12, - QMI_NAS_ACTIVE_BAND_BC_13 = 13, - QMI_NAS_ACTIVE_BAND_BC_14 = 14, - QMI_NAS_ACTIVE_BAND_BC_15 = 15, - QMI_NAS_ACTIVE_BAND_BC_16 = 16, - QMI_NAS_ACTIVE_BAND_BC_17 = 17, - QMI_NAS_ACTIVE_BAND_BC_18 = 18, - QMI_NAS_ACTIVE_BAND_BC_19 = 19, - QMI_NAS_ACTIVE_BAND_GSM_450 = 40, - QMI_NAS_ACTIVE_BAND_GSM_480 = 41, - QMI_NAS_ACTIVE_BAND_GSM_750 = 42, - QMI_NAS_ACTIVE_BAND_GSM_850 = 43, - QMI_NAS_ACTIVE_BAND_GSM_900_EXTENDED = 44, - QMI_NAS_ACTIVE_BAND_GSM_900_PRIMARY = 45, - QMI_NAS_ACTIVE_BAND_GSM_900_RAILWAYS = 46, - QMI_NAS_ACTIVE_BAND_GSM_DCS_1800 = 47, - QMI_NAS_ACTIVE_BAND_GSM_PCS_1900 = 48, - QMI_NAS_ACTIVE_BAND_WCDMA_2100 = 80, - QMI_NAS_ACTIVE_BAND_WCDMA_PCS_1900 = 81, - QMI_NAS_ACTIVE_BAND_WCDMA_DCS_1800 = 82, - QMI_NAS_ACTIVE_BAND_WCDMA_1700_US = 83, - QMI_NAS_ACTIVE_BAND_WCDMA_850 = 84, - QMI_NAS_ACTIVE_BAND_WCDMA_800 = 85, - QMI_NAS_ACTIVE_BAND_WCDMA_2600 = 86, - QMI_NAS_ACTIVE_BAND_WCDMA_900 = 87, - QMI_NAS_ACTIVE_BAND_WCDMA_1700_JAPAN = 88, - QMI_NAS_ACTIVE_BAND_WCDMA_1500_JAPAN = 90, - QMI_NAS_ACTIVE_BAND_WCDMA_850_JAPAN = 91, - QMI_NAS_ACTIVE_BAND_EUTRAN_1 = 120, - QMI_NAS_ACTIVE_BAND_EUTRAN_2 = 121, - QMI_NAS_ACTIVE_BAND_EUTRAN_3 = 122, - QMI_NAS_ACTIVE_BAND_EUTRAN_4 = 123, - QMI_NAS_ACTIVE_BAND_EUTRAN_5 = 124, - QMI_NAS_ACTIVE_BAND_EUTRAN_6 = 125, - QMI_NAS_ACTIVE_BAND_EUTRAN_7 = 126, - QMI_NAS_ACTIVE_BAND_EUTRAN_8 = 127, - QMI_NAS_ACTIVE_BAND_EUTRAN_9 = 128, - QMI_NAS_ACTIVE_BAND_EUTRAN_10 = 129, - QMI_NAS_ACTIVE_BAND_EUTRAN_11 = 130, - QMI_NAS_ACTIVE_BAND_EUTRAN_12 = 131, - QMI_NAS_ACTIVE_BAND_EUTRAN_13 = 132, - QMI_NAS_ACTIVE_BAND_EUTRAN_14 = 133, - QMI_NAS_ACTIVE_BAND_EUTRAN_17 = 134, - QMI_NAS_ACTIVE_BAND_EUTRAN_18 = 143, - QMI_NAS_ACTIVE_BAND_EUTRAN_19 = 144, - QMI_NAS_ACTIVE_BAND_EUTRAN_20 = 145, - QMI_NAS_ACTIVE_BAND_EUTRAN_21 = 146, - QMI_NAS_ACTIVE_BAND_EUTRAN_23 = 152, - QMI_NAS_ACTIVE_BAND_EUTRAN_24 = 147, - QMI_NAS_ACTIVE_BAND_EUTRAN_25 = 148, - QMI_NAS_ACTIVE_BAND_EUTRAN_26 = 153, - QMI_NAS_ACTIVE_BAND_EUTRAN_27 = 164, - QMI_NAS_ACTIVE_BAND_EUTRAN_28 = 158, - QMI_NAS_ACTIVE_BAND_EUTRAN_29 = 159, - QMI_NAS_ACTIVE_BAND_EUTRAN_30 = 160, - QMI_NAS_ACTIVE_BAND_EUTRAN_31 = 165, - QMI_NAS_ACTIVE_BAND_EUTRAN_32 = 154, - QMI_NAS_ACTIVE_BAND_EUTRAN_33 = 135, - QMI_NAS_ACTIVE_BAND_EUTRAN_34 = 136, - QMI_NAS_ACTIVE_BAND_EUTRAN_35 = 137, - QMI_NAS_ACTIVE_BAND_EUTRAN_36 = 138, - QMI_NAS_ACTIVE_BAND_EUTRAN_37 = 139, - QMI_NAS_ACTIVE_BAND_EUTRAN_38 = 140, - QMI_NAS_ACTIVE_BAND_EUTRAN_39 = 141, - QMI_NAS_ACTIVE_BAND_EUTRAN_40 = 142, - QMI_NAS_ACTIVE_BAND_EUTRAN_41 = 149, - QMI_NAS_ACTIVE_BAND_EUTRAN_42 = 150, - QMI_NAS_ACTIVE_BAND_EUTRAN_43 = 151, - QMI_NAS_ACTIVE_BAND_EUTRAN_46 = 163, - QMI_NAS_ACTIVE_BAND_EUTRAN_47 = 166, - QMI_NAS_ACTIVE_BAND_EUTRAN_48 = 167, - QMI_NAS_ACTIVE_BAND_EUTRAN_66 = 161, - QMI_NAS_ACTIVE_BAND_EUTRAN_71 = 168, - QMI_NAS_ACTIVE_BAND_EUTRAN_125 = 155, - QMI_NAS_ACTIVE_BAND_EUTRAN_126 = 156, - QMI_NAS_ACTIVE_BAND_EUTRAN_127 = 157, - QMI_NAS_ACTIVE_BAND_EUTRAN_250 = 162, - QMI_NAS_ACTIVE_BAND_TDSCDMA_A = 200, - QMI_NAS_ACTIVE_BAND_TDSCDMA_B = 201, - QMI_NAS_ACTIVE_BAND_TDSCDMA_C = 202, - QMI_NAS_ACTIVE_BAND_TDSCDMA_D = 203, - QMI_NAS_ACTIVE_BAND_TDSCDMA_E = 204, - QMI_NAS_ACTIVE_BAND_TDSCDMA_F = 205, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_1 = 250, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_2 = 251, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_3 = 252, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_5 = 253, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_7 = 254, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_8 = 255, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_20 = 256, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_28 = 257, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_38 = 258, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_41 = 259, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_50 = 260, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_51 = 261, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_66 = 262, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_70 = 263, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_71 = 264, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_74 = 265, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_75 = 266, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_76 = 267, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_77 = 268, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_78 = 269, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_79 = 270, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_80 = 271, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_81 = 272, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_82 = 273, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_83 = 274, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_84 = 275, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_85 = 276, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_257= 277, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_258= 278, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_259= 279, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_260= 280, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_261= 281, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_12 = 282, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_25 = 283, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_34 = 284, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_39 = 285, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_40 = 286, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_65 = 287, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_86 = 288, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_48 = 289, - QMI_NAS_ACTIVE_BAND_NR5G_BAND_14 = 290 -} QMI_NAS_ACTIVE_BAND_E; - -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - - uint8_t srv_domain_valid; - uint8_t srv_domain; - uint8_t srv_capability_valid; - uint8_t srv_capability; - uint8_t roam_status_valid; - uint8_t roam_status; - uint8_t is_sys_forbidden_valid; - uint8_t is_sys_forbidden; - - uint8_t lac_valid; - uint16_t lac; - uint8_t cell_id_valid; - uint32_t cell_id; - uint8_t reg_reject_info_valid; - uint8_t reject_srv_domain; - uint8_t rej_cause; - uint8_t network_id_valid; - UCHAR MCC[3]; - UCHAR MNC[3]; - - uint8_t tac_valid; - uint16_t tac; -} __attribute__ ((packed)) NR5G_SYSTEM_INFO, *PNR5G_SYSTEM_INFO; - -#if 0 -typedef struct _QMINAS_SERVING_SYSTEM_IND_MSG -{ - USHORT Type; - USHORT Length; -} QMINAS_SERVING_SYSTEM_IND_MSG, *PQMINAS_SERVING_SYSTEM_IND_MSG; - -typedef struct _QMINAS_SET_PREFERRED_NETWORK_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT NumPreferredNetwork; - USHORT MobileCountryCode; - USHORT MobileNetworkCode; - USHORT RadioAccess; -} QMINAS_SET_PREFERRED_NETWORK_REQ_MSG, *PQMINAS_SET_PREFERRED_NETWORK_REQ_MSG; - -typedef struct _QMINAS_SET_PREFERRED_NETWORK_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - 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 -} QMINAS_SET_PREFERRED_NETWORK_RESP_MSG, *PQMINAS_SET_PREFERRED_NETWORK_RESP_MSG; - -typedef struct _QMINAS_SET_FORBIDDEN_NETWORK_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT NumForbiddenNetwork; - USHORT MobileCountryCode; - USHORT MobileNetworkCode; -} QMINAS_SET_FORBIDDEN_NETWORK_REQ_MSG, *PQMINAS_SET_FORBIDDEN_NETWORK_REQ_MSG; - -typedef struct _QMINAS_SET_FORBIDDEN_NETWORK_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - 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 -} QMINAS_SET_FORBIDDEN_NETWORK_RESP_MSG, *PQMINAS_SET_FORBIDDEN_NETWORK_RESP_MSG; - -typedef struct _QMINAS_PERFORM_NETWORK_SCAN_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; -} QMINAS_PERFORM_NETWORK_SCAN_REQ_MSG, *PQMINAS_PERFORM_NETWORK_SCAN_REQ_MSG; - -typedef struct _VISIBLE_NETWORK -{ - USHORT MobileCountryCode; - USHORT MobileNetworkCode; - UCHAR NetworkStatus; - UCHAR NetworkDesclen; -} VISIBLE_NETWORK, *PVISIBLE_NETWORK; - -typedef struct _QMINAS_PERFORM_NETWORK_SCAN_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - 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 -} QMINAS_PERFORM_NETWORK_SCAN_RESP_MSG, *PQMINAS_PERFORM_NETWORK_SCAN_RESP_MSG; - -typedef struct _QMINAS_PERFORM_NETWORK_SCAN_NETWORK_INFO -{ - UCHAR TLVType; // 0x010 - required parameter - USHORT TLVLength; // length - USHORT NumNetworkInstances; -} QMINAS_PERFORM_NETWORK_SCAN_NETWORK_INFO, *PQMINAS_PERFORM_NETWORK_SCAN_NETWORK_INFO; - -typedef struct _QMINAS_PERFORM_NETWORK_SCAN_RAT_INFO -{ - UCHAR TLVType; // 0x011 - required parameter - USHORT TLVLength; // length - USHORT NumInst; -} QMINAS_PERFORM_NETWORK_SCAN_RAT_INFO, *PQMINAS_PERFORM_NETWORK_SCAN_RAT_INFO; - -typedef struct _QMINAS_PERFORM_NETWORK_SCAN_RAT -{ - USHORT MCC; - USHORT MNC; - UCHAR RAT; -} QMINAS_PERFORM_NETWORK_SCAN_RAT, *PQMINAS_PERFORM_NETWORK_SCAN_RAT; - - -typedef struct _QMINAS_MANUAL_NW_REGISTER -{ - UCHAR TLV2Type; // 0x02 - result code - USHORT TLV2Length; // 4 - USHORT MobileCountryCode; - USHORT MobileNetworkCode; - UCHAR RadioAccess; -} QMINAS_MANUAL_NW_REGISTER, *PQMINAS_MANUAL_NW_REGISTER; - -typedef struct _QMINAS_INITIATE_NW_REGISTER_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - UCHAR RegisterAction; -} QMINAS_INITIATE_NW_REGISTER_REQ_MSG, *PQMINAS_INITIATE_NW_REGISTER_REQ_MSG; - -typedef struct _QMINAS_INITIATE_NW_REGISTER_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - 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 -} QMINAS_INITIATE_NW_REGISTER_RESP_MSG, *PQMINAS_INITIATE_NW_REGISTER_RESP_MSG; - -typedef struct _QMINAS_SET_TECHNOLOGY_PREF_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; - UCHAR TLVType; // 0x02 - result code - USHORT TLVLength; // 4 - USHORT TechPref; - UCHAR Duration; -} QMINAS_SET_TECHNOLOGY_PREF_REQ_MSG, *PQMINAS_SET_TECHNOLOGY_PREF_REQ_MSG; - -typedef struct _QMINAS_SET_TECHNOLOGY_PREF_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - 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 -} QMINAS_SET_TECHNOLOGY_PREF_RESP_MSG, *PQMINAS_SET_TECHNOLOGY_PREF_RESP_MSG; - -typedef struct _QMINAS_GET_SIGNAL_STRENGTH_REQ_MSG -{ - USHORT Type; // QMUX type 0x0003 - USHORT Length; -} QMINAS_GET_SIGNAL_STRENGTH_REQ_MSG, *PQMINAS_GET_SIGNAL_STRENGTH_REQ_MSG; - -typedef struct _QMINAS_SIGNAL_STRENGTH -{ - CHAR SigStrength; - UCHAR RadioIf; -} QMINAS_SIGNAL_STRENGTH, *PQMINAS_SIGNAL_STRENGTH; - -typedef struct _QMINAS_SIGNAL_STRENGTH_LIST -{ - UCHAR TLV3Type; - USHORT TLV3Length; - USHORT NumInstance; -} QMINAS_SIGNAL_STRENGTH_LIST, *PQMINAS_SIGNAL_STRENGTH_LIST; - - -typedef struct _QMINAS_GET_SIGNAL_STRENGTH_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - 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 - UCHAR TLV2Type; - USHORT TLV2Length; - CHAR SignalStrength; - UCHAR RadioIf; -} QMINAS_GET_SIGNAL_STRENGTH_RESP_MSG, *PQMINAS_GET_SIGNAL_STRENGTH_RESP_MSG; - - -typedef struct _QMINAS_SET_EVENT_REPORT_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR ReportSigStrength; - UCHAR NumTresholds; - CHAR TresholdList[2]; -} QMINAS_SET_EVENT_REPORT_REQ_MSG, *PQMINAS_SET_EVENT_REPORT_REQ_MSG; - -typedef struct _QMINAS_SET_EVENT_REPORT_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - 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 -} QMINAS_SET_EVENT_REPORT_RESP_MSG, *PQMINAS_SET_EVENT_REPORT_RESP_MSG; - -typedef struct _QMINAS_SIGNAL_STRENGTH_TLV -{ - UCHAR TLVType; - USHORT TLVLength; - CHAR SigStrength; - UCHAR RadioIf; -} QMINAS_SIGNAL_STRENGTH_TLV, *PQMINAS_SIGNAL_STRENGTH_TLV; - -typedef struct _QMINAS_REJECT_CAUSE_TLV -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR ServiceDomain; - USHORT RejectCause; -} QMINAS_REJECT_CAUSE_TLV, *PQMINAS_REJECT_CAUSE_TLV; - -typedef struct _QMINAS_EVENT_REPORT_IND_MSG -{ - USHORT Type; - USHORT Length; -} QMINAS_EVENT_REPORT_IND_MSG, *PQMINAS_EVENT_REPORT_IND_MSG; - -typedef struct _QMINAS_GET_RF_BAND_INFO_REQ_MSG -{ - USHORT Type; - USHORT Length; -} QMINAS_GET_RF_BAND_INFO_REQ_MSG, *PQMINAS_GET_RF_BAND_INFO_REQ_MSG; - -typedef struct _QMINASRF_BAND_INFO -{ - UCHAR RadioIf; - USHORT ActiveBand; - USHORT ActiveChannel; -} QMINASRF_BAND_INFO, *PQMINASRF_BAND_INFO; - -typedef struct _QMINAS_GET_RF_BAND_INFO_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - 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 - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR NumInstances; -} QMINAS_GET_RF_BAND_INFO_RESP_MSG, *PQMINAS_GET_RF_BAND_INFO_RESP_MSG; - - -typedef struct _QMINAS_GET_PLMN_NAME_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT MCC; - USHORT MNC; -} QMINAS_GET_PLMN_NAME_REQ_MSG, *PQMINAS_GET_PLMN_NAME_REQ_MSG; - -typedef struct _QMINAS_GET_PLMN_NAME_RESP_MSG -{ - 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 -} QMINAS_GET_PLMN_NAME_RESP_MSG, *PQMINAS_GET_PLMN_NAME_RESP_MSG; - -typedef struct _QMINAS_GET_PLMN_NAME_SPN -{ - UCHAR TLVType; - USHORT TLVLength; - UCHAR SPN_Enc; - UCHAR SPN_Len; -} QMINAS_GET_PLMN_NAME_SPN, *PQMINAS_GET_PLMN_NAME_SPN; - -typedef struct _QMINAS_GET_PLMN_NAME_PLMN -{ - UCHAR PLMN_Enc; - UCHAR PLMN_Ci; - UCHAR PLMN_SpareBits; - UCHAR PLMN_Len; -} QMINAS_GET_PLMN_NAME_PLMN, *PQMINAS_GET_PLMN_NAME_PLMN; - -typedef struct _QMINAS_INITIATE_ATTACH_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR PsAttachAction; -} QMINAS_INITIATE_ATTACH_REQ_MSG, *PQMINAS_INITIATE_ATTACH_REQ_MSG; - -typedef struct _QMINAS_INITIATE_ATTACH_RESP_MSG -{ - USHORT Type; // QMUX type 0x0003 - 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 -} QMINAS_INITIATE_ATTACH_RESP_MSG, *PQMINAS_INITIATE_ATTACH_RESP_MSG; -#endif -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - CHAR rssi; - SHORT ecio; -} __attribute__ ((packed)) QMINAS_SIG_INFO_CDMA_TLV_MSG, *PQMINAS_SIG_INFO_CDMA_TLV_MSG; - -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - CHAR rssi; - SHORT ecio; - CHAR sinr; - INT io; -} __attribute__ ((packed)) QMINAS_SIG_INFO_HDR_TLV_MSG, *PQMINAS_SIG_INFO_HDR_TLV_MSG; - -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - CHAR rssi; -} __attribute__ ((packed)) QMINAS_SIG_INFO_GSM_TLV_MSG, *PQMINAS_SIG_INFO_GSM_TLV_MSG; - -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - CHAR rssi; - SHORT ecio; -} __attribute__ ((packed)) QMINAS_SIG_INFO_WCDMA_TLV_MSG, *PQMINAS_SIG_INFO_WCDMA_TLV_MSG; - -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - CHAR rssi; - CHAR rsrq; - SHORT rsrp; - SHORT snr; -} __attribute__ ((packed)) QMINAS_SIG_INFO_LTE_TLV_MSG, *PQMINAS_SIG_INFO_LTE_TLV_MSG; - -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - CHAR rscp; -} __attribute__ ((packed)) QMINAS_SIG_INFO_TDSCDMA_TLV_MSG, *PQMINAS_SIG_INFO_TDSCDMA_TLV_MSG; - -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - SHORT rsrp; - SHORT snr; -} __attribute__ ((packed)) QMINAS_SIG_INFO_5G_NSA_TLV_MSG, *PQMINAS_SIG_INFO_5G_NSA_TLV_MSG; - -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - SHORT nr5g_rsrq; -} __attribute__ ((packed)) QMINAS_SIG_INFO_5G_SA_TLV_MSG, *PQMINAS_SIG_INFO_5G_SA_TLV_MSG; - -typedef struct { - uint8 radio_if; - uint16 active_band; - uint16 active_channel; -} __attribute__ ((packed)) NasGetRfBandInfo; - -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - - uint8 num_instances; - NasGetRfBandInfo bands_array[0]; -} __attribute__ ((packed)) NasGetRfBandInfoList; - -typedef struct { - uint8 radio_if; - uint16 dedicated_band; -} __attribute__ ((packed)) NasGetRfBandInfoDedicated; - -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - - uint8 num_instances; - NasGetRfBandInfoDedicated bands_array[0]; -} __attribute__ ((packed)) NasGetRfBandInfoDedicatedList; - -typedef struct { - uint8 radio_if; - uint16 active_band; - uint32 active_channel; -} __attribute__ ((packed)) NasGetRfBandInfoExtended; - -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - - uint8 num_instances; - NasGetRfBandInfoExtended bands_array[0]; -} __attribute__ ((packed)) NasGetRfBandInfoExtendedList; - -typedef struct { - uint8 radio_if; - uint32 bandwidth; -} __attribute__ ((packed)) NasGetRfBandInfoBandWidth; - -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - - uint8 num_instances; - NasGetRfBandInfoBandWidth bands_array[0]; -} __attribute__ ((packed)) NasGetRfBandInfoBandWidthList; - -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - - uint8 plmn[3]; - uint8 tac[3]; - uint64 global_cell_id; - uint16 physical_cell_id; - int16 rsrq; - int16 rsrp; - int16 snr; -} __attribute__ ((packed)) NasGetCellLocationNr5gServingCell; - -typedef struct { - uint16 physical_cell_id; - int16 rsrq; - int16 rsrp; - int16 rssi; - int16 cell_selection_rx_level; -} __attribute__ ((packed)) NasGetCellLocationLteInfoCell; - -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - - uint8 ue_in_idle; - uint8 plmn[3]; - uint16 tracking_area_code; - uint32 global_cell_id; - uint16 absolute_rf_channel_number; - uint16 serving_cell_id; - uint8 cell_reselection_priority; - uint8 s_non_intra_search_threshold; - uint8 serving_cell_low_threshold; - uint8 s_intra_search_threshold; - uint8 cells_len; - NasGetCellLocationLteInfoCell cells_array[0]; -} __attribute__ ((packed)) NasGetCellLocationLteInfoIntrafrequency; - -typedef struct _QmiMessageNasGetCellLocationInfoOutputInterfrequencyLteInfoFrequencyElement { - uint16 eutra_absolute_rf_channel_number; - uint8 cell_selection_rx_level_low_threshold; - uint8 cell_selection_rx_level_high_threshold; - uint8 cell_reselection_priority; - uint8 cells_len; - NasGetCellLocationLteInfoCell cells_array[0]; -} __attribute__ ((packed)) NasGetCellLocationLteInfoInterfrequencyFrequencyElement; - -typedef struct { - UCHAR TLVType; - USHORT TLVLength; - - uint8 ue_in_idle; - uint8 freqs_len; - NasGetCellLocationLteInfoInterfrequencyFrequencyElement freqs[0]; -} __attribute__ ((packed)) NasGetCellLocationLteInfoInterfrequency; - -// ======================= End of NAS ============================== - -// ======================= UIM ============================== -#define QMIUIM_READ_TRANSPARENT_REQ 0x0020 -#define QMIUIM_READ_TRANSPARENT_RESP 0x0020 -#define QMIUIM_READ_TRANSPARENT_IND 0x0020 -#define QMIUIM_READ_RECORD_REQ 0x0021 -#define QMIUIM_READ_RECORD_RESP 0x0021 -#define QMIUIM_READ_RECORD_IND 0x0021 -#define QMIUIM_WRITE_TRANSPARENT_REQ 0x0022 -#define QMIUIM_WRITE_TRANSPARENT_RESP 0x0022 -#define QMIUIM_WRITE_TRANSPARENT_IND 0x0022 -#define QMIUIM_WRITE_RECORD_REQ 0x0023 -#define QMIUIM_WRITE_RECORD_RESP 0x0023 -#define QMIUIM_WRITE_RECORD_IND 0x0023 -#define QMIUIM_SET_PIN_PROTECTION_REQ 0x0025 -#define QMIUIM_SET_PIN_PROTECTION_RESP 0x0025 -#define QMIUIM_SET_PIN_PROTECTION_IND 0x0025 -#define QMIUIM_VERIFY_PIN_REQ 0x0026 -#define QMIUIM_VERIFY_PIN_RESP 0x0026 -#define QMIUIM_VERIFY_PIN_IND 0x0026 -#define QMIUIM_UNBLOCK_PIN_REQ 0x0027 -#define QMIUIM_UNBLOCK_PIN_RESP 0x0027 -#define QMIUIM_UNBLOCK_PIN_IND 0x0027 -#define QMIUIM_CHANGE_PIN_REQ 0x0028 -#define QMIUIM_CHANGE_PIN_RESP 0x0028 -#define QMIUIM_CHANGE_PIN_IND 0x0028 -#define QMIUIM_DEPERSONALIZATION_REQ 0x0029 -#define QMIUIM_DEPERSONALIZATION_RESP 0x0029 -#define QMIUIM_EVENT_REG_REQ 0x002E -#define QMIUIM_EVENT_REG_RESP 0x002E -#define QMIUIM_GET_CARD_STATUS_REQ 0x002F -#define QMIUIM_GET_CARD_STATUS_RESP 0x002F -#define QMIUIM_STATUS_CHANGE_IND 0x0032 -#define QMIUIM_POWER_DOWN 0x0030 -#define QMIUIM_POWER_UP 0x0031 - - -typedef struct _QMIUIM_GET_CARD_STATUS_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} __attribute__ ((packed)) QMIUIM_GET_CARD_STATUS_RESP_MSG, *PQMIUIM_GET_CARD_STATUS_RESP_MSG; - -#define UIM_CARD_STATE_ABSENT 0x00 -#define UIM_CARD_STATE_PRESENT 0x01 -#define UIM_CARD_STATE_ERROR 0x02 - -typedef struct _QMIUIM_CARD_STATUS -{ - UCHAR TLVType; - USHORT TLVLength; - USHORT IndexGWPri; - USHORT Index1XPri; - USHORT IndexGWSec; - USHORT Index1XSec; - UCHAR NumSlot; - UCHAR CardState; - UCHAR UPINState; - UCHAR UPINRetries; - UCHAR UPUKRetries; - UCHAR ErrorCode; - UCHAR NumApp; - UCHAR AppType; - UCHAR AppState; - UCHAR PersoState; - UCHAR PersoFeature; - UCHAR PersoRetries; - UCHAR PersoUnblockRetries; - UCHAR AIDLength; -} __attribute__ ((packed)) QMIUIM_CARD_STATUS, *PQMIUIM_CARD_STATUS; - -typedef struct _QMIUIM_PIN_STATE -{ - UCHAR UnivPIN; - UCHAR PIN1State; - UCHAR PIN1Retries; - UCHAR PUK1Retries; - UCHAR PIN2State; - UCHAR PIN2Retries; - UCHAR PUK2Retries; -} __attribute__ ((packed)) QMIUIM_PIN_STATE, *PQMIUIM_PIN_STATE; - -typedef struct _QMIUIM_VERIFY_PIN_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR Session_Type; - UCHAR Aid_Len; - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR PINID; - UCHAR PINLen; - UCHAR PINValue; -} __attribute__ ((packed)) QMIUIM_VERIFY_PIN_REQ_MSG, *PQMIUIM_VERIFY_PIN_REQ_MSG; - -typedef struct _QMIUIM_VERIFY_PIN_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; - UCHAR TLV2Type; - USHORT TLV2Length; - UCHAR PINVerifyRetriesLeft; - UCHAR PINUnblockRetriesLeft; -} __attribute__ ((packed)) QMIUIM_VERIFY_PIN_RESP_MSG, *PQMIUIM_VERIFY_PIN_RESP_MSG; - -typedef struct _QMIUIM_READ_TRANSPARENT_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR Session_Type; - UCHAR Aid_Len; - UCHAR TLV2Type; - USHORT TLV2Length; - USHORT file_id; - UCHAR path_len; - UCHAR path[]; -} __attribute__ ((packed)) QMIUIM_READ_TRANSPARENT_REQ_MSG, *PQMIUIM_READ_TRANSPARENT_REQ_MSG; - -typedef struct _READ_TRANSPARENT_TLV -{ - UCHAR TLVType; - USHORT TLVLength; - USHORT Offset; - USHORT Length; -} __attribute__ ((packed)) READ_TRANSPARENT_TLV, *PREAD_TRANSPARENT_TLV; - -typedef struct _QMIUIM_CONTENT -{ - UCHAR TLVType; - USHORT TLVLength; - USHORT content_len; - UCHAR content[]; -} __attribute__ ((packed)) QMIUIM_CONTENT, *PQMIUIM_CONTENT; - -typedef struct _QMIUIM_READ_TRANSPARENT_RESP_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - USHORT QMUXResult; - USHORT QMUXError; -} __attribute__ ((packed)) QMIUIM_READ_TRANSPARENT_RESP_MSG, *PQMIUIM_READ_TRANSPARENT_RESP_MSG; - -typedef struct _QMIUIM_SET_CARD_SLOT_REQ_MSG -{ - USHORT Type; - USHORT Length; - UCHAR TLVType; - USHORT TLVLength; - UCHAR slot; -} __attribute__ ((packed)) QMIUIM_SET_CARD_SLOT_REQ_MSG, *PQMIUIM_SET_CARD_SLOT_REQ_MSG; - -// ======================= COEX ============================== -#define QMI_COEX_GET_WWAN_STATE_REQ 0x22 -#define QMI_COEX_GET_WWAN_STATE_RESP 0x22 - -typedef struct { - - uint32_t freq; - /**< Band center frequency in MHz. */ - - uint32_t bandwidth; - /**< Bandwidth in MHz. */ -}coex_band_type_v01; /* Type */ - -typedef struct _QMI_COEX_GET_WWAN_STATE_RESP_MSG_LTE_BAND -{ - UCHAR TLVType; - USHORT TLVLength; - coex_band_type_v01 ul_band; - coex_band_type_v01 dl_band; -} __attribute__ ((packed)) QMI_COEX_GET_WWAN_STATE_RESP_MSG_LTE_BAND, *PQMI_COEX_GET_WWAN_STATE_RESP_MSG_LTE_BAND; - - -typedef struct _QMUX_MSG -{ - QCQMUX_HDR QMUXHdr; - union - { - // Message Header - QCQMUX_MSG_HDR QMUXMsgHdr; - QCQMUX_MSG_HDR_RESP QMUXMsgHdrResp; - - // QMIWDS Message -#if 0 - QMIWDS_GET_PKT_SRVC_STATUS_REQ_MSG PacketServiceStatusReq; - QMIWDS_GET_PKT_SRVC_STATUS_RESP_MSG PacketServiceStatusRsp; - QMIWDS_GET_PKT_SRVC_STATUS_IND_MSG PacketServiceStatusInd; - QMIWDS_EVENT_REPORT_IND_MSG EventReportInd; - QMIWDS_GET_CURRENT_CHANNEL_RATE_REQ_MSG GetCurrChannelRateReq; - QMIWDS_GET_CURRENT_CHANNEL_RATE_RESP_MSG GetCurrChannelRateRsp; - QMIWDS_GET_PKT_STATISTICS_REQ_MSG GetPktStatsReq; - QMIWDS_GET_PKT_STATISTICS_RESP_MSG GetPktStatsRsp; - QMIWDS_SET_EVENT_REPORT_REQ_MSG EventReportReq; - QMIWDS_SET_EVENT_REPORT_RESP_MSG EventReportRsp; -#endif - //#ifdef QC_IP_MODE - QMIWDS_GET_RUNTIME_SETTINGS_REQ_MSG GetRuntimeSettingsReq; - QMIWDS_GET_RUNTIME_SETTINGS_RESP_MSG GetRuntimeSettingsRsp; - //#endif // QC_IP_MODE - QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ_MSG SetClientIpFamilyPrefReq; - QMIWDS_SET_CLIENT_IP_FAMILY_PREF_RESP_MSG SetClientIpFamilyPrefResp; - QMIWDS_SET_AUTO_CONNECT_REQ_MSG SetAutoConnectReq; -#if 0 - QMIWDS_GET_MIP_MODE_REQ_MSG GetMipModeReq; - QMIWDS_GET_MIP_MODE_RESP_MSG GetMipModeResp; -#endif - QMIWDS_START_NETWORK_INTERFACE_REQ_MSG StartNwInterfaceReq; - QMIWDS_START_NETWORK_INTERFACE_RESP_MSG StartNwInterfaceResp; - QMIWDS_STOP_NETWORK_INTERFACE_REQ_MSG StopNwInterfaceReq; - QMIWDS_STOP_NETWORK_INTERFACE_RESP_MSG StopNwInterfaceResp; - QMIWDS_GET_DEFAULT_SETTINGS_REQ_MSG GetDefaultSettingsReq; - QMIWDS_GET_DEFAULT_SETTINGS_RESP_MSG GetDefaultSettingsResp; - QMIWDS_MODIFY_PROFILE_SETTINGS_REQ_MSG ModifyProfileSettingsReq; - QMIWDS_MODIFY_PROFILE_SETTINGS_RESP_MSG ModifyProfileSettingsResp; - QMIWDS_GET_PROFILE_SETTINGS_REQ_MSG GetProfileSettingsReq; - QMIWDS_CREATE_PROFILE_SETTINGS_REQ_MSG CreatetProfileSettingsReq; - QMIWDS_GET_PROFILE_LIST_REQ_MSG GetProfileListReq; - QMIWDS_GET_PROFILE_LIST_RESP_MSG GetProfileListResp; -#if 0 - QMIWDS_GET_DATA_BEARER_REQ_MSG GetDataBearerReq; - QMIWDS_GET_DATA_BEARER_RESP_MSG GetDataBearerResp; - QMIWDS_DUN_CALL_INFO_REQ_MSG DunCallInfoReq; - QMIWDS_DUN_CALL_INFO_RESP_MSG DunCallInfoResp; -#endif - QMIWDS_BIND_MUX_DATA_PORT_REQ_MSG BindMuxDataPortReq; - - // QMIDMS Messages -#if 0 - QMIDMS_GET_DEVICE_MFR_REQ_MSG GetDeviceMfrReq; - QMIDMS_GET_DEVICE_MFR_RESP_MSG GetDeviceMfrRsp; - QMIDMS_GET_DEVICE_MODEL_ID_REQ_MSG GetDeviceModeIdReq; - QMIDMS_GET_DEVICE_MODEL_ID_RESP_MSG GetDeviceModeIdRsp; - QMIDMS_GET_DEVICE_REV_ID_REQ_MSG GetDeviceRevIdReq; - QMIDMS_GET_DEVICE_REV_ID_RESP_MSG GetDeviceRevIdRsp; - QMIDMS_GET_MSISDN_REQ_MSG GetMsisdnReq; - QMIDMS_GET_MSISDN_RESP_MSG GetMsisdnRsp; - QMIDMS_GET_DEVICE_SERIAL_NUMBERS_REQ_MSG GetDeviceSerialNumReq; - QMIDMS_GET_DEVICE_SERIAL_NUMBERS_RESP_MSG GetDeviceSerialNumRsp; - QMIDMS_GET_DEVICE_CAP_REQ_MSG GetDeviceCapReq; - QMIDMS_GET_DEVICE_CAP_RESP_MSG GetDeviceCapResp; - QMIDMS_GET_BAND_CAP_REQ_MSG GetBandCapReq; - QMIDMS_GET_BAND_CAP_RESP_MSG GetBandCapRsp; - QMIDMS_GET_ACTIVATED_STATUS_REQ_MSG GetActivatedStatusReq; - QMIDMS_GET_ACTIVATED_STATUS_RESP_MSG GetActivatedStatusResp; - QMIDMS_GET_OPERATING_MODE_REQ_MSG GetOperatingModeReq; - QMIDMS_GET_OPERATING_MODE_RESP_MSG GetOperatingModeResp; -#endif - QMIDMS_SET_OPERATING_MODE_REQ_MSG SetOperatingModeReq; - QMIDMS_SET_OPERATING_MODE_RESP_MSG SetOperatingModeResp; -#if 0 - QMIDMS_UIM_GET_ICCID_REQ_MSG GetICCIDReq; - QMIDMS_UIM_GET_ICCID_RESP_MSG GetICCIDResp; - QMIDMS_ACTIVATE_AUTOMATIC_REQ_MSG ActivateAutomaticReq; - QMIDMS_ACTIVATE_AUTOMATIC_RESP_MSG ActivateAutomaticResp; - QMIDMS_ACTIVATE_MANUAL_REQ_MSG ActivateManualReq; - QMIDMS_ACTIVATE_MANUAL_RESP_MSG ActivateManualResp; -#endif - QMIDMS_UIM_GET_PIN_STATUS_REQ_MSG UIMGetPinStatusReq; - QMIDMS_UIM_GET_PIN_STATUS_RESP_MSG UIMGetPinStatusResp; - QMIDMS_UIM_VERIFY_PIN_REQ_MSG UIMVerifyPinReq; - QMIDMS_UIM_VERIFY_PIN_RESP_MSG UIMVerifyPinResp; -#if 0 - QMIDMS_UIM_SET_PIN_PROTECTION_REQ_MSG UIMSetPinProtectionReq; - QMIDMS_UIM_SET_PIN_PROTECTION_RESP_MSG UIMSetPinProtectionResp; - QMIDMS_UIM_CHANGE_PIN_REQ_MSG UIMChangePinReq; - QMIDMS_UIM_CHANGE_PIN_RESP_MSG UIMChangePinResp; - QMIDMS_UIM_UNBLOCK_PIN_REQ_MSG UIMUnblockPinReq; - QMIDMS_UIM_UNBLOCK_PIN_RESP_MSG UIMUnblockPinResp; - QMIDMS_SET_EVENT_REPORT_REQ_MSG DmsSetEventReportReq; - QMIDMS_SET_EVENT_REPORT_RESP_MSG DmsSetEventReportResp; - QMIDMS_EVENT_REPORT_IND_MSG DmsEventReportInd; -#endif - QMIDMS_UIM_GET_STATE_REQ_MSG UIMGetStateReq; - QMIDMS_UIM_GET_STATE_RESP_MSG UIMGetStateResp; - QMIDMS_UIM_GET_IMSI_REQ_MSG UIMGetIMSIReq; - QMIDMS_UIM_GET_IMSI_RESP_MSG UIMGetIMSIResp; -#if 0 - QMIDMS_UIM_GET_CK_STATUS_REQ_MSG UIMGetCkStatusReq; - QMIDMS_UIM_GET_CK_STATUS_RESP_MSG UIMGetCkStatusResp; - QMIDMS_UIM_SET_CK_PROTECTION_REQ_MSG UIMSetCkProtectionReq; - QMIDMS_UIM_SET_CK_PROTECTION_RESP_MSG UIMSetCkProtectionResp; - QMIDMS_UIM_UNBLOCK_CK_REQ_MSG UIMUnblockCkReq; - QMIDMS_UIM_UNBLOCK_CK_RESP_MSG UIMUnblockCkResp; -#endif - - // QMIQOS Messages -#if 1 - QMI_QOS_SET_EVENT_REPORT_REQ_MSG QosSetEventReportReq; - QMI_QOS_SET_EVENT_REPORT_RESP_MSG QosSetEventReportRsp; - QMI_QOS_SET_EVENT_REPORT_IND_MSG QosSetEventReportInd; - QMI_QOS_BIND_DATA_PORT_REQ_MSG QosBindDataPortReq; - QMI_QOS_BIND_DATA_PORT_RESP_MSG QosBindDataPortRsp; - QMI_QOS_INDICATION_REGISTER_REQ_MSG QosIndRegReq; - QMI_QOS_INDICATION_REGISTER_RESP_MSG QosIndRegRsp; - QMI_QOS_GLOBAL_QOS_FLOW_IND_MSG QosGlobalQosFlowInd; - QMI_QOS_GET_QOS_INFO_REQ_MSG QosGetQosInfoReq; - QMI_QOS_GET_QOS_INFO_RESP_MSG QosGetQosInfoRsp; -#endif - - // QMIWMS Messages -#if 0 - QMIWMS_GET_MESSAGE_PROTOCOL_REQ_MSG GetMessageProtocolReq; - QMIWMS_GET_MESSAGE_PROTOCOL_RESP_MSG GetMessageProtocolResp; - QMIWMS_GET_SMSC_ADDRESS_REQ_MSG GetSMSCAddressReq; - QMIWMS_GET_SMSC_ADDRESS_RESP_MSG GetSMSCAddressResp; - QMIWMS_SET_SMSC_ADDRESS_REQ_MSG SetSMSCAddressReq; - QMIWMS_SET_SMSC_ADDRESS_RESP_MSG SetSMSCAddressResp; - QMIWMS_GET_STORE_MAX_SIZE_REQ_MSG GetStoreMaxSizeReq; - QMIWMS_GET_STORE_MAX_SIZE_RESP_MSG GetStoreMaxSizeResp; - QMIWMS_LIST_MESSAGES_REQ_MSG ListMessagesReq; - QMIWMS_LIST_MESSAGES_RESP_MSG ListMessagesResp; - QMIWMS_RAW_READ_REQ_MSG RawReadMessagesReq; - QMIWMS_RAW_READ_RESP_MSG RawReadMessagesResp; - QMIWMS_SET_EVENT_REPORT_REQ_MSG WmsSetEventReportReq; - QMIWMS_SET_EVENT_REPORT_RESP_MSG WmsSetEventReportResp; - QMIWMS_EVENT_REPORT_IND_MSG WmsEventReportInd; - QMIWMS_DELETE_REQ_MSG WmsDeleteReq; - QMIWMS_DELETE_RESP_MSG WmsDeleteResp; - QMIWMS_RAW_SEND_REQ_MSG RawSendMessagesReq; - QMIWMS_RAW_SEND_RESP_MSG RawSendMessagesResp; - QMIWMS_MODIFY_TAG_REQ_MSG WmsModifyTagReq; - QMIWMS_MODIFY_TAG_RESP_MSG WmsModifyTagResp; -#endif - - // QMINAS Messages -#if 0 - QMINAS_GET_HOME_NETWORK_REQ_MSG GetHomeNetworkReq; - QMINAS_GET_HOME_NETWORK_RESP_MSG GetHomeNetworkResp; - QMINAS_GET_PREFERRED_NETWORK_REQ_MSG GetPreferredNetworkReq; - QMINAS_GET_PREFERRED_NETWORK_RESP_MSG GetPreferredNetworkResp; - QMINAS_GET_FORBIDDEN_NETWORK_REQ_MSG GetForbiddenNetworkReq; - QMINAS_GET_FORBIDDEN_NETWORK_RESP_MSG GetForbiddenNetworkResp; - QMINAS_GET_SERVING_SYSTEM_REQ_MSG GetServingSystemReq; -#endif - QMINAS_GET_SERVING_SYSTEM_RESP_MSG GetServingSystemResp; - QMINAS_GET_SYS_INFO_RESP_MSG GetSysInfoResp; - QMINAS_SYS_INFO_IND_MSG NasSysInfoInd; -#if 0 - QMINAS_SERVING_SYSTEM_IND_MSG NasServingSystemInd; - QMINAS_SET_PREFERRED_NETWORK_REQ_MSG SetPreferredNetworkReq; - QMINAS_SET_PREFERRED_NETWORK_RESP_MSG SetPreferredNetworkResp; - QMINAS_SET_FORBIDDEN_NETWORK_REQ_MSG SetForbiddenNetworkReq; - QMINAS_SET_FORBIDDEN_NETWORK_RESP_MSG SetForbiddenNetworkResp; - QMINAS_PERFORM_NETWORK_SCAN_REQ_MSG PerformNetworkScanReq; - QMINAS_PERFORM_NETWORK_SCAN_RESP_MSG PerformNetworkScanResp; - QMINAS_INITIATE_NW_REGISTER_REQ_MSG InitiateNwRegisterReq; - QMINAS_INITIATE_NW_REGISTER_RESP_MSG InitiateNwRegisterResp; - QMINAS_SET_TECHNOLOGY_PREF_REQ_MSG SetTechnologyPrefReq; - QMINAS_SET_TECHNOLOGY_PREF_RESP_MSG SetTechnologyPrefResp; - QMINAS_GET_SIGNAL_STRENGTH_REQ_MSG GetSignalStrengthReq; - QMINAS_GET_SIGNAL_STRENGTH_RESP_MSG GetSignalStrengthResp; - QMINAS_SET_EVENT_REPORT_REQ_MSG SetEventReportReq; - QMINAS_SET_EVENT_REPORT_RESP_MSG SetEventReportResp; - QMINAS_EVENT_REPORT_IND_MSG NasEventReportInd; - QMINAS_GET_RF_BAND_INFO_REQ_MSG GetRFBandInfoReq; - QMINAS_GET_RF_BAND_INFO_RESP_MSG GetRFBandInfoResp; - QMINAS_INITIATE_ATTACH_REQ_MSG InitiateAttachReq; - QMINAS_INITIATE_ATTACH_RESP_MSG InitiateAttachResp; - QMINAS_GET_PLMN_NAME_REQ_MSG GetPLMNNameReq; - QMINAS_GET_PLMN_NAME_RESP_MSG GetPLMNNameResp; -#endif - - // QMIUIM Messages - QMIUIM_GET_CARD_STATUS_RESP_MSG UIMGetCardStatus; - QMIUIM_VERIFY_PIN_REQ_MSG UIMUIMVerifyPinReq; - QMIUIM_VERIFY_PIN_RESP_MSG UIMUIMVerifyPinResp; -#if 0 - QMIUIM_SET_PIN_PROTECTION_REQ_MSG UIMUIMSetPinProtectionReq; - QMIUIM_SET_PIN_PROTECTION_RESP_MSG UIMUIMSetPinProtectionResp; - QMIUIM_CHANGE_PIN_REQ_MSG UIMUIMChangePinReq; - QMIUIM_CHANGE_PIN_RESP_MSG UIMUIMChangePinResp; - QMIUIM_UNBLOCK_PIN_REQ_MSG UIMUIMUnblockPinReq; - QMIUIM_UNBLOCK_PIN_RESP_MSG UIMUIMUnblockPinResp; -#endif - QMIUIM_READ_TRANSPARENT_REQ_MSG UIMUIMReadTransparentReq; - QMIUIM_READ_TRANSPARENT_RESP_MSG UIMUIMReadTransparentResp; - QMIUIM_SET_CARD_SLOT_REQ_MSG UIMSetCardSlotReq; - - QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG SetDataFormatReq; - QMI_WDA_SET_LOOPBACK_CONFIG_REQ_MSG SetLoopBackReq; - QMI_WDA_SET_LOOPBACK_CONFIG_IND_MSG SetLoopBackInd; - }; -} __attribute__ ((packed)) QMUX_MSG, *PQMUX_MSG; - -typedef struct _QCQMIMSG { - QCQMI_HDR QMIHdr; - union { - QMICTL_MSG CTLMsg; - QMUX_MSG MUXMsg; - }; -} __attribute__ ((packed)) QCQMIMSG, *PQCQMIMSG; - -#pragma pack(pop) - -#endif // QCQMUX_H - +/****************************************************************************** + @file QCQMUX.h + + DESCRIPTION + This module contains QMI QMUX 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 QCQMUX_H +#define QCQMUX_H + +#include "QCQMI.h" + +#pragma pack(push, 1) + +#define QMIWDS_SET_EVENT_REPORT_REQ 0x0001 +#define QMIWDS_SET_EVENT_REPORT_RESP 0x0001 +#define QMIWDS_EVENT_REPORT_IND 0x0001 +#define QMIWDS_START_NETWORK_INTERFACE_REQ 0x0020 +#define QMIWDS_START_NETWORK_INTERFACE_RESP 0x0020 +#define QMIWDS_STOP_NETWORK_INTERFACE_REQ 0x0021 +#define QMIWDS_STOP_NETWORK_INTERFACE_RESP 0x0021 +#define QMIWDS_GET_PKT_SRVC_STATUS_REQ 0x0022 +#define QMIWDS_GET_PKT_SRVC_STATUS_RESP 0x0022 +#define QMIWDS_GET_PKT_SRVC_STATUS_IND 0x0022 +#define QMIWDS_GET_CURRENT_CHANNEL_RATE_REQ 0x0023 +#define QMIWDS_GET_CURRENT_CHANNEL_RATE_RESP 0x0023 +#define QMIWDS_GET_PKT_STATISTICS_REQ 0x0024 +#define QMIWDS_GET_PKT_STATISTICS_RESP 0x0024 +#define QMIWDS_CREATE_PROFILE_REQ 0x0027 +#define QMIWDS_CREATE_PROFILE_RESP 0x0027 +#define QMIWDS_MODIFY_PROFILE_SETTINGS_REQ 0x0028 +#define QMIWDS_MODIFY_PROFILE_SETTINGS_RESP 0x0028 +#define QMIWDS_GET_PROFILE_LIST_REQ 0x002A +#define QMIWDS_GET_PROFILE_LIST_RESP 0x002A +#define QMIWDS_GET_PROFILE_SETTINGS_REQ 0x002B +#define QMIWDS_GET_PROFILE_SETTINGS_RESP 0x002B +#define QMIWDS_GET_DEFAULT_SETTINGS_REQ 0x002C +#define QMIWDS_GET_DEFAULT_SETTINGS_RESP 0x002C +#define QMIWDS_GET_RUNTIME_SETTINGS_REQ 0x002D +#define QMIWDS_GET_RUNTIME_SETTINGS_RESP 0x002D +#define QMIWDS_GET_MIP_MODE_REQ 0x002F +#define QMIWDS_GET_MIP_MODE_RESP 0x002F +#define QMIWDS_GET_DATA_BEARER_REQ 0x0037 +#define QMIWDS_GET_DATA_BEARER_RESP 0x0037 +#define QMIWDS_DUN_CALL_INFO_REQ 0x0038 +#define QMIWDS_DUN_CALL_INFO_RESP 0x0038 +#define QMIWDS_DUN_CALL_INFO_IND 0x0038 +#define QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ 0x004D +#define QMIWDS_SET_CLIENT_IP_FAMILY_PREF_RESP 0x004D +#define QMIWDS_SET_AUTO_CONNECT_REQ 0x0051 +#define QMIWDS_SET_AUTO_CONNECT_RESP 0x0051 +#define QMIWDS_BIND_MUX_DATA_PORT_REQ 0x00A2 +#define QMIWDS_BIND_MUX_DATA_PORT_RESP 0x00A2 + + +// Stats masks +#define QWDS_STAT_MASK_TX_PKT_OK 0x00000001 +#define QWDS_STAT_MASK_RX_PKT_OK 0x00000002 +#define QWDS_STAT_MASK_TX_PKT_ER 0x00000004 +#define QWDS_STAT_MASK_RX_PKT_ER 0x00000008 +#define QWDS_STAT_MASK_TX_PKT_OF 0x00000010 +#define QWDS_STAT_MASK_RX_PKT_OF 0x00000020 + +// TLV Types for xfer statistics +#define TLV_WDS_TX_GOOD_PKTS 0x10 +#define TLV_WDS_RX_GOOD_PKTS 0x11 +#define TLV_WDS_TX_ERROR 0x12 +#define TLV_WDS_RX_ERROR 0x13 +#define TLV_WDS_TX_OVERFLOW 0x14 +#define TLV_WDS_RX_OVERFLOW 0x15 +#define TLV_WDS_CHANNEL_RATE 0x16 +#define TLV_WDS_DATA_BEARER 0x17 +#define TLV_WDS_DORMANCY_STATUS 0x18 + +#define QWDS_PKT_DATA_UNKNOW 0x00 +#define QWDS_PKT_DATA_DISCONNECTED 0x01 +#define QWDS_PKT_DATA_CONNECTED 0x02 +#define QWDS_PKT_DATA_SUSPENDED 0x03 +#define QWDS_PKT_DATA_AUTHENTICATING 0x04 + +#define QMIWDS_ADMIN_SET_DATA_FORMAT_REQ 0x0020 +#define QMIWDS_ADMIN_SET_DATA_FORMAT_RESP 0x0020 +#define QMIWDS_ADMIN_GET_DATA_FORMAT_REQ 0x0021 +#define QMIWDS_ADMIN_GET_DATA_FORMAT_RESP 0x0021 +#define QMIWDS_ADMIN_SET_QMAP_SETTINGS_REQ 0x002B +#define QMIWDS_ADMIN_SET_QMAP_SETTINGS_RESP 0x002B +#define QMIWDS_ADMIN_GET_QMAP_SETTINGS_REQ 0x002C +#define QMIWDS_ADMIN_GET_QMAP_SETTINGS_RESP 0x002C +#define QMI_WDA_SET_LOOPBACK_CONFIG_REQ 0x002F +#define QMI_WDA_SET_LOOPBACK_CONFIG_RESP 0x002F +#define QMI_WDA_SET_LOOPBACK_CONFIG_IND 0x002F + +#define NETWORK_DESC_ENCODING_OCTET 0x00 +#define NETWORK_DESC_ENCODING_EXTPROTOCOL 0x01 +#define NETWORK_DESC_ENCODING_7BITASCII 0x02 +#define NETWORK_DESC_ENCODING_IA5 0x03 +#define NETWORK_DESC_ENCODING_UNICODE 0x04 +#define NETWORK_DESC_ENCODING_SHIFTJIS 0x05 +#define NETWORK_DESC_ENCODING_KOREAN 0x06 +#define NETWORK_DESC_ENCODING_LATINH 0x07 +#define NETWORK_DESC_ENCODING_LATIN 0x08 +#define NETWORK_DESC_ENCODING_GSM7BIT 0x09 +#define NETWORK_DESC_ENCODING_GSMDATA 0x0A +#define NETWORK_DESC_ENCODING_UNKNOWN 0xFF + +typedef struct _QMIWDS_ADMIN_SET_DATA_FORMAT +{ + USHORT Type; // QMUX type 0x0000 + USHORT Length; +} __attribute__ ((packed)) QMIWDS_ADMIN_SET_DATA_FORMAT, *PQMIWDS_ADMIN_SET_DATA_FORMAT; + +typedef struct _QMIWDS_ADMIN_SET_DATA_FORMAT_TLV_QOS +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR QOSSetting; +} __attribute__ ((packed)) QMIWDS_ADMIN_SET_DATA_FORMAT_TLV_QOS, *PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV_QOS; + +typedef struct _QMIWDS_ADMIN_SET_DATA_FORMAT_TLV +{ + UCHAR TLVType; + USHORT TLVLength; + ULONG Value; +} __attribute__ ((packed)) QMIWDS_ADMIN_SET_DATA_FORMAT_TLV, *PQMIWDS_ADMIN_SET_DATA_FORMAT_TLV; + +typedef struct _QMIWDS_ENDPOINT_TLV +{ + UCHAR TLVType; + USHORT TLVLength; + ULONG ep_type; + ULONG iface_id; +} __attribute__ ((packed)) QMIWDS_ENDPOINT_TLV, *PQMIWDS_ENDPOINT_TLV; + +typedef struct _QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG +{ + USHORT Type; + USHORT Length; + QMIWDS_ADMIN_SET_DATA_FORMAT_TLV_QOS QosDataFormatTlv; + QMIWDS_ADMIN_SET_DATA_FORMAT_TLV UnderlyingLinkLayerProtocolTlv; + QMIWDS_ADMIN_SET_DATA_FORMAT_TLV UplinkDataAggregationProtocolTlv; + QMIWDS_ADMIN_SET_DATA_FORMAT_TLV DownlinkDataAggregationProtocolTlv; + QMIWDS_ADMIN_SET_DATA_FORMAT_TLV DownlinkDataAggregationMaxDatagramsTlv; + QMIWDS_ADMIN_SET_DATA_FORMAT_TLV DownlinkDataAggregationMaxSizeTlv; + QMIWDS_ENDPOINT_TLV epTlv; +#ifdef QUECTEL_UL_DATA_AGG + QMIWDS_ADMIN_SET_DATA_FORMAT_TLV DlMinimumPassingTlv; + QMIWDS_ADMIN_SET_DATA_FORMAT_TLV UplinkDataAggregationMaxDatagramsTlv; + QMIWDS_ADMIN_SET_DATA_FORMAT_TLV UplinkDataAggregationMaxSizeTlv; +#endif +} __attribute__ ((packed)) QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG, *PQMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG; + +typedef struct _QMI_U8_TLV +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR TLVVaule; +} __attribute__ ((packed)) QMI_U8_TLV, *PQMI_U8_TLV; + +typedef struct _QMI_U32_TLV +{ + UCHAR TLVType; + USHORT TLVLength; + ULONG TLVVaule; +} __attribute__ ((packed)) QMI_U32_TLV, *PQMI_U32_TLV; + +typedef struct _QMI_WDA_SET_LOOPBACK_CONFIG_REQ_MSG { + USHORT Type; + USHORT Length; + QMI_U8_TLV loopback_state; //0x01 + QMI_U32_TLV replication_factor; //0x10 +} __attribute__ ((packed)) QMI_WDA_SET_LOOPBACK_CONFIG_REQ_MSG, *PQMI_WDA_SET_LOOPBACK_CONFIG_REQ_MSG; + +typedef struct _QMI_WDA_SET_LOOPBACK_CONFIG_IND_MSG +{ + USHORT Type; + USHORT Length; + QMI_U8_TLV loopback_state; //0x01 + QMI_U32_TLV replication_factor; //0x10 +} __attribute__ ((packed)) QMI_WDA_SET_LOOPBACK_CONFIG_IND_MSG, *PQMI_WDA_SET_LOOPBACK_CONFIG_IND_MSG; + +#if 0 +typedef enum _QMI_RETURN_CODES { + QMI_SUCCESS = 0, + QMI_SUCCESS_NOT_COMPLETE, + QMI_FAILURE +}QMI_RETURN_CODES; + +typedef struct _QMIWDS_GET_PKT_SRVC_STATUS_REQ_MSG +{ + USHORT Type; // 0x0022 + USHORT Length; // 0x0000 +} QMIWDS_GET_PKT_SRVC_STATUS_REQ_MSG, *PQMIWDS_GET_PKT_SRVC_STATUS_REQ_MSG; + +typedef struct _QMIWDS_GET_PKT_SRVC_STATUS_RESP_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + USHORT QMUXResult; + USHORT QMUXError; + UCHAR TLVType2; + USHORT TLVLength2; + UCHAR ConnectionStatus; // 0x01: QWDS_PKT_DATAC_DISCONNECTED + // 0x02: QWDS_PKT_DATA_CONNECTED + // 0x03: QWDS_PKT_DATA_SUSPENDED + // 0x04: QWDS_PKT_DATA_AUTHENTICATING +} QMIWDS_GET_PKT_SRVC_STATUS_RESP_MSG, *PQMIWDS_GET_PKT_SRVC_STATUS_RESP_MSG; + +typedef struct _QMIWDS_GET_PKT_SRVC_STATUS_IND_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + UCHAR ConnectionStatus; // 0x01: QWDS_PKT_DATAC_DISCONNECTED + // 0x02: QWDS_PKT_DATA_CONNECTED + // 0x03: QWDS_PKT_DATA_SUSPENDED + UCHAR ReconfigRequired; // 0x00: No need to reconfigure + // 0x01: Reconfiguration required +} QMIWDS_GET_PKT_SRVC_STATUS_IND_MSG, *PQMIWDS_GET_PKT_SRVC_STATUS_IND_MSG; + +typedef struct _WDS_PKT_SRVC_IP_FAMILY_TLV +{ + UCHAR TLVType; // 0x12 + USHORT TLVLength; // 1 + UCHAR IpFamily; // IPV4-0x04, IPV6-0x06 +} WDS_PKT_SRVC_IP_FAMILY_TLV, *PWDS_PKT_SRVC_IP_FAMILY_TLV; + +typedef struct _QMIWDS_DUN_CALL_INFO_REQ_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + ULONG Mask; + UCHAR TLV2Type; + USHORT TLV2Length; + UCHAR ReportConnectionStatus; +} QMIWDS_DUN_CALL_INFO_REQ_MSG, *PQMIWDS_DUN_CALL_INFO_REQ_MSG; + +typedef struct _QMIWDS_DUN_CALL_INFO_RESP_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + USHORT QMUXResult; + USHORT QMUXError; +} QMIWDS_DUN_CALL_INFO_RESP_MSG, *PQMIWDS_DUN_CALL_INFO_RESP_MSG; + +typedef struct _QMIWDS_DUN_CALL_INFO_IND_MSG +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR ConnectionStatus; +} QMIWDS_DUN_CALL_INFO_IND_MSG, *PQMIWDS_DUN_CALL_INFO_IND_MSG; + +typedef struct _QMIWDS_GET_CURRENT_CHANNEL_RATE_REQ_MSG +{ + USHORT Type; // QMUX type 0x0040 + USHORT Length; +} QMIWDS_GET_CURRENT_CHANNEL_RATE_REQ_MSG, *PQMIWDS_GET_CURRENT_CHANNEL_RATE_REQ_MSG; + +typedef struct _QMIWDS_GET_CURRENT_CHANNEL_RATE_RESP_MSG +{ + USHORT Type; // QMUX type 0x0040 + USHORT Length; + UCHAR TLVType; // 0x02 + 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 + + UCHAR TLV2Type; // 0x01 + USHORT TLV2Length; // 16 + //ULONG CallHandle; // Context corresponding to reported channel + ULONG CurrentTxRate; // bps + ULONG CurrentRxRate; // bps + ULONG ServingSystemTxRate; // bps + ULONG ServingSystemRxRate; // bps + +} QMIWDS_GET_CURRENT_CHANNEL_RATE_RESP_MSG, *PQMIWDS_GET_CURRENT_CHANNEL_RATE_RESP; + +#define QWDS_EVENT_REPORT_MASK_RATES 0x01 +#define QWDS_EVENT_REPORT_MASK_STATS 0x02 + +#ifdef QCUSB_MUX_PROTOCOL +#error code not present +#endif // QCUSB_MUX_PROTOCOL + +typedef struct _QMIWDS_SET_EVENT_REPORT_REQ_MSG +{ + USHORT Type; // QMUX type 0x0042 + USHORT Length; + + UCHAR TLVType; // 0x10 -- current channel rate indicator + USHORT TLVLength; // 1 + UCHAR Mode; // 0-do not report; 1-report when rate changes + + UCHAR TLV2Type; // 0x11 + USHORT TLV2Length; // 5 + UCHAR StatsPeriod; // seconds between reports; 0-do not report + ULONG StatsMask; // + + UCHAR TLV3Type; // 0x12 -- current data bearer indicator + USHORT TLV3Length; // 1 + UCHAR Mode3; // 0-do not report; 1-report when changes + + UCHAR TLV4Type; // 0x13 -- dormancy status indicator + USHORT TLV4Length; // 1 + UCHAR DormancyStatus; // 0-do not report; 1-report when changes +} QMIWDS_SET_EVENT_REPORT_REQ_MSG, *PQMIWDS_SET_EVENT_REPORT_REQ_MSG; + +typedef struct _QMIWDS_SET_EVENT_REPORT_RESP_MSG +{ + USHORT Type; // QMUX type 0x0042 + 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_NO_BATTERY + // QMI_ERR_FAULT +} QMIWDS_SET_EVENT_REPORT_RESP_MSG, *PQMIWDS_SET_EVENT_REPORT_RESP_MSG; + +typedef struct _QMIWDS_EVENT_REPORT_IND_MSG +{ + USHORT Type; // QMUX type 0x0001 + USHORT Length; +} QMIWDS_EVENT_REPORT_IND_MSG, *PQMIWDS_EVENT_REPORT_IND_MSG; + +// PQCTLV_PKT_STATISTICS + +typedef struct _QMIWDS_EVENT_REPORT_IND_CHAN_RATE_TLV +{ + UCHAR Type; + USHORT Length; // 8 + ULONG TxRate; + ULONG RxRate; +} QMIWDS_EVENT_REPORT_IND_CHAN_RATE_TLV, *PQMIWDS_EVENT_REPORT_IND_CHAN_RATE_TLV; + +#ifdef QCUSB_MUX_PROTOCOL +#error code not present +#endif // QCUSB_MUX_PROTOCOL + +typedef struct _QMIWDS_GET_PKT_STATISTICS_REQ_MSG +{ + USHORT Type; // QMUX type 0x0041 + USHORT Length; + UCHAR TLVType; // 0x01 + USHORT TLVLength; // 4 + ULONG StateMask; // 0x00000001 tx success packets + // 0x00000002 rx success packets + // 0x00000004 rx packet errors (checksum) + // 0x00000008 rx packets dropped (memory) + +} QMIWDS_GET_PKT_STATISTICS_REQ_MSG, *PQMIWDS_GET_PKT_STATISTICS_REQ_MSG; + +typedef struct _QMIWDS_GET_PKT_STATISTICS_RESP_MSG +{ + USHORT Type; // QMUX type 0x0041 + USHORT Length; + UCHAR TLVType; // 0x02 + 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 +} QMIWDS_GET_PKT_STATISTICS_RESP_MSG, *PQMIWDS_GET_PKT_STATISTICS_RESP_MSG; + +// optional TLV for stats +typedef struct _QCTLV_PKT_STATISTICS +{ + UCHAR TLVType; // see above definitions for TLV types + USHORT TLVLength; // 4 + ULONG Count; +} QCTLV_PKT_STATISTICS, *PQCTLV_PKT_STATISTICS; +#endif + +//#ifdef QC_IP_MODE + +/* + �Bit 0 �Profile identifier + �Bit 1 �Profile name + �Bit 2 �PDP type + �Bit 3 �APN name + �Bit 4 �DNS address + �Bit 5 �UMTS/GPRS granted QoS + �Bit 6 �Username + �Bit 7 �Authentication Protocol + �Bit 8 �IP address + �Bit 9 �Gateway information (address and subnet mask) + �Bit 10 �PCSCF address using a PCO flag + �Bit 11 �PCSCF server address list + �Bit 12 �PCSCF domain name list + �Bit 13 �MTU + �Bit 14 �Domain name list + �Bit 15 �IP family + �Bit 16 �IM_CM flag + �Bit 17 �Technology name + �Bit 18 �Operator reserved PCO +*/ +#define QMIWDS_GET_RUNTIME_SETTINGS_MASK_IPV4DNS_ADDR (1 << 4) +#define QMIWDS_GET_RUNTIME_SETTINGS_MASK_IPV4_ADDR (1 << 8) +#define QMIWDS_GET_RUNTIME_SETTINGS_MASK_IPV4GATEWAY_ADDR (1 << 9) +#define QMIWDS_GET_RUNTIME_SETTINGS_MASK_MTU (1 << 13) +#define QMIWDS_GET_RUNTIME_SETTINGS_MASK_PCSCF_SV_ADDR (1 << 11) +#define QMIWDS_GET_RUNTIME_SETTINGS_MASK_PCSCF_DOM_NAME (1 << 14) + +typedef struct _QMIWDS_GET_RUNTIME_SETTINGS_REQ_MSG +{ + USHORT Type; // QMIWDS_GET_RUNTIME_SETTINGS_REQ + USHORT Length; + UCHAR TLVType; // 0x10 + USHORT TLVLength; // 0x0004 + ULONG Mask; // mask, bit 8: IP addr -- 0x0100 +} __attribute__ ((packed)) QMIWDS_GET_RUNTIME_SETTINGS_REQ_MSG, *PQMIWDS_GET_RUNTIME_SETTINGS_REQ_MSG; + +typedef struct _QMIWDS_BIND_MUX_DATA_PORT_REQ_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + ULONG ep_type; + ULONG iface_id; + UCHAR TLV2Type; + USHORT TLV2Length; + UCHAR MuxId; + UCHAR TLV3Type; + USHORT TLV3Length; + ULONG client_type; +} __attribute__ ((packed)) QMIWDS_BIND_MUX_DATA_PORT_REQ_MSG, *PQMIWDS_BIND_MUX_DATA_PORT_REQ_MSG; + +#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4PRIMARYDNS 0x15 +#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4SECONDARYDNS 0x16 +#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4 0x1E +#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4GATEWAY 0x20 +#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4SUBNET 0x21 + +#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6 0x25 +#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6GATEWAY 0x26 +#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6PRIMARYDNS 0x27 +#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6SECONDARYDNS 0x28 +#define QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_MTU 0x29 + +typedef struct _QMIWDS_GET_RUNTIME_SETTINGS_TLV_MTU +{ + UCHAR TLVType; // QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_MTU + USHORT TLVLength; // 4 + ULONG Mtu; // MTU +} __attribute__ ((packed)) QMIWDS_GET_RUNTIME_SETTINGS_TLV_MTU, *PQMIWDS_GET_RUNTIME_SETTINGS_TLV_MTU; + +typedef struct _QMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR +{ + UCHAR TLVType; // QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV4 + USHORT TLVLength; // 4 + ULONG IPV4Address; // address +} __attribute__ ((packed)) QMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR, *PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV4_ADDR; + +typedef struct _QMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_ADDR +{ + UCHAR TLVType; // QMIWDS_GET_RUNTIME_SETTINGS_TLV_TYPE_IPV6 + USHORT TLVLength; // 16 + UCHAR IPV6Address[16]; // address + UCHAR PrefixLength; // prefix length +} __attribute__ ((packed)) QMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_ADDR, *PQMIWDS_GET_RUNTIME_SETTINGS_TLV_IPV6_ADDR; + +typedef struct _QMIWDS_GET_RUNNING_SETTINGS_PCSCF_IPV6_ADDR +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR PCSCFNumber; +} __attribute__ ((packed)) QMIWDS_GET_RUNNING_SETTINGS_PCSCF_IPV6_ADDR, *PQMIWDS_GET_RUNNING_SETTINGS_PCSCF_IPV6_ADDR; + +typedef struct _QMIWDS_GET_RUNNING_SETTINGS_PCSCF_IPV4_ADDR +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR PCSCFNumber; +} __attribute__ ((packed)) QMIWDS_GET_RUNNING_SETTINGS_PCSCF_IPV4_ADDR, *PQMIWDS_GET_RUNNING_SETTINGS_PCSCF_IPV4_ADDR; + +typedef struct _QMIWDS_GET_RUNTIME_SETTINGS_RESP_MSG +{ + USHORT Type; // QMIWDS_GET_RUNTIME_SETTINGS_RESP + USHORT Length; + UCHAR TLVType; // QCTLV_TYPE_RESULT_CODE + USHORT TLVLength; // 0x0004 + USHORT QMUXResult; // result code + USHORT QMUXError; // error code +} __attribute__ ((packed)) QMIWDS_GET_RUNTIME_SETTINGS_RESP_MSG, *PQMIWDS_GET_RUNTIME_SETTINGS_RESP_MSG; + +//#endif // QC_IP_MODE + +typedef struct _QMIWDS_IP_FAMILY_TLV +{ + UCHAR TLVType; // 0x12 + USHORT TLVLength; // 1 + UCHAR IpFamily; // IPV4-0x04, IPV6-0x06 +} __attribute__ ((packed)) QMIWDS_IP_FAMILY_TLV, *PQMIWDS_IP_FAMILY_TLV; + +typedef struct _QMIWDS_PKT_SRVC_TLV +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR ConnectionStatus; + UCHAR ReconfigReqd; +} __attribute__ ((packed)) QMIWDS_PKT_SRVC_TLV, *PQMIWDS_PKT_SRVC_TLV; + +typedef struct _QMIWDS_CALL_END_REASON_TLV +{ + UCHAR TLVType; + USHORT TLVLength; + USHORT CallEndReason; +} __attribute__ ((packed)) QMIWDS_CALL_END_REASON_TLV, *PQMIWDS_CALL_END_REASON_TLV; + +typedef struct _QMIWDS_CALL_END_REASON_V_TLV +{ + UCHAR TLVType; + USHORT TLVLength; + USHORT CallEndReasonType; + USHORT CallEndReason; +} __attribute__ ((packed)) QMIWDS_CALL_END_REASON_V_TLV, *PQMIWDS_CALL_END_REASON_V_TLV; + +typedef struct _QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ_MSG +{ + USHORT Type; // QMUX type 0x004D + USHORT Length; + UCHAR TLVType; // 0x01 + USHORT TLVLength; // 1 + UCHAR IpPreference; // IPV4-0x04, IPV6-0x06 +} __attribute__ ((packed)) QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ_MSG, *PQMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ_MSG; + +typedef struct _QMIWDS_SET_CLIENT_IP_FAMILY_PREF_RESP_MSG +{ + USHORT Type; // QMUX type 0x0037 + USHORT Length; + UCHAR TLVType; // 0x02 + USHORT TLVLength; // 4 + USHORT QMUXResult; // QMI_RESULT_SUCCESS, QMI_RESULT_FAILURE + USHORT QMUXError; // QMI_ERR_INTERNAL, QMI_ERR_MALFORMED_MSG, QMI_ERR_INVALID_ARG +} __attribute__ ((packed)) QMIWDS_SET_CLIENT_IP_FAMILY_PREF_RESP_MSG, *PQMIWDS_SET_CLIENT_IP_FAMILY_PREF_RESP_MSG; + +typedef struct _QMIWDS_SET_AUTO_CONNECT_REQ_MSG +{ + USHORT Type; // QMUX type 0x0051 + USHORT Length; + UCHAR TLVType; // 0x01 + USHORT TLVLength; // 1 + UCHAR autoconnect_setting; // 0x00 ?C Disabled, 0x01 ?C Enabled, 0x02 ?C Paused (resume on power cycle) +} __attribute__ ((packed)) QMIWDS_SET_AUTO_CONNECT_REQ_MSG, *PQMIWDS_SET_AUTO_CONNECT_REQ_MSG; + +#if 0 +typedef struct _QMIWDS_GET_MIP_MODE_REQ_MSG +{ + USHORT Type; // QMUX type 0x0040 + USHORT Length; +} QMIWDS_GET_MIP_MODE_REQ_MSG, *PQMIWDS_GET_MIP_MODE_REQ_MSG; + +typedef struct _QMIWDS_GET_MIP_MODE_RESP_MSG +{ + USHORT Type; // QMUX type 0x0040 + USHORT Length; + UCHAR TLVType; // 0x02 + 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 + + UCHAR TLV2Type; // 0x01 + USHORT TLV2Length; // 20 + UCHAR MipMode; // +} QMIWDS_GET_MIP_MODE_RESP_MSG, *PQMIWDS_GET_MIP_MODE_RESP_MSG; +#endif + +typedef struct _QMIWDS_TECHNOLOGY_PREFERECE +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR TechPreference; +} __attribute__ ((packed)) QMIWDS_TECHNOLOGY_PREFERECE, *PQMIWDS_TECHNOLOGY_PREFERECE; + +typedef struct _QMIWDS_PROFILE_IDENTIFIER +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR ProfileIndex; +} __attribute__ ((packed)) QMIWDS_PROFILE_IDENTIFIER, *PQMIWDS_PROFILE_IDENTIFIER; + +#if 0 +typedef struct _QMIWDS_IPADDRESS +{ + UCHAR TLVType; + USHORT TLVLength; + ULONG IPv4Address; +}QMIWDS_IPADDRESS, *PQMIWDS_IPADDRESS; + +/* +typedef struct _QMIWDS_UMTS_QOS +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR TrafficClass; + ULONG MaxUplinkBitRate; + ULONG MaxDownlinkBitRate; + ULONG GuarUplinkBitRate; + ULONG GuarDownlinkBitRate; + UCHAR QOSDevOrder; + ULONG MAXSDUSize; + UCHAR SDUErrorRatio; + UCHAR ResidualBerRatio; + UCHAR DeliveryErrorSDUs; + ULONG TransferDelay; + ULONG TrafficHndPri; +}QMIWDS_UMTS_QOS, *PQMIWDS_UMTS_QOS; + +typedef struct _QMIWDS_GPRS_QOS +{ + UCHAR TLVType; + USHORT TLVLength; + ULONG PrecedenceClass; + ULONG DelayClass; + ULONG ReliabilityClass; + ULONG PeekThroClass; + ULONG MeanThroClass; +}QMIWDS_GPRS_QOS, *PQMIWDS_GPRS_QOS; +*/ +#endif + +typedef struct _QMIWDS_PDPCONTEXT +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR pdp_context; +} __attribute__ ((packed)) QMIWDS_PDPCONTEXT, *PQMIWDS_PDPCONTEXT; + +typedef struct _QMIWDS_PROFILELIST +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR ProfileList[1024]; +} __attribute__ ((packed)) QMIWDS_PROFILELIST, *PQMIWDS_PROFILELIST; + +typedef struct _QMIWDS_PROFILENAME +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR ProfileName; +} __attribute__ ((packed)) QMIWDS_PROFILENAME, *PQMIWDS_PROFILENAME; + +typedef struct _QMIWDS_PDPTYPE +{ + UCHAR TLVType; + USHORT TLVLength; +// 0 ?C PDP-IP (IPv4) +// 1 ?C PDP-PPP +// 2 ?C PDP-IPv6 +// 3 ?C PDP-IPv4v6 + UCHAR PdpType; +} __attribute__ ((packed)) QMIWDS_PDPTYPE, *PQMIWDS_PDPTYPE; + +typedef struct _QMIWDS_USERNAME +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR UserName; +} __attribute__ ((packed)) QMIWDS_USERNAME, *PQMIWDS_USERNAME; + +typedef struct _QMIWDS_PASSWD +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR Passwd; +} __attribute__ ((packed)) QMIWDS_PASSWD, *PQMIWDS_PASSWD; + +typedef struct _QMIWDS_AUTH_PREFERENCE +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR AuthPreference; +} __attribute__ ((packed)) QMIWDS_AUTH_PREFERENCE, *PQMIWDS_AUTH_PREFERENCE; + +typedef struct _QMIWDS_IPTYPE +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR IPType; +} __attribute__ ((packed)) QMIWDS_IPTYPE, *PQMIWDS_IPTYPE; + +typedef struct _QMIWDS_APNNAME +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR ApnName; +} __attribute__ ((packed)) QMIWDS_APNNAME, *PQMIWDS_APNNAME; + +typedef struct _QMIWDS_AUTOCONNECT +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR AutoConnect; +} __attribute__ ((packed)) QMIWDS_AUTOCONNECT, *PQMIWDS_AUTOCONNECT; + +typedef struct _QMIWDS_START_NETWORK_INTERFACE_REQ_MSG +{ + USHORT Type; + USHORT Length; +} __attribute__ ((packed)) QMIWDS_START_NETWORK_INTERFACE_REQ_MSG, *PQMIWDS_START_NETWORK_INTERFACE_REQ_MSG; + +typedef struct _QMIWDS_CALLENDREASON +{ + UCHAR TLVType; + USHORT TLVLength; + USHORT Reason; +}__attribute__ ((packed)) QMIWDS_CALLENDREASON, *PQMIWDS_CALLENDREASON; + +typedef struct _QMIWDS_START_NETWORK_INTERFACE_RESP_MSG +{ + USHORT Type; // QMUX type 0x0040 + USHORT Length; + UCHAR TLVType; // 0x02 + 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 + + UCHAR TLV2Type; // 0x01 + USHORT TLV2Length; // 20 + ULONG Handle; // +} __attribute__ ((packed)) QMIWDS_START_NETWORK_INTERFACE_RESP_MSG, *PQMIWDS_START_NETWORK_INTERFACE_RESP_MSG; + +typedef struct _QMIWDS_STOP_NETWORK_INTERFACE_REQ_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + ULONG Handle; +} __attribute__ ((packed)) QMIWDS_STOP_NETWORK_INTERFACE_REQ_MSG, *PQMIWDS_STOP_NETWORK_INTERFACE_REQ_MSG; + +typedef struct _QMIWDS_STOP_NETWORK_INTERFACE_RESP_MSG +{ + USHORT Type; // QMUX type 0x0040 + USHORT Length; + UCHAR TLVType; // 0x02 + 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)) QMIWDS_STOP_NETWORK_INTERFACE_RESP_MSG, *PQMIWDS_STOP_NETWORK_INTERFACE_RESP_MSG; + +typedef struct _QMIWDS_GET_DEFAULT_SETTINGS_REQ_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + UCHAR ProfileType; +} __attribute__ ((packed)) QMIWDS_GET_DEFAULT_SETTINGS_REQ_MSG, *PQMIWDS_GET_DEFAULT_SETTINGS_REQ_MSG; + +typedef struct _QMIWDS_GET_DEFAULT_SETTINGS_RESP_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + USHORT QMUXResult; + USHORT QMUXError; +} __attribute__ ((packed)) QMIWDS_GET_DEFAULT_SETTINGS_RESP_MSG, *PQMIWDS_GET_DEFAULT_SETTINGS_RESP_MSG; + +typedef struct _QMIWDS_MODIFY_PROFILE_SETTINGS_REQ_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + UCHAR ProfileType; + UCHAR ProfileIndex; +} __attribute__ ((packed)) QMIWDS_MODIFY_PROFILE_SETTINGS_REQ_MSG, *PQMIWDS_MODIFY_PROFILE_SETTINGS_REQ_MSG; + +typedef struct _QMIWDS_MODIFY_PROFILE_SETTINGS_RESP_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + USHORT QMUXResult; + USHORT QMUXError; +} __attribute__ ((packed)) QMIWDS_MODIFY_PROFILE_SETTINGS_RESP_MSG, *PQMIWDS_MODIFY_PROFILE_SETTINGS_RESP_MSG; + +typedef struct _QMIWDS_GET_PROFILE_SETTINGS_REQ_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + UCHAR ProfileType; + UCHAR ProfileIndex; +} __attribute__ ((packed)) QMIWDS_GET_PROFILE_SETTINGS_REQ_MSG, *PQMIWDS_GET_PROFILE_SETTINGS_REQ_MSG; + +typedef struct _QMIWDS_CREATE_PROFILE_SETTINGS_REQ_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + UCHAR ProfileType; + UCHAR TLV2Type; //0x25 + USHORT TLV2Length; + UCHAR pdp_context; +} __attribute__ ((packed)) QMIWDS_CREATE_PROFILE_SETTINGS_REQ_MSG, *PQMIWDS_CREATE_PROFILE_SETTINGS_REQ_MSG; + +typedef struct _QMIWDS_GET_PROFILE_LIST_REQ_MSG +{ + USHORT Type; + USHORT Length; +} __attribute__ ((packed)) QMIWDS_GET_PROFILE_LIST_REQ_MSG, *PQMIWDS_GET_PROFILE_LIST_REQ_MSG; + +typedef struct _QMIWDS_GET_PROFILE_LIST_RESP_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + UCHAR ProfileList[1024]; +} __attribute__ ((packed)) QMIWDS_GET_PROFILE_LIST_RESP_MSG, *PQMIWDS_GET_PROFILE_LIST_RESP_MSG; + +#if 0 +typedef struct _QMIWDS_EVENT_REPORT_IND_DATA_BEARER_TLV +{ + UCHAR Type; + USHORT Length; + UCHAR DataBearer; +} QMIWDS_EVENT_REPORT_IND_DATA_BEARER_TLV, *PQMIWDS_EVENT_REPORT_IND_DATA_BEARER_TLV; + +typedef struct _QMIWDS_EVENT_REPORT_IND_DORMANCY_STATUS_TLV +{ + UCHAR Type; + USHORT Length; + UCHAR DormancyStatus; +} QMIWDS_EVENT_REPORT_IND_DORMANCY_STATUS_TLV, *PQMIWDS_EVENT_REPORT_IND_DORMANCY_STATUS_TLV; + + +typedef struct _QMIWDS_GET_DATA_BEARER_REQ_MSG +{ + USHORT Type; // QMUX type 0x0037 + USHORT Length; +} QMIWDS_GET_DATA_BEARER_REQ_MSG, *PQMIWDS_GET_DATA_BEARER_REQ_MSG; + +typedef struct _QMIWDS_GET_DATA_BEARER_RESP_MSG +{ + USHORT Type; // QMUX type 0x0037 + USHORT Length; + UCHAR TLVType; // 0x02 + USHORT TLVLength; // 4 + USHORT QMUXResult; // QMI_RESULT_SUCCESS + // QMI_RESULT_FAILURE + USHORT QMUXError; // QMI_ERR_INTERNAL + // QMI_ERR_MALFORMED_MSG + // QMI_ERR_NO_MEMORY + // QMI_ERR_OUT_OF_CALL + // QMI_ERR_INFO_UNAVAILABLE + UCHAR TLV2Type; // 0x01 + USHORT TLV2Length; // + UCHAR Technology; // +} QMIWDS_GET_DATA_BEARER_RESP_MSG, *PQMIWDS_GET_DATA_BEARER_RESP_MSG; +#endif + +// ======================= DMS ============================== +#define QMIDMS_SET_EVENT_REPORT_REQ 0x0001 +#define QMIDMS_SET_EVENT_REPORT_RESP 0x0001 +#define QMIDMS_EVENT_REPORT_IND 0x0001 +#define QMIDMS_GET_DEVICE_CAP_REQ 0x0020 +#define QMIDMS_GET_DEVICE_CAP_RESP 0x0020 +#define QMIDMS_GET_DEVICE_MFR_REQ 0x0021 +#define QMIDMS_GET_DEVICE_MFR_RESP 0x0021 +#define QMIDMS_GET_DEVICE_MODEL_ID_REQ 0x0022 +#define QMIDMS_GET_DEVICE_MODEL_ID_RESP 0x0022 +#define QMIDMS_GET_DEVICE_REV_ID_REQ 0x0023 +#define QMIDMS_GET_DEVICE_REV_ID_RESP 0x0023 +#define QMIDMS_GET_MSISDN_REQ 0x0024 +#define QMIDMS_GET_MSISDN_RESP 0x0024 +#define QMIDMS_GET_DEVICE_SERIAL_NUMBERS_REQ 0x0025 +#define QMIDMS_GET_DEVICE_SERIAL_NUMBERS_RESP 0x0025 +#define QMIDMS_UIM_SET_PIN_PROTECTION_REQ 0x0027 +#define QMIDMS_UIM_SET_PIN_PROTECTION_RESP 0x0027 +#define QMIDMS_UIM_VERIFY_PIN_REQ 0x0028 +#define QMIDMS_UIM_VERIFY_PIN_RESP 0x0028 +#define QMIDMS_UIM_UNBLOCK_PIN_REQ 0x0029 +#define QMIDMS_UIM_UNBLOCK_PIN_RESP 0x0029 +#define QMIDMS_UIM_CHANGE_PIN_REQ 0x002A +#define QMIDMS_UIM_CHANGE_PIN_RESP 0x002A +#define QMIDMS_UIM_GET_PIN_STATUS_REQ 0x002B +#define QMIDMS_UIM_GET_PIN_STATUS_RESP 0x002B +#define QMIDMS_GET_DEVICE_HARDWARE_REV_REQ 0x002C +#define QMIDMS_GET_DEVICE_HARDWARE_REV_RESP 0x002C +#define QMIDMS_GET_OPERATING_MODE_REQ 0x002D +#define QMIDMS_GET_OPERATING_MODE_RESP 0x002D +#define QMIDMS_SET_OPERATING_MODE_REQ 0x002E +#define QMIDMS_SET_OPERATING_MODE_RESP 0x002E +#define QMIDMS_GET_ACTIVATED_STATUS_REQ 0x0031 +#define QMIDMS_GET_ACTIVATED_STATUS_RESP 0x0031 +#define QMIDMS_ACTIVATE_AUTOMATIC_REQ 0x0032 +#define QMIDMS_ACTIVATE_AUTOMATIC_RESP 0x0032 +#define QMIDMS_ACTIVATE_MANUAL_REQ 0x0033 +#define QMIDMS_ACTIVATE_MANUAL_RESP 0x0033 +#define QMIDMS_UIM_GET_ICCID_REQ 0x003C +#define QMIDMS_UIM_GET_ICCID_RESP 0x003C +#define QMIDMS_UIM_GET_CK_STATUS_REQ 0x0040 +#define QMIDMS_UIM_GET_CK_STATUS_RESP 0x0040 +#define QMIDMS_UIM_SET_CK_PROTECTION_REQ 0x0041 +#define QMIDMS_UIM_SET_CK_PROTECTION_RESP 0x0041 +#define QMIDMS_UIM_UNBLOCK_CK_REQ 0x0042 +#define QMIDMS_UIM_UNBLOCK_CK_RESP 0x0042 +#define QMIDMS_UIM_GET_IMSI_REQ 0x0043 +#define QMIDMS_UIM_GET_IMSI_RESP 0x0043 +#define QMIDMS_UIM_GET_STATE_REQ 0x0044 +#define QMIDMS_UIM_GET_STATE_RESP 0x0044 +#define QMIDMS_GET_BAND_CAP_REQ 0x0045 +#define QMIDMS_GET_BAND_CAP_RESP 0x0045 + +#if 0 +typedef struct _QMIDMS_GET_DEVICE_MFR_REQ_MSG +{ + USHORT Type; // QMUX type 0x0003 + USHORT Length; +} QMIDMS_GET_DEVICE_MFR_REQ_MSG, *PQMIDMS_GET_DEVICE_MFR_REQ_MSG; + +typedef struct _QMIDMS_GET_DEVICE_MFR_RESP_MSG +{ + USHORT Type; // QMUX type 0x0003 + 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 + UCHAR TLV2Type; // 0x01 - required parameter + USHORT TLV2Length; // length of the mfr string + UCHAR DeviceManufacturer; // first byte of string +} QMIDMS_GET_DEVICE_MFR_RESP_MSG, *PQMIDMS_GET_DEVICE_MFR_RESP_MSG; + +typedef struct _QMIDMS_GET_DEVICE_MODEL_ID_REQ_MSG +{ + USHORT Type; // QMUX type 0x0004 + USHORT Length; +} QMIDMS_GET_DEVICE_MODEL_ID_REQ_MSG, *PQMIDMS_GET_DEVICE_MODEL_ID_REQ_MSG; + +typedef struct _QMIDMS_GET_DEVICE_MODEL_ID_RESP_MSG +{ + USHORT Type; // QMUX type 0x0004 + 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 + UCHAR TLV2Type; // 0x01 - required parameter + USHORT TLV2Length; // length of the modem id string + UCHAR DeviceModelID; // device model id +} QMIDMS_GET_DEVICE_MODEL_ID_RESP_MSG, *PQMIDMS_GET_DEVICE_MODEL_ID_RESP_MSG; +#endif + +typedef struct _QMIDMS_GET_DEVICE_REV_ID_REQ_MSG +{ + USHORT Type; // QMUX type 0x0005 + USHORT Length; +} __attribute__ ((packed)) QMIDMS_GET_DEVICE_REV_ID_REQ_MSG, *PQMIDMS_GET_DEVICE_REV_ID_REQ_MSG; + +typedef struct _DEVICE_REV_ID +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR RevisionID; +} __attribute__ ((packed)) DEVICE_REV_ID, *PDEVICE_REV_ID; + +#if 0 +typedef struct _QMIDMS_GET_DEVICE_REV_ID_RESP_MSG +{ + USHORT Type; // QMUX type 0x0023 + 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 +} QMIDMS_GET_DEVICE_REV_ID_RESP_MSG, *PQMIDMS_GET_DEVICE_REV_ID_RESP_MSG; + +typedef struct _QMIDMS_GET_MSISDN_REQ_MSG +{ + USHORT Type; // QMUX type 0x0024 + USHORT Length; +} QMIDMS_GET_MSISDN_REQ_MSG, *PQMIDMS_GET_MSISDN_REQ_MSG; + +typedef struct _QCTLV_DEVICE_VOICE_NUMBERS +{ + UCHAR TLVType; // as defined above + USHORT TLVLength; // 4/7/7 + UCHAR VoideNumberString; // ESN, IMEI, or MEID + +} QCTLV_DEVICE_VOICE_NUMBERS, *PQCTLV_DEVICE_VOICE_NUMBERS; + + +typedef struct _QMIDMS_GET_MSISDN_RESP_MSG +{ + USHORT Type; // QMUX type 0x0024 + USHORT Length; + UCHAR TLVType; // 0x02 - result code + USHORT TLVLength; // 4 + USHORT QMUXResult; // QMI_RESULT_SUCCESS + // QMI_RESULT_FAILURE + USHORT QMUXError; // QMI_ERR_INVALID_ARG +} QMIDMS_GET_MSISDN_RESP_MSG, *PQMIDMS_GET_MSISDN_RESP_MSG; +#endif + +typedef struct _QMIDMS_UIM_GET_IMSI_REQ_MSG +{ + USHORT Type; + USHORT Length; +} __attribute__ ((packed)) QMIDMS_UIM_GET_IMSI_REQ_MSG, *PQMIDMS_UIM_GET_IMSI_REQ_MSG; + +typedef struct _QMIDMS_UIM_GET_IMSI_RESP_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + USHORT QMUXResult; + USHORT QMUXError; + UCHAR TLV2Type; + USHORT TLV2Length; + UCHAR IMSI; +} __attribute__ ((packed)) QMIDMS_UIM_GET_IMSI_RESP_MSG, *PQMIDMS_UIM_GET_IMSI_RESP_MSG; + +#if 0 +typedef struct _QMIDMS_GET_DEVICE_SERIAL_NUMBERS_REQ_MSG +{ + USHORT Type; // QMUX type 0x0007 + USHORT Length; +} QMIDMS_GET_DEVICE_SERIAL_NUMBERS_REQ_MSG, *PQMIDMS_GET_DEVICE_SERIAL_NUMBERS_REQ_MSG; + +#define QCTLV_TYPE_SER_NUM_ESN 0x10 +#define QCTLV_TYPE_SER_NUM_IMEI 0x11 +#define QCTLV_TYPE_SER_NUM_MEID 0x12 + +typedef struct _QCTLV_DEVICE_SERIAL_NUMBER +{ + UCHAR TLVType; // as defined above + USHORT TLVLength; // 4/7/7 + UCHAR SerialNumberString; // ESN, IMEI, or MEID + +} QCTLV_DEVICE_SERIAL_NUMBER, *PQCTLV_DEVICE_SERIAL_NUMBER; + +typedef struct _QMIDMS_GET_DEVICE_SERIAL_NUMBERS_RESP_MSG +{ + USHORT Type; // QMUX type 0x0007 + 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 + // followed by optional TLV +} QMIDMS_GET_DEVICE_SERIAL_NUMBERS_RESP_MSG, *PQMIDMS_GET_DEVICE_SERIAL_NUMBERS_RESP; + +typedef struct _QMIDMS_GET_DMS_BAND_CAP +{ + USHORT Type; + USHORT Length; +} QMIDMS_GET_BAND_CAP_REQ_MSG, *PQMIDMS_GET_BAND_CAP_REQ_MSG; + +typedef struct _QMIDMS_GET_BAND_CAP_RESP_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; // 0x02 - result code + USHORT TLVLength; // 4 + USHORT QMUXResult; // QMI_RESULT_SUCCESS + // QMI_RESULT_FAILURE + USHORT QMUXError; // QMI_ERR_NONE + // QMI_ERR_INTERNAL + // QMI_ERR_MALFORMED_MSG + // QMI_ERR_NO_MEMORY + + UCHAR TLV2Type; // 0x01 + USHORT TLV2Length; // 2 + ULONG64 BandCap; +} QMIDMS_GET_BAND_CAP_RESP_MSG, *PQMIDMS_GET_BAND_CAP_RESP; + +typedef struct _QMIDMS_GET_DEVICE_CAP_REQ_MSG +{ + USHORT Type; // QMUX type 0x0002 + USHORT Length; +} QMIDMS_GET_DEVICE_CAP_REQ_MSG, *PQMIDMS_GET_DEVICE_CAP_REQ_MSG; + +typedef struct _QMIDMS_GET_DEVICE_CAP_RESP_MSG +{ + USHORT Type; // QMUX type 0x0002 + USHORT Length; + UCHAR TLVType; // 0x02 - result code + USHORT TLVLength; // 4 + USHORT QMUXResult; // QMUX_RESULT_SUCCESS + // QMUX_RESULT_FAILURE + USHORT QMUXError; // QMUX_ERR_INVALID_ARG + // QMUX_ERR_NO_MEMORY + // QMUX_ERR_INTERNAL + // QMUX_ERR_FAULT + UCHAR TLV2Type; // 0x01 + USHORT TLV2Length; // 2 + + ULONG MaxTxChannelRate; + ULONG MaxRxChannelRate; + UCHAR VoiceCap; + UCHAR SimCap; + + UCHAR RadioIfListCnt; // #elements in radio interface list + UCHAR RadioIfList; // N 1-byte elements +} QMIDMS_GET_DEVICE_CAP_RESP_MSG, *PQMIDMS_GET_DEVICE_CAP_RESP_MSG; + +typedef struct _QMIDMS_GET_ACTIVATED_STATUS_REQ_MSG +{ + USHORT Type; // QMUX type 0x0002 + USHORT Length; +} QMIDMS_GET_ACTIVATED_STATUS_REQ_MSG, *PQMIDMS_GET_ACTIVATES_STATUD_REQ_MSG; + +typedef struct _QMIDMS_GET_ACTIVATED_STATUS_RESP_MSG +{ + USHORT Type; // QMUX type 0x0002 + USHORT Length; + UCHAR TLVType; // 0x02 - result code + USHORT TLVLength; // 4 + USHORT QMUXResult; // QMUX_RESULT_SUCCESS + // QMUX_RESULT_FAILURE + USHORT QMUXError; // QMUX_ERR_INVALID_ARG + // QMUX_ERR_NO_MEMORY + // QMUX_ERR_INTERNAL + // QMUX_ERR_FAULT + UCHAR TLV2Type; // 0x01 + USHORT TLV2Length; // 2 + + USHORT ActivatedStatus; +} QMIDMS_GET_ACTIVATED_STATUS_RESP_MSG, *PQMIDMS_GET_ACTIVATED_STATUS_RESP_MSG; + +typedef struct _QMIDMS_GET_OPERATING_MODE_REQ_MSG +{ + USHORT Type; // QMUX type 0x0002 + USHORT Length; +} QMIDMS_GET_OPERATING_MODE_REQ_MSG, *PQMIDMS_GET_OPERATING_MODE_REQ_MSG; + +typedef struct _OFFLINE_REASON +{ + UCHAR TLVType; + USHORT TLVLength; + USHORT OfflineReason; +} OFFLINE_REASON, *POFFLINE_REASON; + +typedef struct _HARDWARE_RESTRICTED_MODE +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR HardwareControlledMode; +} HARDWARE_RESTRICTED_MODE, *PHARDWARE_RESTRICTED_MODE; + +typedef struct _QMIDMS_GET_OPERATING_MODE_RESP_MSG +{ + USHORT Type; // QMUX type 0x0002 + USHORT Length; + UCHAR TLVType; // 0x02 - result code + USHORT TLVLength; // 4 + USHORT QMUXResult; // QMUX_RESULT_SUCCESS + // QMUX_RESULT_FAILURE + USHORT QMUXError; // QMUX_ERR_INVALID_ARG + // QMUX_ERR_NO_MEMORY + // QMUX_ERR_INTERNAL + // QMUX_ERR_FAULT + UCHAR TLV2Type; // 0x01 + USHORT TLV2Length; // 2 + + UCHAR OperatingMode; +} QMIDMS_GET_OPERATING_MODE_RESP_MSG, *PQMIDMS_GET_OPERATING_MODE_RESP_MSG; + +typedef struct _QMIDMS_UIM_GET_ICCID_REQ_MSG +{ + USHORT Type; // QMUX type 0x0024 + USHORT Length; +} QMIDMS_UIM_GET_ICCID_REQ_MSG, *PQMIDMS_UIM_GET_ICCID_REQ_MSG; + +typedef struct _QMIDMS_UIM_GET_ICCID_RESP_MSG +{ + USHORT Type; // QMUX type 0x0024 + 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 + UCHAR TLV2Type; // 0x01 - required parameter + USHORT TLV2Length; // var + UCHAR ICCID; // String of voice number +} QMIDMS_UIM_GET_ICCID_RESP_MSG, *PQMIDMS_UIM_GET_ICCID_RESP_MSG; +#endif + +typedef struct _QMIDMS_SET_OPERATING_MODE_REQ_MSG +{ + USHORT Type; // QMUX type 0x0002 + USHORT Length; + UCHAR TLVType; // 0x02 - result code + USHORT TLVLength; // 4 + UCHAR OperatingMode; +} __attribute__ ((packed)) QMIDMS_SET_OPERATING_MODE_REQ_MSG, *PQMIDMS_SET_OPERATING_MODE_REQ_MSG; + +typedef struct _QMIDMS_SET_OPERATING_MODE_RESP_MSG +{ + USHORT Type; // QMUX type 0x0002 + USHORT Length; + UCHAR TLVType; // 0x02 - result code + USHORT TLVLength; // 4 + USHORT QMUXResult; // QMUX_RESULT_SUCCESS + // QMUX_RESULT_FAILURE + USHORT QMUXError; // QMUX_ERR_INVALID_ARG + // QMUX_ERR_NO_MEMORY + // QMUX_ERR_INTERNAL + // QMUX_ERR_FAULT +} __attribute__ ((packed)) QMIDMS_SET_OPERATING_MODE_RESP_MSG, *PQMIDMS_SET_OPERATING_MODE_RESP_MSG; + +#if 0 +typedef struct _QMIDMS_ACTIVATE_AUTOMATIC_REQ_MSG +{ + USHORT Type; // QMUX type 0x0024 + USHORT Length; + UCHAR TLVType; // 0x02 - result code + USHORT TLVLength; // + UCHAR ActivateCodelen; + UCHAR ActivateCode; +} QMIDMS_ACTIVATE_AUTOMATIC_REQ_MSG, *PQMIDMS_ACTIVATE_AUTOMATIC_REQ_MSG; + +typedef struct _QMIDMS_ACTIVATE_AUTOMATIC_RESP_MSG +{ + USHORT Type; // QMUX type 0x0024 + 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 +} QMIDMS_ACTIVATE_AUTOMATIC_RESP_MSG, *PQMIDMS_ACTIVATE_AUTOMATIC_RESP_MSG; + + +typedef struct _SPC_MSG +{ + UCHAR SPC[6]; + USHORT SID; +} SPC_MSG, *PSPC_MSG; + +typedef struct _MDN_MSG +{ + UCHAR MDNLEN; + UCHAR MDN; +} MDN_MSG, *PMDN_MSG; + +typedef struct _MIN_MSG +{ + UCHAR MINLEN; + UCHAR MIN; +} MIN_MSG, *PMIN_MSG; + +typedef struct _PRL_MSG +{ + UCHAR TLVType; // 0x02 - result code + USHORT TLVLength; // + USHORT PRLLEN; + UCHAR PRL; +} PRL_MSG, *PPRL_MSG; + +typedef struct _MN_HA_KEY_MSG +{ + UCHAR TLVType; // 0x02 - result code + USHORT TLVLength; // + UCHAR MN_HA_KEY_LEN; + UCHAR MN_HA_KEY; +} MN_HA_KEY_MSG, *PMN_HA_KEY_MSG; + +typedef struct _MN_AAA_KEY_MSG +{ + UCHAR TLVType; // 0x02 - result code + USHORT TLVLength; // + UCHAR MN_AAA_KEY_LEN; + UCHAR MN_AAA_KEY; +} MN_AAA_KEY_MSG, *PMN_AAA_KEY_MSG; + +typedef struct _QMIDMS_ACTIVATE_MANUAL_REQ_MSG +{ + USHORT Type; // QMUX type 0x0024 + USHORT Length; + UCHAR TLVType; // 0x02 - result code + USHORT TLVLength; // + UCHAR Value; +} QMIDMS_ACTIVATE_MANUAL_REQ_MSG, *PQMIDMS_ACTIVATE_MANUAL_REQ_MSG; + +typedef struct _QMIDMS_ACTIVATE_MANUAL_RESP_MSG +{ + USHORT Type; // QMUX type 0x0024 + 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 +} QMIDMS_ACTIVATE_MANUAL_RESP_MSG, *PQMIDMS_ACTIVATE_MANUAL_RESP_MSG; +#endif + +typedef struct _QMIDMS_UIM_GET_STATE_REQ_MSG +{ + USHORT Type; + USHORT Length; +} __attribute__ ((packed)) QMIDMS_UIM_GET_STATE_REQ_MSG, *PQMIDMS_UIM_GET_STATE_REQ_MSG; + +typedef struct _QMIDMS_UIM_GET_STATE_RESP_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + USHORT QMUXResult; + USHORT QMUXError; + UCHAR TLV2Type; + USHORT TLV2Length; + UCHAR UIMState; +} __attribute__ ((packed)) QMIDMS_UIM_GET_STATE_RESP_MSG, *PQMIDMS_UIM_GET_STATE_RESP_MSG; + +typedef struct _QMIDMS_UIM_GET_PIN_STATUS_REQ_MSG +{ + USHORT Type; // QMUX type 0x0024 + USHORT Length; +} __attribute__ ((packed)) QMIDMS_UIM_GET_PIN_STATUS_REQ_MSG, *PQMIDMS_UIM_GET_PIN_STATUS_REQ_MSG; + +typedef struct _QMIDMS_UIM_PIN_STATUS +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR PINStatus; + UCHAR PINVerifyRetriesLeft; + UCHAR PINUnblockRetriesLeft; +} __attribute__ ((packed)) QMIDMS_UIM_PIN_STATUS, *PQMIDMS_UIM_PIN_STATUS; + +#define QMI_PIN_STATUS_NOT_INIT 0 +#define QMI_PIN_STATUS_NOT_VERIF 1 +#define QMI_PIN_STATUS_VERIFIED 2 +#define QMI_PIN_STATUS_DISABLED 3 +#define QMI_PIN_STATUS_BLOCKED 4 +#define QMI_PIN_STATUS_PERM_BLOCKED 5 +#define QMI_PIN_STATUS_UNBLOCKED 6 +#define QMI_PIN_STATUS_CHANGED 7 + + +typedef struct _QMIDMS_UIM_GET_PIN_STATUS_RESP_MSG +{ + USHORT Type; // QMUX type 0x0024 + 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 + UCHAR PinStatus; +} __attribute__ ((packed)) QMIDMS_UIM_GET_PIN_STATUS_RESP_MSG, *PQMIDMS_UIM_GET_PIN_STATUS_RESP_MSG; + +#if 0 +typedef struct _QMIDMS_UIM_GET_CK_STATUS_REQ_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + UCHAR Facility; +} QMIDMS_UIM_GET_CK_STATUS_REQ_MSG, *PQMIDMS_UIM_GET_CK_STATUS_REQ_MSG; + + +typedef struct _QMIDMS_UIM_CK_STATUS +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR FacilityStatus; + UCHAR FacilityVerifyRetriesLeft; + UCHAR FacilityUnblockRetriesLeft; +} QMIDMS_UIM_CK_STATUS, *PQMIDMS_UIM_CK_STATUS; + +typedef struct _QMIDMS_UIM_CK_OPERATION_STATUS +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR OperationBlocking; +} QMIDMS_UIM_CK_OPERATION_STATUS, *PQMIDMS_UIM_CK_OPERATION_STATUS; + +typedef struct _QMIDMS_UIM_GET_CK_STATUS_RESP_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + USHORT QMUXResult; + USHORT QMUXError; + UCHAR CkStatus; +} QMIDMS_UIM_GET_CK_STATUS_RESP_MSG, *PQMIDMS_UIM_GET_CK_STATUS_RESP_MSG; +#endif + +typedef struct _QMIDMS_UIM_VERIFY_PIN_REQ_MSG +{ + USHORT Type; // QMUX type 0x0024 + USHORT Length; + UCHAR TLVType; // 0x02 - result code + USHORT TLVLength; // 4 + UCHAR PINID; + UCHAR PINLen; + UCHAR PINValue; +} __attribute__ ((packed)) QMIDMS_UIM_VERIFY_PIN_REQ_MSG, *PQMIDMS_UIM_VERIFY_PIN_REQ_MSG; + +typedef struct _QMIDMS_UIM_VERIFY_PIN_RESP_MSG +{ + USHORT Type; // QMUX type 0x0024 + 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 + UCHAR TLV2Type; + USHORT TLV2Length; + UCHAR PINVerifyRetriesLeft; + UCHAR PINUnblockRetriesLeft; +} __attribute__ ((packed)) QMIDMS_UIM_VERIFY_PIN_RESP_MSG, *PQMIDMS_UIM_VERIFY_PIN_RESP_MSG; + +#if 0 +typedef struct _QMIDMS_UIM_SET_PIN_PROTECTION_REQ_MSG +{ + USHORT Type; // QMUX type 0x0024 + USHORT Length; + UCHAR TLVType; // 0x02 - result code + USHORT TLVLength; // 4 + UCHAR PINID; + UCHAR ProtectionSetting; + UCHAR PINLen; + UCHAR PINValue; +} QMIDMS_UIM_SET_PIN_PROTECTION_REQ_MSG, *PQMIDMS_UIM_SET_PIN_PROTECTION_REQ_MSG; + +typedef struct _QMIDMS_UIM_SET_PIN_PROTECTION_RESP_MSG +{ + USHORT Type; // QMUX type 0x0024 + 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 + UCHAR TLV2Type; + USHORT TLV2Length; + UCHAR PINVerifyRetriesLeft; + UCHAR PINUnblockRetriesLeft; +} QMIDMS_UIM_SET_PIN_PROTECTION_RESP_MSG, *PQMIDMS_UIM_SET_PIN_PROTECTION_RESP_MSG; + +typedef struct _QMIDMS_UIM_SET_CK_PROTECTION_REQ_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + UCHAR Facility; + UCHAR FacilityState; + UCHAR FacliltyLen; + UCHAR FacliltyValue; +} QMIDMS_UIM_SET_CK_PROTECTION_REQ_MSG, *PQMIDMS_UIM_SET_CK_PROTECTION_REQ_MSG; + +typedef struct _QMIDMS_UIM_SET_CK_PROTECTION_RESP_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + USHORT QMUXResult; + USHORT QMUXError; + UCHAR TLV2Type; + USHORT TLV2Length; + UCHAR FacilityRetriesLeft; +} QMIDMS_UIM_SET_CK_PROTECTION_RESP_MSG, *PQMIDMS_UIM_SET_CK_PROTECTION_RESP_MSG; + + +typedef struct _UIM_PIN +{ + UCHAR PinLength; + UCHAR PinValue; +} UIM_PIN, *PUIM_PIN; + +typedef struct _QMIDMS_UIM_CHANGE_PIN_REQ_MSG +{ + USHORT Type; // QMUX type 0x0024 + USHORT Length; + UCHAR TLVType; // 0x02 - result code + USHORT TLVLength; // 4 + UCHAR PINID; + UCHAR PinDetails; +} QMIDMS_UIM_CHANGE_PIN_REQ_MSG, *PQMIDMS_UIM_CHANGE_PIN_REQ_MSG; + +typedef struct QMIDMS_UIM_CHANGE_PIN_RESP_MSG +{ + USHORT Type; // QMUX type 0x0024 + 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 + UCHAR TLV2Type; + USHORT TLV2Length; + UCHAR PINVerifyRetriesLeft; + UCHAR PINUnblockRetriesLeft; +} QMIDMS_UIM_CHANGE_PIN_RESP_MSG, *PQMIDMS_UIM_CHANGE_PIN_RESP_MSG; + +typedef struct _UIM_PUK +{ + UCHAR PukLength; + UCHAR PukValue; +} UIM_PUK, *PUIM_PUK; + +typedef struct _QMIDMS_UIM_UNBLOCK_PIN_REQ_MSG +{ + USHORT Type; // QMUX type 0x0024 + USHORT Length; + UCHAR TLVType; // 0x02 - result code + USHORT TLVLength; // 4 + UCHAR PINID; + UCHAR PinDetails; +} QMIDMS_UIM_UNBLOCK_PIN_REQ_MSG, *PQMIDMS_UIM_BLOCK_PIN_REQ_MSG; + +typedef struct QMIDMS_UIM_UNBLOCK_PIN_RESP_MSG +{ + USHORT Type; // QMUX type 0x0024 + 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 + UCHAR TLV2Type; + USHORT TLV2Length; + UCHAR PINVerifyRetriesLeft; + UCHAR PINUnblockRetriesLeft; +} QMIDMS_UIM_UNBLOCK_PIN_RESP_MSG, *PQMIDMS_UIM_UNBLOCK_PIN_RESP_MSG; + +typedef struct _QMIDMS_UIM_UNBLOCK_CK_REQ_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + UCHAR Facility; + UCHAR FacliltyUnblockLen; + UCHAR FacliltyUnblockValue; +} QMIDMS_UIM_UNBLOCK_CK_REQ_MSG, *PQMIDMS_UIM_BLOCK_CK_REQ_MSG; + +typedef struct QMIDMS_UIM_UNBLOCK_CK_RESP_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + USHORT QMUXResult; + USHORT QMUXError; + UCHAR TLV2Type; + USHORT TLV2Length; + UCHAR FacilityUnblockRetriesLeft; +} QMIDMS_UIM_UNBLOCK_CK_RESP_MSG, *PQMIDMS_UIM_UNBLOCK_CK_RESP_MSG; + +typedef struct _QMIDMS_SET_EVENT_REPORT_REQ_MSG +{ + USHORT Type; + USHORT Length; +} QMIDMS_SET_EVENT_REPORT_REQ_MSG, *PQMIDMS_SET_EVENT_REPORT_REQ_MSG; + +typedef struct _QMIDMS_SET_EVENT_REPORT_RESP_MSG +{ + USHORT Type; // QMUX type 0x0003 + USHORT Length; + UCHAR TLVType; // 0x02 - result code + USHORT TLVLength; // 4 + USHORT QMUXResult; // QMI_RESULT_SUCCESS + // QMI_RESULT_FAILURE + USHORT QMUXError; // QMI_ERR_INVALID_ARG +} QMIDMS_SET_EVENT_REPORT_RESP_MSG, *PQMIDMS_SET_EVENT_REPORT_RESP_MSG; + +typedef struct _PIN_STATUS +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR ReportPinState; +} PIN_STATUS, *PPIN_STATUS; + +typedef struct _POWER_STATUS +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR PowerStatus; + UCHAR BatteryLvl; +} POWER_STATUS, *PPOWER_STATUS; + +typedef struct _ACTIVATION_STATE +{ + UCHAR TLVType; + USHORT TLVLength; + USHORT ActivationState; +} ACTIVATION_STATE, *PACTIVATION_STATE; + +typedef struct _ACTIVATION_STATE_REQ +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR ActivationState; +} ACTIVATION_STATE_REQ, *PACTIVATION_STATE_REQ; + +typedef struct _OPERATING_MODE +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR OperatingMode; +} OPERATING_MODE, *POPERATING_MODE; + +typedef struct _UIM_STATE +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR UIMState; +} UIM_STATE, *PUIM_STATE; + +typedef struct _WIRELESS_DISABLE_STATE +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR WirelessDisableState; +} WIRELESS_DISABLE_STATE, *PWIRELESS_DISABLE_STATE; + +typedef struct _QMIDMS_EVENT_REPORT_IND_MSG +{ + USHORT Type; + USHORT Length; +} QMIDMS_EVENT_REPORT_IND_MSG, *PQMIDMS_EVENT_REPORT_IND_MSG; +#endif + +// ============================ END OF DMS =============================== + +// ======================= QOS ============================== +typedef struct _MPIOC_DEV_INFO MPIOC_DEV_INFO, *PMPIOC_DEV_INFO; + +#define QMI_QOS_SET_EVENT_REPORT_REQ 0x0001 +#define QMI_QOS_SET_EVENT_REPORT_RESP 0x0001 +#define QMI_QOS_SET_EVENT_REPORT_IND 0x0001 +#define QMI_QOS_BIND_DATA_PORT_REQ 0x002B +#define QMI_QOS_BIND_DATA_PORT_RESP 0x002B +#define QMI_QOS_INDICATION_REGISTER_REQ 0x002F +#define QMI_QOS_INDICATION_REGISTER_RESP 0x002F +#define QMI_QOS_GLOBAL_QOS_FLOW_IND 0x0031 +#define QMI_QOS_GET_QOS_INFO_REQ 0x0033 +#define QMI_QOS_GET_QOS_INFO_RESP 0x0033 + + +#if 1 +typedef struct _QMI_QOS_SET_EVENT_REPORT_REQ_MSG +{ + USHORT Type; // QMUX type 0x0001 + USHORT Length; + // UCHAR TLVType; // 0x01 - physical link state + // USHORT TLVLength; // 1 + // UCHAR PhyLinkStatusRpt; // 0-enable; 1-disable + UCHAR TLVType2; // 0x02 = global flow reporting + USHORT TLVLength2; // 1 + UCHAR GlobalFlowRpt; // 1-enable; 0-disable +} QMI_QOS_SET_EVENT_REPORT_REQ_MSG, *PQMI_QOS_SET_EVENT_REPORT_REQ_MSG; + +typedef struct _QMI_QOS_SET_EVENT_REPORT_RESP_MSG +{ + USHORT Type; // QMUX type 0x0010 + USHORT Length; + UCHAR TLVType; // 0x02 - result code + USHORT TLVLength; // 4 + USHORT QMUXResult; // QMUX_RESULT_SUCCESS + // QMUX_RESULT_FAILURE + USHORT QMUXError; // QMUX_ERR_INVALID_ARG + // QMUX_ERR_NO_MEMORY + // QMUX_ERR_INTERNAL + // QMUX_ERR_FAULT +} QMI_QOS_SET_EVENT_REPORT_RESP_MSG, *PQMI_QOS_SET_EVENT_REPORT_RESP_MSG; + +typedef struct _QMI_QOS_SET_EVENT_REPORT_IND_MSG +{ + USHORT Type; // QMUX type 0x0001 + USHORT Length; + UCHAR TLVs; +} QMI_QOS_SET_EVENT_REPORT_IND_MSG, *PQMI_QOS_SET_EVENT_REPORT_IND_MSG; + + +typedef struct _QMI_QOS_BIND_DATA_PORT_TLV_EP_ID +{ + UCHAR TLVType; //0x10 + USHORT TLVLength; + ULONG ep_type; + ULONG iface_id; +} __attribute__ ((packed)) QMI_QOS_BIND_DATA_PORT_TLV_EP_ID, *PQMI_QOS_BIND_DATA_PORT_TLV_EP_ID; + +typedef struct _QMI_QOS_BIND_DATA_PORT_TLV_MUX_ID +{ + UCHAR TLVType; //0x11 + USHORT TLVLength; + UCHAR mux_id; +} __attribute__ ((packed)) QMI_QOS_BIND_DATA_PORT_TLV_MUX_ID, *PQMI_QOS_BIND_DATA_PORT_TLV_MUX_ID; + +typedef struct _QMI_QOS_BIND_DATA_PORT_TLV_DATA_PORT +{ + UCHAR TLVType; //0x12 + USHORT TLVLength; + USHORT data_port; +} __attribute__ ((packed)) QMI_QOS_BIND_DATA_PORT_TLV_DATA_PORT, *PQMI_QOS_BIND_DATA_PORT_TLV_DATA_PORT; + +typedef struct _QMI_QOS_BIND_DATA_PORT_REQ_MSG +{ + USHORT Type; + USHORT Length; + QMI_QOS_BIND_DATA_PORT_TLV_EP_ID EpIdTlv; + QMI_QOS_BIND_DATA_PORT_TLV_MUX_ID MuxIdTlv; + //QMI_QOS_BIND_DATA_PORT_TLV_DATA_PORT DataPortTlv; +} __attribute__ ((packed)) QMI_QOS_BIND_DATA_PORT_REQ_MSG, *PQMI_QOS_BIND_DATA_PORT_REQ_MSG; + +typedef struct _QMI_QOS_BIND_DATA_PORT_RESP_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; //0x02 + USHORT TLVLength; + USHORT QMUXResult; + USHORT QMUXError; +} __attribute__ ((packed)) QMI_QOS_BIND_DATA_PORT_RESP_MSG, *PQMI_QOS_BIND_DATA_PORT_RESP_MSG; + +typedef struct _QMI_QOS_INDICATION_REGISTER_TLV_REPORT_GLOBAL_QOS_FLOW +{ + UCHAR TLVType; //0x10 + USHORT TLVLength; + UCHAR report_global_qos_flows; +} __attribute__ ((packed)) QMI_QOS_INDICATION_REGISTER_TLV_REPORT_GLOBAL_QOS_FLOW, *PQMI_QOS_INDICATION_REGISTER_TLV_REPORT_GLOBAL_QOS_FLOW; + +typedef struct _QMI_QOS_INDICATION_REGISTER_TLV_SUPPRESS_REPORT_FLOW_CTL +{ + UCHAR TLVType; //0x11 + USHORT TLVLength; + UCHAR suppress_report_flow_control; +} __attribute__ ((packed)) QMI_QOS_INDICATION_REGISTER_TLV_SUPPRESS_REPORT_FLOW_CTL, *PQMI_QOS_INDICATION_REGISTER_TLV_SUPPRESS_REPORT_FLOW_CTL; + +typedef struct _QMI_QOS_INDICATION_REGISTER_TLV_SUPPRESS_NW_STATUS_IND +{ + UCHAR TLVType; //0x12 + USHORT TLVLength; + UCHAR suppress_network_status_ind; +} __attribute__ ((packed)) QMI_QOS_INDICATION_REGISTER_TLV_SUPPRESS_NW_STATUS_IND, *PQMI_QOS_INDICATION_REGISTER_TLV_SUPPRESS_NW_STATUS_IND; + +typedef struct _QMI_QOS_INDICATION_REGISTER_REQ_MSG +{ + USHORT Type; + USHORT Length; + QMI_QOS_INDICATION_REGISTER_TLV_REPORT_GLOBAL_QOS_FLOW ReportGlobalQosFlowTlv; + //QMI_QOS_INDICATION_REGISTER_TLV_SUPPRESS_REPORT_FLOW_CTL SuppressReportFlowCtlTlv; + //QMI_QOS_INDICATION_REGISTER_TLV_SUPPRESS_NW_STATUS_IND SuppressNWStatusIndTlv; +} __attribute__ ((packed)) QMI_QOS_INDICATION_REGISTER_REQ_MSG, *PQMI_QOS_INDICATION_REGISTER_REQ_MSG; + +typedef struct _QMI_QOS_INDICATION_REGISTER_RESP_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; //0x02 + USHORT TLVLength; + USHORT QMUXResult; + USHORT QMUXError; +} __attribute__ ((packed)) QMI_QOS_INDICATION_REGISTER_RESP_MSG, *PQMI_QOS_INDICATION_REGISTER_RESP_MSG; + +typedef struct _QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_STATE +{ + UCHAR TLVType; //0x01 + USHORT TLVLength; + ULONG qos_id; + UCHAR new_flow; + ULONG state_change; +} __attribute__ ((packed)) QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_STATE, *PQMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_STATE; + +typedef struct _QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_GRANTED +{ + UCHAR TLVType; //0x10 0x11 + USHORT TLVLength; + ULONG64 flow_valid_params; + ULONG ip_flow_trf_cls; + ULONG64 data_rate_max; + ULONG64 guaranteed_rate; + ULONG peak_rate; + ULONG token_rate; + ULONG bucket_size; + ULONG ip_flow_latency; + ULONG ip_flow_jitter; + USHORT ip_flow_pkt_error_rate_multiplier; + USHORT ip_flow_pkt_error_rate_exponent; + ULONG ip_flow_min_policed_packet_size; + ULONG ip_flow_max_allowed_packet_size; + ULONG ip_flow_3gpp_residual_bit_error_rate; + ULONG ip_flow_3gpp_traffic_handling_priority; + USHORT ip_flow_3gpp2_profile_id; + UCHAR ip_flow_3gpp2_flow_priority; + UCHAR ip_flow_3gpp_im_cn_flag; + UCHAR ip_flow_3gpp_sig_ind; + ULONG ip_flow_lte_qci; +} __attribute__ ((packed)) QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_GRANTED, *PQMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_GRANTED; + +typedef struct _QMI_QOS_GLOBAL_QOS_FLOW_TLV_FILTER +{ + UCHAR TLVType; //0x12 0x13 + USHORT TLVLength; + UCHAR tx_rx_qos_filter_len; + UCHAR ip_version; + ULONG64 valid_params0; + ULONG ipv4_addr0; + ULONG subnet_mask0; + ULONG ipv4_addr1; + ULONG subnet_mask1; + UCHAR val4; + UCHAR mask4; + ULONG64 valid_params01; + UCHAR ipv6_address00; + UCHAR ipv6_address01; + UCHAR ipv6_address02; + UCHAR ipv6_address03; + UCHAR ipv6_address04; + UCHAR ipv6_address05; + UCHAR ipv6_address06; + UCHAR ipv6_address07; + UCHAR ipv6_address08; + UCHAR ipv6_address09; + UCHAR ipv6_address010; + UCHAR ipv6_address011; + UCHAR ipv6_address012; + UCHAR ipv6_address013; + UCHAR ipv6_address014; + ULONG ipv6_address015; + UCHAR prefix_len0; + UCHAR ipv6_address10; + UCHAR ipv6_address11; + UCHAR ipv6_address12; + UCHAR ipv6_address13; + UCHAR ipv6_address14; + UCHAR ipv6_address15; + UCHAR ipv6_address16; + UCHAR ipv6_address17; + UCHAR ipv6_address18; + UCHAR ipv6_address19; + UCHAR ipv6_address110; + UCHAR ipv6_address111; + UCHAR ipv6_address112; + UCHAR ipv6_address113; + UCHAR ipv6_address114; + ULONG ipv6_address115; + UCHAR prefix_len1; + UCHAR val6; + UCHAR mask6; + ULONG flow_label; + ULONG xport_protocol; + ULONG64 valid_params2; + USHORT port0; + USHORT range0; + USHORT port1; + USHORT range1; + ULONG64 valid_params3; + USHORT port2; + USHORT range2; + USHORT port3; + USHORT range3; + ULONG64 valid_params4; + UCHAR type; + UCHAR code; + ULONG64 valid_params5; + ULONG spi0; + ULONG64 valid_params6; + ULONG spi1; + USHORT filter_id; + USHORT filter_precedence; +} __attribute__ ((packed)) QMI_QOS_GLOBAL_QOS_FLOW_TLV_FILTER, *PQMI_QOS_GLOBAL_QOS_FLOW_TLV_FILTER; + +typedef struct _QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_TYPE +{ + UCHAR TLVType; //0x14 + USHORT TLVLength; + ULONG flow_type; +} __attribute__ ((packed)) QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_TYPE, *PQMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_TYPE; + +typedef struct _QMI_QOS_GLOBAL_QOS_FLOW_TLV_BEARER_ID +{ + UCHAR TLVType; //0x15 + USHORT TLVLength; + UCHAR bearer_id; +} __attribute__ ((packed)) QMI_QOS_GLOBAL_QOS_FLOW_TLV_BEARER_ID, *PQMI_QOS_GLOBAL_QOS_FLOW_TLV_BEARER_ID; + +typedef struct _QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_CTL_SEQ_NUM +{ + UCHAR TLVType; //0x16 + USHORT TLVLength; + USHORT fc_seq_num; +} __attribute__ ((packed)) QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_CTL_SEQ_NUM, *PQMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_CTL_SEQ_NUM; + +typedef struct _QMI_QOS_GLOBAL_QOS_FLOW_TLV_5G_QCI +{ + UCHAR TLVType; //0x17 0x18 + USHORT TLVLength; + ULONG tx_rx_5g_qci; +} __attribute__ ((packed)) QMI_QOS_GLOBAL_QOS_FLOW_TLV_5G_QCI, *PQMI_QOS_GLOBAL_QOS_FLOW_TLV_5G_QCI; + +typedef struct _QMI_QOS_GLOBAL_QOS_FLOW_TLV_AVG_WINDOW +{ + UCHAR TLVType; //0x19 0x1A + USHORT TLVLength; + USHORT tx_rx_avg_window; +} __attribute__ ((packed)) QMI_QOS_GLOBAL_QOS_FLOW_TLV_AVG_WINDOW, *PQMI_QOS_GLOBAL_QOS_FLOW_TLV_AVG_WINDOW; + +typedef struct _QMI_QOS_GLOBAL_QOS_FLOW_TLV_TX_FILTER_MATCH_ALL +{ + UCHAR TLVType; //0x1B + USHORT TLVLength; + UCHAR tx_filter_match_all_len; + USHORT filter_id; +} __attribute__ ((packed)) QMI_QOS_GLOBAL_QOS_FLOW_TLV_TX_FILTER_MATCH_ALL, *PQMI_QOS_GLOBAL_QOS_FLOW_TLV_TX_FILTER_MATCH_ALL; + +typedef struct _QMI_QOS_GLOBAL_QOS_FLOW_IND_MSG +{ + USHORT Type; + USHORT Length; + QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_STATE FlowStateTlv; + //QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_GRANTED TxFlowGrantedTlv; + //QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_GRANTED RxFlowGrantedTlv; + //QMI_QOS_GLOBAL_QOS_FLOW_TLV_FILTER TxFilterTlv; + //QMI_QOS_GLOBAL_QOS_FLOW_TLV_FILTER RxFilterTlv; + //QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_TYPE FlowTypeTlv; + //QMI_QOS_GLOBAL_QOS_FLOW_TLV_BEARER_ID BearerIdTlv; + //QMI_QOS_GLOBAL_QOS_FLOW_TLV_FLOW_CTL_SEQ_NUM FlowCtlSeqNumTlv; + //QMI_QOS_GLOBAL_QOS_FLOW_TLV_5G_QCI Tx5GQciTlv; + //QMI_QOS_GLOBAL_QOS_FLOW_TLV_5G_QCI Rx5GQciTlv; + //QMI_QOS_GLOBAL_QOS_FLOW_TLV_AVG_WINDOW AvgWindowTlv; + //QMI_QOS_GLOBAL_QOS_FLOW_TLV_TX_FILTER_MATCH_ALL TxFilterMatchAllTlv; +} __attribute__ ((packed)) QMI_QOS_GLOBAL_QOS_FLOW_IND_MSG, *PQMI_QOS_GLOBAL_QOS_FLOW_IND_MSG; + +typedef struct _QMI_QOS_GET_QOS_INFO_TLV_QOS_ID +{ + UCHAR TLVType; //0x01 + USHORT TLVLength; + ULONG qos_id; +} __attribute__ ((packed)) QMI_QOS_GET_QOS_INFO_TLV_QOS_ID, *PQMI_QOS_GET_QOS_INFO_TLV_QOS_ID; + +typedef struct _QMI_QOS_GET_QOS_INFO_TLV_FLOW_STATUS +{ + UCHAR TLVType; //0x10 + USHORT TLVLength; + UCHAR flow_status; +} __attribute__ ((packed)) QMI_QOS_GET_QOS_INFO_TLV_FLOW_STATUS, *PQMI_QOS_GET_QOS_INFO_TLV_FLOW_STATUS; + +typedef struct _QMI_QOS_GET_QOS_INFO_TLV_GRANTED_FLOW +{ + UCHAR TLVType; //0x11 0x12 + USHORT TLVLength; + ULONG64 flow_valid_params; + ULONG ip_flow_trf_cls; + ULONG64 data_rate_max; + ULONG64 guaranteed_rate; + ULONG peak_rate; + ULONG token_rate; + ULONG bucket_size; + ULONG ip_flow_latency; + ULONG ip_flow_jitter; + USHORT ip_flow_pkt_error_rate_multiplier; + USHORT ip_flow_pkt_error_rate_exponent; + ULONG ip_flow_min_policed_packet_size; + ULONG ip_flow_max_allowed_packet_size; + ULONG ip_flow_3gpp_residual_bit_error_rate; + ULONG ip_flow_3gpp_traffic_handling_priority; + USHORT ip_flow_3gpp2_profile_id; + UCHAR ip_flow_3gpp2_flow_priority; + UCHAR ip_flow_3gpp_im_cn_flag; + UCHAR ip_flow_3gpp_sig_ind; + ULONG ip_flow_lte_qci; +} __attribute__ ((packed)) QMI_QOS_GET_QOS_INFO_TLV_GRANTED_FLOW, *PQMI_QOS_GET_QOS_INFO_TLV_GRANTED_FLOW; + +typedef struct _QMI_QOS_GET_QOS_INFO_TLV_FILTER_SPECS +{ + UCHAR TLVType; //0x13 0x14 + USHORT TLVLength; + UCHAR tx_rx_qos_filter_len; + UCHAR ip_version; + ULONG64 valid_params0; + ULONG ipv4_addr0; + ULONG subnet_mask0; + ULONG ipv4_addr1; + ULONG subnet_mask1; + UCHAR val4; + UCHAR mask4; + ULONG64 valid_params01; + UCHAR ipv6_address00; + UCHAR ipv6_address01; + UCHAR ipv6_address02; + UCHAR ipv6_address03; + UCHAR ipv6_address04; + UCHAR ipv6_address05; + UCHAR ipv6_address06; + UCHAR ipv6_address07; + UCHAR ipv6_address08; + UCHAR ipv6_address09; + UCHAR ipv6_address010; + UCHAR ipv6_address011; + UCHAR ipv6_address012; + UCHAR ipv6_address013; + UCHAR ipv6_address014; + ULONG ipv6_address015; + UCHAR prefix_len0; + UCHAR ipv6_address10; + UCHAR ipv6_address11; + UCHAR ipv6_address12; + UCHAR ipv6_address13; + UCHAR ipv6_address14; + UCHAR ipv6_address15; + UCHAR ipv6_address16; + UCHAR ipv6_address17; + UCHAR ipv6_address18; + UCHAR ipv6_address19; + UCHAR ipv6_address110; + UCHAR ipv6_address111; + UCHAR ipv6_address112; + UCHAR ipv6_address113; + UCHAR ipv6_address114; + ULONG ipv6_address115; + UCHAR prefix_len1; + UCHAR val6; + UCHAR mask6; + ULONG flow_label; + ULONG xport_protocol; + ULONG64 valid_params2; + USHORT port0; + USHORT range0; + USHORT port1; + USHORT range1; + ULONG64 valid_params3; + USHORT port2; + USHORT range2; + USHORT port3; + USHORT range3; + ULONG64 valid_params4; + UCHAR type; + UCHAR code; + ULONG64 valid_params5; + ULONG spi0; + ULONG64 valid_params6; + ULONG spi1; + USHORT filter_id; + USHORT filter_precedence; +} __attribute__ ((packed)) QMI_QOS_GET_QOS_INFO_TLV_FILTER_SPECS, *PQMI_QOS_GET_QOS_INFO_TLV_FILTER_SPECS; + +typedef struct _QMI_QOS_GET_QOS_INFO_TLV_EXT_ERROR_INFO +{ + UCHAR TLVType; //0x15 + USHORT TLVLength; + USHORT ext_error_info; +} __attribute__ ((packed)) QMI_QOS_GET_QOS_INFO_TLV_EXT_ERROR_INFO, *PQMI_QOS_GET_QOS_INFO_TLV_EXT_ERROR_INFO; + +typedef struct _QMI_QOS_GET_QOS_INFO_TLV_5G_QCI +{ + UCHAR TLVType; //0x16 0x17 + USHORT TLVLength; + ULONG tx_rx_5g_qci; +} __attribute__ ((packed)) QMI_QOS_GET_QOS_INFO_TLV_5G_QCI, *PQMI_QOS_GET_QOS_INFO_TLV_5G_QCI; + +typedef struct _QMI_QOS_GET_QOS_INFO_TLV_AVG_WINDOW +{ + UCHAR TLVType; //0x18 0x19 + USHORT TLVLength; + USHORT tx_rx_averaging_window; +} __attribute__ ((packed)) QMI_QOS_GET_QOS_INFO_TLV_AVG_WINDOW, *PQMI_QOS_GET_QOS_INFO_TLV_AVG_WINDOW; + +typedef struct _QMI_QOS_GET_QOS_INFO_TLV_TX_FILTER_MATCH_ALL +{ + UCHAR TLVType; //0x1A + USHORT TLVLength; + UCHAR tx_filter_match_all_len; + USHORT filter_id; +} __attribute__ ((packed)) QMI_QOS_GET_QOS_INFO_TLV_TX_FILTER_MATCH_ALL, *PQMI_QOS_GET_QOS_INFO_TLV_TX_FILTER_MATCH_ALL; + +typedef struct _QMI_QOS_GET_QOS_INFO_REQ_MSG +{ + USHORT Type; + USHORT Length; + QMI_QOS_GET_QOS_INFO_TLV_QOS_ID QosIdTlv; +} __attribute__ ((packed)) QMI_QOS_GET_QOS_INFO_REQ_MSG, *PQMI_QOS_GET_QOS_INFO_REQ_MSG; + +typedef struct _QMI_QOS_GET_QOS_INFO_RESP_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; //0x02 + USHORT TLVLength; + USHORT QMUXResult; + USHORT QMUXError; + //QMI_QOS_GET_QOS_INFO_TLV_FLOW_STATUS FlowStatusTlv; + //QMI_QOS_GET_QOS_INFO_TLV_GRANTED_FLOW TxGrantedFlowTlv; + //QMI_QOS_GET_QOS_INFO_TLV_GRANTED_FLOW RxGrantedFlowTlv; + //QMI_QOS_GET_QOS_INFO_TLV_FILTER_SPECS TxFilterSpecsTlv; + //QMI_QOS_GET_QOS_INFO_TLV_FILTER_SPECS RxFilterSpecsTlv; + //QMI_QOS_GET_QOS_INFO_TLV_EXT_ERROR_INFO ExtErrorInfoTlv; + //QMI_QOS_GET_QOS_INFO_TLV_5G_QCI Tx5GQciTlv; + //QMI_QOS_GET_QOS_INFO_TLV_5G_QCI Rx5GQciTlv; + //QMI_QOS_GET_QOS_INFO_TLV_AVG_WINDOW TxAvgWindowTlv; + //QMI_QOS_GET_QOS_INFO_TLV_AVG_WINDOW RxAvgWindowTlv; + //QMI_QOS_GET_QOS_INFO_TLV_TX_FILTER_MATCH_ALL TxFilterMatchAllTlv; +} __attribute__ ((packed)) QMI_QOS_GET_QOS_INFO_RESP_MSG, *PQMI_QOS_GET_QOS_INFO_RESP_MSG; + +#define QOS_IND_FLOW_STATE_ACTIVATED 0x00 +#define QOS_IND_FLOW_STATE_MODIFIED 0x01 +#define QOS_IND_FLOW_STATE_DELETED 0x02 +#define QOS_IND_FLOW_STATE_SUSPENDED 0x03 +#define QOS_IND_FLOW_STATE_ENABLED 0x04 +#define QOS_IND_FLOW_STATE_DISABLED 0x05 +#define QOS_IND_FLOW_STATE_INVALID 0x06 + +#define QOS_EVENT_RPT_IND_FLOW_ACTIVATED 0x01 +#define QOS_EVENT_RPT_IND_FLOW_MODIFIED 0x02 +#define QOS_EVENT_RPT_IND_FLOW_DELETED 0x03 +#define QOS_EVENT_RPT_IND_FLOW_SUSPENDED 0x04 +#define QOS_EVENT_RPT_IND_FLOW_ENABLED 0x05 +#define QOS_EVENT_RPT_IND_FLOW_DISABLED 0x06 + +#define QOS_EVENT_RPT_IND_TLV_PHY_LINK_STATE_TYPE 0x01 +#define QOS_EVENT_RPT_IND_TLV_GLOBAL_FL_RPT_STATE 0x10 +#define QOS_EVENT_RPT_IND_TLV_GLOBAL_FL_RPT_TYPE 0x10 +#define QOS_EVENT_RPT_IND_TLV_TX_FLOW_TYPE 0x11 +#define QOS_EVENT_RPT_IND_TLV_RX_FLOW_TYPE 0x12 +#define QOS_EVENT_RPT_IND_TLV_TX_FILTER_TYPE 0x13 +#define QOS_EVENT_RPT_IND_TLV_RX_FILTER_TYPE 0x14 +#define QOS_EVENT_RPT_IND_TLV_FLOW_SPEC 0x10 +#define QOS_EVENT_RPT_IND_TLV_FILTER_SPEC 0x10 + +typedef struct _QOS_EVENT_RPT_IND_TLV_PHY_LINK_STATE +{ + UCHAR TLVType; // 0x01 + USHORT TLVLength; // 1 + UCHAR PhyLinkState; // 0-dormant, 1-active +} QOS_EVENT_RPT_IND_TLV_PHY_LINK_STATE, *PQOS_EVENT_RPT_IND_TLV_PHY_LINK_STATE; + +typedef struct _QOS_EVENT_RPT_IND_TLV_GLOBAL_FL_RPT +{ + UCHAR TLVType; // 0x10 + USHORT TLVLength; // 6 + ULONG QosId; + UCHAR NewFlow; // 1: newly added flow; 0: existing flow + UCHAR StateChange; // 1: activated; 2: modified; 3: deleted; + // 4: suspended(delete); 5: enabled; 6: disabled +} QOS_EVENT_RPT_IND_TLV_GLOBAL_FL_RPT, *PQOS_EVENT_RPT_IND_TLV_GLOBAL_FL_RPT; + +// QOS Flow + +typedef struct _QOS_EVENT_RPT_IND_TLV_FLOW +{ + UCHAR TLVType; // 0x10-TX flow; 0x11-RX flow + USHORT TLVLength; // var + // embedded TLV's +} QOS_EVENT_RPT_IND_TLV_TX_FLOW, *PQOS_EVENT_RPT_IND_TLV_TX_FLOW; + +#define QOS_FLOW_TLV_IP_FLOW_IDX_TYPE 0x10 +#define QOS_FLOW_TLV_IP_FLOW_TRAFFIC_CLASS_TYPE 0x11 +#define QOS_FLOW_TLV_IP_FLOW_DATA_RATE_MIN_MAX_TYPE 0x12 +#define QOS_FLOW_TLV_IP_FLOW_DATA_RATE_TOKEN_BUCKET_TYPE 0x13 +#define QOS_FLOW_TLV_IP_FLOW_LATENCY_TYPE 0x14 +#define QOS_FLOW_TLV_IP_FLOW_JITTER_TYPE 0x15 +#define QOS_FLOW_TLV_IP_FLOW_PKT_ERR_RATE_TYPE 0x16 +#define QOS_FLOW_TLV_IP_FLOW_MIN_PKT_SIZE_TYPE 0x17 +#define QOS_FLOW_TLV_IP_FLOW_MAX_PKT_SIZE_TYPE 0x18 +#define QOS_FLOW_TLV_IP_FLOW_3GPP_BIT_ERR_RATE_TYPE 0x19 +#define QOS_FLOW_TLV_IP_FLOW_3GPP_TRAF_PRIORITY_TYPE 0x1A +#define QOS_FLOW_TLV_IP_FLOW_3GPP2_PROFILE_ID_TYPE 0x1B + +typedef struct _QOS_FLOW_TLV_IP_FLOW_IDX +{ + UCHAR TLVType; // 0x10 + USHORT TLVLength; // 1 + UCHAR IpFlowIndex; +} QOS_FLOW_TLV_IP_FLOW_IDX, *PQOS_FLOW_TLV_IP_FLOW_IDX; + +typedef struct _QOS_FLOW_TLV_IP_FLOW_TRAFFIC_CLASS +{ + UCHAR TLVType; // 0x11 + USHORT TLVLength; // 1 + UCHAR TrafficClass; +} QOS_FLOW_TLV_IP_FLOW_TRAFFIC_CLASS, *PQOS_FLOW_TLV_IP_FLOW_TRAFFIC_CLASS; + +typedef struct _QOS_FLOW_TLV_IP_FLOW_DATA_RATE_MIN_MAX +{ + UCHAR TLVType; // 0x12 + USHORT TLVLength; // 8 + ULONG DataRateMax; + ULONG GuaranteedRate; +} QOS_FLOW_TLV_IP_FLOW_DATA_RATE_MIN_MAX, *PQOS_FLOW_TLV_IP_FLOW_DATA_RATE_MIN_MAX; + +typedef struct _QOS_FLOW_TLV_IP_FLOW_DATA_RATE_TOKEN_BUCKET +{ + UCHAR TLVType; // 0x13 + USHORT TLVLength; // 12 + ULONG PeakRate; + ULONG TokenRate; + ULONG BucketSize; +} QOS_FLOW_TLV_IP_FLOW_DATA_RATE_TOKEN_BUCKET, *PQOS_FLOW_TLV_IP_FLOW_DATA_RATE_TOKEN_BUCKET; + +typedef struct _QOS_FLOW_TLV_IP_FLOW_LATENCY +{ + UCHAR TLVType; // 0x14 + USHORT TLVLength; // 4 + ULONG IpFlowLatency; +} QOS_FLOW_TLV_IP_FLOW_LATENCY, *PQOS_FLOW_TLV_IP_FLOW_LATENCY; + +typedef struct _QOS_FLOW_TLV_IP_FLOW_JITTER +{ + UCHAR TLVType; // 0x15 + USHORT TLVLength; // 4 + ULONG IpFlowJitter; +} QOS_FLOW_TLV_IP_FLOW_JITTER, *PQOS_FLOW_TLV_IP_FLOW_JITTER; + +typedef struct _QOS_FLOW_TLV_IP_FLOW_PKT_ERR_RATE +{ + UCHAR TLVType; // 0x16 + USHORT TLVLength; // 4 + USHORT ErrRateMultiplier; + USHORT ErrRateExponent; +} QOS_FLOW_TLV_IP_FLOW_PKT_ERR_RATE, *PQOS_FLOW_TLV_IP_FLOW_PKT_ERR_RATE; + +typedef struct _QOS_FLOW_TLV_IP_FLOW_MIN_PKT_SIZE +{ + UCHAR TLVType; // 0x17 + USHORT TLVLength; // 4 + ULONG MinPolicedPktSize; +} QOS_FLOW_TLV_IP_FLOW_MIN_PKT_SIZE, *PQOS_FLOW_TLV_IP_FLOW_MIN_PKT_SIZE; + +typedef struct _QOS_FLOW_TLV_IP_FLOW_MAX_PKT_SIZE +{ + UCHAR TLVType; // 0x18 + USHORT TLVLength; // 4 + ULONG MaxAllowedPktSize; +} QOS_FLOW_TLV_IP_FLOW_MAX_PKT_SIZE, *PQOS_FLOW_TLV_IP_FLOW_MAX_PKT_SIZE; + +typedef struct _QOS_FLOW_TLV_IP_FLOW_3GPP_BIT_ERR_RATE +{ + UCHAR TLVType; // 0x19 + USHORT TLVLength; // 1 + UCHAR ResidualBitErrorRate; +} QOS_FLOW_TLV_IP_FLOW_3GPP_BIT_ERR_RATE, *PQOS_FLOW_TLV_IP_FLOW_3GPP_BIT_ERR_RATE; + +typedef struct _QOS_FLOW_TLV_IP_FLOW_3GPP_TRAF_PRIORITY +{ + UCHAR TLVType; // 0x1A + USHORT TLVLength; // 1 + UCHAR TrafficHandlingPriority; +} QOS_FLOW_TLV_IP_FLOW_3GPP_TRAF_PRIORITY, *PQOS_FLOW_TLV_IP_FLOW_3GPP_TRAF_PRIORITY; + +typedef struct _QOS_FLOW_TLV_IP_FLOW_3GPP2_PROFILE_ID +{ + UCHAR TLVType; // 0x1B + USHORT TLVLength; // 2 + USHORT ProfileId; +} QOS_FLOW_TLV_IP_FLOW_3GPP2_PROFILE_ID, *PQOS_FLOW_TLV_IP_FLOW_3GPP2_PROFILE_ID; + +// QOS Filter + +#define QOS_FILTER_TLV_IP_FILTER_IDX_TYPE 0x10 +#define QOS_FILTER_TLV_IP_VERSION_TYPE 0x11 +#define QOS_FILTER_TLV_IPV4_SRC_ADDR_TYPE 0x12 +#define QOS_FILTER_TLV_IPV4_DEST_ADDR_TYPE 0x13 +#define QOS_FILTER_TLV_NEXT_HDR_PROTOCOL_TYPE 0x14 +#define QOS_FILTER_TLV_IPV4_TYPE_OF_SERVICE_TYPE 0x15 +#define QOS_FILTER_TLV_TCP_UDP_PORT_SRC_TCP_TYPE 0x1B +#define QOS_FILTER_TLV_TCP_UDP_PORT_DEST_TCP_TYPE 0x1C +#define QOS_FILTER_TLV_TCP_UDP_PORT_SRC_UDP_TYPE 0x1D +#define QOS_FILTER_TLV_TCP_UDP_PORT_DEST_UDP_TYPE 0x1E +#define QOS_FILTER_TLV_ICMP_FILTER_MSG_TYPE_TYPE 0x1F +#define QOS_FILTER_TLV_ICMP_FILTER_MSG_CODE_TYPE 0x20 +#define QOS_FILTER_TLV_TCP_UDP_PORT_SRC_TYPE 0x24 +#define QOS_FILTER_TLV_TCP_UDP_PORT_DEST_TYPE 0x25 + +typedef struct _QOS_EVENT_RPT_IND_TLV_FILTER +{ + UCHAR TLVType; // 0x12-TX filter; 0x13-RX filter + USHORT TLVLength; // var + // embedded TLV's +} QOS_EVENT_RPT_IND_TLV_RX_FILTER, *PQOS_EVENT_RPT_IND_TLV_RX_FILTER; + +typedef struct _QOS_FILTER_TLV_IP_FILTER_IDX +{ + UCHAR TLVType; // 0x10 + USHORT TLVLength; // 1 + UCHAR IpFilterIndex; +} QOS_FILTER_TLV_IP_FILTER_IDX, *PQOS_FILTER_TLV_IP_FILTER_IDX; + +typedef struct _QOS_FILTER_TLV_IP_VERSION +{ + UCHAR TLVType; // 0x11 + USHORT TLVLength; // 1 + UCHAR IpVersion; +} QOS_FILTER_TLV_IP_VERSION, *PQOS_FILTER_TLV_IP_VERSION; + +typedef struct _QOS_FILTER_TLV_IPV4_SRC_ADDR +{ + UCHAR TLVType; // 0x12 + USHORT TLVLength; // 8 + ULONG IpSrcAddr; + ULONG IpSrcSubnetMask; +} QOS_FILTER_TLV_IPV4_SRC_ADDR, *PQOS_FILTER_TLV_IPV4_SRC_ADDR; + +typedef struct _QOS_FILTER_TLV_IPV4_DEST_ADDR +{ + UCHAR TLVType; // 0x13 + USHORT TLVLength; // 8 + ULONG IpDestAddr; + ULONG IpDestSubnetMask; +} QOS_FILTER_TLV_IPV4_DEST_ADDR, *PQOS_FILTER_TLV_IPV4_DEST_ADDR; + +typedef struct _QOS_FILTER_TLV_NEXT_HDR_PROTOCOL +{ + UCHAR TLVType; // 0x14 + USHORT TLVLength; // 1 + UCHAR NextHdrProtocol; +} QOS_FILTER_TLV_NEXT_HDR_PROTOCOL, *PQOS_FILTER_TLV_NEXT_HDR_PROTOCOL; + +typedef struct _QOS_FILTER_TLV_IPV4_TYPE_OF_SERVICE +{ + UCHAR TLVType; // 0x15 + USHORT TLVLength; // 2 + UCHAR Ipv4TypeOfService; + UCHAR Ipv4TypeOfServiceMask; +} QOS_FILTER_TLV_IPV4_TYPE_OF_SERVICE, *PQOS_FILTER_TLV_IPV4_TYPE_OF_SERVICE; + +typedef struct _QOS_FILTER_TLV_TCP_UDP_PORT +{ + UCHAR TLVType; // source port: 0x1B-TCP; 0x1D-UDP + // dest port: 0x1C-TCP; 0x1E-UDP + USHORT TLVLength; // 4 + USHORT FilterPort; + USHORT FilterPortRange; +} QOS_FILTER_TLV_TCP_UDP_PORT, *PQOS_FILTER_TLV_TCP_UDP_PORT; + +typedef struct _QOS_FILTER_TLV_ICMP_FILTER_MSG_TYPE +{ + UCHAR TLVType; // 0x1F + USHORT TLVLength; // 1 + UCHAR IcmpFilterMsgType; +} QOS_FILTER_TLV_ICMP_FILTER_MSG_TYPE, *PQOS_FILTER_TLV_ICMP_FILTER_MSG_TYPE; + +typedef struct _QOS_FILTER_TLV_ICMP_FILTER_MSG_CODE +{ + UCHAR TLVType; // 0x20 + USHORT TLVLength; // 1 + UCHAR IcmpFilterMsgCode; +} QOS_FILTER_TLV_ICMP_FILTER_MSG_CODE, *PQOS_FILTER_TLV_ICMP_FILTER_MSG_CODE; + +#define QOS_FILTER_PRECEDENCE_INVALID 256 +#define QOS_FILTER_TLV_PRECEDENCE_TYPE 0x22 +#define QOS_FILTER_TLV_ID_TYPE 0x23 + +typedef struct _QOS_FILTER_TLV_PRECEDENCE +{ + UCHAR TLVType; // 0x22 + USHORT TLVLength; // 2 + USHORT Precedence; // precedence of the filter +} QOS_FILTER_TLV_PRECEDENCE, *PQOS_FILTER_TLV_PRECEDENCE; + +typedef struct _QOS_FILTER_TLV_ID +{ + UCHAR TLVType; // 0x23 + USHORT TLVLength; // 2 + USHORT FilterId; // filter ID +} QOS_FILTER_TLV_ID, *PQOS_FILTER_TLV_ID; + +#ifdef QCQOS_IPV6 + +#define QOS_FILTER_TLV_IPV6_SRC_ADDR_TYPE 0x16 +#define QOS_FILTER_TLV_IPV6_DEST_ADDR_TYPE 0x17 +#define QOS_FILTER_TLV_IPV6_NEXT_HDR_PROTOCOL_TYPE 0x14 // same as IPV4 +#define QOS_FILTER_TLV_IPV6_TRAFFIC_CLASS_TYPE 0x19 +#define QOS_FILTER_TLV_IPV6_FLOW_LABEL_TYPE 0x1A + +typedef struct _QOS_FILTER_TLV_IPV6_SRC_ADDR +{ + UCHAR TLVType; // 0x16 + USHORT TLVLength; // 17 + UCHAR IpSrcAddr[16]; + UCHAR IpSrcAddrPrefixLen; // [0..128] +} QOS_FILTER_TLV_IPV6_SRC_ADDR, *PQOS_FILTER_TLV_IPV6_SRC_ADDR; + +typedef struct _QOS_FILTER_TLV_IPV6_DEST_ADDR +{ + UCHAR TLVType; // 0x17 + USHORT TLVLength; // 17 + UCHAR IpDestAddr[16]; + UCHAR IpDestAddrPrefixLen; // [0..128] +} QOS_FILTER_TLV_IPV6_DEST_ADDR, *PQOS_FILTER_TLV_IPV6_DEST_ADDR; + +#define QOS_FILTER_IPV6_NEXT_HDR_PROTOCOL_TCP 0x06 +#define QOS_FILTER_IPV6_NEXT_HDR_PROTOCOL_UDP 0x11 + +typedef struct _QOS_FILTER_TLV_IPV6_TRAFFIC_CLASS +{ + UCHAR TLVType; // 0x19 + USHORT TLVLength; // 2 + UCHAR TrafficClass; + UCHAR TrafficClassMask; // compare the first 6 bits only +} QOS_FILTER_TLV_IPV6_TRAFFIC_CLASS, *PQOS_FILTER_TLV_IPV6_TRAFFIC_CLASS; + +typedef struct _QOS_FILTER_TLV_IPV6_FLOW_LABEL +{ + UCHAR TLVType; // 0x1A + USHORT TLVLength; // 4 + ULONG FlowLabel; +} QOS_FILTER_TLV_IPV6_FLOW_LABEL, *PQOS_FILTER_TLV_IPV6_FLOW_LABEL; + +#endif // QCQOS_IPV6 +#endif + +// ======================= WMS ============================== +#define QMIWMS_SET_EVENT_REPORT_REQ 0x0001 +#define QMIWMS_SET_EVENT_REPORT_RESP 0x0001 +#define QMIWMS_EVENT_REPORT_IND 0x0001 +#define QMIWMS_RAW_SEND_REQ 0x0020 +#define QMIWMS_RAW_SEND_RESP 0x0020 +#define QMIWMS_RAW_WRITE_REQ 0x0021 +#define QMIWMS_RAW_WRITE_RESP 0x0021 +#define QMIWMS_RAW_READ_REQ 0x0022 +#define QMIWMS_RAW_READ_RESP 0x0022 +#define QMIWMS_MODIFY_TAG_REQ 0x0023 +#define QMIWMS_MODIFY_TAG_RESP 0x0023 +#define QMIWMS_DELETE_REQ 0x0024 +#define QMIWMS_DELETE_RESP 0x0024 +#define QMIWMS_GET_MESSAGE_PROTOCOL_REQ 0x0030 +#define QMIWMS_GET_MESSAGE_PROTOCOL_RESP 0x0030 +#define QMIWMS_LIST_MESSAGES_REQ 0x0031 +#define QMIWMS_LIST_MESSAGES_RESP 0x0031 +#define QMIWMS_GET_SMSC_ADDRESS_REQ 0x0034 +#define QMIWMS_GET_SMSC_ADDRESS_RESP 0x0034 +#define QMIWMS_SET_SMSC_ADDRESS_REQ 0x0035 +#define QMIWMS_SET_SMSC_ADDRESS_RESP 0x0035 +#define QMIWMS_GET_STORE_MAX_SIZE_REQ 0x0036 +#define QMIWMS_GET_STORE_MAX_SIZE_RESP 0x0036 + + +#define WMS_MESSAGE_PROTOCOL_CDMA 0x00 +#define WMS_MESSAGE_PROTOCOL_WCDMA 0x01 + +#if 0 +typedef struct _QMIWMS_GET_MESSAGE_PROTOCOL_REQ_MSG +{ + USHORT Type; // QMUX type 0x0003 + USHORT Length; +} QMIWMS_GET_MESSAGE_PROTOCOL_REQ_MSG, *PQMIWMS_GET_MESSAGE_PROTOCOL_REQ_MSG; + +typedef struct _QMIWMS_GET_MESSAGE_PROTOCOL_RESP_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + USHORT QMUXResult; + USHORT QMUXError; + UCHAR TLV2Type; + USHORT TLV2Length; + UCHAR MessageProtocol; +} QMIWMS_GET_MESSAGE_PROTOCOL_RESP_MSG, *PQMIWMS_GET_MESSAGE_PROTOCOL_RESP_MSG; + +typedef struct _QMIWMS_GET_STORE_MAX_SIZE_REQ_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + UCHAR StorageType; +} QMIWMS_GET_STORE_MAX_SIZE_REQ_MSG, *PQMIWMS_GET_STORE_MAX_SIZE_REQ_MSG; + +typedef struct _QMIWMS_GET_STORE_MAX_SIZE_RESP_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + USHORT QMUXResult; + USHORT QMUXError; + UCHAR TLV2Type; + USHORT TLV2Length; + ULONG MemStoreMaxSize; +} QMIWMS_GET_STORE_MAX_SIZE_RESP_MSG, *PQMIWMS_GET_STORE_MAX_SIZE_RESP_MSG; + +typedef struct _REQUEST_TAG +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR TagType; +} REQUEST_TAG, *PREQUEST_TAG; + +typedef struct _QMIWMS_LIST_MESSAGES_REQ_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + UCHAR StorageType; +} QMIWMS_LIST_MESSAGES_REQ_MSG, *PQMIWMS_LIST_MESSAGES_REQ_MSG; + +typedef struct _QMIWMS_MESSAGE +{ + ULONG MessageIndex; + UCHAR TagType; +} QMIWMS_MESSAGE, *PQMIWMS_MESSAGE; + +typedef struct _QMIWMS_LIST_MESSAGES_RESP_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + USHORT QMUXResult; + USHORT QMUXError; + UCHAR TLV2Type; + USHORT TLV2Length; + ULONG NumMessages; +} QMIWMS_LIST_MESSAGES_RESP_MSG, *PQMIWMS_LIST_MESSAGES_RESP_MSG; + +typedef struct _QMIWMS_RAW_READ_REQ_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + UCHAR StorageType; + ULONG MemoryIndex; +} QMIWMS_RAW_READ_REQ_MSG, *PQMIWMS_RAW_READ_REQ_MSG; + +typedef struct _QMIWMS_RAW_READ_RESP_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + USHORT QMUXResult; + USHORT QMUXError; + UCHAR TLV2Type; + USHORT TLV2Length; + UCHAR TagType; + UCHAR Format; + USHORT MessageLength; + UCHAR Message; +} QMIWMS_RAW_READ_RESP_MSG, *PQMIWMS_RAW_READ_RESP_MSG; + +typedef struct _QMIWMS_MODIFY_TAG_REQ_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + UCHAR StorageType; + ULONG MemoryIndex; + UCHAR TagType; +} QMIWMS_MODIFY_TAG_REQ_MSG, *PQMIWMS_MODIFY_TAG_REQ_MSG; + +typedef struct _QMIWMS_MODIFY_TAG_RESP_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + USHORT QMUXResult; + USHORT QMUXError; +} QMIWMS_MODIFY_TAG_RESP_MSG, *PQMIWMS_MODIFY_TAG_RESP_MSG; + +typedef struct _QMIWMS_RAW_SEND_REQ_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + UCHAR SmsFormat; + USHORT SmsLength; + UCHAR SmsMessage; +} QMIWMS_RAW_SEND_REQ_MSG, *PQMIWMS_RAW_SEND_REQ_MSG; + +typedef struct _RAW_SEND_CAUSE_CODE +{ + UCHAR TLVType; + USHORT TLVLength; + USHORT CauseCode; +} RAW_SEND_CAUSE_CODE, *PRAW_SEND_CAUSE_CODE; + + +typedef struct _QMIWMS_RAW_SEND_RESP_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + USHORT QMUXResult; + USHORT QMUXError; +} QMIWMS_RAW_SEND_RESP_MSG, *PQMIWMS_RAW_SEND_RESP_MSG; + + +typedef struct _WMS_DELETE_MESSAGE_INDEX +{ + UCHAR TLVType; + USHORT TLVLength; + ULONG MemoryIndex; +} WMS_DELETE_MESSAGE_INDEX, *PWMS_DELETE_MESSAGE_INDEX; + +typedef struct _WMS_DELETE_MESSAGE_TAG +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR MessageTag; +} WMS_DELETE_MESSAGE_TAG, *PWMS_DELETE_MESSAGE_TAG; + +typedef struct _QMIWMS_DELETE_REQ_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + UCHAR StorageType; +} QMIWMS_DELETE_REQ_MSG, *PQMIWMS_DELETE_REQ_MSG; + +typedef struct _QMIWMS_DELETE_RESP_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + USHORT QMUXResult; + USHORT QMUXError; +} QMIWMS_DELETE_RESP_MSG, *PQMIWMS_DELETE_RESP_MSG; + + +typedef struct _QMIWMS_GET_SMSC_ADDRESS_REQ_MSG +{ + USHORT Type; + USHORT Length; +} QMIWMS_GET_SMSC_ADDRESS_REQ_MSG, *PQMIWMS_GET_SMSC_ADDRESS_REQ_MSG; + +typedef struct _QMIWMS_SMSC_ADDRESS +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR SMSCAddressType[3]; + UCHAR SMSCAddressLength; + UCHAR SMSCAddressDigits; +} QMIWMS_SMSC_ADDRESS, *PQMIWMS_SMSC_ADDRESS; + + +typedef struct _QMIWMS_GET_SMSC_ADDRESS_RESP_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + USHORT QMUXResult; + USHORT QMUXError; + UCHAR SMSCAddress; +} QMIWMS_GET_SMSC_ADDRESS_RESP_MSG, *PQMIWMS_GET_SMSC_ADDRESS_RESP_MSG; + +typedef struct _QMIWMS_SET_SMSC_ADDRESS_REQ_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + UCHAR SMSCAddress; +} QMIWMS_SET_SMSC_ADDRESS_REQ_MSG, *PQMIWMS_SET_SMSC_ADDRESS_REQ_MSG; + +typedef struct _QMIWMS_SET_SMSC_ADDRESS_RESP_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + USHORT QMUXResult; + USHORT QMUXError; +} QMIWMS_SET_SMSC_ADDRESS_RESP_MSG, *PQMIWMS_SET_SMSC_ADDRESS_RESP_MSG; + +typedef struct _QMIWMS_SET_EVENT_REPORT_REQ_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + UCHAR ReportNewMessage; +} QMIWMS_SET_EVENT_REPORT_REQ_MSG, *PQMIWMS_SET_EVENT_REPORT_REQ_MSG; + +typedef struct _QMIWMS_SET_EVENT_REPORT_RESP_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + USHORT QMUXResult; + USHORT QMUXError; +} QMIWMS_SET_EVENT_REPORT_RESP_MSG, *PQMIWMS_SET_EVENT_REPORT_RESP_MSG; + +typedef struct _QMIWMS_EVENT_REPORT_IND_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + UCHAR StorageType; + ULONG StorageIndex; +} QMIWMS_EVENT_REPORT_IND_MSG, *PQMIWMS_EVENT_REPORT_IND_MSG; +#endif + +// ======================= End of WMS ============================== + + +// ======================= NAS ============================== +#define QMINAS_SET_EVENT_REPORT_REQ 0x0002 +#define QMINAS_SET_EVENT_REPORT_RESP 0x0002 +#define QMINAS_EVENT_REPORT_IND 0x0002 +#define QMINAS_GET_SIGNAL_STRENGTH_REQ 0x0020 +#define QMINAS_GET_SIGNAL_STRENGTH_RESP 0x0020 +#define QMINAS_PERFORM_NETWORK_SCAN_REQ 0x0021 +#define QMINAS_PERFORM_NETWORK_SCAN_RESP 0x0021 +#define QMINAS_INITIATE_NW_REGISTER_REQ 0x0022 +#define QMINAS_INITIATE_NW_REGISTER_RESP 0x0022 +#define QMINAS_INITIATE_ATTACH_REQ 0x0023 +#define QMINAS_INITIATE_ATTACH_RESP 0x0023 +#define QMINAS_GET_SERVING_SYSTEM_REQ 0x0024 +#define QMINAS_GET_SERVING_SYSTEM_RESP 0x0024 +#define QMINAS_SERVING_SYSTEM_IND 0x0024 +#define QMINAS_GET_HOME_NETWORK_REQ 0x0025 +#define QMINAS_GET_HOME_NETWORK_RESP 0x0025 +#define QMINAS_GET_PREFERRED_NETWORK_REQ 0x0026 +#define QMINAS_GET_PREFERRED_NETWORK_RESP 0x0026 +#define QMINAS_SET_PREFERRED_NETWORK_REQ 0x0027 +#define QMINAS_SET_PREFERRED_NETWORK_RESP 0x0027 +#define QMINAS_GET_FORBIDDEN_NETWORK_REQ 0x0028 +#define QMINAS_GET_FORBIDDEN_NETWORK_RESP 0x0028 +#define QMINAS_SET_FORBIDDEN_NETWORK_REQ 0x0029 +#define QMINAS_SET_FORBIDDEN_NETWORK_RESP 0x0029 +#define QMINAS_SET_TECHNOLOGY_PREF_REQ 0x002A +#define QMINAS_SET_TECHNOLOGY_PREF_RESP 0x002A +#define QMINAS_GET_RF_BAND_INFO_REQ 0x0031 +#define QMINAS_GET_RF_BAND_INFO_RESP 0x0031 +#define QMINAS_GET_CELL_LOCATION_INFO_REQ 0x0043 +#define QMINAS_GET_CELL_LOCATION_INFO_RESP 0x0043 +#define QMINAS_GET_PLMN_NAME_REQ 0x0044 +#define QMINAS_GET_PLMN_NAME_RESP 0x0044 +#define QUECTEL_PACKET_TRANSFER_START_IND 0X100 +#define QUECTEL_PACKET_TRANSFER_END_IND 0X101 +#define QMINAS_GET_SYS_INFO_REQ 0x004D +#define QMINAS_GET_SYS_INFO_RESP 0x004D +#define QMINAS_SYS_INFO_IND 0x004E +#define QMINAS_GET_SIG_INFO_REQ 0x004F +#define QMINAS_GET_SIG_INFO_RESP 0x004F + +typedef struct _QMINAS_GET_HOME_NETWORK_REQ_MSG +{ + USHORT Type; // QMUX type 0x0003 + USHORT Length; +} __attribute__ ((packed)) QMINAS_GET_HOME_NETWORK_REQ_MSG, *PQMINAS_GET_HOME_NETWORK_REQ_MSG; + +typedef struct _HOME_NETWORK_SYSTEMID +{ + UCHAR TLVType; + USHORT TLVLength; + USHORT SystemID; + USHORT NetworkID; +} __attribute__ ((packed)) HOME_NETWORK_SYSTEMID, *PHOME_NETWORK_SYSTEMID; + +typedef struct _HOME_NETWORK +{ + UCHAR TLVType; + USHORT TLVLength; + USHORT MobileCountryCode; + USHORT MobileNetworkCode; + UCHAR NetworkDesclen; + UCHAR NetworkDesc; +} __attribute__ ((packed)) HOME_NETWORK, *PHOME_NETWORK; + +#if 0 +typedef struct _HOME_NETWORK_EXT +{ + UCHAR TLVType; + USHORT TLVLength; + USHORT MobileCountryCode; + USHORT MobileNetworkCode; + UCHAR NetworkDescDisp; + UCHAR NetworkDescEncoding; + UCHAR NetworkDesclen; + UCHAR NetworkDesc; +} HOME_NETWORK_EXT, *PHOME_NETWORK_EXT; + +typedef struct _QMINAS_GET_HOME_NETWORK_RESP_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + USHORT QMUXResult; + USHORT QMUXError; +} QMINAS_GET_HOME_NETWORK_RESP_MSG, *PQMINAS_GET_HOME_NETWORK_RESP_MSG; + +typedef struct _QMINAS_GET_PREFERRED_NETWORK_REQ_MSG +{ + USHORT Type; // QMUX type 0x0003 + USHORT Length; +} QMINAS_GET_PREFERRED_NETWORK_REQ_MSG, *PQMINAS_GET_PREFERRED_NETWORK_REQ_MSG; + + +typedef struct _PREFERRED_NETWORK +{ + USHORT MobileCountryCode; + USHORT MobileNetworkCode; + USHORT RadioAccess; +} PREFERRED_NETWORK, *PPREFERRED_NETWORK; + +typedef struct _QMINAS_GET_PREFERRED_NETWORK_RESP_MSG +{ + USHORT Type; // QMUX type 0x0003 + 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 + UCHAR TLV2Type; // 0x01 - required parameter + USHORT TLV2Length; // length of the mfr string + USHORT NumPreferredNetwork; +} QMINAS_GET_PREFERRED_NETWORK_RESP_MSG, *PQMINAS_GET_PREFERRED_NETWORK_RESP_MSG; + +typedef struct _QMINAS_GET_FORBIDDEN_NETWORK_REQ_MSG +{ + USHORT Type; // QMUX type 0x0003 + USHORT Length; +} QMINAS_GET_FORBIDDEN_NETWORK_REQ_MSG, *PQMINAS_GET_FORBIDDEN_NETWORK_REQ_MSG; + +typedef struct _FORBIDDEN_NETWORK +{ + USHORT MobileCountryCode; + USHORT MobileNetworkCode; +} FORBIDDEN_NETWORK, *PFORBIDDEN_NETWORK; + +typedef struct _QMINAS_GET_FORBIDDEN_NETWORK_RESP_MSG +{ + USHORT Type; // QMUX type 0x0003 + 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 + UCHAR TLV2Type; // 0x01 - required parameter + USHORT TLV2Length; // length of the mfr string + USHORT NumForbiddenNetwork; +} QMINAS_GET_FORBIDDEN_NETWORK_RESP_MSG, *PQMINAS_GET_FORBIDDEN_NETWORK_RESP_MSG; + +typedef struct _QMINAS_GET_SERVING_SYSTEM_REQ_MSG +{ + USHORT Type; // QMUX type 0x0003 + USHORT Length; +} QMINAS_GET_SERVING_SYSTEM_REQ_MSG, *PQMINAS_GET_SERVING_SYSTEM_REQ_MSG; + +typedef struct _QMINAS_ROAMING_INDICATOR_MSG +{ + UCHAR TLVType; // 0x01 - required parameter + USHORT TLVLength; // length of the mfr string + UCHAR RoamingIndicator; +} QMINAS_ROAMING_INDICATOR_MSG, *PQMINAS_ROAMING_INDICATOR_MSG; +#endif + +typedef struct _QMINAS_DATA_CAP +{ + UCHAR TLVType; // 0x01 - required parameter + USHORT TLVLength; // length of the mfr string + UCHAR DataCapListLen; + UCHAR DataCap; +} __attribute__ ((packed)) QMINAS_DATA_CAP, *PQMINAS_DATA_CAP; + +typedef struct _QMINAS_CURRENT_PLMN_MSG +{ + UCHAR TLVType; // 0x01 - required parameter + USHORT TLVLength; // length of the mfr string + USHORT MobileCountryCode; + USHORT MobileNetworkCode; + UCHAR NetworkDesclen; + UCHAR NetworkDesc; +} __attribute__ ((packed)) QMINAS_CURRENT_PLMN_MSG, *PQMINAS_CURRENT_PLMN_MSG; + +typedef struct _QMINAS_GET_SERVING_SYSTEM_RESP_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + USHORT QMUXResult; + USHORT QMUXError; +} __attribute__ ((packed)) QMINAS_GET_SERVING_SYSTEM_RESP_MSG, *PQMINAS_GET_SERVING_SYSTEM_RESP_MSG; + +typedef struct _SERVING_SYSTEM +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR RegistrationState; + UCHAR CSAttachedState; + UCHAR PSAttachedState; + UCHAR RegistredNetwork; + UCHAR InUseRadioIF; + UCHAR RadioIF; +} __attribute__ ((packed)) SERVING_SYSTEM, *PSERVING_SYSTEM; + +typedef struct _QMINAS_GET_SYS_INFO_RESP_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + USHORT QMUXResult; + USHORT QMUXError; +} __attribute__ ((packed)) QMINAS_GET_SYS_INFO_RESP_MSG, *PQMINAS_GET_SYS_INFO_RESP_MSG; + +typedef struct _QMINAS_SYS_INFO_IND_MSG +{ + USHORT Type; + USHORT Length; +} __attribute__ ((packed)) QMINAS_SYS_INFO_IND_MSG, *PQMINAS_SYS_INFO_IND_MSG; + +typedef struct _SERVICE_STATUS_INFO +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR SrvStatus; + UCHAR true_srv_status; + UCHAR IsPrefDataPath; +} __attribute__ ((packed)) SERVICE_STATUS_INFO, *PSERVICE_STATUS_INFO; + +typedef struct _CDMA_SYSTEM_INFO +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR SrvDomainValid; + UCHAR SrvDomain; + UCHAR SrvCapabilityValid; + UCHAR SrvCapability; + UCHAR RoamStatusValid; + UCHAR RoamStatus; + UCHAR IsSysForbiddenValid; + UCHAR IsSysForbidden; + UCHAR IsSysPrlMatchValid; + UCHAR IsSysPrlMatch; + UCHAR PRevInUseValid; + UCHAR PRevInUse; + UCHAR BSPRevValid; + UCHAR BSPRev; + UCHAR CCSSupportedValid; + UCHAR CCSSupported; + UCHAR CDMASysIdValid; + USHORT SID; + USHORT NID; + UCHAR BSInfoValid; + USHORT BaseID; + ULONG BaseLAT; + ULONG BaseLONG; + UCHAR PacketZoneValid; + USHORT PacketZone; + UCHAR NetworkIdValid; + UCHAR MCC[3]; + UCHAR MNC[3]; +} __attribute__ ((packed)) CDMA_SYSTEM_INFO, *PCDMA_SYSTEM_INFO; + +typedef struct _HDR_SYSTEM_INFO +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR SrvDomainValid; + UCHAR SrvDomain; + UCHAR SrvCapabilityValid; + UCHAR SrvCapability; + UCHAR RoamStatusValid; + UCHAR RoamStatus; + UCHAR IsSysForbiddenValid; + UCHAR IsSysForbidden; + UCHAR IsSysPrlMatchValid; + UCHAR IsSysPrlMatch; + UCHAR HdrPersonalityValid; + UCHAR HdrPersonality; + UCHAR HdrActiveProtValid; + UCHAR HdrActiveProt; + UCHAR is856SysIdValid; + UCHAR is856SysId[16]; +} __attribute__ ((packed)) HDR_SYSTEM_INFO, *PHDR_SYSTEM_INFO; + +typedef struct _GSM_SYSTEM_INFO +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR SrvDomainValid; + UCHAR SrvDomain; + UCHAR SrvCapabilityValid; + UCHAR SrvCapability; + UCHAR RoamStatusValid; + UCHAR RoamStatus; + UCHAR IsSysForbiddenValid; + UCHAR IsSysForbidden; + UCHAR LacValid; + USHORT Lac; + UCHAR CellIdValid; + ULONG CellId; + UCHAR RegRejectInfoValid; + UCHAR RejectSrvDomain; + UCHAR RejCause; + UCHAR NetworkIdValid; + UCHAR MCC[3]; + UCHAR MNC[3]; + UCHAR EgprsSuppValid; + UCHAR EgprsSupp; + UCHAR DtmSuppValid; + UCHAR DtmSupp; +} __attribute__ ((packed)) GSM_SYSTEM_INFO, *PGSM_SYSTEM_INFO; + +typedef struct _WCDMA_SYSTEM_INFO +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR SrvDomainValid; + UCHAR SrvDomain; + UCHAR SrvCapabilityValid; + UCHAR SrvCapability; + UCHAR RoamStatusValid; + UCHAR RoamStatus; + UCHAR IsSysForbiddenValid; + UCHAR IsSysForbidden; + UCHAR LacValid; + USHORT Lac; + UCHAR CellIdValid; + ULONG CellId; + UCHAR RegRejectInfoValid; + UCHAR RejectSrvDomain; + UCHAR RejCause; + UCHAR NetworkIdValid; + UCHAR MCC[3]; + UCHAR MNC[3]; + UCHAR HsCallStatusValid; + UCHAR HsCallStatus; + UCHAR HsIndValid; + UCHAR HsInd; + UCHAR PscValid; + UCHAR Psc; +} __attribute__ ((packed)) WCDMA_SYSTEM_INFO, *PWCDMA_SYSTEM_INFO; + +typedef struct _LTE_SYSTEM_INFO +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR SrvDomainValid; + UCHAR SrvDomain; + UCHAR SrvCapabilityValid; + UCHAR SrvCapability; + UCHAR RoamStatusValid; + UCHAR RoamStatus; + UCHAR IsSysForbiddenValid; + UCHAR IsSysForbidden; + UCHAR LacValid; + USHORT Lac; + UCHAR CellIdValid; + ULONG CellId; + UCHAR RegRejectInfoValid; + UCHAR RejectSrvDomain; + UCHAR RejCause; + UCHAR NetworkIdValid; + UCHAR MCC[3]; + UCHAR MNC[3]; + UCHAR TacValid; + USHORT Tac; +} __attribute__ ((packed)) LTE_SYSTEM_INFO, *PLTE_SYSTEM_INFO; + +typedef struct _TDSCDMA_SYSTEM_INFO +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR SrvDomainValid; + UCHAR SrvDomain; + UCHAR SrvCapabilityValid; + UCHAR SrvCapability; + UCHAR RoamStatusValid; + UCHAR RoamStatus; + UCHAR IsSysForbiddenValid; + UCHAR IsSysForbidden; + UCHAR LacValid; + USHORT Lac; + UCHAR CellIdValid; + ULONG CellId; + UCHAR RegRejectInfoValid; + UCHAR RejectSrvDomain; + UCHAR RejCause; + UCHAR NetworkIdValid; + UCHAR MCC[3]; + UCHAR MNC[3]; + UCHAR HsCallStatusValid; + UCHAR HsCallStatus; + UCHAR HsIndValid; + UCHAR HsInd; + UCHAR CellParameterIdValid; + USHORT CellParameterId; + UCHAR CellBroadcastCapValid; + ULONG CellBroadcastCap; + UCHAR CsBarStatusValid; + ULONG CsBarStatus; + UCHAR PsBarStatusValid; + ULONG PsBarStatus; + UCHAR CipherDomainValid; + UCHAR CipherDomain; +} __attribute__ ((packed)) TDSCDMA_SYSTEM_INFO, *PTDSCDMA_SYSTEM_INFO; + +typedef enum { + NAS_SYS_SRV_STATUS_NO_SRV_V01 = 0, + NAS_SYS_SRV_STATUS_LIMITED_V01 = 1, + NAS_SYS_SRV_STATUS_SRV_V01 = 2, + NAS_SYS_SRV_STATUS_LIMITED_REGIONAL_V01 = 3, + NAS_SYS_SRV_STATUS_PWR_SAVE_V01 = 4, +}nas_service_status_enum_type_v01; + +typedef enum { + SYS_SRV_DOMAIN_NO_SRV_V01 = 0, + SYS_SRV_DOMAIN_CS_ONLY_V01 = 1, + SYS_SRV_DOMAIN_PS_ONLY_V01 = 2, + SYS_SRV_DOMAIN_CS_PS_V01 = 3, + SYS_SRV_DOMAIN_CAMPED_V01 = 4, +}nas_service_domain_enum_type_v01; + +typedef enum { + QMI_NAS_RADIO_INTERFACE_UNKNOWN = -1, + QMI_NAS_RADIO_INTERFACE_NONE = 0x00, + QMI_NAS_RADIO_INTERFACE_CDMA_1X = 0x01, + QMI_NAS_RADIO_INTERFACE_CDMA_1XEVDO = 0x02, + QMI_NAS_RADIO_INTERFACE_AMPS = 0x03, + QMI_NAS_RADIO_INTERFACE_GSM = 0x04, + QMI_NAS_RADIO_INTERFACE_UMTS = 0x05, + QMI_NAS_RADIO_INTERFACE_LTE = 0x08, + QMI_NAS_RADIO_INTERFACE_TD_SCDMA = 0x09, + QMI_NAS_RADIO_INTERFACE_5GNR = 0x0C, +} QMI_NAS_RADIO_INTERFACE_E; + +typedef enum { + QMI_NAS_ACTIVE_BAND_BC_0 = 0, + QMI_NAS_ACTIVE_BAND_BC_1 = 1, + QMI_NAS_ACTIVE_BAND_BC_2 = 2, + QMI_NAS_ACTIVE_BAND_BC_3 = 3, + QMI_NAS_ACTIVE_BAND_BC_4 = 4, + QMI_NAS_ACTIVE_BAND_BC_5 = 5, + QMI_NAS_ACTIVE_BAND_BC_6 = 6, + QMI_NAS_ACTIVE_BAND_BC_7 = 7, + QMI_NAS_ACTIVE_BAND_BC_8 = 8, + QMI_NAS_ACTIVE_BAND_BC_9 = 9, + QMI_NAS_ACTIVE_BAND_BC_10 = 10, + QMI_NAS_ACTIVE_BAND_BC_11 = 11, + QMI_NAS_ACTIVE_BAND_BC_12 = 12, + QMI_NAS_ACTIVE_BAND_BC_13 = 13, + QMI_NAS_ACTIVE_BAND_BC_14 = 14, + QMI_NAS_ACTIVE_BAND_BC_15 = 15, + QMI_NAS_ACTIVE_BAND_BC_16 = 16, + QMI_NAS_ACTIVE_BAND_BC_17 = 17, + QMI_NAS_ACTIVE_BAND_BC_18 = 18, + QMI_NAS_ACTIVE_BAND_BC_19 = 19, + QMI_NAS_ACTIVE_BAND_GSM_450 = 40, + QMI_NAS_ACTIVE_BAND_GSM_480 = 41, + QMI_NAS_ACTIVE_BAND_GSM_750 = 42, + QMI_NAS_ACTIVE_BAND_GSM_850 = 43, + QMI_NAS_ACTIVE_BAND_GSM_900_EXTENDED = 44, + QMI_NAS_ACTIVE_BAND_GSM_900_PRIMARY = 45, + QMI_NAS_ACTIVE_BAND_GSM_900_RAILWAYS = 46, + QMI_NAS_ACTIVE_BAND_GSM_DCS_1800 = 47, + QMI_NAS_ACTIVE_BAND_GSM_PCS_1900 = 48, + QMI_NAS_ACTIVE_BAND_WCDMA_2100 = 80, + QMI_NAS_ACTIVE_BAND_WCDMA_PCS_1900 = 81, + QMI_NAS_ACTIVE_BAND_WCDMA_DCS_1800 = 82, + QMI_NAS_ACTIVE_BAND_WCDMA_1700_US = 83, + QMI_NAS_ACTIVE_BAND_WCDMA_850 = 84, + QMI_NAS_ACTIVE_BAND_WCDMA_800 = 85, + QMI_NAS_ACTIVE_BAND_WCDMA_2600 = 86, + QMI_NAS_ACTIVE_BAND_WCDMA_900 = 87, + QMI_NAS_ACTIVE_BAND_WCDMA_1700_JAPAN = 88, + QMI_NAS_ACTIVE_BAND_WCDMA_1500_JAPAN = 90, + QMI_NAS_ACTIVE_BAND_WCDMA_850_JAPAN = 91, + QMI_NAS_ACTIVE_BAND_EUTRAN_1 = 120, + QMI_NAS_ACTIVE_BAND_EUTRAN_2 = 121, + QMI_NAS_ACTIVE_BAND_EUTRAN_3 = 122, + QMI_NAS_ACTIVE_BAND_EUTRAN_4 = 123, + QMI_NAS_ACTIVE_BAND_EUTRAN_5 = 124, + QMI_NAS_ACTIVE_BAND_EUTRAN_6 = 125, + QMI_NAS_ACTIVE_BAND_EUTRAN_7 = 126, + QMI_NAS_ACTIVE_BAND_EUTRAN_8 = 127, + QMI_NAS_ACTIVE_BAND_EUTRAN_9 = 128, + QMI_NAS_ACTIVE_BAND_EUTRAN_10 = 129, + QMI_NAS_ACTIVE_BAND_EUTRAN_11 = 130, + QMI_NAS_ACTIVE_BAND_EUTRAN_12 = 131, + QMI_NAS_ACTIVE_BAND_EUTRAN_13 = 132, + QMI_NAS_ACTIVE_BAND_EUTRAN_14 = 133, + QMI_NAS_ACTIVE_BAND_EUTRAN_17 = 134, + QMI_NAS_ACTIVE_BAND_EUTRAN_18 = 143, + QMI_NAS_ACTIVE_BAND_EUTRAN_19 = 144, + QMI_NAS_ACTIVE_BAND_EUTRAN_20 = 145, + QMI_NAS_ACTIVE_BAND_EUTRAN_21 = 146, + QMI_NAS_ACTIVE_BAND_EUTRAN_23 = 152, + QMI_NAS_ACTIVE_BAND_EUTRAN_24 = 147, + QMI_NAS_ACTIVE_BAND_EUTRAN_25 = 148, + QMI_NAS_ACTIVE_BAND_EUTRAN_26 = 153, + QMI_NAS_ACTIVE_BAND_EUTRAN_27 = 164, + QMI_NAS_ACTIVE_BAND_EUTRAN_28 = 158, + QMI_NAS_ACTIVE_BAND_EUTRAN_29 = 159, + QMI_NAS_ACTIVE_BAND_EUTRAN_30 = 160, + QMI_NAS_ACTIVE_BAND_EUTRAN_31 = 165, + QMI_NAS_ACTIVE_BAND_EUTRAN_32 = 154, + QMI_NAS_ACTIVE_BAND_EUTRAN_33 = 135, + QMI_NAS_ACTIVE_BAND_EUTRAN_34 = 136, + QMI_NAS_ACTIVE_BAND_EUTRAN_35 = 137, + QMI_NAS_ACTIVE_BAND_EUTRAN_36 = 138, + QMI_NAS_ACTIVE_BAND_EUTRAN_37 = 139, + QMI_NAS_ACTIVE_BAND_EUTRAN_38 = 140, + QMI_NAS_ACTIVE_BAND_EUTRAN_39 = 141, + QMI_NAS_ACTIVE_BAND_EUTRAN_40 = 142, + QMI_NAS_ACTIVE_BAND_EUTRAN_41 = 149, + QMI_NAS_ACTIVE_BAND_EUTRAN_42 = 150, + QMI_NAS_ACTIVE_BAND_EUTRAN_43 = 151, + QMI_NAS_ACTIVE_BAND_EUTRAN_46 = 163, + QMI_NAS_ACTIVE_BAND_EUTRAN_47 = 166, + QMI_NAS_ACTIVE_BAND_EUTRAN_48 = 167, + QMI_NAS_ACTIVE_BAND_EUTRAN_66 = 161, + QMI_NAS_ACTIVE_BAND_EUTRAN_71 = 168, + QMI_NAS_ACTIVE_BAND_EUTRAN_125 = 155, + QMI_NAS_ACTIVE_BAND_EUTRAN_126 = 156, + QMI_NAS_ACTIVE_BAND_EUTRAN_127 = 157, + QMI_NAS_ACTIVE_BAND_EUTRAN_250 = 162, + QMI_NAS_ACTIVE_BAND_TDSCDMA_A = 200, + QMI_NAS_ACTIVE_BAND_TDSCDMA_B = 201, + QMI_NAS_ACTIVE_BAND_TDSCDMA_C = 202, + QMI_NAS_ACTIVE_BAND_TDSCDMA_D = 203, + QMI_NAS_ACTIVE_BAND_TDSCDMA_E = 204, + QMI_NAS_ACTIVE_BAND_TDSCDMA_F = 205, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_1 = 250, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_2 = 251, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_3 = 252, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_5 = 253, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_7 = 254, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_8 = 255, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_20 = 256, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_28 = 257, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_38 = 258, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_41 = 259, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_50 = 260, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_51 = 261, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_66 = 262, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_70 = 263, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_71 = 264, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_74 = 265, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_75 = 266, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_76 = 267, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_77 = 268, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_78 = 269, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_79 = 270, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_80 = 271, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_81 = 272, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_82 = 273, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_83 = 274, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_84 = 275, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_85 = 276, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_257= 277, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_258= 278, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_259= 279, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_260= 280, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_261= 281, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_12 = 282, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_25 = 283, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_34 = 284, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_39 = 285, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_40 = 286, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_65 = 287, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_86 = 288, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_48 = 289, + QMI_NAS_ACTIVE_BAND_NR5G_BAND_14 = 290 +} QMI_NAS_ACTIVE_BAND_E; + +typedef struct { + UCHAR TLVType; + USHORT TLVLength; + + uint8_t srv_domain_valid; + uint8_t srv_domain; + uint8_t srv_capability_valid; + uint8_t srv_capability; + uint8_t roam_status_valid; + uint8_t roam_status; + uint8_t is_sys_forbidden_valid; + uint8_t is_sys_forbidden; + + uint8_t lac_valid; + uint16_t lac; + uint8_t cell_id_valid; + uint32_t cell_id; + uint8_t reg_reject_info_valid; + uint8_t reject_srv_domain; + uint8_t rej_cause; + uint8_t network_id_valid; + UCHAR MCC[3]; + UCHAR MNC[3]; + + uint8_t tac_valid; + uint16_t tac; +} __attribute__ ((packed)) NR5G_SYSTEM_INFO, *PNR5G_SYSTEM_INFO; + +#if 0 +typedef struct _QMINAS_SERVING_SYSTEM_IND_MSG +{ + USHORT Type; + USHORT Length; +} QMINAS_SERVING_SYSTEM_IND_MSG, *PQMINAS_SERVING_SYSTEM_IND_MSG; + +typedef struct _QMINAS_SET_PREFERRED_NETWORK_REQ_MSG +{ + USHORT Type; // QMUX type 0x0003 + USHORT Length; + UCHAR TLVType; // 0x02 - result code + USHORT TLVLength; // 4 + USHORT NumPreferredNetwork; + USHORT MobileCountryCode; + USHORT MobileNetworkCode; + USHORT RadioAccess; +} QMINAS_SET_PREFERRED_NETWORK_REQ_MSG, *PQMINAS_SET_PREFERRED_NETWORK_REQ_MSG; + +typedef struct _QMINAS_SET_PREFERRED_NETWORK_RESP_MSG +{ + USHORT Type; // QMUX type 0x0003 + 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 +} QMINAS_SET_PREFERRED_NETWORK_RESP_MSG, *PQMINAS_SET_PREFERRED_NETWORK_RESP_MSG; + +typedef struct _QMINAS_SET_FORBIDDEN_NETWORK_REQ_MSG +{ + USHORT Type; // QMUX type 0x0003 + USHORT Length; + UCHAR TLVType; // 0x02 - result code + USHORT TLVLength; // 4 + USHORT NumForbiddenNetwork; + USHORT MobileCountryCode; + USHORT MobileNetworkCode; +} QMINAS_SET_FORBIDDEN_NETWORK_REQ_MSG, *PQMINAS_SET_FORBIDDEN_NETWORK_REQ_MSG; + +typedef struct _QMINAS_SET_FORBIDDEN_NETWORK_RESP_MSG +{ + USHORT Type; // QMUX type 0x0003 + 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 +} QMINAS_SET_FORBIDDEN_NETWORK_RESP_MSG, *PQMINAS_SET_FORBIDDEN_NETWORK_RESP_MSG; + +typedef struct _QMINAS_PERFORM_NETWORK_SCAN_REQ_MSG +{ + USHORT Type; // QMUX type 0x0003 + USHORT Length; +} QMINAS_PERFORM_NETWORK_SCAN_REQ_MSG, *PQMINAS_PERFORM_NETWORK_SCAN_REQ_MSG; + +typedef struct _VISIBLE_NETWORK +{ + USHORT MobileCountryCode; + USHORT MobileNetworkCode; + UCHAR NetworkStatus; + UCHAR NetworkDesclen; +} VISIBLE_NETWORK, *PVISIBLE_NETWORK; + +typedef struct _QMINAS_PERFORM_NETWORK_SCAN_RESP_MSG +{ + USHORT Type; // QMUX type 0x0003 + 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 +} QMINAS_PERFORM_NETWORK_SCAN_RESP_MSG, *PQMINAS_PERFORM_NETWORK_SCAN_RESP_MSG; + +typedef struct _QMINAS_PERFORM_NETWORK_SCAN_NETWORK_INFO +{ + UCHAR TLVType; // 0x010 - required parameter + USHORT TLVLength; // length + USHORT NumNetworkInstances; +} QMINAS_PERFORM_NETWORK_SCAN_NETWORK_INFO, *PQMINAS_PERFORM_NETWORK_SCAN_NETWORK_INFO; + +typedef struct _QMINAS_PERFORM_NETWORK_SCAN_RAT_INFO +{ + UCHAR TLVType; // 0x011 - required parameter + USHORT TLVLength; // length + USHORT NumInst; +} QMINAS_PERFORM_NETWORK_SCAN_RAT_INFO, *PQMINAS_PERFORM_NETWORK_SCAN_RAT_INFO; + +typedef struct _QMINAS_PERFORM_NETWORK_SCAN_RAT +{ + USHORT MCC; + USHORT MNC; + UCHAR RAT; +} QMINAS_PERFORM_NETWORK_SCAN_RAT, *PQMINAS_PERFORM_NETWORK_SCAN_RAT; + + +typedef struct _QMINAS_MANUAL_NW_REGISTER +{ + UCHAR TLV2Type; // 0x02 - result code + USHORT TLV2Length; // 4 + USHORT MobileCountryCode; + USHORT MobileNetworkCode; + UCHAR RadioAccess; +} QMINAS_MANUAL_NW_REGISTER, *PQMINAS_MANUAL_NW_REGISTER; + +typedef struct _QMINAS_INITIATE_NW_REGISTER_REQ_MSG +{ + USHORT Type; // QMUX type 0x0003 + USHORT Length; + UCHAR TLVType; // 0x02 - result code + USHORT TLVLength; // 4 + UCHAR RegisterAction; +} QMINAS_INITIATE_NW_REGISTER_REQ_MSG, *PQMINAS_INITIATE_NW_REGISTER_REQ_MSG; + +typedef struct _QMINAS_INITIATE_NW_REGISTER_RESP_MSG +{ + USHORT Type; // QMUX type 0x0003 + 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 +} QMINAS_INITIATE_NW_REGISTER_RESP_MSG, *PQMINAS_INITIATE_NW_REGISTER_RESP_MSG; + +typedef struct _QMINAS_SET_TECHNOLOGY_PREF_REQ_MSG +{ + USHORT Type; // QMUX type 0x0003 + USHORT Length; + UCHAR TLVType; // 0x02 - result code + USHORT TLVLength; // 4 + USHORT TechPref; + UCHAR Duration; +} QMINAS_SET_TECHNOLOGY_PREF_REQ_MSG, *PQMINAS_SET_TECHNOLOGY_PREF_REQ_MSG; + +typedef struct _QMINAS_SET_TECHNOLOGY_PREF_RESP_MSG +{ + USHORT Type; // QMUX type 0x0003 + 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 +} QMINAS_SET_TECHNOLOGY_PREF_RESP_MSG, *PQMINAS_SET_TECHNOLOGY_PREF_RESP_MSG; + +typedef struct _QMINAS_GET_SIGNAL_STRENGTH_REQ_MSG +{ + USHORT Type; // QMUX type 0x0003 + USHORT Length; +} QMINAS_GET_SIGNAL_STRENGTH_REQ_MSG, *PQMINAS_GET_SIGNAL_STRENGTH_REQ_MSG; + +typedef struct _QMINAS_SIGNAL_STRENGTH +{ + CHAR SigStrength; + UCHAR RadioIf; +} QMINAS_SIGNAL_STRENGTH, *PQMINAS_SIGNAL_STRENGTH; + +typedef struct _QMINAS_SIGNAL_STRENGTH_LIST +{ + UCHAR TLV3Type; + USHORT TLV3Length; + USHORT NumInstance; +} QMINAS_SIGNAL_STRENGTH_LIST, *PQMINAS_SIGNAL_STRENGTH_LIST; + + +typedef struct _QMINAS_GET_SIGNAL_STRENGTH_RESP_MSG +{ + USHORT Type; // QMUX type 0x0003 + 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 + UCHAR TLV2Type; + USHORT TLV2Length; + CHAR SignalStrength; + UCHAR RadioIf; +} QMINAS_GET_SIGNAL_STRENGTH_RESP_MSG, *PQMINAS_GET_SIGNAL_STRENGTH_RESP_MSG; + + +typedef struct _QMINAS_SET_EVENT_REPORT_REQ_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + UCHAR ReportSigStrength; + UCHAR NumTresholds; + CHAR TresholdList[2]; +} QMINAS_SET_EVENT_REPORT_REQ_MSG, *PQMINAS_SET_EVENT_REPORT_REQ_MSG; + +typedef struct _QMINAS_SET_EVENT_REPORT_RESP_MSG +{ + USHORT Type; // QMUX type 0x0003 + 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 +} QMINAS_SET_EVENT_REPORT_RESP_MSG, *PQMINAS_SET_EVENT_REPORT_RESP_MSG; + +typedef struct _QMINAS_SIGNAL_STRENGTH_TLV +{ + UCHAR TLVType; + USHORT TLVLength; + CHAR SigStrength; + UCHAR RadioIf; +} QMINAS_SIGNAL_STRENGTH_TLV, *PQMINAS_SIGNAL_STRENGTH_TLV; + +typedef struct _QMINAS_REJECT_CAUSE_TLV +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR ServiceDomain; + USHORT RejectCause; +} QMINAS_REJECT_CAUSE_TLV, *PQMINAS_REJECT_CAUSE_TLV; + +typedef struct _QMINAS_EVENT_REPORT_IND_MSG +{ + USHORT Type; + USHORT Length; +} QMINAS_EVENT_REPORT_IND_MSG, *PQMINAS_EVENT_REPORT_IND_MSG; + +typedef struct _QMINAS_GET_RF_BAND_INFO_REQ_MSG +{ + USHORT Type; + USHORT Length; +} QMINAS_GET_RF_BAND_INFO_REQ_MSG, *PQMINAS_GET_RF_BAND_INFO_REQ_MSG; + +typedef struct _QMINASRF_BAND_INFO +{ + UCHAR RadioIf; + USHORT ActiveBand; + USHORT ActiveChannel; +} QMINASRF_BAND_INFO, *PQMINASRF_BAND_INFO; + +typedef struct _QMINAS_GET_RF_BAND_INFO_RESP_MSG +{ + USHORT Type; // QMUX type 0x0003 + 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 + UCHAR TLV2Type; + USHORT TLV2Length; + UCHAR NumInstances; +} QMINAS_GET_RF_BAND_INFO_RESP_MSG, *PQMINAS_GET_RF_BAND_INFO_RESP_MSG; + + +typedef struct _QMINAS_GET_PLMN_NAME_REQ_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + USHORT MCC; + USHORT MNC; +} QMINAS_GET_PLMN_NAME_REQ_MSG, *PQMINAS_GET_PLMN_NAME_REQ_MSG; + +typedef struct _QMINAS_GET_PLMN_NAME_RESP_MSG +{ + 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 +} QMINAS_GET_PLMN_NAME_RESP_MSG, *PQMINAS_GET_PLMN_NAME_RESP_MSG; + +typedef struct _QMINAS_GET_PLMN_NAME_SPN +{ + UCHAR TLVType; + USHORT TLVLength; + UCHAR SPN_Enc; + UCHAR SPN_Len; +} QMINAS_GET_PLMN_NAME_SPN, *PQMINAS_GET_PLMN_NAME_SPN; + +typedef struct _QMINAS_GET_PLMN_NAME_PLMN +{ + UCHAR PLMN_Enc; + UCHAR PLMN_Ci; + UCHAR PLMN_SpareBits; + UCHAR PLMN_Len; +} QMINAS_GET_PLMN_NAME_PLMN, *PQMINAS_GET_PLMN_NAME_PLMN; + +typedef struct _QMINAS_INITIATE_ATTACH_REQ_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + UCHAR PsAttachAction; +} QMINAS_INITIATE_ATTACH_REQ_MSG, *PQMINAS_INITIATE_ATTACH_REQ_MSG; + +typedef struct _QMINAS_INITIATE_ATTACH_RESP_MSG +{ + USHORT Type; // QMUX type 0x0003 + 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 +} QMINAS_INITIATE_ATTACH_RESP_MSG, *PQMINAS_INITIATE_ATTACH_RESP_MSG; +#endif +typedef struct { + UCHAR TLVType; + USHORT TLVLength; + CHAR rssi; + SHORT ecio; +} __attribute__ ((packed)) QMINAS_SIG_INFO_CDMA_TLV_MSG, *PQMINAS_SIG_INFO_CDMA_TLV_MSG; + +typedef struct { + UCHAR TLVType; + USHORT TLVLength; + CHAR rssi; + SHORT ecio; + CHAR sinr; + INT io; +} __attribute__ ((packed)) QMINAS_SIG_INFO_HDR_TLV_MSG, *PQMINAS_SIG_INFO_HDR_TLV_MSG; + +typedef struct { + UCHAR TLVType; + USHORT TLVLength; + CHAR rssi; +} __attribute__ ((packed)) QMINAS_SIG_INFO_GSM_TLV_MSG, *PQMINAS_SIG_INFO_GSM_TLV_MSG; + +typedef struct { + UCHAR TLVType; + USHORT TLVLength; + CHAR rssi; + SHORT ecio; +} __attribute__ ((packed)) QMINAS_SIG_INFO_WCDMA_TLV_MSG, *PQMINAS_SIG_INFO_WCDMA_TLV_MSG; + +typedef struct { + UCHAR TLVType; + USHORT TLVLength; + CHAR rssi; + CHAR rsrq; + SHORT rsrp; + SHORT snr; +} __attribute__ ((packed)) QMINAS_SIG_INFO_LTE_TLV_MSG, *PQMINAS_SIG_INFO_LTE_TLV_MSG; + +typedef struct { + UCHAR TLVType; + USHORT TLVLength; + CHAR rscp; +} __attribute__ ((packed)) QMINAS_SIG_INFO_TDSCDMA_TLV_MSG, *PQMINAS_SIG_INFO_TDSCDMA_TLV_MSG; + +typedef struct { + UCHAR TLVType; + USHORT TLVLength; + SHORT rsrp; + SHORT snr; +} __attribute__ ((packed)) QMINAS_SIG_INFO_5G_NSA_TLV_MSG, *PQMINAS_SIG_INFO_5G_NSA_TLV_MSG; + +typedef struct { + UCHAR TLVType; + USHORT TLVLength; + SHORT nr5g_rsrq; +} __attribute__ ((packed)) QMINAS_SIG_INFO_5G_SA_TLV_MSG, *PQMINAS_SIG_INFO_5G_SA_TLV_MSG; + +typedef struct { + uint8 radio_if; + uint16 active_band; + uint16 active_channel; +} __attribute__ ((packed)) NasGetRfBandInfo; + +typedef struct { + UCHAR TLVType; + USHORT TLVLength; + + uint8 num_instances; + NasGetRfBandInfo bands_array[0]; +} __attribute__ ((packed)) NasGetRfBandInfoList; + +typedef struct { + uint8 radio_if; + uint16 dedicated_band; +} __attribute__ ((packed)) NasGetRfBandInfoDedicated; + +typedef struct { + UCHAR TLVType; + USHORT TLVLength; + + uint8 num_instances; + NasGetRfBandInfoDedicated bands_array[0]; +} __attribute__ ((packed)) NasGetRfBandInfoDedicatedList; + +typedef struct { + uint8 radio_if; + uint16 active_band; + uint32 active_channel; +} __attribute__ ((packed)) NasGetRfBandInfoExtended; + +typedef struct { + UCHAR TLVType; + USHORT TLVLength; + + uint8 num_instances; + NasGetRfBandInfoExtended bands_array[0]; +} __attribute__ ((packed)) NasGetRfBandInfoExtendedList; + +typedef struct { + uint8 radio_if; + uint32 bandwidth; +} __attribute__ ((packed)) NasGetRfBandInfoBandWidth; + +typedef struct { + UCHAR TLVType; + USHORT TLVLength; + + uint8 num_instances; + NasGetRfBandInfoBandWidth bands_array[0]; +} __attribute__ ((packed)) NasGetRfBandInfoBandWidthList; + +typedef struct { + UCHAR TLVType; + USHORT TLVLength; + + uint8 plmn[3]; + uint8 tac[3]; + uint64 global_cell_id; + uint16 physical_cell_id; + int16 rsrq; + int16 rsrp; + int16 snr; +} __attribute__ ((packed)) NasGetCellLocationNr5gServingCell; + +typedef struct { + uint16 physical_cell_id; + int16 rsrq; + int16 rsrp; + int16 rssi; + int16 cell_selection_rx_level; +} __attribute__ ((packed)) NasGetCellLocationLteInfoCell; + +typedef struct { + UCHAR TLVType; + USHORT TLVLength; + + uint8 ue_in_idle; + uint8 plmn[3]; + uint16 tracking_area_code; + uint32 global_cell_id; + uint16 absolute_rf_channel_number; + uint16 serving_cell_id; + uint8 cell_reselection_priority; + uint8 s_non_intra_search_threshold; + uint8 serving_cell_low_threshold; + uint8 s_intra_search_threshold; + uint8 cells_len; + NasGetCellLocationLteInfoCell cells_array[0]; +} __attribute__ ((packed)) NasGetCellLocationLteInfoIntrafrequency; + +typedef struct _QmiMessageNasGetCellLocationInfoOutputInterfrequencyLteInfoFrequencyElement { + uint16 eutra_absolute_rf_channel_number; + uint8 cell_selection_rx_level_low_threshold; + uint8 cell_selection_rx_level_high_threshold; + uint8 cell_reselection_priority; + uint8 cells_len; + NasGetCellLocationLteInfoCell cells_array[0]; +} __attribute__ ((packed)) NasGetCellLocationLteInfoInterfrequencyFrequencyElement; + +typedef struct { + UCHAR TLVType; + USHORT TLVLength; + + uint8 ue_in_idle; + uint8 freqs_len; + NasGetCellLocationLteInfoInterfrequencyFrequencyElement freqs[0]; +} __attribute__ ((packed)) NasGetCellLocationLteInfoInterfrequency; + +// ======================= End of NAS ============================== + +// ======================= UIM ============================== +#define QMIUIM_READ_TRANSPARENT_REQ 0x0020 +#define QMIUIM_READ_TRANSPARENT_RESP 0x0020 +#define QMIUIM_READ_TRANSPARENT_IND 0x0020 +#define QMIUIM_READ_RECORD_REQ 0x0021 +#define QMIUIM_READ_RECORD_RESP 0x0021 +#define QMIUIM_READ_RECORD_IND 0x0021 +#define QMIUIM_WRITE_TRANSPARENT_REQ 0x0022 +#define QMIUIM_WRITE_TRANSPARENT_RESP 0x0022 +#define QMIUIM_WRITE_TRANSPARENT_IND 0x0022 +#define QMIUIM_WRITE_RECORD_REQ 0x0023 +#define QMIUIM_WRITE_RECORD_RESP 0x0023 +#define QMIUIM_WRITE_RECORD_IND 0x0023 +#define QMIUIM_SET_PIN_PROTECTION_REQ 0x0025 +#define QMIUIM_SET_PIN_PROTECTION_RESP 0x0025 +#define QMIUIM_SET_PIN_PROTECTION_IND 0x0025 +#define QMIUIM_VERIFY_PIN_REQ 0x0026 +#define QMIUIM_VERIFY_PIN_RESP 0x0026 +#define QMIUIM_VERIFY_PIN_IND 0x0026 +#define QMIUIM_UNBLOCK_PIN_REQ 0x0027 +#define QMIUIM_UNBLOCK_PIN_RESP 0x0027 +#define QMIUIM_UNBLOCK_PIN_IND 0x0027 +#define QMIUIM_CHANGE_PIN_REQ 0x0028 +#define QMIUIM_CHANGE_PIN_RESP 0x0028 +#define QMIUIM_CHANGE_PIN_IND 0x0028 +#define QMIUIM_DEPERSONALIZATION_REQ 0x0029 +#define QMIUIM_DEPERSONALIZATION_RESP 0x0029 +#define QMIUIM_EVENT_REG_REQ 0x002E +#define QMIUIM_EVENT_REG_RESP 0x002E +#define QMIUIM_GET_CARD_STATUS_REQ 0x002F +#define QMIUIM_GET_CARD_STATUS_RESP 0x002F +#define QMIUIM_STATUS_CHANGE_IND 0x0032 +#define QMIUIM_POWER_DOWN 0x0030 +#define QMIUIM_POWER_UP 0x0031 + + +typedef struct _QMIUIM_GET_CARD_STATUS_RESP_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + USHORT QMUXResult; + USHORT QMUXError; +} __attribute__ ((packed)) QMIUIM_GET_CARD_STATUS_RESP_MSG, *PQMIUIM_GET_CARD_STATUS_RESP_MSG; + +#define UIM_CARD_STATE_ABSENT 0x00 +#define UIM_CARD_STATE_PRESENT 0x01 +#define UIM_CARD_STATE_ERROR 0x02 + +typedef struct _QMIUIM_CARD_STATUS +{ + UCHAR TLVType; + USHORT TLVLength; + USHORT IndexGWPri; + USHORT Index1XPri; + USHORT IndexGWSec; + USHORT Index1XSec; + UCHAR NumSlot; + UCHAR CardState; + UCHAR UPINState; + UCHAR UPINRetries; + UCHAR UPUKRetries; + UCHAR ErrorCode; + UCHAR NumApp; + UCHAR AppType; + UCHAR AppState; + UCHAR PersoState; + UCHAR PersoFeature; + UCHAR PersoRetries; + UCHAR PersoUnblockRetries; + UCHAR AIDLength; +} __attribute__ ((packed)) QMIUIM_CARD_STATUS, *PQMIUIM_CARD_STATUS; + +typedef struct _QMIUIM_PIN_STATE +{ + UCHAR UnivPIN; + UCHAR PIN1State; + UCHAR PIN1Retries; + UCHAR PUK1Retries; + UCHAR PIN2State; + UCHAR PIN2Retries; + UCHAR PUK2Retries; +} __attribute__ ((packed)) QMIUIM_PIN_STATE, *PQMIUIM_PIN_STATE; + +typedef struct _QMIUIM_VERIFY_PIN_REQ_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + UCHAR Session_Type; + UCHAR Aid_Len; + UCHAR TLV2Type; + USHORT TLV2Length; + UCHAR PINID; + UCHAR PINLen; + UCHAR PINValue; +} __attribute__ ((packed)) QMIUIM_VERIFY_PIN_REQ_MSG, *PQMIUIM_VERIFY_PIN_REQ_MSG; + +typedef struct _QMIUIM_VERIFY_PIN_RESP_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + USHORT QMUXResult; + USHORT QMUXError; + UCHAR TLV2Type; + USHORT TLV2Length; + UCHAR PINVerifyRetriesLeft; + UCHAR PINUnblockRetriesLeft; +} __attribute__ ((packed)) QMIUIM_VERIFY_PIN_RESP_MSG, *PQMIUIM_VERIFY_PIN_RESP_MSG; + +typedef struct _QMIUIM_READ_TRANSPARENT_REQ_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + UCHAR Session_Type; + UCHAR Aid_Len; + UCHAR TLV2Type; + USHORT TLV2Length; + USHORT file_id; + UCHAR path_len; + UCHAR path[]; +} __attribute__ ((packed)) QMIUIM_READ_TRANSPARENT_REQ_MSG, *PQMIUIM_READ_TRANSPARENT_REQ_MSG; + +typedef struct _READ_TRANSPARENT_TLV +{ + UCHAR TLVType; + USHORT TLVLength; + USHORT Offset; + USHORT Length; +} __attribute__ ((packed)) READ_TRANSPARENT_TLV, *PREAD_TRANSPARENT_TLV; + +typedef struct _QMIUIM_CONTENT +{ + UCHAR TLVType; + USHORT TLVLength; + USHORT content_len; + UCHAR content[]; +} __attribute__ ((packed)) QMIUIM_CONTENT, *PQMIUIM_CONTENT; + +typedef struct _QMIUIM_READ_TRANSPARENT_RESP_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + USHORT QMUXResult; + USHORT QMUXError; +} __attribute__ ((packed)) QMIUIM_READ_TRANSPARENT_RESP_MSG, *PQMIUIM_READ_TRANSPARENT_RESP_MSG; + +typedef struct _QMIUIM_SET_CARD_SLOT_REQ_MSG +{ + USHORT Type; + USHORT Length; + UCHAR TLVType; + USHORT TLVLength; + UCHAR slot; +} __attribute__ ((packed)) QMIUIM_SET_CARD_SLOT_REQ_MSG, *PQMIUIM_SET_CARD_SLOT_REQ_MSG; + +// ======================= COEX ============================== +#define QMI_COEX_GET_WWAN_STATE_REQ 0x22 +#define QMI_COEX_GET_WWAN_STATE_RESP 0x22 + +typedef struct { + + uint32_t freq; + /**< Band center frequency in MHz. */ + + uint32_t bandwidth; + /**< Bandwidth in MHz. */ +}coex_band_type_v01; /* Type */ + +typedef struct _QMI_COEX_GET_WWAN_STATE_RESP_MSG_LTE_BAND +{ + UCHAR TLVType; + USHORT TLVLength; + coex_band_type_v01 ul_band; + coex_band_type_v01 dl_band; +} __attribute__ ((packed)) QMI_COEX_GET_WWAN_STATE_RESP_MSG_LTE_BAND, *PQMI_COEX_GET_WWAN_STATE_RESP_MSG_LTE_BAND; + + +typedef struct _QMUX_MSG +{ + QCQMUX_HDR QMUXHdr; + union + { + // Message Header + QCQMUX_MSG_HDR QMUXMsgHdr; + QCQMUX_MSG_HDR_RESP QMUXMsgHdrResp; + + // QMIWDS Message +#if 0 + QMIWDS_GET_PKT_SRVC_STATUS_REQ_MSG PacketServiceStatusReq; + QMIWDS_GET_PKT_SRVC_STATUS_RESP_MSG PacketServiceStatusRsp; + QMIWDS_GET_PKT_SRVC_STATUS_IND_MSG PacketServiceStatusInd; + QMIWDS_EVENT_REPORT_IND_MSG EventReportInd; + QMIWDS_GET_CURRENT_CHANNEL_RATE_REQ_MSG GetCurrChannelRateReq; + QMIWDS_GET_CURRENT_CHANNEL_RATE_RESP_MSG GetCurrChannelRateRsp; + QMIWDS_GET_PKT_STATISTICS_REQ_MSG GetPktStatsReq; + QMIWDS_GET_PKT_STATISTICS_RESP_MSG GetPktStatsRsp; + QMIWDS_SET_EVENT_REPORT_REQ_MSG EventReportReq; + QMIWDS_SET_EVENT_REPORT_RESP_MSG EventReportRsp; +#endif + //#ifdef QC_IP_MODE + QMIWDS_GET_RUNTIME_SETTINGS_REQ_MSG GetRuntimeSettingsReq; + QMIWDS_GET_RUNTIME_SETTINGS_RESP_MSG GetRuntimeSettingsRsp; + //#endif // QC_IP_MODE + QMIWDS_SET_CLIENT_IP_FAMILY_PREF_REQ_MSG SetClientIpFamilyPrefReq; + QMIWDS_SET_CLIENT_IP_FAMILY_PREF_RESP_MSG SetClientIpFamilyPrefResp; + QMIWDS_SET_AUTO_CONNECT_REQ_MSG SetAutoConnectReq; +#if 0 + QMIWDS_GET_MIP_MODE_REQ_MSG GetMipModeReq; + QMIWDS_GET_MIP_MODE_RESP_MSG GetMipModeResp; +#endif + QMIWDS_START_NETWORK_INTERFACE_REQ_MSG StartNwInterfaceReq; + QMIWDS_START_NETWORK_INTERFACE_RESP_MSG StartNwInterfaceResp; + QMIWDS_STOP_NETWORK_INTERFACE_REQ_MSG StopNwInterfaceReq; + QMIWDS_STOP_NETWORK_INTERFACE_RESP_MSG StopNwInterfaceResp; + QMIWDS_GET_DEFAULT_SETTINGS_REQ_MSG GetDefaultSettingsReq; + QMIWDS_GET_DEFAULT_SETTINGS_RESP_MSG GetDefaultSettingsResp; + QMIWDS_MODIFY_PROFILE_SETTINGS_REQ_MSG ModifyProfileSettingsReq; + QMIWDS_MODIFY_PROFILE_SETTINGS_RESP_MSG ModifyProfileSettingsResp; + QMIWDS_GET_PROFILE_SETTINGS_REQ_MSG GetProfileSettingsReq; + QMIWDS_CREATE_PROFILE_SETTINGS_REQ_MSG CreatetProfileSettingsReq; + QMIWDS_GET_PROFILE_LIST_REQ_MSG GetProfileListReq; + QMIWDS_GET_PROFILE_LIST_RESP_MSG GetProfileListResp; +#if 0 + QMIWDS_GET_DATA_BEARER_REQ_MSG GetDataBearerReq; + QMIWDS_GET_DATA_BEARER_RESP_MSG GetDataBearerResp; + QMIWDS_DUN_CALL_INFO_REQ_MSG DunCallInfoReq; + QMIWDS_DUN_CALL_INFO_RESP_MSG DunCallInfoResp; +#endif + QMIWDS_BIND_MUX_DATA_PORT_REQ_MSG BindMuxDataPortReq; + + // QMIDMS Messages +#if 0 + QMIDMS_GET_DEVICE_MFR_REQ_MSG GetDeviceMfrReq; + QMIDMS_GET_DEVICE_MFR_RESP_MSG GetDeviceMfrRsp; + QMIDMS_GET_DEVICE_MODEL_ID_REQ_MSG GetDeviceModeIdReq; + QMIDMS_GET_DEVICE_MODEL_ID_RESP_MSG GetDeviceModeIdRsp; + QMIDMS_GET_DEVICE_REV_ID_REQ_MSG GetDeviceRevIdReq; + QMIDMS_GET_DEVICE_REV_ID_RESP_MSG GetDeviceRevIdRsp; + QMIDMS_GET_MSISDN_REQ_MSG GetMsisdnReq; + QMIDMS_GET_MSISDN_RESP_MSG GetMsisdnRsp; + QMIDMS_GET_DEVICE_SERIAL_NUMBERS_REQ_MSG GetDeviceSerialNumReq; + QMIDMS_GET_DEVICE_SERIAL_NUMBERS_RESP_MSG GetDeviceSerialNumRsp; + QMIDMS_GET_DEVICE_CAP_REQ_MSG GetDeviceCapReq; + QMIDMS_GET_DEVICE_CAP_RESP_MSG GetDeviceCapResp; + QMIDMS_GET_BAND_CAP_REQ_MSG GetBandCapReq; + QMIDMS_GET_BAND_CAP_RESP_MSG GetBandCapRsp; + QMIDMS_GET_ACTIVATED_STATUS_REQ_MSG GetActivatedStatusReq; + QMIDMS_GET_ACTIVATED_STATUS_RESP_MSG GetActivatedStatusResp; + QMIDMS_GET_OPERATING_MODE_REQ_MSG GetOperatingModeReq; + QMIDMS_GET_OPERATING_MODE_RESP_MSG GetOperatingModeResp; +#endif + QMIDMS_SET_OPERATING_MODE_REQ_MSG SetOperatingModeReq; + QMIDMS_SET_OPERATING_MODE_RESP_MSG SetOperatingModeResp; +#if 0 + QMIDMS_UIM_GET_ICCID_REQ_MSG GetICCIDReq; + QMIDMS_UIM_GET_ICCID_RESP_MSG GetICCIDResp; + QMIDMS_ACTIVATE_AUTOMATIC_REQ_MSG ActivateAutomaticReq; + QMIDMS_ACTIVATE_AUTOMATIC_RESP_MSG ActivateAutomaticResp; + QMIDMS_ACTIVATE_MANUAL_REQ_MSG ActivateManualReq; + QMIDMS_ACTIVATE_MANUAL_RESP_MSG ActivateManualResp; +#endif + QMIDMS_UIM_GET_PIN_STATUS_REQ_MSG UIMGetPinStatusReq; + QMIDMS_UIM_GET_PIN_STATUS_RESP_MSG UIMGetPinStatusResp; + QMIDMS_UIM_VERIFY_PIN_REQ_MSG UIMVerifyPinReq; + QMIDMS_UIM_VERIFY_PIN_RESP_MSG UIMVerifyPinResp; +#if 0 + QMIDMS_UIM_SET_PIN_PROTECTION_REQ_MSG UIMSetPinProtectionReq; + QMIDMS_UIM_SET_PIN_PROTECTION_RESP_MSG UIMSetPinProtectionResp; + QMIDMS_UIM_CHANGE_PIN_REQ_MSG UIMChangePinReq; + QMIDMS_UIM_CHANGE_PIN_RESP_MSG UIMChangePinResp; + QMIDMS_UIM_UNBLOCK_PIN_REQ_MSG UIMUnblockPinReq; + QMIDMS_UIM_UNBLOCK_PIN_RESP_MSG UIMUnblockPinResp; + QMIDMS_SET_EVENT_REPORT_REQ_MSG DmsSetEventReportReq; + QMIDMS_SET_EVENT_REPORT_RESP_MSG DmsSetEventReportResp; + QMIDMS_EVENT_REPORT_IND_MSG DmsEventReportInd; +#endif + QMIDMS_UIM_GET_STATE_REQ_MSG UIMGetStateReq; + QMIDMS_UIM_GET_STATE_RESP_MSG UIMGetStateResp; + QMIDMS_UIM_GET_IMSI_REQ_MSG UIMGetIMSIReq; + QMIDMS_UIM_GET_IMSI_RESP_MSG UIMGetIMSIResp; +#if 0 + QMIDMS_UIM_GET_CK_STATUS_REQ_MSG UIMGetCkStatusReq; + QMIDMS_UIM_GET_CK_STATUS_RESP_MSG UIMGetCkStatusResp; + QMIDMS_UIM_SET_CK_PROTECTION_REQ_MSG UIMSetCkProtectionReq; + QMIDMS_UIM_SET_CK_PROTECTION_RESP_MSG UIMSetCkProtectionResp; + QMIDMS_UIM_UNBLOCK_CK_REQ_MSG UIMUnblockCkReq; + QMIDMS_UIM_UNBLOCK_CK_RESP_MSG UIMUnblockCkResp; +#endif + + // QMIQOS Messages +#if 1 + QMI_QOS_SET_EVENT_REPORT_REQ_MSG QosSetEventReportReq; + QMI_QOS_SET_EVENT_REPORT_RESP_MSG QosSetEventReportRsp; + QMI_QOS_SET_EVENT_REPORT_IND_MSG QosSetEventReportInd; + QMI_QOS_BIND_DATA_PORT_REQ_MSG QosBindDataPortReq; + QMI_QOS_BIND_DATA_PORT_RESP_MSG QosBindDataPortRsp; + QMI_QOS_INDICATION_REGISTER_REQ_MSG QosIndRegReq; + QMI_QOS_INDICATION_REGISTER_RESP_MSG QosIndRegRsp; + QMI_QOS_GLOBAL_QOS_FLOW_IND_MSG QosGlobalQosFlowInd; + QMI_QOS_GET_QOS_INFO_REQ_MSG QosGetQosInfoReq; + QMI_QOS_GET_QOS_INFO_RESP_MSG QosGetQosInfoRsp; +#endif + + // QMIWMS Messages +#if 0 + QMIWMS_GET_MESSAGE_PROTOCOL_REQ_MSG GetMessageProtocolReq; + QMIWMS_GET_MESSAGE_PROTOCOL_RESP_MSG GetMessageProtocolResp; + QMIWMS_GET_SMSC_ADDRESS_REQ_MSG GetSMSCAddressReq; + QMIWMS_GET_SMSC_ADDRESS_RESP_MSG GetSMSCAddressResp; + QMIWMS_SET_SMSC_ADDRESS_REQ_MSG SetSMSCAddressReq; + QMIWMS_SET_SMSC_ADDRESS_RESP_MSG SetSMSCAddressResp; + QMIWMS_GET_STORE_MAX_SIZE_REQ_MSG GetStoreMaxSizeReq; + QMIWMS_GET_STORE_MAX_SIZE_RESP_MSG GetStoreMaxSizeResp; + QMIWMS_LIST_MESSAGES_REQ_MSG ListMessagesReq; + QMIWMS_LIST_MESSAGES_RESP_MSG ListMessagesResp; + QMIWMS_RAW_READ_REQ_MSG RawReadMessagesReq; + QMIWMS_RAW_READ_RESP_MSG RawReadMessagesResp; + QMIWMS_SET_EVENT_REPORT_REQ_MSG WmsSetEventReportReq; + QMIWMS_SET_EVENT_REPORT_RESP_MSG WmsSetEventReportResp; + QMIWMS_EVENT_REPORT_IND_MSG WmsEventReportInd; + QMIWMS_DELETE_REQ_MSG WmsDeleteReq; + QMIWMS_DELETE_RESP_MSG WmsDeleteResp; + QMIWMS_RAW_SEND_REQ_MSG RawSendMessagesReq; + QMIWMS_RAW_SEND_RESP_MSG RawSendMessagesResp; + QMIWMS_MODIFY_TAG_REQ_MSG WmsModifyTagReq; + QMIWMS_MODIFY_TAG_RESP_MSG WmsModifyTagResp; +#endif + + // QMINAS Messages +#if 0 + QMINAS_GET_HOME_NETWORK_REQ_MSG GetHomeNetworkReq; + QMINAS_GET_HOME_NETWORK_RESP_MSG GetHomeNetworkResp; + QMINAS_GET_PREFERRED_NETWORK_REQ_MSG GetPreferredNetworkReq; + QMINAS_GET_PREFERRED_NETWORK_RESP_MSG GetPreferredNetworkResp; + QMINAS_GET_FORBIDDEN_NETWORK_REQ_MSG GetForbiddenNetworkReq; + QMINAS_GET_FORBIDDEN_NETWORK_RESP_MSG GetForbiddenNetworkResp; + QMINAS_GET_SERVING_SYSTEM_REQ_MSG GetServingSystemReq; +#endif + QMINAS_GET_SERVING_SYSTEM_RESP_MSG GetServingSystemResp; + QMINAS_GET_SYS_INFO_RESP_MSG GetSysInfoResp; + QMINAS_SYS_INFO_IND_MSG NasSysInfoInd; +#if 0 + QMINAS_SERVING_SYSTEM_IND_MSG NasServingSystemInd; + QMINAS_SET_PREFERRED_NETWORK_REQ_MSG SetPreferredNetworkReq; + QMINAS_SET_PREFERRED_NETWORK_RESP_MSG SetPreferredNetworkResp; + QMINAS_SET_FORBIDDEN_NETWORK_REQ_MSG SetForbiddenNetworkReq; + QMINAS_SET_FORBIDDEN_NETWORK_RESP_MSG SetForbiddenNetworkResp; + QMINAS_PERFORM_NETWORK_SCAN_REQ_MSG PerformNetworkScanReq; + QMINAS_PERFORM_NETWORK_SCAN_RESP_MSG PerformNetworkScanResp; + QMINAS_INITIATE_NW_REGISTER_REQ_MSG InitiateNwRegisterReq; + QMINAS_INITIATE_NW_REGISTER_RESP_MSG InitiateNwRegisterResp; + QMINAS_SET_TECHNOLOGY_PREF_REQ_MSG SetTechnologyPrefReq; + QMINAS_SET_TECHNOLOGY_PREF_RESP_MSG SetTechnologyPrefResp; + QMINAS_GET_SIGNAL_STRENGTH_REQ_MSG GetSignalStrengthReq; + QMINAS_GET_SIGNAL_STRENGTH_RESP_MSG GetSignalStrengthResp; + QMINAS_SET_EVENT_REPORT_REQ_MSG SetEventReportReq; + QMINAS_SET_EVENT_REPORT_RESP_MSG SetEventReportResp; + QMINAS_EVENT_REPORT_IND_MSG NasEventReportInd; + QMINAS_GET_RF_BAND_INFO_REQ_MSG GetRFBandInfoReq; + QMINAS_GET_RF_BAND_INFO_RESP_MSG GetRFBandInfoResp; + QMINAS_INITIATE_ATTACH_REQ_MSG InitiateAttachReq; + QMINAS_INITIATE_ATTACH_RESP_MSG InitiateAttachResp; + QMINAS_GET_PLMN_NAME_REQ_MSG GetPLMNNameReq; + QMINAS_GET_PLMN_NAME_RESP_MSG GetPLMNNameResp; +#endif + + // QMIUIM Messages + QMIUIM_GET_CARD_STATUS_RESP_MSG UIMGetCardStatus; + QMIUIM_VERIFY_PIN_REQ_MSG UIMUIMVerifyPinReq; + QMIUIM_VERIFY_PIN_RESP_MSG UIMUIMVerifyPinResp; +#if 0 + QMIUIM_SET_PIN_PROTECTION_REQ_MSG UIMUIMSetPinProtectionReq; + QMIUIM_SET_PIN_PROTECTION_RESP_MSG UIMUIMSetPinProtectionResp; + QMIUIM_CHANGE_PIN_REQ_MSG UIMUIMChangePinReq; + QMIUIM_CHANGE_PIN_RESP_MSG UIMUIMChangePinResp; + QMIUIM_UNBLOCK_PIN_REQ_MSG UIMUIMUnblockPinReq; + QMIUIM_UNBLOCK_PIN_RESP_MSG UIMUIMUnblockPinResp; +#endif + QMIUIM_READ_TRANSPARENT_REQ_MSG UIMUIMReadTransparentReq; + QMIUIM_READ_TRANSPARENT_RESP_MSG UIMUIMReadTransparentResp; + QMIUIM_SET_CARD_SLOT_REQ_MSG UIMSetCardSlotReq; + + QMIWDS_ADMIN_SET_DATA_FORMAT_REQ_MSG SetDataFormatReq; + QMI_WDA_SET_LOOPBACK_CONFIG_REQ_MSG SetLoopBackReq; + QMI_WDA_SET_LOOPBACK_CONFIG_IND_MSG SetLoopBackInd; + }; +} __attribute__ ((packed)) QMUX_MSG, *PQMUX_MSG; + +typedef struct _QCQMIMSG { + QCQMI_HDR QMIHdr; + union { + QMICTL_MSG CTLMsg; + QMUX_MSG MUXMsg; + }; +} __attribute__ ((packed)) QCQMIMSG, *PQCQMIMSG; + +#pragma pack(pop) + +#endif // QCQMUX_H + diff --git a/wwan/app/quectel_cm_5G/src/QMIThread.c b/wwan/app/quectel-cm/src/QMIThread.c similarity index 100% rename from wwan/app/quectel_cm_5G/src/QMIThread.c rename to wwan/app/quectel-cm/src/QMIThread.c diff --git a/wwan/app/quectel_cm_5G/src/QMIThread.h b/wwan/app/quectel-cm/src/QMIThread.h similarity index 96% rename from wwan/app/quectel_cm_5G/src/QMIThread.h rename to wwan/app/quectel-cm/src/QMIThread.h index bbf2d4b..8ce2cff 100644 --- a/wwan/app/quectel_cm_5G/src/QMIThread.h +++ b/wwan/app/quectel-cm/src/QMIThread.h @@ -1,423 +1,423 @@ -#ifndef __QMI_THREAD_H__ -#define __QMI_THREAD_H__ - -#define CONFIG_GOBINET -#define CONFIG_QMIWWAN -#define CONFIG_SIM -#define CONFIG_APN -#define CONFIG_VERSION -//#define CONFIG_SIGNALINFO -//#define CONFIG_CELLINFO -//#define CONFIG_COEX_WWAN_STATE -#define CONFIG_DEFAULT_PDP 1 -//#define CONFIG_IMSI_ICCID -#define QUECTEL_UL_DATA_AGG -//#define QUECTEL_QMI_MERGE -//#define REBOOT_SIM_CARD_WHEN_APN_CHANGE -//#define REBOOT_SIM_CARD_WHEN_LONG_TIME_NO_PS 60 //unit is seconds -//#define CONFIG_QRTR -//#define CONFIG_ENABLE_QOS -//#define CONFIG_REG_QOS_IND -//#define CONFIG_GET_QOS_INFO -//#define CONFIG_GET_QOS_DATA_RATE - -#if (defined(CONFIG_REG_QOS_IND) || defined(CONFIG_GET_QOS_INFO) || defined(CONFIG_GET_QOS_DATA_RATE)) -#ifndef CONFIG_REG_QOS_IND -#define CONFIG_REG_QOS_IND -#endif -#ifndef CONFIG_ENABLE_QOS -#define CONFIG_ENABLE_QOS -#endif -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "qendian.h" -#include "QCQMI.h" -#include "QCQCTL.h" -#include "QCQMUX.h" -#include "util.h" - -#define DEVICE_CLASS_UNKNOWN 0 -#define DEVICE_CLASS_CDMA 1 -#define DEVICE_CLASS_GSM 2 - -#define WWAN_DATA_CLASS_NONE 0x00000000 -#define WWAN_DATA_CLASS_GPRS 0x00000001 -#define WWAN_DATA_CLASS_EDGE 0x00000002 /* EGPRS */ -#define WWAN_DATA_CLASS_UMTS 0x00000004 -#define WWAN_DATA_CLASS_HSDPA 0x00000008 -#define WWAN_DATA_CLASS_HSUPA 0x00000010 -#define WWAN_DATA_CLASS_LTE 0x00000020 -#define WWAN_DATA_CLASS_5G_NSA 0x00000040 -#define WWAN_DATA_CLASS_5G_SA 0x00000080 -#define WWAN_DATA_CLASS_1XRTT 0x00010000 -#define WWAN_DATA_CLASS_1XEVDO 0x00020000 -#define WWAN_DATA_CLASS_1XEVDO_REVA 0x00040000 -#define WWAN_DATA_CLASS_1XEVDV 0x00080000 -#define WWAN_DATA_CLASS_3XRTT 0x00100000 -#define WWAN_DATA_CLASS_1XEVDO_REVB 0x00200000 /* for future use */ -#define WWAN_DATA_CLASS_UMB 0x00400000 -#define WWAN_DATA_CLASS_CUSTOM 0x80000000 - -struct wwan_data_class_str { - ULONG class; - const char *str; -}; - -#pragma pack(push, 1) -typedef struct __IPV4 { - uint32_t Address; - uint32_t Gateway; - uint32_t SubnetMask; - uint32_t DnsPrimary; - uint32_t DnsSecondary; - uint32_t Mtu; -} IPV4_T; - -typedef struct __IPV6 { - UCHAR Address[16]; - UCHAR Gateway[16]; - UCHAR SubnetMask[16]; - UCHAR DnsPrimary[16]; - UCHAR DnsSecondary[16]; - UCHAR PrefixLengthIPAddr; - UCHAR PrefixLengthGateway; - ULONG Mtu; -} IPV6_T; - -typedef struct { - UINT size; - UINT rx_urb_size; - UINT ep_type; - UINT iface_id; - UINT MuxId; - UINT ul_data_aggregation_max_datagrams; //0x17 - UINT ul_data_aggregation_max_size ;//0x18 - UINT dl_minimum_padding; //0x1A -} QMAP_SETTING; - -//Configured downlink data aggregationprotocol -#define WDA_DL_DATA_AGG_DISABLED (0x00) //DL data aggregation is disabled (default) -#define WDA_DL_DATA_AGG_TLP_ENABLED (0x01) // DL TLP is enabled -#define WDA_DL_DATA_AGG_QC_NCM_ENABLED (0x02) // DL QC_NCM isenabled -#define WDA_DL_DATA_AGG_MBIM_ENABLED (0x03) // DL MBIM isenabled -#define WDA_DL_DATA_AGG_RNDIS_ENABLED (0x04) // DL RNDIS is enabled -#define WDA_DL_DATA_AGG_QMAP_ENABLED (0x05) // DL QMAP isenabled -#define WDA_DL_DATA_AGG_QMAP_V2_ENABLED (0x06) // DL QMAP V2 is enabled -#define WDA_DL_DATA_AGG_QMAP_V3_ENABLED (0x07) // DL QMAP V3 is enabled -#define WDA_DL_DATA_AGG_QMAP_V4_ENABLED (0x08) // DL QMAP V4 is enabled -#define WDA_DL_DATA_AGG_QMAP_V5_ENABLED (0x09) // DL QMAP V5 is enabled - -typedef struct { - unsigned int size; - unsigned int rx_urb_size; - unsigned int ep_type; - unsigned int iface_id; - unsigned int qmap_mode; - unsigned int qmap_version; - unsigned int dl_minimum_padding; - char ifname[8][16]; - unsigned char mux_id[8]; -} RMNET_INFO; - -#define IpFamilyV4 (0x04) -#define IpFamilyV6 (0x06) - -struct __PROFILE; -struct qmi_device_ops { - int (*init)(struct __PROFILE *profile); - int (*deinit)(void); - int (*send)(PQCQMIMSG pRequest); - void* (*read)(void *pData); -}; -#ifdef CONFIG_QRTR -extern const struct qmi_device_ops qrtr_qmidev_ops; -#endif -extern const struct qmi_device_ops gobi_qmidev_ops; -extern const struct qmi_device_ops qmiwwan_qmidev_ops; -extern const struct qmi_device_ops mbim_dev_ops; -extern const struct qmi_device_ops atc_dev_ops; -extern int (*qmidev_send)(PQCQMIMSG pRequest); - -struct usb_device_info { - int idVendor; - int idProduct; - int busnum; - int devnum; - int bNumInterfaces; -}; - -struct usb_interface_info { - int bNumEndpoints; - int bInterfaceClass; - int bInterfaceSubClass; - int bInterfaceProtocol; - char driver[32]; -}; - -#define LIBQMI_PROXY "qmi-proxy" //src/libqmi-glib/qmi-proxy.h -#define LIBMBIM_PROXY "mbim-proxy" -#define QUECTEL_QMI_PROXY "quectel-qmi-proxy" -#define QUECTEL_MBIM_PROXY "quectel-mbim-proxy" -#define QUECTEL_ATC_PROXY "quectel-atc-proxy" -#define QUECTEL_QRTR_PROXY "quectel-qrtr-proxy" - -#ifndef bool -#define bool uint8_t -#endif -struct request_ops; -typedef struct __PROFILE { - //user input start - const char *apn; - const char *user; - const char *password; - int auth; - int iptype; - const char *pincode; - char proxy[32]; - int pdp;//pdp_context - int profile_index;//profile_index - int enable_bridge; - bool enable_ipv4; - bool enable_ipv6; - bool no_dhcp; - const char *logfile; - const char *usblogfile; - char expect_adapter[32]; - int kill_pdp; - int replication_factor; - //user input end - - char qmichannel[32]; - char usbnet_adapter[32]; - char qmapnet_adapter[32]; - char driver_name[32]; - int qmap_mode; - int qmap_size; - int qmap_version; - int curIpFamily; - int rawIP; - int muxid; -#ifdef CONFIG_ENABLE_QOS - UINT qos_id; -#endif - int wda_client; - uint32_t udhcpc_ip; - IPV4_T ipv4; - IPV6_T ipv6; - UINT PCSCFIpv4Addr1; - UINT PCSCFIpv4Addr2; - UCHAR PCSCFIpv6Addr1[16]; - UCHAR PCSCFIpv6Addr2[16]; - bool reattach_flag; - int hardware_interface; - int software_interface; - - struct usb_device_info usb_dev; - struct usb_interface_info usb_intf; - - int usbmon_fd; - FILE *usbmon_logfile_fp; - bool loopback_state; - - char BaseBandVersion[64]; - char old_apn[64]; - char old_user[64]; - char old_password[64]; - int old_auth; - int old_iptype; - - const struct qmi_device_ops *qmi_ops; - const struct request_ops *request_ops; - RMNET_INFO rmnet_info; -} PROFILE_T; - -#ifdef QUECTEL_QMI_MERGE -#define MERGE_PACKET_IDENTITY 0x2c7c -#define MERGE_PACKET_VERSION 0x0001 -#define MERGE_PACKET_MAX_PAYLOAD_SIZE 56 -typedef struct __QMI_MSG_HEADER { - uint16_t idenity; - uint16_t version; - uint16_t cur_len; - uint16_t total_len; -} QMI_MSG_HEADER; - -typedef struct __QMI_MSG_PACKET { - QMI_MSG_HEADER header; - uint16_t len; - char buf[4096]; -} QMI_MSG_PACKET; -#endif - -typedef enum { - SIM_ABSENT = 0, - SIM_NOT_READY = 1, - SIM_READY = 2, /* SIM_READY means the radio state is RADIO_STATE_SIM_READY */ - SIM_PIN = 3, - SIM_PUK = 4, - SIM_NETWORK_PERSONALIZATION = 5, - SIM_BAD = 6, -} SIM_Status; - -#pragma pack(pop) - -#define WDM_DEFAULT_BUFSIZE 256 -#define RIL_REQUEST_QUIT 0x1000 -#define RIL_INDICATE_DEVICE_CONNECTED 0x1002 -#define RIL_INDICATE_DEVICE_DISCONNECTED 0x1003 -#define RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED 0x1004 -#define RIL_UNSOL_DATA_CALL_LIST_CHANGED 0x1005 -#define MODEM_REPORT_RESET_EVENT 0x1006 -#define RIL_UNSOL_LOOPBACK_CONFIG_IND 0x1007 -#ifdef CONFIG_REG_QOS_IND -#define RIL_UNSOL_GLOBAL_QOS_FLOW_IND_QOS_ID 0x1008 -#endif - -extern pthread_mutex_t cm_command_mutex; -extern pthread_cond_t cm_command_cond; -extern unsigned int cm_recv_buf[1024]; -extern int cm_open_dev(const char *dev); -extern int cm_open_proxy(const char *name); -extern int pthread_cond_timeout_np(pthread_cond_t *cond, pthread_mutex_t * mutex, unsigned msecs); -extern int QmiThreadSendQMITimeout(PQCQMIMSG pRequest, PQCQMIMSG *ppResponse, unsigned msecs, const char *funcname); -#define QmiThreadSendQMI(pRequest, ppResponse) QmiThreadSendQMITimeout(pRequest, ppResponse, 30 * 1000, __func__) -extern void QmiThreadRecvQMI(PQCQMIMSG pResponse); -extern void udhcpc_start(PROFILE_T *profile); -extern void udhcpc_stop(PROFILE_T *profile); -extern void ql_set_driver_link_state(PROFILE_T *profile, int link_state); -extern void ql_set_driver_qmap_setting(PROFILE_T *profile, QMAP_SETTING *qmap_settings); -extern void ql_get_driver_rmnet_info(PROFILE_T *profile, RMNET_INFO *rmnet_info); -extern void dump_qmi(void *dataBuffer, int dataLen); -extern void qmidevice_send_event_to_main(int triger_event); -extern void qmidevice_send_event_to_main_ext(int triger_event, void *data, unsigned len); -extern uint8_t qmi_over_mbim_get_client_id(uint8_t QMIType); -extern uint8_t qmi_over_mbim_release_client_id(uint8_t QMIType, uint8_t ClientId); -#ifdef CONFIG_REG_QOS_IND -extern UCHAR ql_get_global_qos_flow_ind_qos_id(PQCQMIMSG pResponse, UINT *qos_id); -#endif -#ifdef CONFIG_GET_QOS_DATA_RATE -extern UCHAR ql_get_global_qos_flow_ind_data_rate(PQCQMIMSG pResponse, void *max_data_rate); -#endif - -struct request_ops { - int (*requestBaseBandVersion)(PROFILE_T *profile); - int (*requestSetEthMode)(PROFILE_T *profile); - int (*requestSetLoopBackState)(UCHAR loopback_state, ULONG replication_factor); - int (*requestGetSIMStatus)(SIM_Status *pSIMStatus); - int (*requestEnterSimPin)(const char *pPinCode); - int (*requestSetProfile)(PROFILE_T *profile); // 1 ~ success and apn change, 0 ~ success and no apn change, -1 ~ fail - int (*requestGetProfile)(PROFILE_T *profile); - int (*requestRegistrationState)(UCHAR *pPSAttachedState); - int (*requestSetupDataCall)(PROFILE_T *profile, int curIpFamily); - int (*requestQueryDataCall)(UCHAR *pConnectionStatus, int curIpFamily); - int (*requestDeactivateDefaultPDP)(PROFILE_T *profile, int curIpFamily); - int (*requestGetIPAddress)(PROFILE_T *profile, int curIpFamily); - int (*requestGetSignalInfo)(void); - int (*requestGetCellInfoList)(void); - int (*requestGetICCID)(void); - int (*requestGetIMSI)(void); - int (*requestRadioPower)(int state); - int (*requestRegisterQos)(PROFILE_T *profile); - int (*requestGetQosInfo)(PROFILE_T *profile); - int (*requestGetCoexWWANState)(void); -}; -extern const struct request_ops qmi_request_ops; -extern const struct request_ops mbim_request_ops; -extern const struct request_ops atc_request_ops; - -extern int get_driver_type(PROFILE_T *profile); -extern BOOL qmidevice_detect(char *qmichannel, char *usbnet_adapter, unsigned bufsize, PROFILE_T *profile); -int mhidevice_detect(char *qmichannel, char *usbnet_adapter, PROFILE_T *profile); -int atdevice_detect(char *atchannel, char *usbnet_adapter, PROFILE_T *profile); -extern int ql_bridge_mode_detect(PROFILE_T *profile); -extern int ql_enable_qmi_wwan_rawip_mode(PROFILE_T *profile); -extern int ql_qmap_mode_detect(PROFILE_T *profile); -#ifdef CONFIG_QRTR -extern int rtrmnet_ctl_create_vnd(char *devname, char *vndname, uint8_t muxid, - uint32_t qmap_version, uint32_t ul_agg_cnt, uint32_t ul_agg_size); -#endif - -#define qmidev_is_gobinet(_qmichannel) (strncmp(_qmichannel, "/dev/qcqmi", strlen("/dev/qcqmi")) == 0) -#define qmidev_is_qmiwwan(_qmichannel) (strncmp(_qmichannel, "/dev/cdc-wdm", strlen("/dev/cdc-wdm")) == 0) -#define qmidev_is_pciemhi(_qmichannel) (strncmp(_qmichannel, "/dev/mhi_", strlen("/dev/mhi_")) == 0) - -#define driver_is_qmi(_drv_name) (strncasecmp(_drv_name, "qmi_wwan", strlen("qmi_wwan")) == 0) -#define driver_is_mbim(_drv_name) (strncasecmp(_drv_name, "cdc_mbim", strlen("cdc_mbim")) == 0) - -extern FILE *logfilefp; -extern int debug_qmi; -extern int qmidevice_control_fd[2]; -extern int g_donot_exit_when_modem_hangup; -extern void update_resolv_conf(int iptype, const char *ifname, const char *dns1, const char *dns2); -void update_ipv4_address(const char *ifname, const char *ip, const char *gw, unsigned prefix); -void update_ipv6_address(const char *ifname, const char *ip, const char *gw, unsigned prefix); -int reattach_driver(PROFILE_T *profile); -extern void no_trunc_strncpy(char *dest, const char *src, size_t dest_size); - -enum -{ - DRV_INVALID, - SOFTWARE_QMI, - SOFTWARE_MBIM, - SOFTWARE_ECM_RNDIS_NCM, - SOFTWARE_QRTR, - HARDWARE_PCIE, - HARDWARE_USB, -}; - -enum -{ - SIG_EVENT_START, - SIG_EVENT_CHECK, - SIG_EVENT_STOP, -}; - -typedef enum -{ - DMS_OP_MODE_ONLINE, - DMS_OP_MODE_LOW_POWER, - DMS_OP_MODE_FACTORY_TEST_MODE, - DMS_OP_MODE_OFFLINE, - DMS_OP_MODE_RESETTING, - DMS_OP_MODE_SHUTTING_DOWN, - DMS_OP_MODE_PERSISTENT_LOW_POWER, - DMS_OP_MODE_MODE_ONLY_LOW_POWER, - DMS_OP_MODE_NET_TEST_GW, -}Device_operating_mode; - -#ifdef CM_DEBUG -#define dbg_time(fmt, args...) do { \ - fprintf(stdout, "[%15s-%04d: %s] " fmt "\n", __FILE__, __LINE__, get_time(), ##args); \ - fflush(stdout);\ - if (logfilefp) fprintf(logfilefp, "[%s-%04d: %s] " fmt "\n", __FILE__, __LINE__, get_time(), ##args); \ -} while(0) -#else -#define dbg_time(fmt, args...) do { \ - fprintf(stdout, "[%s] " fmt "\n", get_time(), ##args); \ - fflush(stdout);\ - if (logfilefp) fprintf(logfilefp, "[%s] " fmt "\n", get_time(), ##args); \ -} while(0) -#endif -#endif +#ifndef __QMI_THREAD_H__ +#define __QMI_THREAD_H__ + +#define CONFIG_GOBINET +#define CONFIG_QMIWWAN +#define CONFIG_SIM +#define CONFIG_APN +#define CONFIG_VERSION +//#define CONFIG_SIGNALINFO +//#define CONFIG_CELLINFO +//#define CONFIG_COEX_WWAN_STATE +#define CONFIG_DEFAULT_PDP 1 +//#define CONFIG_IMSI_ICCID +#define QUECTEL_UL_DATA_AGG +//#define QUECTEL_QMI_MERGE +//#define REBOOT_SIM_CARD_WHEN_APN_CHANGE +//#define REBOOT_SIM_CARD_WHEN_LONG_TIME_NO_PS 60 //unit is seconds +//#define CONFIG_QRTR +//#define CONFIG_ENABLE_QOS +//#define CONFIG_REG_QOS_IND +//#define CONFIG_GET_QOS_INFO +//#define CONFIG_GET_QOS_DATA_RATE + +#if (defined(CONFIG_REG_QOS_IND) || defined(CONFIG_GET_QOS_INFO) || defined(CONFIG_GET_QOS_DATA_RATE)) +#ifndef CONFIG_REG_QOS_IND +#define CONFIG_REG_QOS_IND +#endif +#ifndef CONFIG_ENABLE_QOS +#define CONFIG_ENABLE_QOS +#endif +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "qendian.h" +#include "QCQMI.h" +#include "QCQCTL.h" +#include "QCQMUX.h" +#include "util.h" + +#define DEVICE_CLASS_UNKNOWN 0 +#define DEVICE_CLASS_CDMA 1 +#define DEVICE_CLASS_GSM 2 + +#define WWAN_DATA_CLASS_NONE 0x00000000 +#define WWAN_DATA_CLASS_GPRS 0x00000001 +#define WWAN_DATA_CLASS_EDGE 0x00000002 /* EGPRS */ +#define WWAN_DATA_CLASS_UMTS 0x00000004 +#define WWAN_DATA_CLASS_HSDPA 0x00000008 +#define WWAN_DATA_CLASS_HSUPA 0x00000010 +#define WWAN_DATA_CLASS_LTE 0x00000020 +#define WWAN_DATA_CLASS_5G_NSA 0x00000040 +#define WWAN_DATA_CLASS_5G_SA 0x00000080 +#define WWAN_DATA_CLASS_1XRTT 0x00010000 +#define WWAN_DATA_CLASS_1XEVDO 0x00020000 +#define WWAN_DATA_CLASS_1XEVDO_REVA 0x00040000 +#define WWAN_DATA_CLASS_1XEVDV 0x00080000 +#define WWAN_DATA_CLASS_3XRTT 0x00100000 +#define WWAN_DATA_CLASS_1XEVDO_REVB 0x00200000 /* for future use */ +#define WWAN_DATA_CLASS_UMB 0x00400000 +#define WWAN_DATA_CLASS_CUSTOM 0x80000000 + +struct wwan_data_class_str { + ULONG class; + const char *str; +}; + +#pragma pack(push, 1) +typedef struct __IPV4 { + uint32_t Address; + uint32_t Gateway; + uint32_t SubnetMask; + uint32_t DnsPrimary; + uint32_t DnsSecondary; + uint32_t Mtu; +} IPV4_T; + +typedef struct __IPV6 { + UCHAR Address[16]; + UCHAR Gateway[16]; + UCHAR SubnetMask[16]; + UCHAR DnsPrimary[16]; + UCHAR DnsSecondary[16]; + UCHAR PrefixLengthIPAddr; + UCHAR PrefixLengthGateway; + ULONG Mtu; +} IPV6_T; + +typedef struct { + UINT size; + UINT rx_urb_size; + UINT ep_type; + UINT iface_id; + UINT MuxId; + UINT ul_data_aggregation_max_datagrams; //0x17 + UINT ul_data_aggregation_max_size ;//0x18 + UINT dl_minimum_padding; //0x1A +} QMAP_SETTING; + +//Configured downlink data aggregationprotocol +#define WDA_DL_DATA_AGG_DISABLED (0x00) //DL data aggregation is disabled (default) +#define WDA_DL_DATA_AGG_TLP_ENABLED (0x01) // DL TLP is enabled +#define WDA_DL_DATA_AGG_QC_NCM_ENABLED (0x02) // DL QC_NCM isenabled +#define WDA_DL_DATA_AGG_MBIM_ENABLED (0x03) // DL MBIM isenabled +#define WDA_DL_DATA_AGG_RNDIS_ENABLED (0x04) // DL RNDIS is enabled +#define WDA_DL_DATA_AGG_QMAP_ENABLED (0x05) // DL QMAP isenabled +#define WDA_DL_DATA_AGG_QMAP_V2_ENABLED (0x06) // DL QMAP V2 is enabled +#define WDA_DL_DATA_AGG_QMAP_V3_ENABLED (0x07) // DL QMAP V3 is enabled +#define WDA_DL_DATA_AGG_QMAP_V4_ENABLED (0x08) // DL QMAP V4 is enabled +#define WDA_DL_DATA_AGG_QMAP_V5_ENABLED (0x09) // DL QMAP V5 is enabled + +typedef struct { + unsigned int size; + unsigned int rx_urb_size; + unsigned int ep_type; + unsigned int iface_id; + unsigned int qmap_mode; + unsigned int qmap_version; + unsigned int dl_minimum_padding; + char ifname[8][16]; + unsigned char mux_id[8]; +} RMNET_INFO; + +#define IpFamilyV4 (0x04) +#define IpFamilyV6 (0x06) + +struct __PROFILE; +struct qmi_device_ops { + int (*init)(struct __PROFILE *profile); + int (*deinit)(void); + int (*send)(PQCQMIMSG pRequest); + void* (*read)(void *pData); +}; +#ifdef CONFIG_QRTR +extern const struct qmi_device_ops qrtr_qmidev_ops; +#endif +extern const struct qmi_device_ops gobi_qmidev_ops; +extern const struct qmi_device_ops qmiwwan_qmidev_ops; +extern const struct qmi_device_ops mbim_dev_ops; +extern const struct qmi_device_ops atc_dev_ops; +extern int (*qmidev_send)(PQCQMIMSG pRequest); + +struct usb_device_info { + int idVendor; + int idProduct; + int busnum; + int devnum; + int bNumInterfaces; +}; + +struct usb_interface_info { + int bNumEndpoints; + int bInterfaceClass; + int bInterfaceSubClass; + int bInterfaceProtocol; + char driver[32]; +}; + +#define LIBQMI_PROXY "qmi-proxy" //src/libqmi-glib/qmi-proxy.h +#define LIBMBIM_PROXY "mbim-proxy" +#define QUECTEL_QMI_PROXY "quectel-qmi-proxy" +#define QUECTEL_MBIM_PROXY "quectel-mbim-proxy" +#define QUECTEL_ATC_PROXY "quectel-atc-proxy" +#define QUECTEL_QRTR_PROXY "quectel-qrtr-proxy" + +#ifndef bool +#define bool uint8_t +#endif +struct request_ops; +typedef struct __PROFILE { + //user input start + const char *apn; + const char *user; + const char *password; + int auth; + int iptype; + const char *pincode; + char proxy[32]; + int pdp;//pdp_context + int profile_index;//profile_index + int enable_bridge; + bool enable_ipv4; + bool enable_ipv6; + bool no_dhcp; + const char *logfile; + const char *usblogfile; + char expect_adapter[32]; + int kill_pdp; + int replication_factor; + //user input end + + char qmichannel[32]; + char usbnet_adapter[32]; + char qmapnet_adapter[32]; + char driver_name[32]; + int qmap_mode; + int qmap_size; + int qmap_version; + int curIpFamily; + int rawIP; + int muxid; +#ifdef CONFIG_ENABLE_QOS + UINT qos_id; +#endif + int wda_client; + uint32_t udhcpc_ip; + IPV4_T ipv4; + IPV6_T ipv6; + UINT PCSCFIpv4Addr1; + UINT PCSCFIpv4Addr2; + UCHAR PCSCFIpv6Addr1[16]; + UCHAR PCSCFIpv6Addr2[16]; + bool reattach_flag; + int hardware_interface; + int software_interface; + + struct usb_device_info usb_dev; + struct usb_interface_info usb_intf; + + int usbmon_fd; + FILE *usbmon_logfile_fp; + bool loopback_state; + + char BaseBandVersion[64]; + char old_apn[64]; + char old_user[64]; + char old_password[64]; + int old_auth; + int old_iptype; + + const struct qmi_device_ops *qmi_ops; + const struct request_ops *request_ops; + RMNET_INFO rmnet_info; +} PROFILE_T; + +#ifdef QUECTEL_QMI_MERGE +#define MERGE_PACKET_IDENTITY 0x2c7c +#define MERGE_PACKET_VERSION 0x0001 +#define MERGE_PACKET_MAX_PAYLOAD_SIZE 56 +typedef struct __QMI_MSG_HEADER { + uint16_t idenity; + uint16_t version; + uint16_t cur_len; + uint16_t total_len; +} QMI_MSG_HEADER; + +typedef struct __QMI_MSG_PACKET { + QMI_MSG_HEADER header; + uint16_t len; + char buf[4096]; +} QMI_MSG_PACKET; +#endif + +typedef enum { + SIM_ABSENT = 0, + SIM_NOT_READY = 1, + SIM_READY = 2, /* SIM_READY means the radio state is RADIO_STATE_SIM_READY */ + SIM_PIN = 3, + SIM_PUK = 4, + SIM_NETWORK_PERSONALIZATION = 5, + SIM_BAD = 6, +} SIM_Status; + +#pragma pack(pop) + +#define WDM_DEFAULT_BUFSIZE 256 +#define RIL_REQUEST_QUIT 0x1000 +#define RIL_INDICATE_DEVICE_CONNECTED 0x1002 +#define RIL_INDICATE_DEVICE_DISCONNECTED 0x1003 +#define RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED 0x1004 +#define RIL_UNSOL_DATA_CALL_LIST_CHANGED 0x1005 +#define MODEM_REPORT_RESET_EVENT 0x1006 +#define RIL_UNSOL_LOOPBACK_CONFIG_IND 0x1007 +#ifdef CONFIG_REG_QOS_IND +#define RIL_UNSOL_GLOBAL_QOS_FLOW_IND_QOS_ID 0x1008 +#endif + +extern pthread_mutex_t cm_command_mutex; +extern pthread_cond_t cm_command_cond; +extern unsigned int cm_recv_buf[1024]; +extern int cm_open_dev(const char *dev); +extern int cm_open_proxy(const char *name); +extern int pthread_cond_timeout_np(pthread_cond_t *cond, pthread_mutex_t * mutex, unsigned msecs); +extern int QmiThreadSendQMITimeout(PQCQMIMSG pRequest, PQCQMIMSG *ppResponse, unsigned msecs, const char *funcname); +#define QmiThreadSendQMI(pRequest, ppResponse) QmiThreadSendQMITimeout(pRequest, ppResponse, 30 * 1000, __func__) +extern void QmiThreadRecvQMI(PQCQMIMSG pResponse); +extern void udhcpc_start(PROFILE_T *profile); +extern void udhcpc_stop(PROFILE_T *profile); +extern void ql_set_driver_link_state(PROFILE_T *profile, int link_state); +extern void ql_set_driver_qmap_setting(PROFILE_T *profile, QMAP_SETTING *qmap_settings); +extern void ql_get_driver_rmnet_info(PROFILE_T *profile, RMNET_INFO *rmnet_info); +extern void dump_qmi(void *dataBuffer, int dataLen); +extern void qmidevice_send_event_to_main(int triger_event); +extern void qmidevice_send_event_to_main_ext(int triger_event, void *data, unsigned len); +extern uint8_t qmi_over_mbim_get_client_id(uint8_t QMIType); +extern uint8_t qmi_over_mbim_release_client_id(uint8_t QMIType, uint8_t ClientId); +#ifdef CONFIG_REG_QOS_IND +extern UCHAR ql_get_global_qos_flow_ind_qos_id(PQCQMIMSG pResponse, UINT *qos_id); +#endif +#ifdef CONFIG_GET_QOS_DATA_RATE +extern UCHAR ql_get_global_qos_flow_ind_data_rate(PQCQMIMSG pResponse, void *max_data_rate); +#endif + +struct request_ops { + int (*requestBaseBandVersion)(PROFILE_T *profile); + int (*requestSetEthMode)(PROFILE_T *profile); + int (*requestSetLoopBackState)(UCHAR loopback_state, ULONG replication_factor); + int (*requestGetSIMStatus)(SIM_Status *pSIMStatus); + int (*requestEnterSimPin)(const char *pPinCode); + int (*requestSetProfile)(PROFILE_T *profile); // 1 ~ success and apn change, 0 ~ success and no apn change, -1 ~ fail + int (*requestGetProfile)(PROFILE_T *profile); + int (*requestRegistrationState)(UCHAR *pPSAttachedState); + int (*requestSetupDataCall)(PROFILE_T *profile, int curIpFamily); + int (*requestQueryDataCall)(UCHAR *pConnectionStatus, int curIpFamily); + int (*requestDeactivateDefaultPDP)(PROFILE_T *profile, int curIpFamily); + int (*requestGetIPAddress)(PROFILE_T *profile, int curIpFamily); + int (*requestGetSignalInfo)(void); + int (*requestGetCellInfoList)(void); + int (*requestGetICCID)(void); + int (*requestGetIMSI)(void); + int (*requestRadioPower)(int state); + int (*requestRegisterQos)(PROFILE_T *profile); + int (*requestGetQosInfo)(PROFILE_T *profile); + int (*requestGetCoexWWANState)(void); +}; +extern const struct request_ops qmi_request_ops; +extern const struct request_ops mbim_request_ops; +extern const struct request_ops atc_request_ops; + +extern int get_driver_type(PROFILE_T *profile); +extern BOOL qmidevice_detect(char *qmichannel, char *usbnet_adapter, unsigned bufsize, PROFILE_T *profile); +int mhidevice_detect(char *qmichannel, char *usbnet_adapter, PROFILE_T *profile); +int atdevice_detect(char *atchannel, char *usbnet_adapter, PROFILE_T *profile); +extern int ql_bridge_mode_detect(PROFILE_T *profile); +extern int ql_enable_qmi_wwan_rawip_mode(PROFILE_T *profile); +extern int ql_qmap_mode_detect(PROFILE_T *profile); +#ifdef CONFIG_QRTR +extern int rtrmnet_ctl_create_vnd(char *devname, char *vndname, uint8_t muxid, + uint32_t qmap_version, uint32_t ul_agg_cnt, uint32_t ul_agg_size); +#endif + +#define qmidev_is_gobinet(_qmichannel) (strncmp(_qmichannel, "/dev/qcqmi", strlen("/dev/qcqmi")) == 0) +#define qmidev_is_qmiwwan(_qmichannel) (strncmp(_qmichannel, "/dev/cdc-wdm", strlen("/dev/cdc-wdm")) == 0) +#define qmidev_is_pciemhi(_qmichannel) (strncmp(_qmichannel, "/dev/mhi_", strlen("/dev/mhi_")) == 0) + +#define driver_is_qmi(_drv_name) (strncasecmp(_drv_name, "qmi_wwan", strlen("qmi_wwan")) == 0) +#define driver_is_mbim(_drv_name) (strncasecmp(_drv_name, "cdc_mbim", strlen("cdc_mbim")) == 0) + +extern FILE *logfilefp; +extern int debug_qmi; +extern int qmidevice_control_fd[2]; +extern int g_donot_exit_when_modem_hangup; +extern void update_resolv_conf(int iptype, const char *ifname, const char *dns1, const char *dns2); +void update_ipv4_address(const char *ifname, const char *ip, const char *gw, unsigned prefix); +void update_ipv6_address(const char *ifname, const char *ip, const char *gw, unsigned prefix); +int reattach_driver(PROFILE_T *profile); +extern void no_trunc_strncpy(char *dest, const char *src, size_t dest_size); + +enum +{ + DRV_INVALID, + SOFTWARE_QMI, + SOFTWARE_MBIM, + SOFTWARE_ECM_RNDIS_NCM, + SOFTWARE_QRTR, + HARDWARE_PCIE, + HARDWARE_USB, +}; + +enum +{ + SIG_EVENT_START, + SIG_EVENT_CHECK, + SIG_EVENT_STOP, +}; + +typedef enum +{ + DMS_OP_MODE_ONLINE, + DMS_OP_MODE_LOW_POWER, + DMS_OP_MODE_FACTORY_TEST_MODE, + DMS_OP_MODE_OFFLINE, + DMS_OP_MODE_RESETTING, + DMS_OP_MODE_SHUTTING_DOWN, + DMS_OP_MODE_PERSISTENT_LOW_POWER, + DMS_OP_MODE_MODE_ONLY_LOW_POWER, + DMS_OP_MODE_NET_TEST_GW, +}Device_operating_mode; + +#ifdef CM_DEBUG +#define dbg_time(fmt, args...) do { \ + fprintf(stdout, "[%15s-%04d: %s] " fmt "\n", __FILE__, __LINE__, get_time(), ##args); \ + fflush(stdout);\ + if (logfilefp) fprintf(logfilefp, "[%s-%04d: %s] " fmt "\n", __FILE__, __LINE__, get_time(), ##args); \ +} while(0) +#else +#define dbg_time(fmt, args...) do { \ + fprintf(stdout, "[%s] " fmt "\n", get_time(), ##args); \ + fflush(stdout);\ + if (logfilefp) fprintf(logfilefp, "[%s] " fmt "\n", get_time(), ##args); \ +} while(0) +#endif +#endif diff --git a/wwan/app/quectel_cm_5G/src/QmiWwanCM.c b/wwan/app/quectel-cm/src/QmiWwanCM.c similarity index 97% rename from wwan/app/quectel_cm_5G/src/QmiWwanCM.c rename to wwan/app/quectel-cm/src/QmiWwanCM.c index bea11c6..1800f64 100644 --- a/wwan/app/quectel_cm_5G/src/QmiWwanCM.c +++ b/wwan/app/quectel-cm/src/QmiWwanCM.c @@ -1,459 +1,459 @@ -/****************************************************************************** - @file QmiWwanCM.c - @brief QMI WWAN connectivity manager. - - 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 -#include -#include -#include -#include -#include "QMIThread.h" - -#ifdef CONFIG_QMIWWAN -static int cdc_wdm_fd = -1; -static UCHAR qmiclientId[QMUX_TYPE_ALL]; - -static UCHAR GetQCTLTransactionId(void) { - static int TransactionId = 0; - if (++TransactionId > 0xFF) - TransactionId = 1; - return TransactionId; -} - -typedef USHORT (*CUSTOMQCTL)(PQMICTL_MSG pCTLMsg, void *arg); - -static PQCQMIMSG ComposeQCTLMsg(USHORT QMICTLType, CUSTOMQCTL customQctlMsgFunction, void *arg) { - UCHAR QMIBuf[WDM_DEFAULT_BUFSIZE]; - PQCQMIMSG pRequest = (PQCQMIMSG)QMIBuf; - int Length; - - pRequest->QMIHdr.IFType = USB_CTL_MSG_TYPE_QMI; - pRequest->QMIHdr.CtlFlags = 0x00; - pRequest->QMIHdr.QMIType = QMUX_TYPE_CTL; - pRequest->QMIHdr.ClientId= 0x00; - - pRequest->CTLMsg.QMICTLMsgHdr.CtlFlags = QMICTL_FLAG_REQUEST; - pRequest->CTLMsg.QMICTLMsgHdr.TransactionId = GetQCTLTransactionId(); - pRequest->CTLMsg.QMICTLMsgHdr.QMICTLType = cpu_to_le16(QMICTLType); - if (customQctlMsgFunction) - pRequest->CTLMsg.QMICTLMsgHdr.Length = cpu_to_le16(customQctlMsgFunction(&pRequest->CTLMsg, arg) - sizeof(QCQMICTL_MSG_HDR)); - else - pRequest->CTLMsg.QMICTLMsgHdr.Length = cpu_to_le16(0x0000); - - pRequest->QMIHdr.Length = cpu_to_le16(le16_to_cpu(pRequest->CTLMsg.QMICTLMsgHdr.Length) + sizeof(QCQMICTL_MSG_HDR) + sizeof(QCQMI_HDR) - 1); - Length = le16_to_cpu(pRequest->QMIHdr.Length) + 1; - - pRequest = (PQCQMIMSG)malloc(Length); - if (pRequest == NULL) { - dbg_time("%s fail to malloc", __func__); - } else { - memcpy(pRequest, QMIBuf, Length); - } - - return pRequest; -} - -static USHORT CtlGetVersionReq(PQMICTL_MSG QCTLMsg, void *arg) -{ - (void)arg; - QCTLMsg->GetVersionReq.TLVType = QCTLV_TYPE_REQUIRED_PARAMETER; - QCTLMsg->GetVersionReq.TLVLength = cpu_to_le16(0x0001); - QCTLMsg->GetVersionReq.QMUXTypes = QMUX_TYPE_ALL; - return sizeof(QMICTL_GET_VERSION_REQ_MSG); -} - -static USHORT CtlGetClientIdReq(PQMICTL_MSG QCTLMsg, void *arg) { - QCTLMsg->GetClientIdReq.TLVType = QCTLV_TYPE_REQUIRED_PARAMETER; - QCTLMsg->GetClientIdReq.TLVLength = cpu_to_le16(0x0001); - QCTLMsg->GetClientIdReq.QMIType = ((UCHAR *)arg)[0]; - return sizeof(QMICTL_GET_CLIENT_ID_REQ_MSG); -} - -static USHORT CtlReleaseClientIdReq(PQMICTL_MSG QCTLMsg, void *arg) { - QCTLMsg->ReleaseClientIdReq.TLVType = QCTLV_TYPE_REQUIRED_PARAMETER; - QCTLMsg->ReleaseClientIdReq.TLVLength = cpu_to_le16(0x0002); - QCTLMsg->ReleaseClientIdReq.QMIType = ((UCHAR *)arg)[0]; - QCTLMsg->ReleaseClientIdReq.ClientId = ((UCHAR *)arg)[1] ; - return sizeof(QMICTL_RELEASE_CLIENT_ID_REQ_MSG); -} - -static USHORT CtlLibQmiProxyOpenReq(PQMICTL_MSG QCTLMsg, void *arg) -{ - (void)arg; - const char *device_path = (const char *)(arg); - QCTLMsg->LibQmiProxyOpenReq.TLVType = 0x01; - QCTLMsg->LibQmiProxyOpenReq.TLVLength = cpu_to_le16(strlen(device_path)); - //strcpy(QCTLMsg->LibQmiProxyOpenReq.device_path, device_path); - //__builtin___strcpy_chk - memcpy(QCTLMsg->LibQmiProxyOpenReq.device_path, device_path, strlen(device_path)); - return sizeof(QMICTL_LIBQMI_PROXY_OPEN_MSG) + (strlen(device_path)); -} - -static int libqmi_proxy_open(const char *cdc_wdm) { - int ret; - PQCQMIMSG pResponse; - - ret = QmiThreadSendQMI(ComposeQCTLMsg(QMI_MESSAGE_CTL_INTERNAL_PROXY_OPEN, - CtlLibQmiProxyOpenReq, (void *)cdc_wdm), &pResponse); - if (!ret && pResponse - && pResponse->CTLMsg.QMICTLMsgHdrRsp.QMUXResult == 0 - && pResponse->CTLMsg.QMICTLMsgHdrRsp.QMUXError == 0) { - ret = 0; - } - else { - return -1; - } - - if (pResponse) - free(pResponse); - - return ret; -} - -static int QmiWwanSendQMI(PQCQMIMSG pRequest) { - struct pollfd pollfds[]= {{cdc_wdm_fd, POLLOUT, 0}}; - int ret; - - if (cdc_wdm_fd == -1) { - dbg_time("%s cdc_wdm_fd = -1", __func__); - return -ENODEV; - } - - if (pRequest->QMIHdr.QMIType != QMUX_TYPE_CTL) { - pRequest->QMIHdr.ClientId = qmiclientId[pRequest->QMIHdr.QMIType]; - if (pRequest->QMIHdr.ClientId == 0) { - dbg_time("QMIType %d has no clientID", pRequest->QMIHdr.QMIType); - return -ENODEV; - } - - if (pRequest->QMIHdr.QMIType == QMUX_TYPE_WDS_IPV6) - pRequest->QMIHdr.QMIType = QMUX_TYPE_WDS; - } - - do { - ret = poll(pollfds, sizeof(pollfds)/sizeof(pollfds[0]), 5000); - } while ((ret < 0) && (errno == EINTR)); - - if (pollfds[0].revents & POLLOUT) { - ssize_t nwrites = le16_to_cpu(pRequest->QMIHdr.Length) + 1; - ret = write(cdc_wdm_fd, pRequest, nwrites); - if (ret == nwrites) { - ret = 0; - } else { - dbg_time("%s write=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno)); - } - } else { - dbg_time("%s poll=%d, revents = 0x%x, errno: %d (%s)", __func__, ret, pollfds[0].revents, errno, strerror(errno)); - } - - return ret; -} - -static UCHAR QmiWwanGetClientID(UCHAR QMIType) { - PQCQMIMSG pResponse; - - QmiThreadSendQMI(ComposeQCTLMsg(QMICTL_GET_CLIENT_ID_REQ, CtlGetClientIdReq, &QMIType), &pResponse); - - if (pResponse) { - USHORT QMUXResult = cpu_to_le16(pResponse->CTLMsg.QMICTLMsgHdrRsp.QMUXResult); // QMI_RESULT_SUCCESS - USHORT QMUXError = cpu_to_le16(pResponse->CTLMsg.QMICTLMsgHdrRsp.QMUXError); // QMI_ERR_INVALID_ARG - //UCHAR QMIType = pResponse->CTLMsg.GetClientIdRsp.QMIType; - UCHAR ClientId = pResponse->CTLMsg.GetClientIdRsp.ClientId; - - if (!QMUXResult && !QMUXError && (QMIType == pResponse->CTLMsg.GetClientIdRsp.QMIType)) { - switch (QMIType) { - case QMUX_TYPE_WDS: dbg_time("Get clientWDS = %d", ClientId); break; - case QMUX_TYPE_DMS: dbg_time("Get clientDMS = %d", ClientId); break; - case QMUX_TYPE_NAS: dbg_time("Get clientNAS = %d", ClientId); break; - case QMUX_TYPE_QOS: dbg_time("Get clientQOS = %d", ClientId); break; - case QMUX_TYPE_WMS: dbg_time("Get clientWMS = %d", ClientId); break; - case QMUX_TYPE_PDS: dbg_time("Get clientPDS = %d", ClientId); break; - case QMUX_TYPE_UIM: dbg_time("Get clientUIM = %d", ClientId); break; - case QMUX_TYPE_COEX: dbg_time("Get clientCOEX = %d", ClientId); break; - case QMUX_TYPE_WDS_ADMIN: dbg_time("Get clientWDA = %d", ClientId); - break; - default: break; - } - return ClientId; - } - } - return 0; -} - -static int QmiWwanReleaseClientID(QMI_SERVICE_TYPE QMIType, UCHAR ClientId) { - UCHAR argv[] = {QMIType, ClientId}; - QmiThreadSendQMI(ComposeQCTLMsg(QMICTL_RELEASE_CLIENT_ID_REQ, CtlReleaseClientIdReq, argv), NULL); - return 0; -} - -static int QmiWwanInit(PROFILE_T *profile) { - unsigned i; - int ret; - PQCQMIMSG pResponse; - - if (profile->proxy[0] && !strcmp(profile->proxy, LIBQMI_PROXY)) { - ret = libqmi_proxy_open(profile->qmichannel); - if (ret) - return ret; - } - - if (!profile->proxy[0]) { - for (i = 0; i < 10; i++) { - ret = QmiThreadSendQMITimeout(ComposeQCTLMsg(QMICTL_SYNC_REQ, NULL, NULL), NULL, 1 * 1000, __func__); - if (!ret) - break; - sleep(1); - } - if (ret) - return ret; - } - - QmiThreadSendQMI(ComposeQCTLMsg(QMICTL_GET_VERSION_REQ, CtlGetVersionReq, NULL), &pResponse); - if (profile->qmap_mode) { - if (pResponse) { - if (pResponse->CTLMsg.QMICTLMsgHdrRsp.QMUXResult == 0 && pResponse->CTLMsg.QMICTLMsgHdrRsp.QMUXError == 0) { - uint8_t NumElements = 0; - - for (NumElements = 0; NumElements < pResponse->CTLMsg.GetVersionRsp.NumElements; NumElements++) { -#if 0 - dbg_time("QMUXType = %02x Version = %d.%d", - pResponse->CTLMsg.GetVersionRsp.TypeVersion[NumElements].QMUXType, - pResponse->CTLMsg.GetVersionRsp.TypeVersion[NumElements].MajorVersion, - pResponse->CTLMsg.GetVersionRsp.TypeVersion[NumElements].MinorVersion); -#endif - if (pResponse->CTLMsg.GetVersionRsp.TypeVersion[NumElements].QMUXType == QMUX_TYPE_WDS_ADMIN) - profile->qmap_version = (pResponse->CTLMsg.GetVersionRsp.TypeVersion[NumElements].MinorVersion > 16); - } - } - } - } - if (pResponse) free(pResponse); - qmiclientId[QMUX_TYPE_WDS] = QmiWwanGetClientID(QMUX_TYPE_WDS); - if (profile->enable_ipv6) - qmiclientId[QMUX_TYPE_WDS_IPV6] = QmiWwanGetClientID(QMUX_TYPE_WDS); - qmiclientId[QMUX_TYPE_DMS] = QmiWwanGetClientID(QMUX_TYPE_DMS); - qmiclientId[QMUX_TYPE_NAS] = QmiWwanGetClientID(QMUX_TYPE_NAS); - qmiclientId[QMUX_TYPE_UIM] = QmiWwanGetClientID(QMUX_TYPE_UIM); - qmiclientId[QMUX_TYPE_WDS_ADMIN] = QmiWwanGetClientID(QMUX_TYPE_WDS_ADMIN); -#ifdef CONFIG_COEX_WWAN_STATE - qmiclientId[QMUX_TYPE_COEX] = QmiWwanGetClientID(QMUX_TYPE_COEX); -#endif -#ifdef CONFIG_ENABLE_QOS - qmiclientId[QMUX_TYPE_QOS] = QmiWwanGetClientID(QMUX_TYPE_QOS); -#endif - profile->wda_client = qmiclientId[QMUX_TYPE_WDS_ADMIN]; - - return 0; -} - -static int QmiWwanDeInit(void) { - unsigned int i; - for (i = 0; i < sizeof(qmiclientId)/sizeof(qmiclientId[0]); i++) - { - if (qmiclientId[i] != 0) - { - QmiWwanReleaseClientID((QMUX_TYPE_WDS_IPV6 == i ? QMUX_TYPE_WDS : i), qmiclientId[i]); - qmiclientId[i] = 0; - } - } - - return 0; -} - -static ssize_t qmi_proxy_read (int fd, void *buf, size_t size) { - ssize_t nreads; - PQCQMI_HDR pHdr = (PQCQMI_HDR)buf; - - nreads = read(fd, pHdr, sizeof(QCQMI_HDR)); - if (nreads == sizeof(QCQMI_HDR) && le16_to_cpu(pHdr->Length) < size) { - nreads += read(fd, pHdr+1, le16_to_cpu(pHdr->Length) + 1 - sizeof(QCQMI_HDR)); - } - - return nreads; -} - -#ifdef QUECTEL_QMI_MERGE -static int QmiWwanMergeQmiRsp(void *buf, ssize_t *src_size) { - static QMI_MSG_PACKET s_QMIPacket; - QMI_MSG_HEADER *header = NULL; - ssize_t size = *src_size; - - if((uint16_t)size < sizeof(QMI_MSG_HEADER)) - return -1; - - header = (QMI_MSG_HEADER *)buf; - if(le16_to_cpu(header->idenity) != MERGE_PACKET_IDENTITY || le16_to_cpu(header->version) != MERGE_PACKET_VERSION || le16_to_cpu(header->cur_len) > le16_to_cpu(header->total_len)) - return -1; - - if(le16_to_cpu(header->cur_len) == le16_to_cpu(header->total_len)) { - *src_size = le16_to_cpu(header->total_len); - memcpy(buf, buf + sizeof(QMI_MSG_HEADER), *src_size); - s_QMIPacket.len = 0; - return 0; - } - - memcpy(s_QMIPacket.buf + s_QMIPacket.len, buf + sizeof(QMI_MSG_HEADER), le16_to_cpu(header->cur_len)); - s_QMIPacket.len += le16_to_cpu(header->cur_len); - - if (le16_to_cpu(header->cur_len) < MERGE_PACKET_MAX_PAYLOAD_SIZE || s_QMIPacket.len >= le16_to_cpu(header->total_len)) { - memcpy(buf, s_QMIPacket.buf, s_QMIPacket.len); - *src_size = s_QMIPacket.len; - s_QMIPacket.len = 0; - return 0; - } - - return -1; -} -#endif - -static void * QmiWwanThread(void *pData) { - PROFILE_T *profile = (PROFILE_T *)pData; - const char *cdc_wdm = (const char *)profile->qmichannel; - int wait_for_request_quit = 0; - char num = cdc_wdm[strlen(cdc_wdm)-1]; - - if (profile->proxy[0]) { - if (!strncmp(profile->proxy, QUECTEL_QMI_PROXY, strlen(QUECTEL_QMI_PROXY))) { - snprintf(profile->proxy, sizeof(profile->proxy), "%s%c", QUECTEL_QMI_PROXY, num); - } - } - else if (!strncmp(cdc_wdm, "/dev/mhi_IPCR", strlen("/dev/mhi_IPCR"))) { - snprintf(profile->proxy, sizeof(profile->proxy), "%s%c", QUECTEL_QRTR_PROXY, num); - } - else if (profile->qmap_mode > 1) { - snprintf(profile->proxy, sizeof(profile->proxy), "%s%c", QUECTEL_QMI_PROXY, num); - } - - if (profile->proxy[0]) - cdc_wdm_fd = cm_open_proxy(profile->proxy); - else - cdc_wdm_fd = cm_open_dev(cdc_wdm); - - if (cdc_wdm_fd == -1) { - dbg_time("%s Failed to open %s, errno: %d (%s)", __func__, cdc_wdm, errno, strerror(errno)); - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED); - pthread_exit(NULL); - return NULL; - } - - dbg_time("cdc_wdm_fd = %d", cdc_wdm_fd); - - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_CONNECTED); - while (1) { - struct pollfd pollfds[] = {{qmidevice_control_fd[1], POLLIN, 0}, {cdc_wdm_fd, POLLIN, 0}}; - int ne, ret, nevents = sizeof(pollfds)/sizeof(pollfds[0]); - - do { - ret = poll(pollfds, nevents, wait_for_request_quit ? 1000 : -1); - } while ((ret < 0) && (errno == EINTR)); - - if (ret == 0 && wait_for_request_quit) { - QmiThreadRecvQMI(NULL); - continue; - } - - if (ret <= 0) { - dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno)); - break; - } - - for (ne = 0; ne < nevents; ne++) { - int fd = pollfds[ne].fd; - short revents = pollfds[ne].revents; - - //dbg_time("{%d, %x, %x}", pollfds[ne].fd, pollfds[ne].events, pollfds[ne].revents); - - if (revents & (POLLERR | POLLHUP | POLLNVAL)) { - dbg_time("%s poll err/hup/inval", __func__); - dbg_time("poll fd = %d, events = 0x%04x", fd, revents); - if (fd == cdc_wdm_fd) { - } else { - } - if (revents & (POLLHUP | POLLNVAL)) //EC20 bug, Can get POLLERR - goto __QmiWwanThread_quit; - } - - if ((revents & POLLIN) == 0) - continue; - - if (fd == qmidevice_control_fd[1]) { - int triger_event; - if (read(fd, &triger_event, sizeof(triger_event)) == sizeof(triger_event)) { - //DBG("triger_event = 0x%x", triger_event); - switch (triger_event) { - case RIL_REQUEST_QUIT: - goto __QmiWwanThread_quit; - break; - case SIG_EVENT_STOP: - wait_for_request_quit = 1; - break; - default: - break; - } - } - } - - if (fd == cdc_wdm_fd) { - ssize_t nreads; - PQCQMIMSG pResponse = (PQCQMIMSG)cm_recv_buf; - - if (!profile->proxy[0]) - nreads = read(fd, cm_recv_buf, sizeof(cm_recv_buf)); - else - nreads = qmi_proxy_read(fd, cm_recv_buf, sizeof(cm_recv_buf)); - //dbg_time("%s read=%d errno: %d (%s)", __func__, (int)nreads, errno, strerror(errno)); - if (nreads <= 0) { - dbg_time("%s read=%d errno: %d (%s)", __func__, (int)nreads, errno, strerror(errno)); - break; - } -#ifdef QUECTEL_QMI_MERGE - if((profile->qmap_mode == 0 || profile->qmap_mode == 1) && QmiWwanMergeQmiRsp(cm_recv_buf, &nreads)) - continue; -#endif - if (nreads != (le16_to_cpu(pResponse->QMIHdr.Length) + 1)) { - dbg_time("%s nreads=%d, pQCQMI->QMIHdr.Length = %d", __func__, (int)nreads, le16_to_cpu(pResponse->QMIHdr.Length)); - continue; - } - - QmiThreadRecvQMI(pResponse); - } - } - } - -__QmiWwanThread_quit: - if (cdc_wdm_fd != -1) { close(cdc_wdm_fd); cdc_wdm_fd = -1; } - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED); - QmiThreadRecvQMI(NULL); //main thread may pending on QmiThreadSendQMI() - dbg_time("%s exit", __func__); - pthread_exit(NULL); - return NULL; -} - -const struct qmi_device_ops qmiwwan_qmidev_ops = { - .init = QmiWwanInit, - .deinit = QmiWwanDeInit, - .send = QmiWwanSendQMI, - .read = QmiWwanThread, -}; - -uint8_t qmi_over_mbim_get_client_id(uint8_t QMIType) { - return QmiWwanGetClientID(QMIType); -} - -uint8_t qmi_over_mbim_release_client_id(uint8_t QMIType, uint8_t ClientId) { - return QmiWwanReleaseClientID(QMIType, ClientId); -} -#endif - +/****************************************************************************** + @file QmiWwanCM.c + @brief QMI WWAN connectivity manager. + + 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 +#include +#include +#include +#include +#include "QMIThread.h" + +#ifdef CONFIG_QMIWWAN +static int cdc_wdm_fd = -1; +static UCHAR qmiclientId[QMUX_TYPE_ALL]; + +static UCHAR GetQCTLTransactionId(void) { + static int TransactionId = 0; + if (++TransactionId > 0xFF) + TransactionId = 1; + return TransactionId; +} + +typedef USHORT (*CUSTOMQCTL)(PQMICTL_MSG pCTLMsg, void *arg); + +static PQCQMIMSG ComposeQCTLMsg(USHORT QMICTLType, CUSTOMQCTL customQctlMsgFunction, void *arg) { + UCHAR QMIBuf[WDM_DEFAULT_BUFSIZE]; + PQCQMIMSG pRequest = (PQCQMIMSG)QMIBuf; + int Length; + + pRequest->QMIHdr.IFType = USB_CTL_MSG_TYPE_QMI; + pRequest->QMIHdr.CtlFlags = 0x00; + pRequest->QMIHdr.QMIType = QMUX_TYPE_CTL; + pRequest->QMIHdr.ClientId= 0x00; + + pRequest->CTLMsg.QMICTLMsgHdr.CtlFlags = QMICTL_FLAG_REQUEST; + pRequest->CTLMsg.QMICTLMsgHdr.TransactionId = GetQCTLTransactionId(); + pRequest->CTLMsg.QMICTLMsgHdr.QMICTLType = cpu_to_le16(QMICTLType); + if (customQctlMsgFunction) + pRequest->CTLMsg.QMICTLMsgHdr.Length = cpu_to_le16(customQctlMsgFunction(&pRequest->CTLMsg, arg) - sizeof(QCQMICTL_MSG_HDR)); + else + pRequest->CTLMsg.QMICTLMsgHdr.Length = cpu_to_le16(0x0000); + + pRequest->QMIHdr.Length = cpu_to_le16(le16_to_cpu(pRequest->CTLMsg.QMICTLMsgHdr.Length) + sizeof(QCQMICTL_MSG_HDR) + sizeof(QCQMI_HDR) - 1); + Length = le16_to_cpu(pRequest->QMIHdr.Length) + 1; + + pRequest = (PQCQMIMSG)malloc(Length); + if (pRequest == NULL) { + dbg_time("%s fail to malloc", __func__); + } else { + memcpy(pRequest, QMIBuf, Length); + } + + return pRequest; +} + +static USHORT CtlGetVersionReq(PQMICTL_MSG QCTLMsg, void *arg) +{ + (void)arg; + QCTLMsg->GetVersionReq.TLVType = QCTLV_TYPE_REQUIRED_PARAMETER; + QCTLMsg->GetVersionReq.TLVLength = cpu_to_le16(0x0001); + QCTLMsg->GetVersionReq.QMUXTypes = QMUX_TYPE_ALL; + return sizeof(QMICTL_GET_VERSION_REQ_MSG); +} + +static USHORT CtlGetClientIdReq(PQMICTL_MSG QCTLMsg, void *arg) { + QCTLMsg->GetClientIdReq.TLVType = QCTLV_TYPE_REQUIRED_PARAMETER; + QCTLMsg->GetClientIdReq.TLVLength = cpu_to_le16(0x0001); + QCTLMsg->GetClientIdReq.QMIType = ((UCHAR *)arg)[0]; + return sizeof(QMICTL_GET_CLIENT_ID_REQ_MSG); +} + +static USHORT CtlReleaseClientIdReq(PQMICTL_MSG QCTLMsg, void *arg) { + QCTLMsg->ReleaseClientIdReq.TLVType = QCTLV_TYPE_REQUIRED_PARAMETER; + QCTLMsg->ReleaseClientIdReq.TLVLength = cpu_to_le16(0x0002); + QCTLMsg->ReleaseClientIdReq.QMIType = ((UCHAR *)arg)[0]; + QCTLMsg->ReleaseClientIdReq.ClientId = ((UCHAR *)arg)[1] ; + return sizeof(QMICTL_RELEASE_CLIENT_ID_REQ_MSG); +} + +static USHORT CtlLibQmiProxyOpenReq(PQMICTL_MSG QCTLMsg, void *arg) +{ + (void)arg; + const char *device_path = (const char *)(arg); + QCTLMsg->LibQmiProxyOpenReq.TLVType = 0x01; + QCTLMsg->LibQmiProxyOpenReq.TLVLength = cpu_to_le16(strlen(device_path)); + //strcpy(QCTLMsg->LibQmiProxyOpenReq.device_path, device_path); + //__builtin___strcpy_chk + memcpy(QCTLMsg->LibQmiProxyOpenReq.device_path, device_path, strlen(device_path)); + return sizeof(QMICTL_LIBQMI_PROXY_OPEN_MSG) + (strlen(device_path)); +} + +static int libqmi_proxy_open(const char *cdc_wdm) { + int ret; + PQCQMIMSG pResponse; + + ret = QmiThreadSendQMI(ComposeQCTLMsg(QMI_MESSAGE_CTL_INTERNAL_PROXY_OPEN, + CtlLibQmiProxyOpenReq, (void *)cdc_wdm), &pResponse); + if (!ret && pResponse + && pResponse->CTLMsg.QMICTLMsgHdrRsp.QMUXResult == 0 + && pResponse->CTLMsg.QMICTLMsgHdrRsp.QMUXError == 0) { + ret = 0; + } + else { + return -1; + } + + if (pResponse) + free(pResponse); + + return ret; +} + +static int QmiWwanSendQMI(PQCQMIMSG pRequest) { + struct pollfd pollfds[]= {{cdc_wdm_fd, POLLOUT, 0}}; + int ret; + + if (cdc_wdm_fd == -1) { + dbg_time("%s cdc_wdm_fd = -1", __func__); + return -ENODEV; + } + + if (pRequest->QMIHdr.QMIType != QMUX_TYPE_CTL) { + pRequest->QMIHdr.ClientId = qmiclientId[pRequest->QMIHdr.QMIType]; + if (pRequest->QMIHdr.ClientId == 0) { + dbg_time("QMIType %d has no clientID", pRequest->QMIHdr.QMIType); + return -ENODEV; + } + + if (pRequest->QMIHdr.QMIType == QMUX_TYPE_WDS_IPV6) + pRequest->QMIHdr.QMIType = QMUX_TYPE_WDS; + } + + do { + ret = poll(pollfds, sizeof(pollfds)/sizeof(pollfds[0]), 5000); + } while ((ret < 0) && (errno == EINTR)); + + if (pollfds[0].revents & POLLOUT) { + ssize_t nwrites = le16_to_cpu(pRequest->QMIHdr.Length) + 1; + ret = write(cdc_wdm_fd, pRequest, nwrites); + if (ret == nwrites) { + ret = 0; + } else { + dbg_time("%s write=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno)); + } + } else { + dbg_time("%s poll=%d, revents = 0x%x, errno: %d (%s)", __func__, ret, pollfds[0].revents, errno, strerror(errno)); + } + + return ret; +} + +static UCHAR QmiWwanGetClientID(UCHAR QMIType) { + PQCQMIMSG pResponse; + + QmiThreadSendQMI(ComposeQCTLMsg(QMICTL_GET_CLIENT_ID_REQ, CtlGetClientIdReq, &QMIType), &pResponse); + + if (pResponse) { + USHORT QMUXResult = cpu_to_le16(pResponse->CTLMsg.QMICTLMsgHdrRsp.QMUXResult); // QMI_RESULT_SUCCESS + USHORT QMUXError = cpu_to_le16(pResponse->CTLMsg.QMICTLMsgHdrRsp.QMUXError); // QMI_ERR_INVALID_ARG + //UCHAR QMIType = pResponse->CTLMsg.GetClientIdRsp.QMIType; + UCHAR ClientId = pResponse->CTLMsg.GetClientIdRsp.ClientId; + + if (!QMUXResult && !QMUXError && (QMIType == pResponse->CTLMsg.GetClientIdRsp.QMIType)) { + switch (QMIType) { + case QMUX_TYPE_WDS: dbg_time("Get clientWDS = %d", ClientId); break; + case QMUX_TYPE_DMS: dbg_time("Get clientDMS = %d", ClientId); break; + case QMUX_TYPE_NAS: dbg_time("Get clientNAS = %d", ClientId); break; + case QMUX_TYPE_QOS: dbg_time("Get clientQOS = %d", ClientId); break; + case QMUX_TYPE_WMS: dbg_time("Get clientWMS = %d", ClientId); break; + case QMUX_TYPE_PDS: dbg_time("Get clientPDS = %d", ClientId); break; + case QMUX_TYPE_UIM: dbg_time("Get clientUIM = %d", ClientId); break; + case QMUX_TYPE_COEX: dbg_time("Get clientCOEX = %d", ClientId); break; + case QMUX_TYPE_WDS_ADMIN: dbg_time("Get clientWDA = %d", ClientId); + break; + default: break; + } + return ClientId; + } + } + return 0; +} + +static int QmiWwanReleaseClientID(QMI_SERVICE_TYPE QMIType, UCHAR ClientId) { + UCHAR argv[] = {QMIType, ClientId}; + QmiThreadSendQMI(ComposeQCTLMsg(QMICTL_RELEASE_CLIENT_ID_REQ, CtlReleaseClientIdReq, argv), NULL); + return 0; +} + +static int QmiWwanInit(PROFILE_T *profile) { + unsigned i; + int ret; + PQCQMIMSG pResponse; + + if (profile->proxy[0] && !strcmp(profile->proxy, LIBQMI_PROXY)) { + ret = libqmi_proxy_open(profile->qmichannel); + if (ret) + return ret; + } + + if (!profile->proxy[0]) { + for (i = 0; i < 10; i++) { + ret = QmiThreadSendQMITimeout(ComposeQCTLMsg(QMICTL_SYNC_REQ, NULL, NULL), NULL, 1 * 1000, __func__); + if (!ret) + break; + sleep(1); + } + if (ret) + return ret; + } + + QmiThreadSendQMI(ComposeQCTLMsg(QMICTL_GET_VERSION_REQ, CtlGetVersionReq, NULL), &pResponse); + if (profile->qmap_mode) { + if (pResponse) { + if (pResponse->CTLMsg.QMICTLMsgHdrRsp.QMUXResult == 0 && pResponse->CTLMsg.QMICTLMsgHdrRsp.QMUXError == 0) { + uint8_t NumElements = 0; + + for (NumElements = 0; NumElements < pResponse->CTLMsg.GetVersionRsp.NumElements; NumElements++) { +#if 0 + dbg_time("QMUXType = %02x Version = %d.%d", + pResponse->CTLMsg.GetVersionRsp.TypeVersion[NumElements].QMUXType, + pResponse->CTLMsg.GetVersionRsp.TypeVersion[NumElements].MajorVersion, + pResponse->CTLMsg.GetVersionRsp.TypeVersion[NumElements].MinorVersion); +#endif + if (pResponse->CTLMsg.GetVersionRsp.TypeVersion[NumElements].QMUXType == QMUX_TYPE_WDS_ADMIN) + profile->qmap_version = (pResponse->CTLMsg.GetVersionRsp.TypeVersion[NumElements].MinorVersion > 16); + } + } + } + } + if (pResponse) free(pResponse); + qmiclientId[QMUX_TYPE_WDS] = QmiWwanGetClientID(QMUX_TYPE_WDS); + if (profile->enable_ipv6) + qmiclientId[QMUX_TYPE_WDS_IPV6] = QmiWwanGetClientID(QMUX_TYPE_WDS); + qmiclientId[QMUX_TYPE_DMS] = QmiWwanGetClientID(QMUX_TYPE_DMS); + qmiclientId[QMUX_TYPE_NAS] = QmiWwanGetClientID(QMUX_TYPE_NAS); + qmiclientId[QMUX_TYPE_UIM] = QmiWwanGetClientID(QMUX_TYPE_UIM); + qmiclientId[QMUX_TYPE_WDS_ADMIN] = QmiWwanGetClientID(QMUX_TYPE_WDS_ADMIN); +#ifdef CONFIG_COEX_WWAN_STATE + qmiclientId[QMUX_TYPE_COEX] = QmiWwanGetClientID(QMUX_TYPE_COEX); +#endif +#ifdef CONFIG_ENABLE_QOS + qmiclientId[QMUX_TYPE_QOS] = QmiWwanGetClientID(QMUX_TYPE_QOS); +#endif + profile->wda_client = qmiclientId[QMUX_TYPE_WDS_ADMIN]; + + return 0; +} + +static int QmiWwanDeInit(void) { + unsigned int i; + for (i = 0; i < sizeof(qmiclientId)/sizeof(qmiclientId[0]); i++) + { + if (qmiclientId[i] != 0) + { + QmiWwanReleaseClientID((QMUX_TYPE_WDS_IPV6 == i ? QMUX_TYPE_WDS : i), qmiclientId[i]); + qmiclientId[i] = 0; + } + } + + return 0; +} + +static ssize_t qmi_proxy_read (int fd, void *buf, size_t size) { + ssize_t nreads; + PQCQMI_HDR pHdr = (PQCQMI_HDR)buf; + + nreads = read(fd, pHdr, sizeof(QCQMI_HDR)); + if (nreads == sizeof(QCQMI_HDR) && le16_to_cpu(pHdr->Length) < size) { + nreads += read(fd, pHdr+1, le16_to_cpu(pHdr->Length) + 1 - sizeof(QCQMI_HDR)); + } + + return nreads; +} + +#ifdef QUECTEL_QMI_MERGE +static int QmiWwanMergeQmiRsp(void *buf, ssize_t *src_size) { + static QMI_MSG_PACKET s_QMIPacket; + QMI_MSG_HEADER *header = NULL; + ssize_t size = *src_size; + + if((uint16_t)size < sizeof(QMI_MSG_HEADER)) + return -1; + + header = (QMI_MSG_HEADER *)buf; + if(le16_to_cpu(header->idenity) != MERGE_PACKET_IDENTITY || le16_to_cpu(header->version) != MERGE_PACKET_VERSION || le16_to_cpu(header->cur_len) > le16_to_cpu(header->total_len)) + return -1; + + if(le16_to_cpu(header->cur_len) == le16_to_cpu(header->total_len)) { + *src_size = le16_to_cpu(header->total_len); + memcpy(buf, buf + sizeof(QMI_MSG_HEADER), *src_size); + s_QMIPacket.len = 0; + return 0; + } + + memcpy(s_QMIPacket.buf + s_QMIPacket.len, buf + sizeof(QMI_MSG_HEADER), le16_to_cpu(header->cur_len)); + s_QMIPacket.len += le16_to_cpu(header->cur_len); + + if (le16_to_cpu(header->cur_len) < MERGE_PACKET_MAX_PAYLOAD_SIZE || s_QMIPacket.len >= le16_to_cpu(header->total_len)) { + memcpy(buf, s_QMIPacket.buf, s_QMIPacket.len); + *src_size = s_QMIPacket.len; + s_QMIPacket.len = 0; + return 0; + } + + return -1; +} +#endif + +static void * QmiWwanThread(void *pData) { + PROFILE_T *profile = (PROFILE_T *)pData; + const char *cdc_wdm = (const char *)profile->qmichannel; + int wait_for_request_quit = 0; + char num = cdc_wdm[strlen(cdc_wdm)-1]; + + if (profile->proxy[0]) { + if (!strncmp(profile->proxy, QUECTEL_QMI_PROXY, strlen(QUECTEL_QMI_PROXY))) { + snprintf(profile->proxy, sizeof(profile->proxy), "%s%c", QUECTEL_QMI_PROXY, num); + } + } + else if (!strncmp(cdc_wdm, "/dev/mhi_IPCR", strlen("/dev/mhi_IPCR"))) { + snprintf(profile->proxy, sizeof(profile->proxy), "%s%c", QUECTEL_QRTR_PROXY, num); + } + else if (profile->qmap_mode > 1) { + snprintf(profile->proxy, sizeof(profile->proxy), "%s%c", QUECTEL_QMI_PROXY, num); + } + + if (profile->proxy[0]) + cdc_wdm_fd = cm_open_proxy(profile->proxy); + else + cdc_wdm_fd = cm_open_dev(cdc_wdm); + + if (cdc_wdm_fd == -1) { + dbg_time("%s Failed to open %s, errno: %d (%s)", __func__, cdc_wdm, errno, strerror(errno)); + qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED); + pthread_exit(NULL); + return NULL; + } + + dbg_time("cdc_wdm_fd = %d", cdc_wdm_fd); + + qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_CONNECTED); + while (1) { + struct pollfd pollfds[] = {{qmidevice_control_fd[1], POLLIN, 0}, {cdc_wdm_fd, POLLIN, 0}}; + int ne, ret, nevents = sizeof(pollfds)/sizeof(pollfds[0]); + + do { + ret = poll(pollfds, nevents, wait_for_request_quit ? 1000 : -1); + } while ((ret < 0) && (errno == EINTR)); + + if (ret == 0 && wait_for_request_quit) { + QmiThreadRecvQMI(NULL); + continue; + } + + if (ret <= 0) { + dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno)); + break; + } + + for (ne = 0; ne < nevents; ne++) { + int fd = pollfds[ne].fd; + short revents = pollfds[ne].revents; + + //dbg_time("{%d, %x, %x}", pollfds[ne].fd, pollfds[ne].events, pollfds[ne].revents); + + if (revents & (POLLERR | POLLHUP | POLLNVAL)) { + dbg_time("%s poll err/hup/inval", __func__); + dbg_time("poll fd = %d, events = 0x%04x", fd, revents); + if (fd == cdc_wdm_fd) { + } else { + } + if (revents & (POLLHUP | POLLNVAL)) //EC20 bug, Can get POLLERR + goto __QmiWwanThread_quit; + } + + if ((revents & POLLIN) == 0) + continue; + + if (fd == qmidevice_control_fd[1]) { + int triger_event; + if (read(fd, &triger_event, sizeof(triger_event)) == sizeof(triger_event)) { + //DBG("triger_event = 0x%x", triger_event); + switch (triger_event) { + case RIL_REQUEST_QUIT: + goto __QmiWwanThread_quit; + break; + case SIG_EVENT_STOP: + wait_for_request_quit = 1; + break; + default: + break; + } + } + } + + if (fd == cdc_wdm_fd) { + ssize_t nreads; + PQCQMIMSG pResponse = (PQCQMIMSG)cm_recv_buf; + + if (!profile->proxy[0]) + nreads = read(fd, cm_recv_buf, sizeof(cm_recv_buf)); + else + nreads = qmi_proxy_read(fd, cm_recv_buf, sizeof(cm_recv_buf)); + //dbg_time("%s read=%d errno: %d (%s)", __func__, (int)nreads, errno, strerror(errno)); + if (nreads <= 0) { + dbg_time("%s read=%d errno: %d (%s)", __func__, (int)nreads, errno, strerror(errno)); + break; + } +#ifdef QUECTEL_QMI_MERGE + if((profile->qmap_mode == 0 || profile->qmap_mode == 1) && QmiWwanMergeQmiRsp(cm_recv_buf, &nreads)) + continue; +#endif + if (nreads != (le16_to_cpu(pResponse->QMIHdr.Length) + 1)) { + dbg_time("%s nreads=%d, pQCQMI->QMIHdr.Length = %d", __func__, (int)nreads, le16_to_cpu(pResponse->QMIHdr.Length)); + continue; + } + + QmiThreadRecvQMI(pResponse); + } + } + } + +__QmiWwanThread_quit: + if (cdc_wdm_fd != -1) { close(cdc_wdm_fd); cdc_wdm_fd = -1; } + qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED); + QmiThreadRecvQMI(NULL); //main thread may pending on QmiThreadSendQMI() + dbg_time("%s exit", __func__); + pthread_exit(NULL); + return NULL; +} + +const struct qmi_device_ops qmiwwan_qmidev_ops = { + .init = QmiWwanInit, + .deinit = QmiWwanDeInit, + .send = QmiWwanSendQMI, + .read = QmiWwanThread, +}; + +uint8_t qmi_over_mbim_get_client_id(uint8_t QMIType) { + return QmiWwanGetClientID(QMIType); +} + +uint8_t qmi_over_mbim_release_client_id(uint8_t QMIType, uint8_t ClientId) { + return QmiWwanReleaseClientID(QMIType, ClientId); +} +#endif + diff --git a/wwan/app/quectel_cm_5G/src/ReleaseNote.txt b/wwan/app/quectel-cm/src/ReleaseNote.txt similarity index 96% rename from wwan/app/quectel_cm_5G/src/ReleaseNote.txt rename to wwan/app/quectel-cm/src/ReleaseNote.txt index a5eb77d..4ac3c68 100644 --- a/wwan/app/quectel_cm_5G/src/ReleaseNote.txt +++ b/wwan/app/quectel-cm/src/ReleaseNote.txt @@ -1,339 +1,339 @@ -Release Notes - -[V1.6.5] -Date: 7/3/2023 -enhancement: - 1. Fix the issue of qmi client id leakage caused by kill 9 killing the client of quectel-qmi-proxy - 2. Fix wds_ipv6 client ID can't be released issue - 3. Fix wds_ipv6 client ID can't be released issue - 4. Resolve PDP_ Context&Profile_ The issue of index mixing - 5. Add parameter - d to obtain IP and DNS information through qmi - 6. Fix mbim dialing. When the user does not specify apn through - s, prompt the user and exit the dialing program - 7. Prioritize the use of IP commands for optimization, and use ifconfig if not available - 8. Optimize and add/remove copyright -fix: - - -[V1.6.4] -Date: 9/7/2022 -enhancement: - 1. set cflags as -Wall -Wextra -Werror -O1, and fix compile errors - 2. some code refactoring - 3. add quectel-qrtr-proxy -fix: - 1. netmask error when use ifconfig on little endian cpu - -[V1.6.2] -Date: 11/18/2021 -enhancement: - 1. support 'LTE && WiFi Coexistence Solution via QMI'. - If customer want use this feature, need enable CONFIG_COEX_WWAN_STATE in QMIThread.h - -[V1.6.1] -Date: 7/20/2021 -enhancement: - 1. add requestGetCellInfoList requestRadioPower - 2. add QMI OVER MBIM - 3. support qrtr and rmnet - 4. support RG500U PCIE - 5. add qos service && get qos flow data_rate_max func -fix: - 1. mbim: increase mbim open timeout to 3 seconds. some modem take long time for open cmd. - 2. support MsChapV2 - 3. mbim: invalid memory access when only get one DNS - 4. some bug fix for use AT Command to setup data call - -[V1.6.0.26] -Date: 4/22/2021 -enhancement: - 1. add lots of log file to show how to use this tool - 2. support pcie mhi multiple call - 3. at command: support EC200U/EC200T/EC200S/RG801H/RG500U/ -fix: - 1. mbim-proxy: fix errors on big endian cpu, ignore mbim open/close cmd from quectel-cm - -[V1.6.0.25] -Date: 4/8/2021 -enhancement: -fix: - 1. fix compile error when use gcc 9.3.0 - 2. fix yocto 'QA Issue: No GNU_HASH in the ELF binary' - -[V1.6.0.24] -Date: 3/9/2021 -enhancement: - 1. '-p [quectel-][qmi|mbim]-proxy', can connect to quectel/libqmi/libmbim's proxy, even only one data - 2. set variable s_9x07 as 1 (from 0), most of modems are base on MDM90x7 and later QCOM chip. -fix: - 1. define CHAR as signed char - 2. mofidy Makefile to generate more compile warnnings and fix them - -[V1.6.0.23] -Date: 2/26/2021 -enhancement: - 1. support 'AT+QNETDEVCTL' (not release) -fix: - 1. modify help/usage - 2. fix some memroy access error in mbim-cm.c - -[V1.6.0.22] -Date: 2/4/2021 -enhancement: - 1. support connect to libqmi's qmi-proxy - 2. only allow ' 0/1/2/none/pap/chap' for auth of '-s' - 3. '-m iface-idx' bind QMAP data call to wwan0_ -fix: - -[V1.6.0.21] -Date: 1/28/2021 -enhancement: - 1. print 5G signal -fix: - 1. fix compile errors: -Werror=format-truncation= - -[V1.6.0.20] -Date: 12/29/2020 -enhancement: - 1. Code refactoring - 2. support 'AT+QNETDEVCTL' (not release) -fix: - -[V1.6.0.19] -Date: 12/4/2020 -enhancement: - 1. if 'udhcpc's default.script' missed, directy set ip/dns/route by 'ip' co,mand -fix: - -[V1.6.0.18] -Date: 12/4/2020 -enhancement: - 1. Code refactoring -fix: - -[V1.6.0.17] -Date: 8/25/2020 -enhancement: - 1. support MBIM multi-call - 2. support unisoc RG500U mbim - 3. QUECTEL_QMI_MERGE: some SOC can not read more then 64 bytes (QMI)data via USB Endpoint 0 -fix: - -[V1.6.0.15] -Date: 7/24/2020 -enhancement: -fix: - 1. QMAP multi-call, AT+CFUN=4 then AT+CFUN=1, only one call can obtain IP by DHCP - -[V1.6.0.14] -Date: 6/10/2020 -enhancement: - 1. support X55's GobiNet LOOPBACK -fix: - 1. very old uclib do not support htole32 and pthread_condattr_setclock - 2. pthread_cond_wait tv_nsec >= 1000000000U is wrong - 3. do not close socket in udhcpc.c ifc_get_addr() - -[V1.6.0.13] -Date: 6/9/2020 -enhancement: - 1. add some example for openwrt, marco 'QL_OPENWER_NETWORK_SETUP' -fix: - -[V1.6.0.12] -Date: 5/29/2020 -enhancement: -fix: - 1. some EM12's usb-net-qmi/mbim interface is at 8 (not 4) - -[V1.6.0.11] -Date: 5/28/2020 -enhancement: -fix: - 1. fix mbim debug on Big Endian CPU - -[V1.6.0.10] -Date: 5/25/2020 -enhancement: -fix: - 1. set QMAP .ul_data_aggregation_max_datagrams to 11 (from 16) - -[V1.6.0.9] -Date: 5/22/2020 -enhancement: -fix: - 1. dial fail when register to 5G-SA - -[V1.6.0.8] -Date: 4/30/2020 -enhancement: - 1. support '-b' to seletc brige mode -fix: - -[V1.6.0.7] -Date: 4/29/2020 -enhancement: - 1. support QMAP multi-call for qmi_wwan_q and pcie_mhi 's rmnet driver -fix: - -[V1.6.0.6] -Date: 4/20/2020 -enhancement: - 1. support '-k pdn_idx' to hangup call '-n pdn_idx' -fix: - 1. fix set dl_minimum_padding as 0, modems do not support this featrue - -[V1.6.0.5] -Date: 4/10/2020 -enhancement: - 1. support X55's QMAPV5 for PCIE -fix: - -[V1.6.0.3] -Date: 4/8/2020 -enhancement: - 1. support multi-modems all use multi-data-calls -fix: - -[V1.6.0.2] -Date: 4/7/2020 -enhancement: - 1. support X55's QMAPV5 for USB -fix: - -[V1.6.0.1] -Date: 4/1/2020 -enhancement: - 1. support QMAP UL AGG (multi data call) -fix: - 1. some EM12's usb-net-qmi/mbim interface is at 8 (not 4) - -[V1.5.9] -Date: 3/4/2020 -enhancement: - 1. support pcie mhi multi-APN data call - 3. support QMAP UL AGG (single data call) -fix: - 1. set 4 bytes aligned for mbim parameters, or cause dial mbim call fail - -[V1.5.8] -Date: 2/18/2020 -enhancement: - 1. support '-l 14' X55's loopback function -fix: - -[V1.5.7] -Date: 2/6/2020 -enhancement: - 1. support '-u usbmon_log_file' to catch usbmon log -fix: - -[V1.5.6] -Date: 1/20/202 -enhancement: - 1. show driver name and version - 2. support PCSCF - 3. support bridge in mbim -fix: - -[V1.5.5] -Date: 12/31/2019 -enhancement: -fix: - 1. fix some memory access bug in mbim-cm.c - -[WCDMA<E_QConnectManager_Linux&Android_V1.5.4] -Date: 12/17/2019 -enhancement: - 1. Add copyright - 2. auto detect pcie mhi /dev/mhi* -fix: - -[WCDMA<E_QConnectManager_Linux&Android_V1.5.3] -Date: 2019/12/11 -enhancement: -1. support show SignalInfo, controlled by macro CONFIG_SIGNALINFO -2. support show 5G_NSA/5G_NA -3. support Microsoft Extend MBIM message -fix: -1. quectel-qmi-proxy bugs on Big-Endian CPU - -[WCDMA<E_QConnectManager_Linux&Android_V1.5.2] -Date: 12/2/2019 -enhancement: - 1. support requestGetSignalInfo() -fix: - -[WCDMA<E_QConnectManager_Linux&Android_V1.4.1] -Date: 10/23/2019 -enhancement: - 1. support QMI_CTL_REVOKE_CLIENT_ID_IND (Quectel define QMI) - 2. add copyright -fix: - 1. remove SIGUSR - -[WCDMA<E_QConnectManager_Linux&Android_V1.3.10] -Date: 10/14/2019 -enhancement: - 1. increase retry interval -fix: - -[WCDMA<E_QConnectManager_Linux&Android_V1.2.1] -Date: 2019/02/26 -enhancement: -1. Implement help message. - -root@ubuntu:# ./quectel-CM -h -[02-26_10:39:21:353] Usage: ./quectel-CM [options] -[02-26_10:39:21:353] -s [apn [user password auth]] Set apn/user/password/auth get from your network provider -[02-26_10:39:21:353] -p pincode Verify sim card pin if sim card is locked -[02-26_10:39:21:353] -f logfilename Save log message of this program to file -[02-26_10:39:21:353] -i interface Specify network interface(default auto-detect) -[02-26_10:39:21:353] -4 IPv4 protocol -[02-26_10:39:21:353] -6 IPv6 protocol -[02-26_10:39:21:353] -m muxID Specify muxid when set multi-pdn data connection. -[02-26_10:39:21:353] -n channelID Specify channelID when set multi-pdn data connection(default 1). -[02-26_10:39:21:353] [Examples] -[02-26_10:39:21:353] Example 1: ./quectel-CM -[02-26_10:39:21:353] Example 2: ./quectel-CM -s 3gnet -[02-26_10:39:21:353] Example 3: ./quectel-CM -s 3gnet carl 1234 0 -p 1234 -f gobinet_log.txt -root@ubuntu:# -2. Support bridge mode when set multi-pdn data connections. -3. Host device can access network in bridge mode. - -[WCDMA<E_QConnectManager_Linux&Android_V1.1.46] -Date: 2019/02/18 -enhancement: -1. support only IPV6 data call. quectel-CM now support three dialing methods: IPV4 only, IPV6 only, IPV4V6. - ./quectel-CM -4(or no argument) only IPV4 - -6 only IPV6 - -4 -6 IPV4 && IPV6 - -[WCDMA<E_QConnectManager_Linux&Android_V1.1.45] -Date: 2018/09/13 -enhancement: -1. support EG12 PCIE interface - -[WCDMA<E_QConnectManager_Linux&Android_V1.1.44] -Date: 2018/09/10 -enhancement: -1. support setup IPV4&IPV6 data call. - -[WCDMA<E_QConnectManager_Linux&Android_V1.1.43] -[WCDMA<E_QConnectManager_Linux&Android_V1.1.42] -Date: 2018/08/29 -enhancement: -1. support QMI_WWAN's QMAP fucntion and bridge mode, please contact Quectel FAE to get qmi_wwan.c patch. - when enable QMI_WWAN's QMAP IP Mux function, must run 'quectel-qmi-proxy -d /dev/cdc-wdmX' before quectel-CM - -[WCDMA<E_QConnectManager_Linux&Android_V1.1.41] -Date: 2018/05/24 -enhancement: -1. fix a cdma data call error - -[WCDMA<E_QConnectManager_Linux&Android_V1.1.40] -Date: 2018/05/12 -enhancement: -1. support GobiNet's QMAP fucntion and bridge mode. - 'Quectel_WCDMA<E_Linux&Android_GobiNet_Driver_V1.3.5' and later version is required to use QMAP and bridge mode. - for detail, please refer to GobiNet Driver - +Release Notes + +[V1.6.5] +Date: 7/3/2023 +enhancement: + 1. Fix the issue of qmi client id leakage caused by kill 9 killing the client of quectel-qmi-proxy + 2. Fix wds_ipv6 client ID can't be released issue + 3. Fix wds_ipv6 client ID can't be released issue + 4. Resolve PDP_ Context&Profile_ The issue of index mixing + 5. Add parameter - d to obtain IP and DNS information through qmi + 6. Fix mbim dialing. When the user does not specify apn through - s, prompt the user and exit the dialing program + 7. Prioritize the use of IP commands for optimization, and use ifconfig if not available + 8. Optimize and add/remove copyright +fix: + + +[V1.6.4] +Date: 9/7/2022 +enhancement: + 1. set cflags as -Wall -Wextra -Werror -O1, and fix compile errors + 2. some code refactoring + 3. add quectel-qrtr-proxy +fix: + 1. netmask error when use ifconfig on little endian cpu + +[V1.6.2] +Date: 11/18/2021 +enhancement: + 1. support 'LTE && WiFi Coexistence Solution via QMI'. + If customer want use this feature, need enable CONFIG_COEX_WWAN_STATE in QMIThread.h + +[V1.6.1] +Date: 7/20/2021 +enhancement: + 1. add requestGetCellInfoList requestRadioPower + 2. add QMI OVER MBIM + 3. support qrtr and rmnet + 4. support RG500U PCIE + 5. add qos service && get qos flow data_rate_max func +fix: + 1. mbim: increase mbim open timeout to 3 seconds. some modem take long time for open cmd. + 2. support MsChapV2 + 3. mbim: invalid memory access when only get one DNS + 4. some bug fix for use AT Command to setup data call + +[V1.6.0.26] +Date: 4/22/2021 +enhancement: + 1. add lots of log file to show how to use this tool + 2. support pcie mhi multiple call + 3. at command: support EC200U/EC200T/EC200S/RG801H/RG500U/ +fix: + 1. mbim-proxy: fix errors on big endian cpu, ignore mbim open/close cmd from quectel-cm + +[V1.6.0.25] +Date: 4/8/2021 +enhancement: +fix: + 1. fix compile error when use gcc 9.3.0 + 2. fix yocto 'QA Issue: No GNU_HASH in the ELF binary' + +[V1.6.0.24] +Date: 3/9/2021 +enhancement: + 1. '-p [quectel-][qmi|mbim]-proxy', can connect to quectel/libqmi/libmbim's proxy, even only one data + 2. set variable s_9x07 as 1 (from 0), most of modems are base on MDM90x7 and later QCOM chip. +fix: + 1. define CHAR as signed char + 2. mofidy Makefile to generate more compile warnnings and fix them + +[V1.6.0.23] +Date: 2/26/2021 +enhancement: + 1. support 'AT+QNETDEVCTL' (not release) +fix: + 1. modify help/usage + 2. fix some memroy access error in mbim-cm.c + +[V1.6.0.22] +Date: 2/4/2021 +enhancement: + 1. support connect to libqmi's qmi-proxy + 2. only allow ' 0/1/2/none/pap/chap' for auth of '-s' + 3. '-m iface-idx' bind QMAP data call to wwan0_ +fix: + +[V1.6.0.21] +Date: 1/28/2021 +enhancement: + 1. print 5G signal +fix: + 1. fix compile errors: -Werror=format-truncation= + +[V1.6.0.20] +Date: 12/29/2020 +enhancement: + 1. Code refactoring + 2. support 'AT+QNETDEVCTL' (not release) +fix: + +[V1.6.0.19] +Date: 12/4/2020 +enhancement: + 1. if 'udhcpc's default.script' missed, directy set ip/dns/route by 'ip' co,mand +fix: + +[V1.6.0.18] +Date: 12/4/2020 +enhancement: + 1. Code refactoring +fix: + +[V1.6.0.17] +Date: 8/25/2020 +enhancement: + 1. support MBIM multi-call + 2. support unisoc RG500U mbim + 3. QUECTEL_QMI_MERGE: some SOC can not read more then 64 bytes (QMI)data via USB Endpoint 0 +fix: + +[V1.6.0.15] +Date: 7/24/2020 +enhancement: +fix: + 1. QMAP multi-call, AT+CFUN=4 then AT+CFUN=1, only one call can obtain IP by DHCP + +[V1.6.0.14] +Date: 6/10/2020 +enhancement: + 1. support X55's GobiNet LOOPBACK +fix: + 1. very old uclib do not support htole32 and pthread_condattr_setclock + 2. pthread_cond_wait tv_nsec >= 1000000000U is wrong + 3. do not close socket in udhcpc.c ifc_get_addr() + +[V1.6.0.13] +Date: 6/9/2020 +enhancement: + 1. add some example for openwrt, marco 'QL_OPENWER_NETWORK_SETUP' +fix: + +[V1.6.0.12] +Date: 5/29/2020 +enhancement: +fix: + 1. some EM12's usb-net-qmi/mbim interface is at 8 (not 4) + +[V1.6.0.11] +Date: 5/28/2020 +enhancement: +fix: + 1. fix mbim debug on Big Endian CPU + +[V1.6.0.10] +Date: 5/25/2020 +enhancement: +fix: + 1. set QMAP .ul_data_aggregation_max_datagrams to 11 (from 16) + +[V1.6.0.9] +Date: 5/22/2020 +enhancement: +fix: + 1. dial fail when register to 5G-SA + +[V1.6.0.8] +Date: 4/30/2020 +enhancement: + 1. support '-b' to seletc brige mode +fix: + +[V1.6.0.7] +Date: 4/29/2020 +enhancement: + 1. support QMAP multi-call for qmi_wwan_q and pcie_mhi 's rmnet driver +fix: + +[V1.6.0.6] +Date: 4/20/2020 +enhancement: + 1. support '-k pdn_idx' to hangup call '-n pdn_idx' +fix: + 1. fix set dl_minimum_padding as 0, modems do not support this featrue + +[V1.6.0.5] +Date: 4/10/2020 +enhancement: + 1. support X55's QMAPV5 for PCIE +fix: + +[V1.6.0.3] +Date: 4/8/2020 +enhancement: + 1. support multi-modems all use multi-data-calls +fix: + +[V1.6.0.2] +Date: 4/7/2020 +enhancement: + 1. support X55's QMAPV5 for USB +fix: + +[V1.6.0.1] +Date: 4/1/2020 +enhancement: + 1. support QMAP UL AGG (multi data call) +fix: + 1. some EM12's usb-net-qmi/mbim interface is at 8 (not 4) + +[V1.5.9] +Date: 3/4/2020 +enhancement: + 1. support pcie mhi multi-APN data call + 3. support QMAP UL AGG (single data call) +fix: + 1. set 4 bytes aligned for mbim parameters, or cause dial mbim call fail + +[V1.5.8] +Date: 2/18/2020 +enhancement: + 1. support '-l 14' X55's loopback function +fix: + +[V1.5.7] +Date: 2/6/2020 +enhancement: + 1. support '-u usbmon_log_file' to catch usbmon log +fix: + +[V1.5.6] +Date: 1/20/202 +enhancement: + 1. show driver name and version + 2. support PCSCF + 3. support bridge in mbim +fix: + +[V1.5.5] +Date: 12/31/2019 +enhancement: +fix: + 1. fix some memory access bug in mbim-cm.c + +[WCDMA<E_QConnectManager_Linux&Android_V1.5.4] +Date: 12/17/2019 +enhancement: + 1. Add copyright + 2. auto detect pcie mhi /dev/mhi* +fix: + +[WCDMA<E_QConnectManager_Linux&Android_V1.5.3] +Date: 2019/12/11 +enhancement: +1. support show SignalInfo, controlled by macro CONFIG_SIGNALINFO +2. support show 5G_NSA/5G_NA +3. support Microsoft Extend MBIM message +fix: +1. quectel-qmi-proxy bugs on Big-Endian CPU + +[WCDMA<E_QConnectManager_Linux&Android_V1.5.2] +Date: 12/2/2019 +enhancement: + 1. support requestGetSignalInfo() +fix: + +[WCDMA<E_QConnectManager_Linux&Android_V1.4.1] +Date: 10/23/2019 +enhancement: + 1. support QMI_CTL_REVOKE_CLIENT_ID_IND (Quectel define QMI) + 2. add copyright +fix: + 1. remove SIGUSR + +[WCDMA<E_QConnectManager_Linux&Android_V1.3.10] +Date: 10/14/2019 +enhancement: + 1. increase retry interval +fix: + +[WCDMA<E_QConnectManager_Linux&Android_V1.2.1] +Date: 2019/02/26 +enhancement: +1. Implement help message. + +root@ubuntu:# ./quectel-CM -h +[02-26_10:39:21:353] Usage: ./quectel-CM [options] +[02-26_10:39:21:353] -s [apn [user password auth]] Set apn/user/password/auth get from your network provider +[02-26_10:39:21:353] -p pincode Verify sim card pin if sim card is locked +[02-26_10:39:21:353] -f logfilename Save log message of this program to file +[02-26_10:39:21:353] -i interface Specify network interface(default auto-detect) +[02-26_10:39:21:353] -4 IPv4 protocol +[02-26_10:39:21:353] -6 IPv6 protocol +[02-26_10:39:21:353] -m muxID Specify muxid when set multi-pdn data connection. +[02-26_10:39:21:353] -n channelID Specify channelID when set multi-pdn data connection(default 1). +[02-26_10:39:21:353] [Examples] +[02-26_10:39:21:353] Example 1: ./quectel-CM +[02-26_10:39:21:353] Example 2: ./quectel-CM -s 3gnet +[02-26_10:39:21:353] Example 3: ./quectel-CM -s 3gnet carl 1234 0 -p 1234 -f gobinet_log.txt +root@ubuntu:# +2. Support bridge mode when set multi-pdn data connections. +3. Host device can access network in bridge mode. + +[WCDMA<E_QConnectManager_Linux&Android_V1.1.46] +Date: 2019/02/18 +enhancement: +1. support only IPV6 data call. quectel-CM now support three dialing methods: IPV4 only, IPV6 only, IPV4V6. + ./quectel-CM -4(or no argument) only IPV4 + -6 only IPV6 + -4 -6 IPV4 && IPV6 + +[WCDMA<E_QConnectManager_Linux&Android_V1.1.45] +Date: 2018/09/13 +enhancement: +1. support EG12 PCIE interface + +[WCDMA<E_QConnectManager_Linux&Android_V1.1.44] +Date: 2018/09/10 +enhancement: +1. support setup IPV4&IPV6 data call. + +[WCDMA<E_QConnectManager_Linux&Android_V1.1.43] +[WCDMA<E_QConnectManager_Linux&Android_V1.1.42] +Date: 2018/08/29 +enhancement: +1. support QMI_WWAN's QMAP fucntion and bridge mode, please contact Quectel FAE to get qmi_wwan.c patch. + when enable QMI_WWAN's QMAP IP Mux function, must run 'quectel-qmi-proxy -d /dev/cdc-wdmX' before quectel-CM + +[WCDMA<E_QConnectManager_Linux&Android_V1.1.41] +Date: 2018/05/24 +enhancement: +1. fix a cdma data call error + +[WCDMA<E_QConnectManager_Linux&Android_V1.1.40] +Date: 2018/05/12 +enhancement: +1. support GobiNet's QMAP fucntion and bridge mode. + 'Quectel_WCDMA<E_Linux&Android_GobiNet_Driver_V1.3.5' and later version is required to use QMAP and bridge mode. + for detail, please refer to GobiNet Driver + diff --git a/wwan/app/quectel_cm_5G/src/at_tok.c b/wwan/app/quectel-cm/src/at_tok.c similarity index 100% rename from wwan/app/quectel_cm_5G/src/at_tok.c rename to wwan/app/quectel-cm/src/at_tok.c diff --git a/wwan/app/quectel_cm_5G/src/at_tok.h b/wwan/app/quectel-cm/src/at_tok.h similarity index 100% rename from wwan/app/quectel_cm_5G/src/at_tok.h rename to wwan/app/quectel-cm/src/at_tok.h diff --git a/wwan/app/quectel_cm_5G/src/atc.c b/wwan/app/quectel-cm/src/atc.c similarity index 96% rename from wwan/app/quectel_cm_5G/src/atc.c rename to wwan/app/quectel-cm/src/atc.c index ef78ec6..55497ee 100644 --- a/wwan/app/quectel_cm_5G/src/atc.c +++ b/wwan/app/quectel-cm/src/atc.c @@ -1,1055 +1,1055 @@ -/****************************************************************************** - @file atc.c - @brief at command. - - 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern int asprintf(char **s, const char *fmt, ...); - -#include "QMIThread.h" - -#include "atchannel.h" -#include "at_tok.h" - -static int asr_style_atc = 0; -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;}} - -#define at_response_error(err, p_response) \ - (err \ - || p_response == NULL \ - || p_response->finalResponse == NULL \ - || p_response->success == 0) - -static int atc_init(PROFILE_T *profile) { - int err; - char *cmd; - ATResponse *p_response = NULL; - - if (profile->proxy[0]) { - s_pdp = profile->pdp; - err = at_send_command_singleline("AT+QNETDEVSTATUS=?", "+QNETDEVSTATUS:", &p_response); - if (at_response_error(err, p_response)) - asr_style_atc = 1; //EC200T/EC100Y do not support this AT, but RG801/RG500U support - safe_at_response_free(p_response); - - return err; - } - - err = at_handshake(); - if (err) { - dbg_time("handshake fail, TODO ... "); - goto exit; - } - - s_pdp = profile->pdp; - at_send_command_singleline("AT+QCFG=\"usbnet\"", "+QCFG:", NULL); - at_send_command_multiline("AT+QNETDEVCTL=?", "+QNETDEVCTL:", NULL); - at_send_command("AT+CGREG=2", NULL); //GPRS Network Registration Status - at_send_command("AT+CEREG=2", NULL); //EPS Network Registration Status - at_send_command("AT+C5GREG=2", NULL); //5GS Network Registration Status - - err = at_send_command_singleline("AT+QNETDEVSTATUS=?", "+QNETDEVSTATUS:", &p_response); - if (at_response_error(err, p_response)) - asr_style_atc = 1; //EC200T/EC100Y do not support this AT, but RG801/RG500U support - safe_at_response_free(p_response); - - err = at_send_command_singleline("AT+QCFG=\"NAT\"", "+QCFG:", &p_response); - if (!at_response_error(err, p_response)) { - int old_nat, new_nat = asr_style_atc ? 1 : 0; - - err = at_tok_scanf(p_response->p_intermediates->line, "%s%d", NULL, &old_nat); - if (err == 2 && old_nat != new_nat) { - safe_at_response_free(p_response); - asprintf(&cmd, "AT+QCFG=\"NAT\",%d", new_nat); - err = at_send_command(cmd, &p_response); - safe_free(cmd); - if (!at_response_error(err, p_response)) { - err = at_send_command("at+cfun=1,1",NULL); - if (!err) - g_donot_exit_when_modem_hangup = 1; - //reboot to take effect - } - safe_at_response_free(p_response); - } - err = 0; - } - safe_at_response_free(p_response); - -exit: - return err; -} - -static int atc_deinit(void) { - return 0; -} - -/** - * Called by atchannel when an unsolicited line appears - * This is called on atchannel's reader thread. AT commands may - * not be issued here - */ -static void onUnsolicited (const char *s, const char *sms_pdu) -{ - (void)sms_pdu; - - if (strStartsWith(s, "+QNETDEVSTATUS:")) { - qmidevice_send_event_to_main(RIL_UNSOL_DATA_CALL_LIST_CHANGED); - } - else if (strStartsWith(s, "+CGREG:") - || strStartsWith(s, "+CEREG:") - || strStartsWith(s, "+C5GREG:")) { - qmidevice_send_event_to_main(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED); - } -} - -static void onTimeout(void) { - dbg_time("%s", __func__); - //TODO -} - -static void onClose(void) { - dbg_time("%s", __func__); -} - -static void * atc_read_thread(void *param) { - PROFILE_T *profile = (PROFILE_T *)param; - const char *cdc_wdm = (const char *)profile->qmichannel; - int wait_for_request_quit = 0; - int atc_fd; - - atc_fd = cm_open_dev(cdc_wdm); - if (atc_fd <= 0) { - dbg_time("fail to open (%s), errno: %d (%s)", cdc_wdm, errno, strerror(errno)); - goto __quit; - } - - dbg_time("atc_fd = %d", atc_fd); - - if (at_open(atc_fd, onUnsolicited, 0)) - goto __quit; - - at_set_on_timeout(onTimeout); - at_set_on_reader_closed(onClose); - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_CONNECTED); - - while (atc_fd > 0) { - struct pollfd pollfds[] = {{atc_fd, POLLIN, 0}, {qmidevice_control_fd[1], POLLIN, 0}}; - int ne, ret, nevents = 2; - - ret = poll(pollfds, nevents, wait_for_request_quit ? 1000 : -1); - - if (ret == 0 && wait_for_request_quit) { - break; - } - - if (ret < 0) { - dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno)); - break; - } - - for (ne = 0; ne < nevents; ne++) { - int fd = pollfds[ne].fd; - short revents = pollfds[ne].revents; - - if (revents & (POLLERR | POLLHUP | POLLNVAL)) { - dbg_time("%s poll err/hup/inval", __func__); - dbg_time("epoll fd = %d, events = 0x%04x", fd, revents); - if (revents & (POLLERR | POLLHUP | POLLNVAL)) - goto __quit; - } - - if ((revents & POLLIN) == 0) - continue; - - if (atc_fd == fd) { - usleep(10*1000); //let atchannel.c read at response. - } - else if (fd == qmidevice_control_fd[1]) { - int triger_event; - if (read(fd, &triger_event, sizeof(triger_event)) == sizeof(triger_event)) { - //dbg_time("triger_event = 0x%x", triger_event); - switch (triger_event) { - case RIL_REQUEST_QUIT: - goto __quit; - break; - case SIG_EVENT_STOP: - wait_for_request_quit = 1; - break; - default: - break; - } - } - } - } - } - -__quit: - at_close(); - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED); - dbg_time("%s exit", __func__); - - return NULL; -} - -const struct qmi_device_ops atc_dev_ops = { - .init = atc_init, - .deinit = atc_deinit, - .read = atc_read_thread, -}; - -static int requestBaseBandVersion(PROFILE_T *profile) { - int retVal = -1; - int err; - ATResponse *p_response = NULL; - - (void)profile; - - err = at_send_command_multiline("AT+CGMR", "\0", &p_response); - if (at_response_error(err, p_response)) - goto exit; - - if (p_response->p_intermediates && p_response->p_intermediates->line) { - strncpy(profile->BaseBandVersion, p_response->p_intermediates->line, sizeof(profile->BaseBandVersion) - 1); - retVal = 0; - } - -exit: - safe_at_response_free(p_response); - return retVal; -} - -static int requestGetSIMStatus(SIM_Status *pSIMStatus) -{ - int err; - ATResponse *p_response = NULL; - char *cpinLine; - char *cpinResult; - int ret = SIM_NOT_READY; - - err = at_send_command_singleline("AT+CPIN?", "+CPIN:", &p_response); - if (at_response_error(err, p_response)) - goto done; - - switch (at_get_cme_error(p_response)) - { - case CME_SUCCESS: - break; - - case CME_SIM_NOT_INSERTED: - case CME_OPERATION_NOT_ALLOWED: - case CME_FAILURE: - ret = SIM_ABSENT; - goto done; - - default: - ret = SIM_NOT_READY; - goto done; - } - - cpinLine = p_response->p_intermediates->line; - err = at_tok_start (&cpinLine); - - if (err < 0) - { - ret = SIM_NOT_READY; - goto done; - } - - err = at_tok_nextstr(&cpinLine, &cpinResult); - - if (err < 0) - { - ret = SIM_NOT_READY; - goto done; - } - - if (0 == strcmp (cpinResult, "SIM PIN")) - { - ret = SIM_PIN; - goto done; - } - else if (0 == strcmp (cpinResult, "SIM PUK")) - { - ret = SIM_PUK; - goto done; - } - else if (0 == strcmp (cpinResult, "PH-NET PIN")) - { - return SIM_NETWORK_PERSONALIZATION; - } - else if (0 != strcmp (cpinResult, "READY")) - { - /* we're treating unsupported lock types as "sim absent" */ - ret = SIM_ABSENT; - goto done; - } - - ret = SIM_READY; - -done: - safe_at_response_free(p_response); - *pSIMStatus = ret; - return err; -} - -static int requestEnterSimPin(const char *pPinCode) { - int retVal = -1; - int err; - ATResponse *p_response = NULL; - char *cmd = NULL; - - asprintf(&cmd, "AT+CPIN=%s", pPinCode); - err = at_send_command(cmd, NULL); - safe_free(cmd); - - if (!at_response_error(err, p_response)) { - retVal = 0; - } - - safe_at_response_free(p_response); - return retVal; -} - -static int requestSetProfile(PROFILE_T *profile) { - int err; - ATResponse *p_response = NULL; - char *cmd = NULL; - const char *new_apn = profile->apn ? profile->apn : ""; - const char *new_user = profile->user ? profile->user : ""; - const char *new_password = profile->password ? profile->password : ""; - const char *ipStr[] = {"NULL", "IPV4", "IPV6", "IPV4V6"}; - - dbg_time("%s[%d] %s/%s/%s/%d/%s", __func__, - profile->pdp, profile->apn, profile->user, profile->password, - profile->auth,ipStr[profile->iptype]); - - if ( !strcmp(profile->old_apn, new_apn) && !strcmp(profile->old_user, new_user) - && !strcmp(profile->old_password, new_password) - && profile->old_iptype == profile->iptype - && profile->old_auth == profile->auth) - { - dbg_time("no need to set skip the rest"); - return 0; - } - - asprintf(&cmd, "AT+QICSGP=%d,%d,\"%s\",\"%s\",\"%s\",%d", - profile->pdp, profile->iptype, new_apn, new_user, new_password, profile->auth); - err = at_send_command(cmd, &p_response); - safe_free(cmd); - if (at_response_error(err, p_response)) { - safe_at_response_free(p_response); - asprintf(&cmd, "AT+CGDCONT=%d,\"%s\",\"%s\"", profile->pdp, ipStr[profile->iptype], new_apn); - err = at_send_command(cmd, &p_response); - safe_free(cmd); - } - - safe_at_response_free(p_response); - return 1; -} - -static int requestGetProfile(PROFILE_T *profile) { - int retVal = -1; - int err; - ATResponse *p_response = NULL; - char *cmd = NULL; - int pdp; - int old_iptype = 1; // 1 ~ IPV4, 2 ~ IPV6, 3 ~ IPV4V6 - char *old_apn = "", *old_user = "", *old_password = ""; - int old_auth = 0; - const char *ipStr[] = {"NULL", "IPV4", "IPV6", "IPV4V6"}; - - if (profile->enable_ipv4 && profile->enable_ipv6) - profile->iptype = 3; - else if (profile->enable_ipv6) - profile->iptype = 2; - else - profile->iptype = 1; - -_re_check: - asprintf(&cmd, "AT+QICSGP=%d", profile->pdp); - err = at_send_command_singleline(cmd, "+QICSGP:", &p_response); - safe_free(cmd); - if (err == AT_ERROR_INVALID_RESPONSE && p_response == NULL) { - //bug of RG801H - safe_at_response_free(p_response); - asprintf(&cmd, "AT+QICSGP=%d,%d,\"\",\"\",\"\",0", profile->pdp, profile->iptype); - err = at_send_command(cmd, &p_response); - safe_free(cmd); - if (!at_response_error(err, p_response)) { - safe_at_response_free(p_response); - goto _re_check; - } - } - - if (!at_response_error(err, p_response)) { - err = at_tok_scanf(p_response->p_intermediates->line, - "%d%s%s%s%d", &old_iptype, &old_apn, &old_user, &old_password, &old_auth); - - if (err != 4 || pdp != profile->pdp) - goto _error; - } - else { - ATLine *atLine = NULL; - char *cgdcont_iptype = NULL; - - safe_at_response_free(p_response); - err = at_send_command_multiline("AT+CGDCONT?", "+CGDCONT:", &p_response); - if (at_response_error(err, p_response)) - goto _error; - - atLine = p_response->p_intermediates; - while (atLine) { - err = at_tok_scanf(atLine->line, "%d%s%s", &pdp, &cgdcont_iptype, &old_apn); - if (err == 3 && pdp == profile->pdp) { - if (!strcasecmp(cgdcont_iptype, ipStr[3])) - old_iptype = 3; - else if (!strcasecmp(cgdcont_iptype, ipStr[2])) - old_iptype = 2; - else - old_iptype = 1; - break; - } - old_apn = NULL; - atLine = atLine->p_next; - } - } - - retVal = 0; - -_error: - if (!old_apn) old_apn = ""; - if (!old_user) old_user = ""; - if (!old_password) old_password = ""; - - strncpy(profile->old_apn, old_apn, sizeof(profile->old_apn)); - strncpy(profile->old_user, old_user, sizeof(profile->old_user)); - strncpy(profile->old_password, old_password, sizeof(profile->old_password)); - profile->old_auth = old_auth; - profile->old_iptype = 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]); - - safe_at_response_free(p_response); - - return retVal; -} - -static int requestRegistrationState(UCHAR *pPSAttachedState) { - int retVal = -1; - int err; - ATResponse *p_response = NULL; - ATLine *p_cur; - int i; - int cops_act = -1; - int state = 0, lac = 0, cid = 0, act = 0; - int commas; - char *line; - - *pPSAttachedState = 0; - - err = at_send_command_multiline( - "AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?", - "+COPS:", &p_response); - if (at_response_error(err, p_response)) - goto error; - -/* -AT< +COPS: 0,0,"CHINA MOBILE",13 -AT< +COPS: 0,1,"CMCC",13 -AT< +COPS: 0,2,"46000",13 -AT< OK -*/ - retVal = 0; - for (i = 0, p_cur = p_response->p_intermediates; p_cur != NULL; p_cur = p_cur->p_next, i++) { - err = at_tok_scanf(p_cur->line, "%d%d%s%d", NULL, NULL, NULL, &cops_act); - if (err != 4) goto error; - - break; - } - - 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 - //AT+CGREG GPRS Network Registration Status - err = at_send_command_singleline("AT+CGREG?", "+CGREG:", &p_response); - break; - - case 7: //E-UTRAN - case 13: //E-UTRAN-NR dual connectivity - //AT+CEREG EPS Network Registration Status - err = at_send_command_singleline("AT+CEREG?", "+CEREG:", &p_response); - break; - - case 10: //E-UTRAN connected to a 5GCN - case 11: //NR connected to a 5GCN - case 12: //NG-RAN - //AT+C5GREG 5GS Network Registration Status - err = at_send_command_singleline("AT+C5GREG?", "+C5GREG:", &p_response); - break; - - default: - goto error; - break; - } - - if (at_response_error(err, p_response)) - goto error; - if (!p_response->p_intermediates || !p_response->p_intermediates->line) goto error; - - line = p_response->p_intermediates->line; - commas = at_tok_count(line); - switch (commas) { - case 0: /* +CREG: */ - err = at_tok_nextint(&line, &state); - if (err < 0) goto error; - break; - - case 1: /* +CREG: , */ - err = at_tok_scanf(line, "%d%d", NULL, &state); - if (err != 2) goto error; - break; - - case 2: /* +CREG: , , */ - err = at_tok_scanf(line, "%d%x%x", NULL, &state, &lac, &cid); - if (err != 3) goto error; - break; - - case 3: /* +CREG: , , , */ - err = at_tok_scanf(line, "%d%d%x%x", NULL, &state, &lac, &cid); - if (err != 4) goto error; - break; - - case 4: //, , , , */ - case 5: - case 6: - case 7: - err = at_tok_scanf(line, "%d%d%x%x%d", NULL, &state, &lac, &cid, &act); - if (err != 5) goto error; - break; - - default: - goto error; - } - - //dbg_time("state=%d", state); - - if (state == 1 || state == 5) { //Registered, home network / roaming - *pPSAttachedState = 1; - } - -error: - safe_at_response_free(p_response); - return retVal; -} - -static int requestSetupDataCall(PROFILE_T *profile, int curIpFamily) { - int err; - ATResponse *p_response = NULL; - char *cmd = NULL; - ATLine *p_cur = NULL; - int pdp = profile->pdp; - int state = 0; - - (void)curIpFamily; - - if (strStartsWith(profile->BaseBandVersion, "RG801H") || strStartsWith(profile->BaseBandVersion, "EC200H")) { - //RG801H will miss USB_CDC_NOTIFY_NETWORK_CONNECTION - asprintf(&cmd, "ifconfig %s up", profile->usbnet_adapter); - if (system(cmd)) {}; - safe_free(cmd); - } - - if (asr_style_atc) { - err = at_send_command_multiline("AT+CGACT?", "+CGACT:", &p_response); - if (at_response_error(err, p_response)) - goto _error; - - for (p_cur = p_response->p_intermediates; p_cur != NULL; p_cur = p_cur->p_next) { - int cid = 0; - state = 0; - - err = at_tok_scanf(p_cur->line, "%d%d", &cid, &state); - if (cid == pdp) - break; - else if(state) - state = 0; - } - safe_at_response_free(p_response); - - if (state == 0) { - asprintf(&cmd, "AT+CGACT=1,%d", pdp); - err = at_send_command(cmd, &p_response); - safe_free(cmd); - if (at_response_error(err, p_response)) - goto _error; - } - } - - if(asr_style_atc) - asprintf(&cmd, "AT+QNETDEVCTL=1,%d,%d", pdp, 1); - else - asprintf(&cmd, "AT+QNETDEVCTL=%d,1,%d", pdp, 1); - err = at_send_command(cmd, &p_response); - safe_free(cmd); - - if (at_response_error(err, p_response)) - goto _error; - - if (!asr_style_atc) { //TODO some modems do not sync return setup call resule - int t = 0; - - while (t++ < 15) { - asprintf(&cmd, "AT+QNETDEVSTATUS=%d", pdp); - err = at_send_command_singleline(cmd, "+QNETDEVSTATUS", &p_response); - safe_free(cmd); - if (err) goto _error; - - if (!at_response_error(err, p_response)) { - break; - } - safe_at_response_free(p_response); - sleep(1); - } - } - - //some modem do not report URC - qmidevice_send_event_to_main(RIL_UNSOL_DATA_CALL_LIST_CHANGED); - -_error: - safe_at_response_free(p_response); - //dbg_time("%s err=%d", __func__, err); - return err; -} - -static int at_netdevstatus(int pdp, unsigned int *pV4Addr) { - int err; - ATResponse *p_response = NULL; - char *cmd = NULL; - char *ipv4_address = NULL; - char *ipv4_gate = NULL; - char *ipv4_DHCP = NULL; - char *ipv4_pDNS = NULL; - char *ipv4_sDNS = NULL; - char *ipv6_address = NULL; - char *ipv6_gate = NULL; - char *ipv6_DHCP = NULL; - char *ipv6_pDNS = NULL; - char *ipv6_sDNS = NULL; - - *pV4Addr = 0; - - asprintf(&cmd, "AT+QNETDEVSTATUS=%d", pdp); - err = at_send_command_singleline(cmd, "+QNETDEVSTATUS", &p_response); - safe_free(cmd); - if (at_response_error(err, p_response)) goto _error; - if (!p_response->p_intermediates || !p_response->p_intermediates->line) goto _error; - - err = at_tok_scanf(p_response->p_intermediates->line, "%s%s%s%s%s%s%s%s%s%s", - &ipv4_address, &ipv4_gate, &ipv4_DHCP, &ipv4_pDNS, &ipv4_sDNS, - &ipv6_address, &ipv6_gate, &ipv6_DHCP, &ipv6_pDNS, &ipv6_sDNS); - if (err > 0) { -#if 0 - dbg_time("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s", - ipv4_address, ipv4_gate, ipv4_DHCP, ipv4_pDNS, ipv4_sDNS, - ipv6_address, ipv6_gate, ipv6_DHCP, ipv6_pDNS, ipv6_sDNS); -#endif - - if (ipv4_address && ipv4_address[0]) { - int addr[4] = {0, 0, 0, 0}; - - if (strstr(ipv4_address, ".")) { - sscanf(ipv4_address, "%d.%d.%d.%d", &addr[0], &addr[1], &addr[2], &addr[3]); - } - else { - sscanf(ipv4_address, "%02X%02X%02X%02X", &addr[3], &addr[2], &addr[1], &addr[0]); - } - *pV4Addr = (addr[0]) | (addr[1]<<8) | (addr[2]<<16) | (addr[3]<<24); - } - } - -_error: - safe_at_response_free(p_response); - return 0; -} - -static int requestQueryDataCall(UCHAR *pConnectionStatus, int curIpFamily) { - int err; - ATResponse *p_response = NULL; - ATLine *p_cur = NULL; - int state = 0; - int bind = 0; - int cid; - int pdp = s_pdp; - unsigned int v4Addr = 0; - - (void)curIpFamily; - - *pConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; - - if (!asr_style_atc) { - err = at_netdevstatus(pdp, &v4Addr); - if (!err && v4Addr) { - *pConnectionStatus = QWDS_PKT_DATA_CONNECTED; - //if (profile->ipv4.Address == v4Addr) {} //TODO - } - return err; - } - - err = at_send_command_multiline("AT+QNETDEVCTL?", "+QNETDEVCTL:", &p_response); - if (at_response_error(err, p_response)) - goto _error; - - for (p_cur = p_response->p_intermediates; p_cur != NULL; p_cur = p_cur->p_next) - { - //+QNETDECTL:,,, - err = at_tok_scanf(p_cur->line, "%d%d%d%d", &bind, &cid, NULL, &state); - if (err != 4 || cid != pdp) - continue; - if (bind != 1) - bind = 0; - } - safe_at_response_free(p_response); - - if (bind == 0 || state == 0) - goto _error; - - err = at_send_command_multiline("AT+CGACT?", "+CGACT:", &p_response); - if (at_response_error(err, p_response)) - goto _error; - - for (p_cur = p_response->p_intermediates; p_cur != NULL; p_cur = p_cur->p_next) - { - state = 0; - err = at_tok_scanf(p_cur->line, "%d%d", &cid, &state); - if (cid == pdp) - break; - else if(state) - state = 0; - } - safe_at_response_free(p_response); - - if (bind && state) - *pConnectionStatus = QWDS_PKT_DATA_CONNECTED; - -_error: - safe_at_response_free(p_response); - //dbg_time("%s err=%d, call_state=%d", __func__, err, *pConnectionStatus); - return 0; -} - -static int requestDeactivateDefaultPDP(PROFILE_T *profile, int curIpFamily) { - char *cmd = NULL; - int pdp = profile->pdp; - - (void)curIpFamily; - - if (asr_style_atc) - asprintf(&cmd, "AT+QNETDEVCTL=0,%d,%d", pdp, 0); - else - asprintf(&cmd, "AT+QNETDEVCTL=%d,0,%d", pdp, 0); - at_send_command(cmd, NULL); - safe_free(cmd); - - //dbg_time("%s err=%d", __func__, err); - return 0; -} - -static int requestGetIPAddress(PROFILE_T *profile, int curIpFamily) { - int err; - ATResponse *p_response = NULL; - char *cmd = NULL; - ATLine *p_cur = NULL; - int pdp = profile->pdp; - unsigned int v4Addr = 0; - - (void)curIpFamily; - - if (!asr_style_atc) { - err = at_netdevstatus(pdp, &v4Addr); - goto _error; - } - - asprintf(&cmd, "AT+CGPADDR=%d", profile->pdp); - err = at_send_command_singleline(cmd, "+CGPADDR:", &p_response); - safe_free(cmd); - if (at_response_error(err, p_response)) - goto _error; - - //+CGPADDR: 1,"10.201.80.91","2409:8930:4B3:41C7:F9B8:3D9B:A2F7:CA96" - for (p_cur = p_response->p_intermediates; p_cur != NULL; p_cur = p_cur->p_next) - { - char *ipv4 = NULL; - char *ipv6 = NULL; - - err = at_tok_scanf(p_cur->line, "%d%s%s", &pdp, &ipv4, &ipv6); - if (err < 2 || pdp != profile->pdp) - continue; - - if (ipv4) { - int addr[4] = {0, 0, 0, 0}; - - sscanf(ipv4, "%d.%d.%d.%d", &addr[0], &addr[1], &addr[2], &addr[3]); - v4Addr = (addr[0]) | (addr[1]<<8) | (addr[2]<<16) | (addr[3]<<24); - break; - } - } - -_error: - if (v4Addr && profile->ipv4.Address != v4Addr) { - unsigned char *v4 = (unsigned char *)&v4Addr; - - profile->ipv4.Address = v4Addr; - dbg_time("%s %d.%d.%d.%d", __func__, v4[0], v4[1], v4[2], v4[3]); - } - - //dbg_time("%s err=%d", __func__, err); - return v4Addr ? 0 : -1; -} - -static int requestGetSignalInfo(void) { - int retVal = -1; - int err; - ATResponse *p_response = NULL; - int i; - ATLine *p_cur = NULL; - char *rat = NULL; - int cops_act = 0; - int is_nr5g_nsa = 0, nr5g_sa = 0; - int verbose = 0; - - err = at_send_command_singleline("at+cops?", "+COPS:", &p_response); - if (at_response_error(err, p_response)) goto _error; - if (!p_response->p_intermediates || !p_response->p_intermediates->line) goto _error; - - retVal = 0; - err = at_tok_scanf(p_response->p_intermediates->line, "%d%d%s%d", NULL, NULL, NULL, &cops_act); - if (err != 4) goto _error; - - nr5g_sa = (cops_act == 11); - - safe_at_response_free(p_response); - err = at_send_command_multiline("at+qeng=\"servingcell\"", "+QENG:", &p_response); - if (at_response_error(err, p_response)) - goto _error; - - for (i = 0, p_cur = p_response->p_intermediates; p_cur != NULL; p_cur = p_cur->p_next, i++) { - char *type, *state; - - err = at_tok_scanf(p_cur->line, "%s%s", &type, &state); - if (err != 2 || strcmp(type, "servingcell")) - continue; - - if (!strcmp(state, "SEARCH") || !strcmp(state, "LIMSRV")) - continue; - - if (!strcmp(state, "NOCONN") || !strcmp(state, "CONNECT")) { - err = at_tok_scanf(p_cur->line, "%s%s%s", &type, &state, &rat); - if (err != 3) - continue; - } - else { - rat = state; - } - - if (!strcmp(rat, "NR5G-SA")) - { - //+QENG: "servingcell",,"NR5G-SA",,,,,,,,,,,,,, - //+QENG: "servingcell","NOCONN","NR5G-SA","TDD", 454,12,0,21,4ED,636576,78,3,-85,-11,32,0,5184 - struct qeng_servingcell_nr5g_sa { - char *cell_type, *state, *rat, *is_tdd; - int MCC, MNC, cellID/*hex*/; - int PCID, TAC/*hex*/, ARFCN; - int band, NR_DL_bandwidth; - int RSRP, RSRQ, RSSI, SINR; - }; - struct qeng_servingcell_nr5g_sa nr5g_sa; - - memset(&nr5g_sa, 0, sizeof(nr5g_sa)); - err = at_tok_scanf(p_cur->line, "%s,%s,%s,%s,%d,%d,%x,%d,%x,%d,%d,%d,%d,%d,%d,%d", - &nr5g_sa.cell_type, &nr5g_sa.state, &nr5g_sa.rat, &nr5g_sa.is_tdd, - &nr5g_sa.MCC, &nr5g_sa.MNC, &nr5g_sa.cellID, &nr5g_sa.PCID, &nr5g_sa.TAC, - &nr5g_sa.ARFCN, &nr5g_sa.band, &nr5g_sa.NR_DL_bandwidth, - &nr5g_sa.RSRP, &nr5g_sa.RSRQ, &nr5g_sa.RSSI, &nr5g_sa.SINR); - - if (err >= 13 && verbose) { - dbg_time("%s,%s,%s,%s,%d,%d,%x,%d,%x,%d,%d,%d,%d,%d,%d,%d", - nr5g_sa.cell_type, nr5g_sa.state, nr5g_sa.rat, nr5g_sa.is_tdd, - nr5g_sa.MCC, nr5g_sa.MNC, nr5g_sa.cellID, nr5g_sa.PCID, nr5g_sa.TAC, - nr5g_sa.ARFCN, nr5g_sa.band, nr5g_sa.NR_DL_bandwidth, - nr5g_sa.RSRP, nr5g_sa.RSRQ, nr5g_sa.RSSI, nr5g_sa.SINR); - } - } - else if (!strcmp(rat, "NR5G-NSA")) - { - //+QENG: "NR5G-NSA",,,,,< SINR>,,, - struct qeng_servingcell_nr5g_nsa { - char *mcc, *mnc; - int pcid, rsrp, sinr, rsrq; - }; - struct qeng_servingcell_nr5g_nsa nr5g_nsa; - - memset(&nr5g_nsa, 0, sizeof(nr5g_nsa)); - err = at_tok_scanf(p_cur->line, "%s%s%s%s%d%d%d%dd", - NULL, NULL, &nr5g_nsa.mcc, &nr5g_nsa.mnc, &nr5g_nsa.pcid, &nr5g_nsa.rsrp, &nr5g_nsa.sinr, &nr5g_nsa.rsrq); - if (err == 8 && verbose) - { - dbg_time("mcc=%s, mnc=%s, pcid=%d, rsrp=%d, sinr=%d, rsrq=%d", - nr5g_nsa.mcc, nr5g_nsa.mnc, nr5g_nsa.pcid, nr5g_nsa.rsrp, nr5g_nsa.sinr, nr5g_nsa.rsrq); - } - - is_nr5g_nsa = 1; - } - else if (!strcmp(rat, "LTE")) - { - //+QENG: "LTE",,,,,,,,,,,,,,,,, - struct qeng_servingcell_lte { - char *is_tdd, *mcc, *mnc; - int cellID/*hex*/, pcid, earfcn, freq_band_ind, ul_bandwidth, dl_bandwidth; - int tac/*hex*/, rsrp, rsrq, rssi, sinr, cqi,tx_power,srxlev; - }; - struct qeng_servingcell_lte lte; - - memset(<e, 0, sizeof(lte)); - if (!strcmp(rat, state)) - err = at_tok_scanf(p_cur->line, "%s%s%s%s%s%x%d%d%d%d%d%x%d%d%d%d%d%d%d", - NULL, NULL, <e.is_tdd, <e.mcc, <e.mnc, - <e.cellID, <e.pcid, <e.earfcn, <e.freq_band_ind, <e.ul_bandwidth, <e.dl_bandwidth, - <e.tac, <e.rsrp, <e.rsrq, <e.rssi, <e.sinr, <e.cqi, <e.tx_power, <e.srxlev); - else - err = at_tok_scanf(p_cur->line, "%s%s%s%s%s%s%x%d%d%d%d%d%x%d%d%d%d%d%d%d", - NULL, NULL, NULL, <e.is_tdd, <e.mcc, <e.mnc, - <e.cellID, <e.pcid, <e.earfcn, <e.freq_band_ind, <e.ul_bandwidth, <e.dl_bandwidth, - <e.tac, <e.rsrp, <e.rsrq, <e.rssi, <e.sinr, <e.cqi, <e.tx_power, <e.srxlev); - - if (err >= 18 && verbose) - { - dbg_time("is_tdd=%s, mcc=%s, mnc=%s", lte.is_tdd, lte.mcc, lte.mnc); - dbg_time("cellID=%x, pcid=%d, earfcn=%d", lte.cellID, lte.pcid, lte.earfcn); - dbg_time("freq_band_ind=%d, ul_bandwidth=%d, dl_bandwidth=%d", lte.freq_band_ind, lte.ul_bandwidth, lte.dl_bandwidth); - dbg_time("tac=%x, rsrp=%d, rsrq=%d, rssi=%d, sinr=%d", lte.tac, lte.rsrp, lte.rsrq, lte.rssi, lte.sinr); - dbg_time("cqi=%d, tx_power=%d, earfcn=%d", lte.cqi, lte.tx_power, lte.srxlev); - } - } - } - - if (is_nr5g_nsa) { - int endc_avl, plmn_info_list_r15_avl, endc_rstr, nr5g_basic; - - is_nr5g_nsa = 0; - safe_at_response_free(p_response); - err = at_send_command_multiline("at+qendc", "+QENDC:", &p_response); - if (at_response_error(err, p_response)) goto _error; - if (!p_response->p_intermediates || !p_response->p_intermediates->line) goto _error; - - err = at_tok_scanf(p_response->p_intermediates->line, "%d%d%d%d", - &endc_avl, &plmn_info_list_r15_avl, &endc_rstr, &nr5g_basic); - if (err == 4 && nr5g_basic) { - is_nr5g_nsa = 1; - } - } - - if (verbose) - dbg_time("cops_act=%d, nr5g_nsa=%d, nr5g_sa=%d", cops_act, is_nr5g_nsa, nr5g_sa); - -_error: - safe_at_response_free(p_response); - return retVal; -} - -static int requestGetICCID(void) { - int retVal = -1; - int err; - ATResponse *p_response = NULL; - char *iccid; - - err = at_send_command_singleline("AT+QCCID", "+QCCID:", &p_response); - if (at_response_error(err, p_response)) goto _error; - if (!p_response->p_intermediates || !p_response->p_intermediates->line) goto _error; - - err = at_tok_scanf(p_response->p_intermediates->line, "%s", &iccid); - if (err != 1) goto _error; - - if (iccid && iccid[0]) { - dbg_time("%s %s", __func__, iccid); - retVal = 0; - } - -_error: - safe_at_response_free(p_response); - return retVal; -} - -static int requestGetIMSI(void) { - int retVal = -1; - int err; - ATResponse *p_response = NULL; - char *imsi; - - err = at_send_command_numeric("AT+CIMI", &p_response); - if (at_response_error(err, p_response)) goto _error; - if (!p_response->p_intermediates || !p_response->p_intermediates->line) goto _error; - - imsi = p_response->p_intermediates->line; - if (imsi) { - dbg_time("%s %s", __func__, imsi); - retVal = 0; - } - -_error: - safe_at_response_free(p_response); - return retVal; -} - -const struct request_ops atc_request_ops = { - .requestBaseBandVersion = requestBaseBandVersion, - .requestGetSIMStatus = requestGetSIMStatus, - .requestEnterSimPin = requestEnterSimPin, - .requestSetProfile = requestSetProfile, - .requestGetProfile = requestGetProfile, - .requestRegistrationState = requestRegistrationState, - .requestSetupDataCall = requestSetupDataCall, - .requestQueryDataCall = requestQueryDataCall, - .requestDeactivateDefaultPDP = requestDeactivateDefaultPDP, - .requestGetIPAddress = requestGetIPAddress, - .requestGetSignalInfo = requestGetSignalInfo, - .requestGetICCID = requestGetICCID, - .requestGetIMSI = requestGetIMSI, -}; - +/****************************************************************************** + @file atc.c + @brief at command. + + 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern int asprintf(char **s, const char *fmt, ...); + +#include "QMIThread.h" + +#include "atchannel.h" +#include "at_tok.h" + +static int asr_style_atc = 0; +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;}} + +#define at_response_error(err, p_response) \ + (err \ + || p_response == NULL \ + || p_response->finalResponse == NULL \ + || p_response->success == 0) + +static int atc_init(PROFILE_T *profile) { + int err; + char *cmd; + ATResponse *p_response = NULL; + + if (profile->proxy[0]) { + s_pdp = profile->pdp; + err = at_send_command_singleline("AT+QNETDEVSTATUS=?", "+QNETDEVSTATUS:", &p_response); + if (at_response_error(err, p_response)) + asr_style_atc = 1; //EC200T/EC100Y do not support this AT, but RG801/RG500U support + safe_at_response_free(p_response); + + return err; + } + + err = at_handshake(); + if (err) { + dbg_time("handshake fail, TODO ... "); + goto exit; + } + + s_pdp = profile->pdp; + at_send_command_singleline("AT+QCFG=\"usbnet\"", "+QCFG:", NULL); + at_send_command_multiline("AT+QNETDEVCTL=?", "+QNETDEVCTL:", NULL); + at_send_command("AT+CGREG=2", NULL); //GPRS Network Registration Status + at_send_command("AT+CEREG=2", NULL); //EPS Network Registration Status + at_send_command("AT+C5GREG=2", NULL); //5GS Network Registration Status + + err = at_send_command_singleline("AT+QNETDEVSTATUS=?", "+QNETDEVSTATUS:", &p_response); + if (at_response_error(err, p_response)) + asr_style_atc = 1; //EC200T/EC100Y do not support this AT, but RG801/RG500U support + safe_at_response_free(p_response); + + err = at_send_command_singleline("AT+QCFG=\"NAT\"", "+QCFG:", &p_response); + if (!at_response_error(err, p_response)) { + int old_nat, new_nat = asr_style_atc ? 1 : 0; + + err = at_tok_scanf(p_response->p_intermediates->line, "%s%d", NULL, &old_nat); + if (err == 2 && old_nat != new_nat) { + safe_at_response_free(p_response); + asprintf(&cmd, "AT+QCFG=\"NAT\",%d", new_nat); + err = at_send_command(cmd, &p_response); + safe_free(cmd); + if (!at_response_error(err, p_response)) { + err = at_send_command("at+cfun=1,1",NULL); + if (!err) + g_donot_exit_when_modem_hangup = 1; + //reboot to take effect + } + safe_at_response_free(p_response); + } + err = 0; + } + safe_at_response_free(p_response); + +exit: + return err; +} + +static int atc_deinit(void) { + return 0; +} + +/** + * Called by atchannel when an unsolicited line appears + * This is called on atchannel's reader thread. AT commands may + * not be issued here + */ +static void onUnsolicited (const char *s, const char *sms_pdu) +{ + (void)sms_pdu; + + if (strStartsWith(s, "+QNETDEVSTATUS:")) { + qmidevice_send_event_to_main(RIL_UNSOL_DATA_CALL_LIST_CHANGED); + } + else if (strStartsWith(s, "+CGREG:") + || strStartsWith(s, "+CEREG:") + || strStartsWith(s, "+C5GREG:")) { + qmidevice_send_event_to_main(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED); + } +} + +static void onTimeout(void) { + dbg_time("%s", __func__); + //TODO +} + +static void onClose(void) { + dbg_time("%s", __func__); +} + +static void * atc_read_thread(void *param) { + PROFILE_T *profile = (PROFILE_T *)param; + const char *cdc_wdm = (const char *)profile->qmichannel; + int wait_for_request_quit = 0; + int atc_fd; + + atc_fd = cm_open_dev(cdc_wdm); + if (atc_fd <= 0) { + dbg_time("fail to open (%s), errno: %d (%s)", cdc_wdm, errno, strerror(errno)); + goto __quit; + } + + dbg_time("atc_fd = %d", atc_fd); + + if (at_open(atc_fd, onUnsolicited, 0)) + goto __quit; + + at_set_on_timeout(onTimeout); + at_set_on_reader_closed(onClose); + qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_CONNECTED); + + while (atc_fd > 0) { + struct pollfd pollfds[] = {{atc_fd, POLLIN, 0}, {qmidevice_control_fd[1], POLLIN, 0}}; + int ne, ret, nevents = 2; + + ret = poll(pollfds, nevents, wait_for_request_quit ? 1000 : -1); + + if (ret == 0 && wait_for_request_quit) { + break; + } + + if (ret < 0) { + dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno)); + break; + } + + for (ne = 0; ne < nevents; ne++) { + int fd = pollfds[ne].fd; + short revents = pollfds[ne].revents; + + if (revents & (POLLERR | POLLHUP | POLLNVAL)) { + dbg_time("%s poll err/hup/inval", __func__); + dbg_time("epoll fd = %d, events = 0x%04x", fd, revents); + if (revents & (POLLERR | POLLHUP | POLLNVAL)) + goto __quit; + } + + if ((revents & POLLIN) == 0) + continue; + + if (atc_fd == fd) { + usleep(10*1000); //let atchannel.c read at response. + } + else if (fd == qmidevice_control_fd[1]) { + int triger_event; + if (read(fd, &triger_event, sizeof(triger_event)) == sizeof(triger_event)) { + //dbg_time("triger_event = 0x%x", triger_event); + switch (triger_event) { + case RIL_REQUEST_QUIT: + goto __quit; + break; + case SIG_EVENT_STOP: + wait_for_request_quit = 1; + break; + default: + break; + } + } + } + } + } + +__quit: + at_close(); + qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED); + dbg_time("%s exit", __func__); + + return NULL; +} + +const struct qmi_device_ops atc_dev_ops = { + .init = atc_init, + .deinit = atc_deinit, + .read = atc_read_thread, +}; + +static int requestBaseBandVersion(PROFILE_T *profile) { + int retVal = -1; + int err; + ATResponse *p_response = NULL; + + (void)profile; + + err = at_send_command_multiline("AT+CGMR", "\0", &p_response); + if (at_response_error(err, p_response)) + goto exit; + + if (p_response->p_intermediates && p_response->p_intermediates->line) { + strncpy(profile->BaseBandVersion, p_response->p_intermediates->line, sizeof(profile->BaseBandVersion) - 1); + retVal = 0; + } + +exit: + safe_at_response_free(p_response); + return retVal; +} + +static int requestGetSIMStatus(SIM_Status *pSIMStatus) +{ + int err; + ATResponse *p_response = NULL; + char *cpinLine; + char *cpinResult; + int ret = SIM_NOT_READY; + + err = at_send_command_singleline("AT+CPIN?", "+CPIN:", &p_response); + if (at_response_error(err, p_response)) + goto done; + + switch (at_get_cme_error(p_response)) + { + case CME_SUCCESS: + break; + + case CME_SIM_NOT_INSERTED: + case CME_OPERATION_NOT_ALLOWED: + case CME_FAILURE: + ret = SIM_ABSENT; + goto done; + + default: + ret = SIM_NOT_READY; + goto done; + } + + cpinLine = p_response->p_intermediates->line; + err = at_tok_start (&cpinLine); + + if (err < 0) + { + ret = SIM_NOT_READY; + goto done; + } + + err = at_tok_nextstr(&cpinLine, &cpinResult); + + if (err < 0) + { + ret = SIM_NOT_READY; + goto done; + } + + if (0 == strcmp (cpinResult, "SIM PIN")) + { + ret = SIM_PIN; + goto done; + } + else if (0 == strcmp (cpinResult, "SIM PUK")) + { + ret = SIM_PUK; + goto done; + } + else if (0 == strcmp (cpinResult, "PH-NET PIN")) + { + return SIM_NETWORK_PERSONALIZATION; + } + else if (0 != strcmp (cpinResult, "READY")) + { + /* we're treating unsupported lock types as "sim absent" */ + ret = SIM_ABSENT; + goto done; + } + + ret = SIM_READY; + +done: + safe_at_response_free(p_response); + *pSIMStatus = ret; + return err; +} + +static int requestEnterSimPin(const char *pPinCode) { + int retVal = -1; + int err; + ATResponse *p_response = NULL; + char *cmd = NULL; + + asprintf(&cmd, "AT+CPIN=%s", pPinCode); + err = at_send_command(cmd, NULL); + safe_free(cmd); + + if (!at_response_error(err, p_response)) { + retVal = 0; + } + + safe_at_response_free(p_response); + return retVal; +} + +static int requestSetProfile(PROFILE_T *profile) { + int err; + ATResponse *p_response = NULL; + char *cmd = NULL; + const char *new_apn = profile->apn ? profile->apn : ""; + const char *new_user = profile->user ? profile->user : ""; + const char *new_password = profile->password ? profile->password : ""; + const char *ipStr[] = {"NULL", "IPV4", "IPV6", "IPV4V6"}; + + dbg_time("%s[%d] %s/%s/%s/%d/%s", __func__, + profile->pdp, profile->apn, profile->user, profile->password, + profile->auth,ipStr[profile->iptype]); + + if ( !strcmp(profile->old_apn, new_apn) && !strcmp(profile->old_user, new_user) + && !strcmp(profile->old_password, new_password) + && profile->old_iptype == profile->iptype + && profile->old_auth == profile->auth) + { + dbg_time("no need to set skip the rest"); + return 0; + } + + asprintf(&cmd, "AT+QICSGP=%d,%d,\"%s\",\"%s\",\"%s\",%d", + profile->pdp, profile->iptype, new_apn, new_user, new_password, profile->auth); + err = at_send_command(cmd, &p_response); + safe_free(cmd); + if (at_response_error(err, p_response)) { + safe_at_response_free(p_response); + asprintf(&cmd, "AT+CGDCONT=%d,\"%s\",\"%s\"", profile->pdp, ipStr[profile->iptype], new_apn); + err = at_send_command(cmd, &p_response); + safe_free(cmd); + } + + safe_at_response_free(p_response); + return 1; +} + +static int requestGetProfile(PROFILE_T *profile) { + int retVal = -1; + int err; + ATResponse *p_response = NULL; + char *cmd = NULL; + int pdp; + int old_iptype = 1; // 1 ~ IPV4, 2 ~ IPV6, 3 ~ IPV4V6 + char *old_apn = "", *old_user = "", *old_password = ""; + int old_auth = 0; + const char *ipStr[] = {"NULL", "IPV4", "IPV6", "IPV4V6"}; + + if (profile->enable_ipv4 && profile->enable_ipv6) + profile->iptype = 3; + else if (profile->enable_ipv6) + profile->iptype = 2; + else + profile->iptype = 1; + +_re_check: + asprintf(&cmd, "AT+QICSGP=%d", profile->pdp); + err = at_send_command_singleline(cmd, "+QICSGP:", &p_response); + safe_free(cmd); + if (err == AT_ERROR_INVALID_RESPONSE && p_response == NULL) { + //bug of RG801H + safe_at_response_free(p_response); + asprintf(&cmd, "AT+QICSGP=%d,%d,\"\",\"\",\"\",0", profile->pdp, profile->iptype); + err = at_send_command(cmd, &p_response); + safe_free(cmd); + if (!at_response_error(err, p_response)) { + safe_at_response_free(p_response); + goto _re_check; + } + } + + if (!at_response_error(err, p_response)) { + err = at_tok_scanf(p_response->p_intermediates->line, + "%d%s%s%s%d", &old_iptype, &old_apn, &old_user, &old_password, &old_auth); + + if (err != 4 || pdp != profile->pdp) + goto _error; + } + else { + ATLine *atLine = NULL; + char *cgdcont_iptype = NULL; + + safe_at_response_free(p_response); + err = at_send_command_multiline("AT+CGDCONT?", "+CGDCONT:", &p_response); + if (at_response_error(err, p_response)) + goto _error; + + atLine = p_response->p_intermediates; + while (atLine) { + err = at_tok_scanf(atLine->line, "%d%s%s", &pdp, &cgdcont_iptype, &old_apn); + if (err == 3 && pdp == profile->pdp) { + if (!strcasecmp(cgdcont_iptype, ipStr[3])) + old_iptype = 3; + else if (!strcasecmp(cgdcont_iptype, ipStr[2])) + old_iptype = 2; + else + old_iptype = 1; + break; + } + old_apn = NULL; + atLine = atLine->p_next; + } + } + + retVal = 0; + +_error: + if (!old_apn) old_apn = ""; + if (!old_user) old_user = ""; + if (!old_password) old_password = ""; + + strncpy(profile->old_apn, old_apn, sizeof(profile->old_apn)); + strncpy(profile->old_user, old_user, sizeof(profile->old_user)); + strncpy(profile->old_password, old_password, sizeof(profile->old_password)); + profile->old_auth = old_auth; + profile->old_iptype = 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]); + + safe_at_response_free(p_response); + + return retVal; +} + +static int requestRegistrationState(UCHAR *pPSAttachedState) { + int retVal = -1; + int err; + ATResponse *p_response = NULL; + ATLine *p_cur; + int i; + int cops_act = -1; + int state = 0, lac = 0, cid = 0, act = 0; + int commas; + char *line; + + *pPSAttachedState = 0; + + err = at_send_command_multiline( + "AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS?", + "+COPS:", &p_response); + if (at_response_error(err, p_response)) + goto error; + +/* +AT< +COPS: 0,0,"CHINA MOBILE",13 +AT< +COPS: 0,1,"CMCC",13 +AT< +COPS: 0,2,"46000",13 +AT< OK +*/ + retVal = 0; + for (i = 0, p_cur = p_response->p_intermediates; p_cur != NULL; p_cur = p_cur->p_next, i++) { + err = at_tok_scanf(p_cur->line, "%d%d%s%d", NULL, NULL, NULL, &cops_act); + if (err != 4) goto error; + + break; + } + + 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 + //AT+CGREG GPRS Network Registration Status + err = at_send_command_singleline("AT+CGREG?", "+CGREG:", &p_response); + break; + + case 7: //E-UTRAN + case 13: //E-UTRAN-NR dual connectivity + //AT+CEREG EPS Network Registration Status + err = at_send_command_singleline("AT+CEREG?", "+CEREG:", &p_response); + break; + + case 10: //E-UTRAN connected to a 5GCN + case 11: //NR connected to a 5GCN + case 12: //NG-RAN + //AT+C5GREG 5GS Network Registration Status + err = at_send_command_singleline("AT+C5GREG?", "+C5GREG:", &p_response); + break; + + default: + goto error; + break; + } + + if (at_response_error(err, p_response)) + goto error; + if (!p_response->p_intermediates || !p_response->p_intermediates->line) goto error; + + line = p_response->p_intermediates->line; + commas = at_tok_count(line); + switch (commas) { + case 0: /* +CREG: */ + err = at_tok_nextint(&line, &state); + if (err < 0) goto error; + break; + + case 1: /* +CREG: , */ + err = at_tok_scanf(line, "%d%d", NULL, &state); + if (err != 2) goto error; + break; + + case 2: /* +CREG: , , */ + err = at_tok_scanf(line, "%d%x%x", NULL, &state, &lac, &cid); + if (err != 3) goto error; + break; + + case 3: /* +CREG: , , , */ + err = at_tok_scanf(line, "%d%d%x%x", NULL, &state, &lac, &cid); + if (err != 4) goto error; + break; + + case 4: //, , , , */ + case 5: + case 6: + case 7: + err = at_tok_scanf(line, "%d%d%x%x%d", NULL, &state, &lac, &cid, &act); + if (err != 5) goto error; + break; + + default: + goto error; + } + + //dbg_time("state=%d", state); + + if (state == 1 || state == 5) { //Registered, home network / roaming + *pPSAttachedState = 1; + } + +error: + safe_at_response_free(p_response); + return retVal; +} + +static int requestSetupDataCall(PROFILE_T *profile, int curIpFamily) { + int err; + ATResponse *p_response = NULL; + char *cmd = NULL; + ATLine *p_cur = NULL; + int pdp = profile->pdp; + int state = 0; + + (void)curIpFamily; + + if (strStartsWith(profile->BaseBandVersion, "RG801H") || strStartsWith(profile->BaseBandVersion, "EC200H")) { + //RG801H will miss USB_CDC_NOTIFY_NETWORK_CONNECTION + asprintf(&cmd, "ifconfig %s up", profile->usbnet_adapter); + if (system(cmd)) {}; + safe_free(cmd); + } + + if (asr_style_atc) { + err = at_send_command_multiline("AT+CGACT?", "+CGACT:", &p_response); + if (at_response_error(err, p_response)) + goto _error; + + for (p_cur = p_response->p_intermediates; p_cur != NULL; p_cur = p_cur->p_next) { + int cid = 0; + state = 0; + + err = at_tok_scanf(p_cur->line, "%d%d", &cid, &state); + if (cid == pdp) + break; + else if(state) + state = 0; + } + safe_at_response_free(p_response); + + if (state == 0) { + asprintf(&cmd, "AT+CGACT=1,%d", pdp); + err = at_send_command(cmd, &p_response); + safe_free(cmd); + if (at_response_error(err, p_response)) + goto _error; + } + } + + if(asr_style_atc) + asprintf(&cmd, "AT+QNETDEVCTL=1,%d,%d", pdp, 1); + else + asprintf(&cmd, "AT+QNETDEVCTL=%d,1,%d", pdp, 1); + err = at_send_command(cmd, &p_response); + safe_free(cmd); + + if (at_response_error(err, p_response)) + goto _error; + + if (!asr_style_atc) { //TODO some modems do not sync return setup call resule + int t = 0; + + while (t++ < 15) { + asprintf(&cmd, "AT+QNETDEVSTATUS=%d", pdp); + err = at_send_command_singleline(cmd, "+QNETDEVSTATUS", &p_response); + safe_free(cmd); + if (err) goto _error; + + if (!at_response_error(err, p_response)) { + break; + } + safe_at_response_free(p_response); + sleep(1); + } + } + + //some modem do not report URC + qmidevice_send_event_to_main(RIL_UNSOL_DATA_CALL_LIST_CHANGED); + +_error: + safe_at_response_free(p_response); + //dbg_time("%s err=%d", __func__, err); + return err; +} + +static int at_netdevstatus(int pdp, unsigned int *pV4Addr) { + int err; + ATResponse *p_response = NULL; + char *cmd = NULL; + char *ipv4_address = NULL; + char *ipv4_gate = NULL; + char *ipv4_DHCP = NULL; + char *ipv4_pDNS = NULL; + char *ipv4_sDNS = NULL; + char *ipv6_address = NULL; + char *ipv6_gate = NULL; + char *ipv6_DHCP = NULL; + char *ipv6_pDNS = NULL; + char *ipv6_sDNS = NULL; + + *pV4Addr = 0; + + asprintf(&cmd, "AT+QNETDEVSTATUS=%d", pdp); + err = at_send_command_singleline(cmd, "+QNETDEVSTATUS", &p_response); + safe_free(cmd); + if (at_response_error(err, p_response)) goto _error; + if (!p_response->p_intermediates || !p_response->p_intermediates->line) goto _error; + + err = at_tok_scanf(p_response->p_intermediates->line, "%s%s%s%s%s%s%s%s%s%s", + &ipv4_address, &ipv4_gate, &ipv4_DHCP, &ipv4_pDNS, &ipv4_sDNS, + &ipv6_address, &ipv6_gate, &ipv6_DHCP, &ipv6_pDNS, &ipv6_sDNS); + if (err > 0) { +#if 0 + dbg_time("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s", + ipv4_address, ipv4_gate, ipv4_DHCP, ipv4_pDNS, ipv4_sDNS, + ipv6_address, ipv6_gate, ipv6_DHCP, ipv6_pDNS, ipv6_sDNS); +#endif + + if (ipv4_address && ipv4_address[0]) { + int addr[4] = {0, 0, 0, 0}; + + if (strstr(ipv4_address, ".")) { + sscanf(ipv4_address, "%d.%d.%d.%d", &addr[0], &addr[1], &addr[2], &addr[3]); + } + else { + sscanf(ipv4_address, "%02X%02X%02X%02X", &addr[3], &addr[2], &addr[1], &addr[0]); + } + *pV4Addr = (addr[0]) | (addr[1]<<8) | (addr[2]<<16) | (addr[3]<<24); + } + } + +_error: + safe_at_response_free(p_response); + return 0; +} + +static int requestQueryDataCall(UCHAR *pConnectionStatus, int curIpFamily) { + int err; + ATResponse *p_response = NULL; + ATLine *p_cur = NULL; + int state = 0; + int bind = 0; + int cid; + int pdp = s_pdp; + unsigned int v4Addr = 0; + + (void)curIpFamily; + + *pConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; + + if (!asr_style_atc) { + err = at_netdevstatus(pdp, &v4Addr); + if (!err && v4Addr) { + *pConnectionStatus = QWDS_PKT_DATA_CONNECTED; + //if (profile->ipv4.Address == v4Addr) {} //TODO + } + return err; + } + + err = at_send_command_multiline("AT+QNETDEVCTL?", "+QNETDEVCTL:", &p_response); + if (at_response_error(err, p_response)) + goto _error; + + for (p_cur = p_response->p_intermediates; p_cur != NULL; p_cur = p_cur->p_next) + { + //+QNETDECTL:,,, + err = at_tok_scanf(p_cur->line, "%d%d%d%d", &bind, &cid, NULL, &state); + if (err != 4 || cid != pdp) + continue; + if (bind != 1) + bind = 0; + } + safe_at_response_free(p_response); + + if (bind == 0 || state == 0) + goto _error; + + err = at_send_command_multiline("AT+CGACT?", "+CGACT:", &p_response); + if (at_response_error(err, p_response)) + goto _error; + + for (p_cur = p_response->p_intermediates; p_cur != NULL; p_cur = p_cur->p_next) + { + state = 0; + err = at_tok_scanf(p_cur->line, "%d%d", &cid, &state); + if (cid == pdp) + break; + else if(state) + state = 0; + } + safe_at_response_free(p_response); + + if (bind && state) + *pConnectionStatus = QWDS_PKT_DATA_CONNECTED; + +_error: + safe_at_response_free(p_response); + //dbg_time("%s err=%d, call_state=%d", __func__, err, *pConnectionStatus); + return 0; +} + +static int requestDeactivateDefaultPDP(PROFILE_T *profile, int curIpFamily) { + char *cmd = NULL; + int pdp = profile->pdp; + + (void)curIpFamily; + + if (asr_style_atc) + asprintf(&cmd, "AT+QNETDEVCTL=0,%d,%d", pdp, 0); + else + asprintf(&cmd, "AT+QNETDEVCTL=%d,0,%d", pdp, 0); + at_send_command(cmd, NULL); + safe_free(cmd); + + //dbg_time("%s err=%d", __func__, err); + return 0; +} + +static int requestGetIPAddress(PROFILE_T *profile, int curIpFamily) { + int err; + ATResponse *p_response = NULL; + char *cmd = NULL; + ATLine *p_cur = NULL; + int pdp = profile->pdp; + unsigned int v4Addr = 0; + + (void)curIpFamily; + + if (!asr_style_atc) { + err = at_netdevstatus(pdp, &v4Addr); + goto _error; + } + + asprintf(&cmd, "AT+CGPADDR=%d", profile->pdp); + err = at_send_command_singleline(cmd, "+CGPADDR:", &p_response); + safe_free(cmd); + if (at_response_error(err, p_response)) + goto _error; + + //+CGPADDR: 1,"10.201.80.91","2409:8930:4B3:41C7:F9B8:3D9B:A2F7:CA96" + for (p_cur = p_response->p_intermediates; p_cur != NULL; p_cur = p_cur->p_next) + { + char *ipv4 = NULL; + char *ipv6 = NULL; + + err = at_tok_scanf(p_cur->line, "%d%s%s", &pdp, &ipv4, &ipv6); + if (err < 2 || pdp != profile->pdp) + continue; + + if (ipv4) { + int addr[4] = {0, 0, 0, 0}; + + sscanf(ipv4, "%d.%d.%d.%d", &addr[0], &addr[1], &addr[2], &addr[3]); + v4Addr = (addr[0]) | (addr[1]<<8) | (addr[2]<<16) | (addr[3]<<24); + break; + } + } + +_error: + if (v4Addr && profile->ipv4.Address != v4Addr) { + unsigned char *v4 = (unsigned char *)&v4Addr; + + profile->ipv4.Address = v4Addr; + dbg_time("%s %d.%d.%d.%d", __func__, v4[0], v4[1], v4[2], v4[3]); + } + + //dbg_time("%s err=%d", __func__, err); + return v4Addr ? 0 : -1; +} + +static int requestGetSignalInfo(void) { + int retVal = -1; + int err; + ATResponse *p_response = NULL; + int i; + ATLine *p_cur = NULL; + char *rat = NULL; + int cops_act = 0; + int is_nr5g_nsa = 0, nr5g_sa = 0; + int verbose = 0; + + err = at_send_command_singleline("at+cops?", "+COPS:", &p_response); + if (at_response_error(err, p_response)) goto _error; + if (!p_response->p_intermediates || !p_response->p_intermediates->line) goto _error; + + retVal = 0; + err = at_tok_scanf(p_response->p_intermediates->line, "%d%d%s%d", NULL, NULL, NULL, &cops_act); + if (err != 4) goto _error; + + nr5g_sa = (cops_act == 11); + + safe_at_response_free(p_response); + err = at_send_command_multiline("at+qeng=\"servingcell\"", "+QENG:", &p_response); + if (at_response_error(err, p_response)) + goto _error; + + for (i = 0, p_cur = p_response->p_intermediates; p_cur != NULL; p_cur = p_cur->p_next, i++) { + char *type, *state; + + err = at_tok_scanf(p_cur->line, "%s%s", &type, &state); + if (err != 2 || strcmp(type, "servingcell")) + continue; + + if (!strcmp(state, "SEARCH") || !strcmp(state, "LIMSRV")) + continue; + + if (!strcmp(state, "NOCONN") || !strcmp(state, "CONNECT")) { + err = at_tok_scanf(p_cur->line, "%s%s%s", &type, &state, &rat); + if (err != 3) + continue; + } + else { + rat = state; + } + + if (!strcmp(rat, "NR5G-SA")) + { + //+QENG: "servingcell",,"NR5G-SA",,,,,,,,,,,,,, + //+QENG: "servingcell","NOCONN","NR5G-SA","TDD", 454,12,0,21,4ED,636576,78,3,-85,-11,32,0,5184 + struct qeng_servingcell_nr5g_sa { + char *cell_type, *state, *rat, *is_tdd; + int MCC, MNC, cellID/*hex*/; + int PCID, TAC/*hex*/, ARFCN; + int band, NR_DL_bandwidth; + int RSRP, RSRQ, RSSI, SINR; + }; + struct qeng_servingcell_nr5g_sa nr5g_sa; + + memset(&nr5g_sa, 0, sizeof(nr5g_sa)); + err = at_tok_scanf(p_cur->line, "%s,%s,%s,%s,%d,%d,%x,%d,%x,%d,%d,%d,%d,%d,%d,%d", + &nr5g_sa.cell_type, &nr5g_sa.state, &nr5g_sa.rat, &nr5g_sa.is_tdd, + &nr5g_sa.MCC, &nr5g_sa.MNC, &nr5g_sa.cellID, &nr5g_sa.PCID, &nr5g_sa.TAC, + &nr5g_sa.ARFCN, &nr5g_sa.band, &nr5g_sa.NR_DL_bandwidth, + &nr5g_sa.RSRP, &nr5g_sa.RSRQ, &nr5g_sa.RSSI, &nr5g_sa.SINR); + + if (err >= 13 && verbose) { + dbg_time("%s,%s,%s,%s,%d,%d,%x,%d,%x,%d,%d,%d,%d,%d,%d,%d", + nr5g_sa.cell_type, nr5g_sa.state, nr5g_sa.rat, nr5g_sa.is_tdd, + nr5g_sa.MCC, nr5g_sa.MNC, nr5g_sa.cellID, nr5g_sa.PCID, nr5g_sa.TAC, + nr5g_sa.ARFCN, nr5g_sa.band, nr5g_sa.NR_DL_bandwidth, + nr5g_sa.RSRP, nr5g_sa.RSRQ, nr5g_sa.RSSI, nr5g_sa.SINR); + } + } + else if (!strcmp(rat, "NR5G-NSA")) + { + //+QENG: "NR5G-NSA",,,,,< SINR>,,, + struct qeng_servingcell_nr5g_nsa { + char *mcc, *mnc; + int pcid, rsrp, sinr, rsrq; + }; + struct qeng_servingcell_nr5g_nsa nr5g_nsa; + + memset(&nr5g_nsa, 0, sizeof(nr5g_nsa)); + err = at_tok_scanf(p_cur->line, "%s%s%s%s%d%d%d%dd", + NULL, NULL, &nr5g_nsa.mcc, &nr5g_nsa.mnc, &nr5g_nsa.pcid, &nr5g_nsa.rsrp, &nr5g_nsa.sinr, &nr5g_nsa.rsrq); + if (err == 8 && verbose) + { + dbg_time("mcc=%s, mnc=%s, pcid=%d, rsrp=%d, sinr=%d, rsrq=%d", + nr5g_nsa.mcc, nr5g_nsa.mnc, nr5g_nsa.pcid, nr5g_nsa.rsrp, nr5g_nsa.sinr, nr5g_nsa.rsrq); + } + + is_nr5g_nsa = 1; + } + else if (!strcmp(rat, "LTE")) + { + //+QENG: "LTE",,,,,,,,,,,,,,,,, + struct qeng_servingcell_lte { + char *is_tdd, *mcc, *mnc; + int cellID/*hex*/, pcid, earfcn, freq_band_ind, ul_bandwidth, dl_bandwidth; + int tac/*hex*/, rsrp, rsrq, rssi, sinr, cqi,tx_power,srxlev; + }; + struct qeng_servingcell_lte lte; + + memset(<e, 0, sizeof(lte)); + if (!strcmp(rat, state)) + err = at_tok_scanf(p_cur->line, "%s%s%s%s%s%x%d%d%d%d%d%x%d%d%d%d%d%d%d", + NULL, NULL, <e.is_tdd, <e.mcc, <e.mnc, + <e.cellID, <e.pcid, <e.earfcn, <e.freq_band_ind, <e.ul_bandwidth, <e.dl_bandwidth, + <e.tac, <e.rsrp, <e.rsrq, <e.rssi, <e.sinr, <e.cqi, <e.tx_power, <e.srxlev); + else + err = at_tok_scanf(p_cur->line, "%s%s%s%s%s%s%x%d%d%d%d%d%x%d%d%d%d%d%d%d", + NULL, NULL, NULL, <e.is_tdd, <e.mcc, <e.mnc, + <e.cellID, <e.pcid, <e.earfcn, <e.freq_band_ind, <e.ul_bandwidth, <e.dl_bandwidth, + <e.tac, <e.rsrp, <e.rsrq, <e.rssi, <e.sinr, <e.cqi, <e.tx_power, <e.srxlev); + + if (err >= 18 && verbose) + { + dbg_time("is_tdd=%s, mcc=%s, mnc=%s", lte.is_tdd, lte.mcc, lte.mnc); + dbg_time("cellID=%x, pcid=%d, earfcn=%d", lte.cellID, lte.pcid, lte.earfcn); + dbg_time("freq_band_ind=%d, ul_bandwidth=%d, dl_bandwidth=%d", lte.freq_band_ind, lte.ul_bandwidth, lte.dl_bandwidth); + dbg_time("tac=%x, rsrp=%d, rsrq=%d, rssi=%d, sinr=%d", lte.tac, lte.rsrp, lte.rsrq, lte.rssi, lte.sinr); + dbg_time("cqi=%d, tx_power=%d, earfcn=%d", lte.cqi, lte.tx_power, lte.srxlev); + } + } + } + + if (is_nr5g_nsa) { + int endc_avl, plmn_info_list_r15_avl, endc_rstr, nr5g_basic; + + is_nr5g_nsa = 0; + safe_at_response_free(p_response); + err = at_send_command_multiline("at+qendc", "+QENDC:", &p_response); + if (at_response_error(err, p_response)) goto _error; + if (!p_response->p_intermediates || !p_response->p_intermediates->line) goto _error; + + err = at_tok_scanf(p_response->p_intermediates->line, "%d%d%d%d", + &endc_avl, &plmn_info_list_r15_avl, &endc_rstr, &nr5g_basic); + if (err == 4 && nr5g_basic) { + is_nr5g_nsa = 1; + } + } + + if (verbose) + dbg_time("cops_act=%d, nr5g_nsa=%d, nr5g_sa=%d", cops_act, is_nr5g_nsa, nr5g_sa); + +_error: + safe_at_response_free(p_response); + return retVal; +} + +static int requestGetICCID(void) { + int retVal = -1; + int err; + ATResponse *p_response = NULL; + char *iccid; + + err = at_send_command_singleline("AT+QCCID", "+QCCID:", &p_response); + if (at_response_error(err, p_response)) goto _error; + if (!p_response->p_intermediates || !p_response->p_intermediates->line) goto _error; + + err = at_tok_scanf(p_response->p_intermediates->line, "%s", &iccid); + if (err != 1) goto _error; + + if (iccid && iccid[0]) { + dbg_time("%s %s", __func__, iccid); + retVal = 0; + } + +_error: + safe_at_response_free(p_response); + return retVal; +} + +static int requestGetIMSI(void) { + int retVal = -1; + int err; + ATResponse *p_response = NULL; + char *imsi; + + err = at_send_command_numeric("AT+CIMI", &p_response); + if (at_response_error(err, p_response)) goto _error; + if (!p_response->p_intermediates || !p_response->p_intermediates->line) goto _error; + + imsi = p_response->p_intermediates->line; + if (imsi) { + dbg_time("%s %s", __func__, imsi); + retVal = 0; + } + +_error: + safe_at_response_free(p_response); + return retVal; +} + +const struct request_ops atc_request_ops = { + .requestBaseBandVersion = requestBaseBandVersion, + .requestGetSIMStatus = requestGetSIMStatus, + .requestEnterSimPin = requestEnterSimPin, + .requestSetProfile = requestSetProfile, + .requestGetProfile = requestGetProfile, + .requestRegistrationState = requestRegistrationState, + .requestSetupDataCall = requestSetupDataCall, + .requestQueryDataCall = requestQueryDataCall, + .requestDeactivateDefaultPDP = requestDeactivateDefaultPDP, + .requestGetIPAddress = requestGetIPAddress, + .requestGetSignalInfo = requestGetSignalInfo, + .requestGetICCID = requestGetICCID, + .requestGetIMSI = requestGetIMSI, +}; + diff --git a/wwan/app/quectel_cm_5G/src/atchannel.c b/wwan/app/quectel-cm/src/atchannel.c similarity index 100% rename from wwan/app/quectel_cm_5G/src/atchannel.c rename to wwan/app/quectel-cm/src/atchannel.c diff --git a/wwan/app/quectel_cm_5G/src/atchannel.h b/wwan/app/quectel-cm/src/atchannel.h similarity index 100% rename from wwan/app/quectel_cm_5G/src/atchannel.h rename to wwan/app/quectel-cm/src/atchannel.h diff --git a/wwan/app/quectel_cm_5G/src/configure.ac b/wwan/app/quectel-cm/src/configure.ac similarity index 100% rename from wwan/app/quectel_cm_5G/src/configure.ac rename to wwan/app/quectel-cm/src/configure.ac diff --git a/wwan/app/quectel_cm_5G/src/default.script b/wwan/app/quectel-cm/src/default.script similarity index 100% rename from wwan/app/quectel_cm_5G/src/default.script rename to wwan/app/quectel-cm/src/default.script diff --git a/wwan/app/quectel_cm_5G/src/default.script_ip b/wwan/app/quectel-cm/src/default.script_ip similarity index 100% rename from wwan/app/quectel_cm_5G/src/default.script_ip rename to wwan/app/quectel-cm/src/default.script_ip diff --git a/wwan/app/quectel_cm_5G/src/device.c b/wwan/app/quectel-cm/src/device.c similarity index 96% rename from wwan/app/quectel_cm_5G/src/device.c rename to wwan/app/quectel-cm/src/device.c index fba46c6..58bf298 100644 --- a/wwan/app/quectel_cm_5G/src/device.c +++ b/wwan/app/quectel-cm/src/device.c @@ -1,746 +1,746 @@ -/****************************************************************************** - @file device.c - @brief QMI device dirver. - - 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "QMIThread.h" -#include "ethtool-copy.h" - -#define USB_CLASS_VENDOR_SPEC 0xff -#define USB_CLASS_COMM 2 -#define USB_CDC_SUBCLASS_ACM 0x02 -#define USB_CDC_SUBCLASS_ETHERNET 0x06 -#define USB_CDC_SUBCLASS_NCM 0x0d -#define USB_CDC_SUBCLASS_MBIM 0x0e -#define USB_CLASS_WIRELESS_CONTROLLER 0xe0 - -#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) -{ - FILE *fp = NULL; - long num; - char buff[32 + 1] = {'\0'}; - char *endptr = NULL; - - fp = fopen(fname, "r"); - if (!fp) goto error; - if (fgets(buff, sizeof(buff), fp) == NULL) - goto error; - fclose(fp); - - num = (int)strtol(buff, &endptr, base); - if (errno == ERANGE && (num == LONG_MAX || num == LONG_MIN)) - goto error; - /* if there is no digit in buff */ - if (endptr == buff) - goto error; - - if (debug_qmi) - dbg_time("(%s) = %lx", fname, num); - return (int)num; - -error: - if (fp) fclose(fp); - return CM_INVALID_VAL; -} - -/* - * 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) -{ - struct dirent *entptr = NULL; - DIR *dirptr; - - buff[0] = 0; - - dirptr = opendir(dirname); - if (!dirptr) - return -1; - - while ((entptr = readdir(dirptr))) { - if (entptr->d_name[0] == '.') - continue; - if (prefix && strlen(prefix) && strncmp(entptr->d_name, prefix, strlen(prefix))) - continue; - snprintf(buff, bufsize, "%.31s", entptr->d_name); - break; - } - closedir(dirptr); - - return 0; -} - -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)) { - char prefix[128] = {'\0'}; - char tail[128] = {'\0'}; - /* To eliminate cppcheck warnning: Assume string length is no more than 15 */ - sscanf(buff, "%15[^=]=%15s", prefix, tail); - if (!strncasecmp(prefix, key, strlen(key))) { - fclose(fp); - return atoi(tail); - } - } - - fclose(fp); - return CM_INVALID_VAL; -} - -static void query_usb_device_info(char *path, struct usb_device_info *p) { - size_t offset = strlen(path); - - memset(p, 0, sizeof(*p)); - - path[offset] = '\0'; - strcat(path, "/idVendor"); - p->idVendor = file_get_value(path, 16); - - if (p->idVendor == CM_INVALID_VAL) - return; - - path[offset] = '\0'; - strcat(path, "/idProduct"); - p->idProduct = file_get_value(path, 16); - - path[offset] = '\0'; - strcat(path, "/busnum"); - p->busnum = file_get_value(path, 10); - - path[offset] = '\0'; - strcat(path, "/devnum"); - p->devnum = file_get_value(path, 10); - - path[offset] = '\0'; - strcat(path, "/bNumInterfaces"); - p->bNumInterfaces = file_get_value(path, 10); - - path[offset] = '\0'; -} - -static void query_usb_interface_info(char *path, struct usb_interface_info *p) { - char driver[128]; - size_t offset = strlen(path); - int n; - - memset(p, 0, sizeof(*p)); - - path[offset] = '\0'; - strcat(path, "/bNumEndpoints"); - p->bInterfaceClass = file_get_value(path, 16); - - path[offset] = '\0'; - strcat(path, "/bInterfaceClass"); - p->bInterfaceClass = file_get_value(path, 16); - - path[offset] = '\0'; - strcat(path, "/bInterfaceSubClass"); - p->bInterfaceSubClass = file_get_value(path, 16); - - path[offset] = '\0'; - strcat(path, "/bInterfaceProtocol"); - p->bInterfaceProtocol = file_get_value(path, 16); - - path[offset] = '\0'; - strcat(path, "/driver"); - n = readlink(path, driver, sizeof(driver)); - if (n > 0) { - driver[n] = 0; - if (debug_qmi) dbg_time("driver -> %s", driver); - n = strlen(driver); - while (n > 0) { - if (driver[n] == '/') - break; - n--; - } - 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) -{ - size_t offset = strlen(path); - char tmp[32]; - - devname[0] = 0; - - if (access(path, R_OK)) - return -1; - - path[offset] = '\0'; - strcat(path, "/GobiQMI"); - if (!access(path, R_OK)) - goto step_1; - - path[offset] = '\0'; - strcat(path, "/usbmisc"); - if (!access(path, R_OK)) - goto step_1; - - path[offset] = '\0'; - strcat(path, "/usb"); - if (!access(path, R_OK)) - goto step_1; - - return -1; - -step_1: - /* get device(qcqmiX|cdc-wdmX) */ - if (debug_qmi) dbg_time("%s", path); - dir_get_child(path, tmp, sizeof(tmp), NULL); - if (tmp[0] == '\0') - return -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) - { - int major, minor; - - dbg_time("access %s failed, errno: %d (%s)", devname, errno, strerror(errno)); - strcat(path, "/"); - strcat(path, tmp); - strcat(path, "/uevent"); - major = conf_get_val(path, "MAJOR"); - minor = conf_get_val(path, "MINOR"); - - 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)))) - dbg_time("please mknod %s c %d %d", devname, major, minor); - } - - return 0; -} - -/* To detect the device info of the modem. - * return: - * FALSE -> fail - * TRUE -> ok - */ -BOOL qmidevice_detect(char *qmichannel, char *usbnet_adapter, unsigned bufsize, PROFILE_T *profile) { - struct dirent* ent = NULL; - DIR *pDir; - const char *rootdir = "/sys/bus/usb/devices"; - struct { - char path[255*2]; - } *pl; - pl = (typeof(pl)) malloc(sizeof(*pl)); - memset(pl, 0x00, sizeof(*pl)); - - pDir = opendir(rootdir); - if (!pDir) { - dbg_time("opendir %s failed: %s", rootdir, strerror(errno)); - goto error; - } - - while ((ent = readdir(pDir)) != NULL) { - char netcard[32+1] = {'\0'}; - char devname[32+5] = {'\0'}; //+strlen("/dev/") - int netIntf; - int driver_type; - - if (ent->d_name[0] == 'u') - continue; - - snprintf(pl->path, sizeof(pl->path), "%s/%s", rootdir, ent->d_name); - query_usb_device_info(pl->path, &profile->usb_dev); - if (profile->usb_dev.idVendor == CM_INVALID_VAL) - continue; - - if (profile->usb_dev.idVendor == 0x2c7c || profile->usb_dev.idVendor == 0x05c6) { - dbg_time("Find %s/%s idVendor=0x%x idProduct=0x%x, bus=0x%03x, dev=0x%03x", - rootdir, ent->d_name, profile->usb_dev.idVendor, profile->usb_dev.idProduct, - profile->usb_dev.busnum, profile->usb_dev.devnum); - } - - /* get network interface */ - /* NOTICE: there is a case that, bNumberInterface=6, but the net interface is 8 */ - /* toolchain-mips_24kc_gcc-5.4.0_musl donot support GLOB_BRACE */ - /* RG500U's MBIM is at inteface 0 */ - for (netIntf = 0; netIntf < (profile->usb_dev.bNumInterfaces + 8); netIntf++) { - snprintf(pl->path, sizeof(pl->path), "%s/%s:1.%d/net", rootdir, ent->d_name, netIntf); - dir_get_child(pl->path, netcard, sizeof(netcard), NULL); - if (netcard[0]) - break; - } - - if (netcard[0] == '\0') { //for centos 2.6.x - 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); - if (!access(pl->path, F_OK)) { - snprintf(pl->path, sizeof(pl->path), "%s/%s:1.4/GobiQMI:%s", rootdir, ent->d_name, c); - if (!access(pl->path, F_OK)) { - snprintf(qmichannel, bufsize, "/dev/%s", c); - snprintf(usbnet_adapter, bufsize, "%s", n); - snprintf(pl->path, sizeof(pl->path), "%s/%s:1.4", rootdir, ent->d_name); - query_usb_interface_info(pl->path, &profile->usb_intf); - break; - } - } - } - - if (netcard[0] == '\0') - continue; - - /* not '-i iface' */ - if (usbnet_adapter[0] && strcmp(usbnet_adapter, netcard)) - continue; - - snprintf(pl->path, sizeof(pl->path), "%s/%s:1.%d", rootdir, ent->d_name, netIntf); - query_usb_interface_info(pl->path, &profile->usb_intf); - driver_type = get_driver_type(profile); - - 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) - { - int atIntf = -1; - - if (profile->usb_dev.idVendor == 0x2c7c) { //Quectel - switch (profile->usb_dev.idProduct) { //EC200U - case 0x0901: //EC200U - case 0x8101: //RG801H - atIntf = 2; - break; - case 0x0900: //RG500U - atIntf = 4; - break; - case 0x6026: //EC200T - case 0x6005: //EC200A - case 0x6002: //EC200S - case 0x6001: //EC100Y - atIntf = 3; - break; - default: - dbg_time("unknow at interface for USB idProduct:%04x\n", profile->usb_dev.idProduct); - break; - } - } - - if (atIntf != -1) { - snprintf(pl->path, sizeof(pl->path), "%s/%s:1.%d", rootdir, ent->d_name, atIntf); - dir_get_child(pl->path, devname, sizeof(devname), "tty"); - if (devname[0] && !strcmp(devname, "tty")) { - snprintf(pl->path, sizeof(pl->path), "%s/%s:1.%d/tty", rootdir, ent->d_name, atIntf); - dir_get_child(pl->path, devname, sizeof(devname), "tty"); - } - } - } - - if (netcard[0] && devname[0]) { - if (devname[0] == '/') - snprintf(qmichannel, bufsize, "%s", devname); - else - snprintf(qmichannel, bufsize, "/dev/%s", devname); - snprintf(usbnet_adapter, bufsize, "%s", netcard); - dbg_time("Auto find qmichannel = %s", qmichannel); - dbg_time("Auto find usbnet_adapter = %s", usbnet_adapter); - break; - } - } - closedir(pDir); - - if (qmichannel[0] == '\0' || usbnet_adapter[0] == '\0') { - dbg_time("network interface '%s' or qmidev '%s' is not exist", usbnet_adapter, qmichannel); - goto error; - } - free(pl); - return TRUE; -error: - free(pl); - return FALSE; -} - -int mhidevice_detect(char *qmichannel, char *usbnet_adapter, PROFILE_T *profile) { - 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++]; - - pDir = opendir(rootdir); - if (!pDir) { - 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) - continue; - - snprintf(path, sizeof(path), "%s/%.32s/net", rootdir, ent->d_name); - dir_get_child(path, netcard, sizeof(netcard), NULL); - if (!netcard[0]) - continue; - - 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) - 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' */ - sprintf(usbnet_adapter, "%s", netcard); - sprintf(qmichannel, "qrtr-%d", 3); // 3 is sdx modem's node id - profile->software_interface = SOFTWARE_QRTR; - find = 1; - break; - } - continue; - } - - snprintf(path, sizeof(path), "%s/%.13s_IPCR", rootdir, ent->d_name); - if (access(path, F_OK)) { - snprintf(path, sizeof(path), "%s/%.13s_QMI0", rootdir, ent->d_name); - if (access(path, F_OK)) { - snprintf(path, sizeof(path), "%s/%.13s_MBIM", rootdir, ent->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); - dir_get_child(path, devname, sizeof(devname), NULL); - if (!devname[0]) - continue; - - sprintf(usbnet_adapter, "%s", netcard); - sprintf(qmichannel, "/dev/%s", devname); - profile->software_interface = software_interface; - find = 1; - break; - } - - closedir(pDir); - } - - return find; -} - -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 { - dbg_time("atdevice_detect failed"); - goto error; - } - - if (!access("/dev/stty_nr31", F_OK)) { - strcpy(atchannel, "/dev/stty_nr31"); - profile->software_interface = SOFTWARE_ECM_RNDIS_NCM; - } - else { - goto error; - } - - return 1; -error: - return 0; -} - - -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) { - switch (profile->usb_intf.bInterfaceSubClass) { - case USB_CDC_SUBCLASS_MBIM: - return SOFTWARE_MBIM; - break; - case USB_CDC_SUBCLASS_ETHERNET: - case USB_CDC_SUBCLASS_NCM: - return SOFTWARE_ECM_RNDIS_NCM; - break; - default: - break; - } - } - 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; - } - - dbg_time("%s unknow bInterfaceClass=%d, bInterfaceSubClass=%d", __func__, - profile->usb_intf.bInterfaceClass, profile->usb_intf.bInterfaceSubClass); - return DRV_INVALID; -} - -struct usbfs_getdriver -{ - unsigned int interface; - char driver[255 + 1]; -}; - -struct usbfs_ioctl -{ - int ifno; /* interface 0..N ; negative numbers reserved */ - int ioctl_code; /* MUST encode size + direction of data so the - * macros in give correct values */ - void *data; /* param buffer (in, or out) */ -}; - -#define IOCTL_USBFS_DISCONNECT _IO('U', 22) -#define IOCTL_USBFS_CONNECT _IO('U', 23) - -int usbfs_is_kernel_driver_alive(int fd, int ifnum) -{ - struct usbfs_getdriver getdrv; - getdrv.interface = ifnum; - if (ioctl(fd, USBDEVFS_GETDRIVER, &getdrv) < 0) { - dbg_time("%s ioctl USBDEVFS_GETDRIVER failed, kernel driver may be inactive", __func__); - return 0; - } - dbg_time("%s find interface %d has match the driver %s", __func__, ifnum, getdrv.driver); - return 1; -} - -void usbfs_detach_kernel_driver(int fd, int ifnum) -{ - struct usbfs_ioctl operate; - operate.data = NULL; - operate.ifno = ifnum; - operate.ioctl_code = IOCTL_USBFS_DISCONNECT; - if (ioctl(fd, USBDEVFS_IOCTL, &operate) < 0) { - dbg_time("%s detach kernel driver failed", __func__); - } else { - dbg_time("%s detach kernel driver success", __func__); - } -} - -void usbfs_attach_kernel_driver(int fd, int ifnum) -{ - struct usbfs_ioctl operate; - operate.data = NULL; - operate.ifno = ifnum; - operate.ioctl_code = IOCTL_USBFS_CONNECT; - if (ioctl(fd, USBDEVFS_IOCTL, &operate) < 0) { - dbg_time("%s detach kernel driver failed", __func__); - } else { - dbg_time("%s detach kernel driver success", __func__); - } -} - -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) - { - dbg_time("%s fail to open %s", __func__, devpath); - return -1; - } - usbfs_detach_kernel_driver(fd, ifnum); - usbfs_attach_kernel_driver(fd, ifnum); - close(fd); - return 0; -} - -#define SIOCETHTOOL 0x8946 -int ql_get_netcard_driver_info(const char *devname) -{ - int fd = -1; - struct ethtool_drvinfo drvinfo; - struct ifreq ifr; /* ifreq suitable for ethtool ioctl */ - - memset(&ifr, 0, sizeof(ifr)); - strcpy(ifr.ifr_name, devname); - - fd = socket(AF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - dbg_time("Cannot get control socket: errno(%d)(%s)", errno, strerror(errno)); - return -1; - } - - drvinfo.cmd = ETHTOOL_GDRVINFO; - ifr.ifr_data = (void *)&drvinfo; - - if (ioctl(fd, SIOCETHTOOL, &ifr) < 0) { - dbg_time("ioctl() error: errno(%d)(%s)", errno, strerror(errno)); - close(fd); - return -1; - } - - dbg_time("netcard driver = %s, driver version = %s", drvinfo.driver, drvinfo.version); - - close(fd); - - return 0; -} - -int ql_get_netcard_carrier_state(const char *devname) -{ - int fd = -1; - struct ethtool_value edata; - struct ifreq ifr; /* ifreq suitable for ethtool ioctl */ - - memset(&ifr, 0, sizeof(ifr)); - strcpy(ifr.ifr_name, devname); - - fd = socket(AF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - dbg_time("Cannot get control socket: errno(%d)(%s)", errno, strerror(errno)); - return -1; - } - - edata.cmd = ETHTOOL_GLINK; - edata.data = 0; - ifr.ifr_data = (void *)&edata; - - if (ioctl(fd, SIOCETHTOOL, &ifr) < 0) { - dbg_time("ioctl('%s') error: errno(%d)(%s)", devname, errno, strerror(errno)); - return -1; - } - - if (!edata.data) - dbg_time("netcard carrier = %d", edata.data); - - close(fd); - - return edata.data; -} - -static void *catch_log(void *arg) -{ - PROFILE_T *profile = (PROFILE_T *)arg; - int nreads = 0; - 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) { - nreads = read(profile->usbmon_fd, tbuff + tsize, sizeof(tbuff) - tsize - 1); - if (nreads <= 0) { - if (nreads == -1 && errno == EINTR) - continue; - break; - } - - tbuff[tsize+nreads] = '\0'; // printf("%s", buff); - - if (!strstr(tbuff+tsize, filter)) - continue; - - snprintf(tbuff, sizeof(tbuff), "%s", get_time()); - tbuff[tsize-1] = ' '; - - fwrite(tbuff, strlen(tbuff), 1, profile->usbmon_logfile_fp); - } - - return NULL; -} - -int ql_capture_usbmon_log(PROFILE_T *profile, const char *log_path) -{ - char usbmon_path[256]; - pthread_t pt; - pthread_attr_t attr; - - if (access("/sys/module/usbmon", F_OK)) { - dbg_time("usbmon is not load, please execute \"modprobe usbmon\" or \"insmod usbmon.ko\""); - return -1; - } - - if (access("/sys/kernel/debug/usb", F_OK)) { - dbg_time("debugfs is not mount, please execute \"mount -t debugfs none_debugs /sys/kernel/debug\""); - return -1; - } - - snprintf(usbmon_path, sizeof(usbmon_path), "/sys/kernel/debug/usb/usbmon/%du", profile->usb_dev.busnum); - profile->usbmon_fd = open(usbmon_path, O_RDONLY); - if (profile->usbmon_fd < 0) { - dbg_time("open %s error(%d) (%s)", usbmon_path, errno, strerror(errno)); - return -1; - } - - snprintf(usbmon_path, sizeof(usbmon_path), "cat /sys/kernel/debug/usb/devices >> %s", log_path); - if (system(usbmon_path) == -1) {}; - - profile->usbmon_logfile_fp = fopen(log_path, "wb"); - if (!profile->usbmon_logfile_fp) { - dbg_time("open %s error(%d) (%s)", log_path, errno, strerror(errno)); - close(profile->usbmon_fd); - profile->usbmon_fd = -1; - return -1; - } - - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - - pthread_create(&pt, &attr, catch_log, (void *)profile); - - return 0; -} - -void ql_stop_usbmon_log(PROFILE_T *profile) { - if (profile->usbmon_fd > 0) - close(profile->usbmon_fd); - if (profile->usbmon_logfile_fp) - fclose(profile->usbmon_logfile_fp); -} +/****************************************************************************** + @file device.c + @brief QMI device dirver. + + 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "QMIThread.h" +#include "ethtool-copy.h" + +#define USB_CLASS_VENDOR_SPEC 0xff +#define USB_CLASS_COMM 2 +#define USB_CDC_SUBCLASS_ACM 0x02 +#define USB_CDC_SUBCLASS_ETHERNET 0x06 +#define USB_CDC_SUBCLASS_NCM 0x0d +#define USB_CDC_SUBCLASS_MBIM 0x0e +#define USB_CLASS_WIRELESS_CONTROLLER 0xe0 + +#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) +{ + FILE *fp = NULL; + long num; + char buff[32 + 1] = {'\0'}; + char *endptr = NULL; + + fp = fopen(fname, "r"); + if (!fp) goto error; + if (fgets(buff, sizeof(buff), fp) == NULL) + goto error; + fclose(fp); + + num = (int)strtol(buff, &endptr, base); + if (errno == ERANGE && (num == LONG_MAX || num == LONG_MIN)) + goto error; + /* if there is no digit in buff */ + if (endptr == buff) + goto error; + + if (debug_qmi) + dbg_time("(%s) = %lx", fname, num); + return (int)num; + +error: + if (fp) fclose(fp); + return CM_INVALID_VAL; +} + +/* + * 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) +{ + struct dirent *entptr = NULL; + DIR *dirptr; + + buff[0] = 0; + + dirptr = opendir(dirname); + if (!dirptr) + return -1; + + while ((entptr = readdir(dirptr))) { + if (entptr->d_name[0] == '.') + continue; + if (prefix && strlen(prefix) && strncmp(entptr->d_name, prefix, strlen(prefix))) + continue; + snprintf(buff, bufsize, "%.31s", entptr->d_name); + break; + } + closedir(dirptr); + + return 0; +} + +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)) { + char prefix[128] = {'\0'}; + char tail[128] = {'\0'}; + /* To eliminate cppcheck warnning: Assume string length is no more than 15 */ + sscanf(buff, "%15[^=]=%15s", prefix, tail); + if (!strncasecmp(prefix, key, strlen(key))) { + fclose(fp); + return atoi(tail); + } + } + + fclose(fp); + return CM_INVALID_VAL; +} + +static void query_usb_device_info(char *path, struct usb_device_info *p) { + size_t offset = strlen(path); + + memset(p, 0, sizeof(*p)); + + path[offset] = '\0'; + strcat(path, "/idVendor"); + p->idVendor = file_get_value(path, 16); + + if (p->idVendor == CM_INVALID_VAL) + return; + + path[offset] = '\0'; + strcat(path, "/idProduct"); + p->idProduct = file_get_value(path, 16); + + path[offset] = '\0'; + strcat(path, "/busnum"); + p->busnum = file_get_value(path, 10); + + path[offset] = '\0'; + strcat(path, "/devnum"); + p->devnum = file_get_value(path, 10); + + path[offset] = '\0'; + strcat(path, "/bNumInterfaces"); + p->bNumInterfaces = file_get_value(path, 10); + + path[offset] = '\0'; +} + +static void query_usb_interface_info(char *path, struct usb_interface_info *p) { + char driver[128]; + size_t offset = strlen(path); + int n; + + memset(p, 0, sizeof(*p)); + + path[offset] = '\0'; + strcat(path, "/bNumEndpoints"); + p->bInterfaceClass = file_get_value(path, 16); + + path[offset] = '\0'; + strcat(path, "/bInterfaceClass"); + p->bInterfaceClass = file_get_value(path, 16); + + path[offset] = '\0'; + strcat(path, "/bInterfaceSubClass"); + p->bInterfaceSubClass = file_get_value(path, 16); + + path[offset] = '\0'; + strcat(path, "/bInterfaceProtocol"); + p->bInterfaceProtocol = file_get_value(path, 16); + + path[offset] = '\0'; + strcat(path, "/driver"); + n = readlink(path, driver, sizeof(driver)); + if (n > 0) { + driver[n] = 0; + if (debug_qmi) dbg_time("driver -> %s", driver); + n = strlen(driver); + while (n > 0) { + if (driver[n] == '/') + break; + n--; + } + 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) +{ + size_t offset = strlen(path); + char tmp[32]; + + devname[0] = 0; + + if (access(path, R_OK)) + return -1; + + path[offset] = '\0'; + strcat(path, "/GobiQMI"); + if (!access(path, R_OK)) + goto step_1; + + path[offset] = '\0'; + strcat(path, "/usbmisc"); + if (!access(path, R_OK)) + goto step_1; + + path[offset] = '\0'; + strcat(path, "/usb"); + if (!access(path, R_OK)) + goto step_1; + + return -1; + +step_1: + /* get device(qcqmiX|cdc-wdmX) */ + if (debug_qmi) dbg_time("%s", path); + dir_get_child(path, tmp, sizeof(tmp), NULL); + if (tmp[0] == '\0') + return -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) + { + int major, minor; + + dbg_time("access %s failed, errno: %d (%s)", devname, errno, strerror(errno)); + strcat(path, "/"); + strcat(path, tmp); + strcat(path, "/uevent"); + major = conf_get_val(path, "MAJOR"); + minor = conf_get_val(path, "MINOR"); + + 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)))) + dbg_time("please mknod %s c %d %d", devname, major, minor); + } + + return 0; +} + +/* To detect the device info of the modem. + * return: + * FALSE -> fail + * TRUE -> ok + */ +BOOL qmidevice_detect(char *qmichannel, char *usbnet_adapter, unsigned bufsize, PROFILE_T *profile) { + struct dirent* ent = NULL; + DIR *pDir; + const char *rootdir = "/sys/bus/usb/devices"; + struct { + char path[255*2]; + } *pl; + pl = (typeof(pl)) malloc(sizeof(*pl)); + memset(pl, 0x00, sizeof(*pl)); + + pDir = opendir(rootdir); + if (!pDir) { + dbg_time("opendir %s failed: %s", rootdir, strerror(errno)); + goto error; + } + + while ((ent = readdir(pDir)) != NULL) { + char netcard[32+1] = {'\0'}; + char devname[32+5] = {'\0'}; //+strlen("/dev/") + int netIntf; + int driver_type; + + if (ent->d_name[0] == 'u') + continue; + + snprintf(pl->path, sizeof(pl->path), "%s/%s", rootdir, ent->d_name); + query_usb_device_info(pl->path, &profile->usb_dev); + if (profile->usb_dev.idVendor == CM_INVALID_VAL) + continue; + + if (profile->usb_dev.idVendor == 0x2c7c || profile->usb_dev.idVendor == 0x05c6) { + dbg_time("Find %s/%s idVendor=0x%x idProduct=0x%x, bus=0x%03x, dev=0x%03x", + rootdir, ent->d_name, profile->usb_dev.idVendor, profile->usb_dev.idProduct, + profile->usb_dev.busnum, profile->usb_dev.devnum); + } + + /* get network interface */ + /* NOTICE: there is a case that, bNumberInterface=6, but the net interface is 8 */ + /* toolchain-mips_24kc_gcc-5.4.0_musl donot support GLOB_BRACE */ + /* RG500U's MBIM is at inteface 0 */ + for (netIntf = 0; netIntf < (profile->usb_dev.bNumInterfaces + 8); netIntf++) { + snprintf(pl->path, sizeof(pl->path), "%s/%s:1.%d/net", rootdir, ent->d_name, netIntf); + dir_get_child(pl->path, netcard, sizeof(netcard), NULL); + if (netcard[0]) + break; + } + + if (netcard[0] == '\0') { //for centos 2.6.x + 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); + if (!access(pl->path, F_OK)) { + snprintf(pl->path, sizeof(pl->path), "%s/%s:1.4/GobiQMI:%s", rootdir, ent->d_name, c); + if (!access(pl->path, F_OK)) { + snprintf(qmichannel, bufsize, "/dev/%s", c); + snprintf(usbnet_adapter, bufsize, "%s", n); + snprintf(pl->path, sizeof(pl->path), "%s/%s:1.4", rootdir, ent->d_name); + query_usb_interface_info(pl->path, &profile->usb_intf); + break; + } + } + } + + if (netcard[0] == '\0') + continue; + + /* not '-i iface' */ + if (usbnet_adapter[0] && strcmp(usbnet_adapter, netcard)) + continue; + + snprintf(pl->path, sizeof(pl->path), "%s/%s:1.%d", rootdir, ent->d_name, netIntf); + query_usb_interface_info(pl->path, &profile->usb_intf); + driver_type = get_driver_type(profile); + + 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) + { + int atIntf = -1; + + if (profile->usb_dev.idVendor == 0x2c7c) { //Quectel + switch (profile->usb_dev.idProduct) { //EC200U + case 0x0901: //EC200U + case 0x8101: //RG801H + atIntf = 2; + break; + case 0x0900: //RG500U + atIntf = 4; + break; + case 0x6026: //EC200T + case 0x6005: //EC200A + case 0x6002: //EC200S + case 0x6001: //EC100Y + atIntf = 3; + break; + default: + dbg_time("unknow at interface for USB idProduct:%04x\n", profile->usb_dev.idProduct); + break; + } + } + + if (atIntf != -1) { + snprintf(pl->path, sizeof(pl->path), "%s/%s:1.%d", rootdir, ent->d_name, atIntf); + dir_get_child(pl->path, devname, sizeof(devname), "tty"); + if (devname[0] && !strcmp(devname, "tty")) { + snprintf(pl->path, sizeof(pl->path), "%s/%s:1.%d/tty", rootdir, ent->d_name, atIntf); + dir_get_child(pl->path, devname, sizeof(devname), "tty"); + } + } + } + + if (netcard[0] && devname[0]) { + if (devname[0] == '/') + snprintf(qmichannel, bufsize, "%s", devname); + else + snprintf(qmichannel, bufsize, "/dev/%s", devname); + snprintf(usbnet_adapter, bufsize, "%s", netcard); + dbg_time("Auto find qmichannel = %s", qmichannel); + dbg_time("Auto find usbnet_adapter = %s", usbnet_adapter); + break; + } + } + closedir(pDir); + + if (qmichannel[0] == '\0' || usbnet_adapter[0] == '\0') { + dbg_time("network interface '%s' or qmidev '%s' is not exist", usbnet_adapter, qmichannel); + goto error; + } + free(pl); + return TRUE; +error: + free(pl); + return FALSE; +} + +int mhidevice_detect(char *qmichannel, char *usbnet_adapter, PROFILE_T *profile) { + 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++]; + + pDir = opendir(rootdir); + if (!pDir) { + 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) + continue; + + snprintf(path, sizeof(path), "%s/%.32s/net", rootdir, ent->d_name); + dir_get_child(path, netcard, sizeof(netcard), NULL); + if (!netcard[0]) + continue; + + 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) + 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' */ + sprintf(usbnet_adapter, "%s", netcard); + sprintf(qmichannel, "qrtr-%d", 3); // 3 is sdx modem's node id + profile->software_interface = SOFTWARE_QRTR; + find = 1; + break; + } + continue; + } + + snprintf(path, sizeof(path), "%s/%.13s_IPCR", rootdir, ent->d_name); + if (access(path, F_OK)) { + snprintf(path, sizeof(path), "%s/%.13s_QMI0", rootdir, ent->d_name); + if (access(path, F_OK)) { + snprintf(path, sizeof(path), "%s/%.13s_MBIM", rootdir, ent->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); + dir_get_child(path, devname, sizeof(devname), NULL); + if (!devname[0]) + continue; + + sprintf(usbnet_adapter, "%s", netcard); + sprintf(qmichannel, "/dev/%s", devname); + profile->software_interface = software_interface; + find = 1; + break; + } + + closedir(pDir); + } + + return find; +} + +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 { + dbg_time("atdevice_detect failed"); + goto error; + } + + if (!access("/dev/stty_nr31", F_OK)) { + strcpy(atchannel, "/dev/stty_nr31"); + profile->software_interface = SOFTWARE_ECM_RNDIS_NCM; + } + else { + goto error; + } + + return 1; +error: + return 0; +} + + +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) { + switch (profile->usb_intf.bInterfaceSubClass) { + case USB_CDC_SUBCLASS_MBIM: + return SOFTWARE_MBIM; + break; + case USB_CDC_SUBCLASS_ETHERNET: + case USB_CDC_SUBCLASS_NCM: + return SOFTWARE_ECM_RNDIS_NCM; + break; + default: + break; + } + } + 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; + } + + dbg_time("%s unknow bInterfaceClass=%d, bInterfaceSubClass=%d", __func__, + profile->usb_intf.bInterfaceClass, profile->usb_intf.bInterfaceSubClass); + return DRV_INVALID; +} + +struct usbfs_getdriver +{ + unsigned int interface; + char driver[255 + 1]; +}; + +struct usbfs_ioctl +{ + int ifno; /* interface 0..N ; negative numbers reserved */ + int ioctl_code; /* MUST encode size + direction of data so the + * macros in give correct values */ + void *data; /* param buffer (in, or out) */ +}; + +#define IOCTL_USBFS_DISCONNECT _IO('U', 22) +#define IOCTL_USBFS_CONNECT _IO('U', 23) + +int usbfs_is_kernel_driver_alive(int fd, int ifnum) +{ + struct usbfs_getdriver getdrv; + getdrv.interface = ifnum; + if (ioctl(fd, USBDEVFS_GETDRIVER, &getdrv) < 0) { + dbg_time("%s ioctl USBDEVFS_GETDRIVER failed, kernel driver may be inactive", __func__); + return 0; + } + dbg_time("%s find interface %d has match the driver %s", __func__, ifnum, getdrv.driver); + return 1; +} + +void usbfs_detach_kernel_driver(int fd, int ifnum) +{ + struct usbfs_ioctl operate; + operate.data = NULL; + operate.ifno = ifnum; + operate.ioctl_code = IOCTL_USBFS_DISCONNECT; + if (ioctl(fd, USBDEVFS_IOCTL, &operate) < 0) { + dbg_time("%s detach kernel driver failed", __func__); + } else { + dbg_time("%s detach kernel driver success", __func__); + } +} + +void usbfs_attach_kernel_driver(int fd, int ifnum) +{ + struct usbfs_ioctl operate; + operate.data = NULL; + operate.ifno = ifnum; + operate.ioctl_code = IOCTL_USBFS_CONNECT; + if (ioctl(fd, USBDEVFS_IOCTL, &operate) < 0) { + dbg_time("%s detach kernel driver failed", __func__); + } else { + dbg_time("%s detach kernel driver success", __func__); + } +} + +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) + { + dbg_time("%s fail to open %s", __func__, devpath); + return -1; + } + usbfs_detach_kernel_driver(fd, ifnum); + usbfs_attach_kernel_driver(fd, ifnum); + close(fd); + return 0; +} + +#define SIOCETHTOOL 0x8946 +int ql_get_netcard_driver_info(const char *devname) +{ + int fd = -1; + struct ethtool_drvinfo drvinfo; + struct ifreq ifr; /* ifreq suitable for ethtool ioctl */ + + memset(&ifr, 0, sizeof(ifr)); + strcpy(ifr.ifr_name, devname); + + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + dbg_time("Cannot get control socket: errno(%d)(%s)", errno, strerror(errno)); + return -1; + } + + drvinfo.cmd = ETHTOOL_GDRVINFO; + ifr.ifr_data = (void *)&drvinfo; + + if (ioctl(fd, SIOCETHTOOL, &ifr) < 0) { + dbg_time("ioctl() error: errno(%d)(%s)", errno, strerror(errno)); + close(fd); + return -1; + } + + dbg_time("netcard driver = %s, driver version = %s", drvinfo.driver, drvinfo.version); + + close(fd); + + return 0; +} + +int ql_get_netcard_carrier_state(const char *devname) +{ + int fd = -1; + struct ethtool_value edata; + struct ifreq ifr; /* ifreq suitable for ethtool ioctl */ + + memset(&ifr, 0, sizeof(ifr)); + strcpy(ifr.ifr_name, devname); + + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + dbg_time("Cannot get control socket: errno(%d)(%s)", errno, strerror(errno)); + return -1; + } + + edata.cmd = ETHTOOL_GLINK; + edata.data = 0; + ifr.ifr_data = (void *)&edata; + + if (ioctl(fd, SIOCETHTOOL, &ifr) < 0) { + dbg_time("ioctl('%s') error: errno(%d)(%s)", devname, errno, strerror(errno)); + return -1; + } + + if (!edata.data) + dbg_time("netcard carrier = %d", edata.data); + + close(fd); + + return edata.data; +} + +static void *catch_log(void *arg) +{ + PROFILE_T *profile = (PROFILE_T *)arg; + int nreads = 0; + 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) { + nreads = read(profile->usbmon_fd, tbuff + tsize, sizeof(tbuff) - tsize - 1); + if (nreads <= 0) { + if (nreads == -1 && errno == EINTR) + continue; + break; + } + + tbuff[tsize+nreads] = '\0'; // printf("%s", buff); + + if (!strstr(tbuff+tsize, filter)) + continue; + + snprintf(tbuff, sizeof(tbuff), "%s", get_time()); + tbuff[tsize-1] = ' '; + + fwrite(tbuff, strlen(tbuff), 1, profile->usbmon_logfile_fp); + } + + return NULL; +} + +int ql_capture_usbmon_log(PROFILE_T *profile, const char *log_path) +{ + char usbmon_path[256]; + pthread_t pt; + pthread_attr_t attr; + + if (access("/sys/module/usbmon", F_OK)) { + dbg_time("usbmon is not load, please execute \"modprobe usbmon\" or \"insmod usbmon.ko\""); + return -1; + } + + if (access("/sys/kernel/debug/usb", F_OK)) { + dbg_time("debugfs is not mount, please execute \"mount -t debugfs none_debugs /sys/kernel/debug\""); + return -1; + } + + snprintf(usbmon_path, sizeof(usbmon_path), "/sys/kernel/debug/usb/usbmon/%du", profile->usb_dev.busnum); + profile->usbmon_fd = open(usbmon_path, O_RDONLY); + if (profile->usbmon_fd < 0) { + dbg_time("open %s error(%d) (%s)", usbmon_path, errno, strerror(errno)); + return -1; + } + + snprintf(usbmon_path, sizeof(usbmon_path), "cat /sys/kernel/debug/usb/devices >> %s", log_path); + if (system(usbmon_path) == -1) {}; + + profile->usbmon_logfile_fp = fopen(log_path, "wb"); + if (!profile->usbmon_logfile_fp) { + dbg_time("open %s error(%d) (%s)", log_path, errno, strerror(errno)); + close(profile->usbmon_fd); + profile->usbmon_fd = -1; + return -1; + } + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + pthread_create(&pt, &attr, catch_log, (void *)profile); + + return 0; +} + +void ql_stop_usbmon_log(PROFILE_T *profile) { + if (profile->usbmon_fd > 0) + close(profile->usbmon_fd); + if (profile->usbmon_logfile_fp) + fclose(profile->usbmon_logfile_fp); +} diff --git a/wwan/app/quectel_cm_5G/src/ethtool-copy.h b/wwan/app/quectel-cm/src/ethtool-copy.h similarity index 100% rename from wwan/app/quectel_cm_5G/src/ethtool-copy.h rename to wwan/app/quectel-cm/src/ethtool-copy.h diff --git a/wwan/app/quectel-cm/src/log/cdc_mbim.txt b/wwan/app/quectel-cm/src/log/cdc_mbim.txt new file mode 100644 index 0000000..8acdfde --- /dev/null +++ b/wwan/app/quectel-cm/src/log/cdc_mbim.txt @@ -0,0 +1,71 @@ +root@ZhuoTK:/# dmesg +[ 788.920000] usb 1-1.3: new high-speed USB device number 4 using ehci-platform +[ 789.160000] cdc_mbim 1-1.3:1.4: cdc-wdm0: USB WDM device +[ 789.170000] cdc_mbim 1-1.3:1.4 wwan0: register 'cdc_mbim' at usb-101c0000.ehci-1.3, CDC MBIM, a2:58:dc:4d:dd:ca + +root@ZhuoTK:/# quectel-CM -s cmnet & +[04-13_05:24:38:767] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-13_05:24:38:769] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x004 +[04-13_05:24:38:771] Auto find qmichannel = /dev/cdc-wdm0 +[04-13_05:24:38:771] Auto find usbnet_adapter = wwan0 +[04-13_05:24:38:771] netcard driver = cdc_mbim, driver version = 22-Aug-2005 +[04-13_05:24:38:771] Modem works in MBIM mode +[04-13_05:24:38:779] cdc_wdm_fd = 7 +[04-13_05:24:38:779] mbim_open_device() +[04-13_05:24:39:624] mbim_device_caps_query() +[04-13_05:24:39:656] DeviceId: 866758045439136 +[04-13_05:24:39:656] FirmwareInfo: EC25EFAR06A11M4G +[04-13_05:24:39:656] HardwareInfo: QUECTEL Mobile Broadband Modul +[04-13_05:24:39:657] mbim_device_services_query() +[04-13_05:24:39:688] mbim_set_radio_state( 1 ) +[04-13_05:24:39:721] HwRadioState: 1, SwRadioState: 1 +[04-13_05:24:39:721] mbim_subscriber_status_query() +[04-13_05:24:39:784] SubscriberId: 460028563800461 +[04-13_05:24:39:784] SimIccId: 89860015120716380461 +[04-13_05:24:39:785] SubscriberReadyState NotInitialized -> Initialized +[04-13_05:24:39:785] mbim_register_state_query() +[04-13_05:24:39:816] RegisterState Unknown -> Home +[04-13_05:24:39:816] mbim_packet_service_query() +[04-13_05:24:39:848] PacketServiceState Unknown -> Attached +[04-13_05:24:39:848] mbim_query_connect(sessionID=0) +[04-13_05:24:39:880] ActivationState Unknown -> Deactivated +[04-13_05:24:39:881] ifconfig wwan0 0.0.0.0 +[04-13_05:24:39:899] ifconfig wwan0 down +[04-13_05:24:39:913] mbim_set_connect(onoff=1, sessionID=0) +[04-13_05:24:39:976] ActivationState Deactivated -> Activated +[04-13_05:24:39:977] mbim_ip_config(sessionID=0) +[04-13_05:24:40:008] < SessionId = 0 +[04-13_05:24:40:008] < IPv4ConfigurationAvailable = 0xf +[04-13_05:24:40:008] < IPv6ConfigurationAvailable = 0x0 +[04-13_05:24:40:008] < IPv4AddressCount = 0x1 +[04-13_05:24:40:008] < IPv4AddressOffset = 0x3c +[04-13_05:24:40:009] < IPv6AddressCount = 0x0 +[04-13_05:24:40:009] < IPv6AddressOffset = 0x0 +[04-13_05:24:40:009] < IPv4 = 10.129.90.29/30 +[04-13_05:24:40:009] < gw = 10.129.90.30 +[04-13_05:24:40:009] < dns1 = 211.138.180.2 +[04-13_05:24:40:009 < dns2 = 211.138.180.3 +[04-13_05:24:40:009] < ipv4 mtu = 1500 +[04-13_05:24:40:041] ifconfig wwan0 up +[04-13_05:24:40:063] ip -4 address flush dev wwan0 +[04-13_05:24:40:073] ip -4 address add 10.129.90.29/30 dev wwan0 +[04-13_05:24:40:084] ip -4 route add default via 10.129.90.30 dev wwan0 + +root@ZhuoTK:/# ifconfig wwan0 +wwan0 Link encap:Ethernet HWaddr A2:58:DC:4D:DD:CA + inet addr:10.129.90.29 Bcast:0.0.0.0 Mask:255.255.255.252 + inet6 addr: fe80::a058:dcff:fe4d:ddca/64 Scope:Link + UP BROADCAST RUNNING NOARP MULTICAST MTU:1500 Metric:1 + RX packets:0 errors:0 dropped:0 overruns:0 frame:0 + TX packets:5 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:0 (0.0 B) TX bytes:380 (380.0 B) + +root@ZhuoTK:/# ip ro show +default via 10.129.90.30 dev wwan0 +10.129.90.28/30 dev wwan0 proto kernel scope link src 10.129.90.29 +192.168.1.0/24 dev br-lan proto kernel scope link src 192.168.1.251 + +root@ZhuoTK:/# ping www.qq.com +PING www.qq.com (183.194.238.117): 56 data bytes +64 bytes from 183.194.238.117: seq=0 ttl=53 time=58.674 ms \ No newline at end of file diff --git a/wwan/app/quectel-cm/src/log/cdc_mbim_vlan.txt b/wwan/app/quectel-cm/src/log/cdc_mbim_vlan.txt new file mode 100644 index 0000000..79e15a4 --- /dev/null +++ b/wwan/app/quectel-cm/src/log/cdc_mbim_vlan.txt @@ -0,0 +1,168 @@ +root@ZhuoTK:/# dmesg +[ 788.920000] usb 1-1.3: new high-speed USB device number 4 using ehci-platform +[ 789.160000] cdc_mbim 1-1.3:1.4: cdc-wdm0: USB WDM device +[ 789.170000] cdc_mbim 1-1.3:1.4 wwan0: register 'cdc_mbim' at usb-101c0000.ehci-1.3, CDC MBIM, a2:58:dc:4d:dd:ca + +root@ZhuoTK:/# ip link add link wwan0 name wwan0.1 type vlan id 1 +root@ZhuoTK:/# ip link add link wwan0 name wwan0.2 type vlan id 2 +root@ZhuoTK:/# ifconfig wwan0.1 +wwan0.1 Link encap:Ethernet HWaddr A2:58:DC:4D:DD:CA + BROADCAST NOARP MULTICAST MTU:1500 Metric:1 + RX packets:0 errors:0 dropped:0 overruns:0 frame:0 + TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:0 + RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) + +root@ZhuoTK:/# ifconfig wwan0.2 +wwan0.2 Link encap:Ethernet HWaddr A2:58:DC:4D:DD:CA + BROADCAST NOARP MULTICAST MTU:1500 Metric:1 + RX packets:0 errors:0 dropped:0 overruns:0 frame:0 + TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:0 + RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) + +root@ZhuoTK:/# quectel-mbim-proxy & +root@ZhuoTK:/# [04-13_07:04:27:543] mbim_dev_fd=3 +[04-13_07:04:27:543] mbim_send_open_msg() +[04-13_07:04:28:321] receive MBIM_OPEN_DONE, status=0 +[04-13_07:04:28:321] mbim_server_fd=4 + +root@ZhuoTK:/# quectel-CM -n 1 -s cmnet & +[04-13_07:04:34:256] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-13_07:04:34:259] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x004 +[04-13_07:04:34:260] Auto find qmichannel = /dev/cdc-wdm0 +[04-13_07:04:34:260] Auto find usbnet_adapter = wwan0 +[04-13_07:04:34:260] netcard driver = cdc_mbim, driver version = 22-Aug-2005 +[04-13_07:04:34:261] mbim_qmap_mode = 4, vlan_id = 0x01, qmap_netcard = wwan0.1 +[04-13_07:04:34:261] Modem works in MBIM mode +[04-13_07:04:34:261] handle_client_connect client_fd=5, client_idx=1 +[04-13_07:04:34:262] connect to quectel-mbim-proxy sockfd = 7 +[04-13_07:04:34:262] cdc_wdm_fd = 7 +[04-13_07:04:34:262] mbim_open_device() +[04-13_07:04:35:106] mbim_device_caps_query() +[04-13_07:04:35:139] DeviceId: 866758045439136 +[04-13_07:04:35:139] FirmwareInfo: EC25EFAR06A11M4G +[04-13_07:04:35:139] HardwareInfo: QUECTEL Mobile Broadband Modul +[04-13_07:04:35:139] mbim_device_services_query() +[04-13_07:04:35:170] mbim_set_radio_state( 1 ) +[04-13_07:04:35:202] HwRadioState: 1, SwRadioState: 1 +[04-13_07:04:35:202] mbim_subscriber_status_query() +[04-13_07:04:35:267] SubscriberId: 460028563800461 +[04-13_07:04:35:267] SimIccId: 89860015120716380461 +[04-13_07:04:35:267] SubscriberReadyState NotInitialized -> Initialized +[04-13_07:04:35:267] mbim_register_state_query() +[04-13_07:04:35:297] RegisterState Unknown -> Home +[04-13_07:04:35:298] mbim_packet_service_query() +[04-13_07:04:35:329] PacketServiceState Unknown -> Attached +[04-13_07:04:35:330] mbim_query_connect(sessionID=1) +[04-13_07:04:35:361] ActivationState Unknown -> Deactivated +[04-13_07:04:35:362] ifconfig wwan0.1 0.0.0.0 +[04-13_07:04:35:373] ifconfig wwan0.1 down +[04-13_07:04:35:383] mbim_set_connect(onoff=1, sessionID=1) +[04-13_07:04:35:426] ActivationState Deactivated -> Activated +[04-13_07:04:35:426] mbim_ip_config(sessionID=1) +[04-13_07:04:35:457] < SessionId = 1 +[04-13_07:04:35:457] < IPv4ConfigurationAvailable = 0xf +[04-13_07:04:35:457] < IPv6ConfigurationAvailable = 0x0 +[04-13_07:04:35:457] < IPv4AddressCount = 0x1 +[04-13_07:04:35:458] < IPv4AddressOffset = 0x3c +[04-13_07:04:35:458] < IPv6AddressCount = 0x0 +[04-13_07:04:35:458] < IPv6AddressOffset = 0x0 +[04-13_07:04:35:458] < IPv4 = 10.129.90.29/30 +[04-13_07:04:35:458] < gw = 10.129.90.30 +[04-13_07:04:35:458] < dns1 = 211.138.180.2 +[04-13_07:04:35:458] < dns2 = 211.138.180.3 +[04-13_07:04:35:458] < ipv4 mtu = 1500 +[04-13_07:04:35:489] ifconfig wwan0 up +[04-13_07:04:35:509] ifconfig wwan0.1 down +[04-13_07:04:35:522] ifconfig wwan0.1 up +[04-13_07:04:35:535] ip -4 address flush dev wwan0.1 +[04-13_07:04:35:545] ip -4 address add 10.129.90.29/30 dev wwan0.1 +[04-13_07:04:35:556] ip -4 route add default via 10.129.90.30 dev wwan0.1 + +root@ZhuoTK:/# quectel-CM -n 2 -s 4gnet & +[04-13_07:04:45:150] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-13_07:04:45:152] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x004 +[04-13_07:04:45:154] Auto find qmichannel = /dev/cdc-wdm0 +[04-13_07:04:45:154] Auto find usbnet_adapter = wwan0 +[04-13_07:04:45:154] netcard driver = cdc_mbim, driver version = 22-Aug-2005 +[04-13_07:04:45:155] mbim_qmap_mode = 4, vlan_id = 0x02, qmap_netcard = wwan0.2 +[04-13_07:04:45:155] Modem works in MBIM mode +[04-13_07:04:45:155] handle_client_connect client_fd=6, client_idx=2 +[04-13_07:04:45:156] connect to quectel-mbim-proxy sockfd = 7 +[04-13_07:04:45:156] cdc_wdm_fd = 7 +[04-13_07:04:45:156] mbim_open_device() +[04-13_07:04:46:025] mbim_device_caps_query() +[04-13_07:04:46:056] DeviceId: 866758045439136 +[04-13_07:04:46:056] FirmwareInfo: EC25EFAR06A11M4G +[04-13_07:04:46:056] HardwareInfo: QUECTEL Mobile Broadband Modul +[04-13_07:04:46:056] mbim_device_services_query() +[04-13_07:04:46:088] mbim_set_radio_state( 1 ) +[04-13_07:04:46:119] HwRadioState: 1, SwRadioState: 1 +[04-13_07:04:46:119] mbim_subscriber_status_query() +[04-13_07:04:46:183] SubscriberId: 460028563800461 +[04-13_07:04:46:184] SimIccId: 89860015120716380461 +[04-13_07:04:46:184] SubscriberReadyState NotInitialized -> Initialized +[04-13_07:04:46:184] mbim_register_state_query() +[04-13_07:04:46:216] RegisterState Unknown -> Home +[04-13_07:04:46:216] mbim_packet_service_query() +[04-13_07:04:46:248] PacketServiceState Unknown -> Attached +[04-13_07:04:46:248] mbim_query_connect(sessionID=2) +[04-13_07:04:46:280] ActivationState Unknown -> Deactivated +[04-13_07:04:46:280] ifconfig wwan0.2 0.0.0.0 +[04-13_07:04:46:291] ifconfig wwan0.2 down +[04-13_07:04:46:304] mbim_set_connect(onoff=1, sessionID=2) +[04-13_07:04:46:504] ActivationState Deactivated -> Activated +[04-13_07:04:46:505] mbim_ip_config(sessionID=2) +[04-13_07:04:46:537] < SessionId = 2 +[04-13_07:04:46:537] < IPv4ConfigurationAvailable = 0xf +[04-13_07:04:46:537] < IPv6ConfigurationAvailable = 0x0 +[04-13_07:04:46:538] < IPv4AddressCount = 0x1 +[04-13_07:04:46:538] < IPv4AddressOffset = 0x3c +[04-13_07:04:46:538] < IPv6AddressCount = 0x0 +[04-13_07:04:46:538] < IPv6AddressOffset = 0x0 +[04-13_07:04:46:538] < IPv4 = 10.129.37.205/30 +[04-13_07:04:46:538] < gw = 10.129.37.206 +[04-13_07:04:46:538] < dns1 = 211.138.180.2 +[04-13_07:04:46:538] < dns2 = 211.138.180.3 +[04-13_07:04:46:538] < ipv4 mtu = 1500 +[04-13_07:04:46:569] ifconfig wwan0 up +[04-13_07:04:46:579] ifconfig wwan0.2 up +[04-13_07:04:46:592] ip -4 address flush dev wwan0.2 +[04-13_07:04:46:602] ip -4 address add 10.129.37.205/30 dev wwan0.2 +[04-13_07:04:46:613] ip -4 route add default via 10.129.37.206 dev wwan0.2 + +root@ZhuoTK:/# ifconfig wwan0.1 +wwan0.1 Link encap:Ethernet HWaddr A2:58:DC:4D:DD:CA + inet addr:10.129.90.29 Bcast:0.0.0.0 Mask:255.255.255.252 + inet6 addr: fe80::a058:dcff:fe4d:ddca/64 Scope:Link + UP BROADCAST RUNNING NOARP MULTICAST MTU:1500 Metric:1 + RX packets:4 errors:0 dropped:0 overruns:0 frame:0 + TX packets:13 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:0 + RX bytes:304 (304.0 B) TX bytes:1170 (1.1 KiB) + +root@ZhuoTK:/# ifconfig wwan0.2 +wwan0.2 Link encap:Ethernet HWaddr A2:58:DC:4D:DD:CA + inet addr:10.129.37.205 Bcast:0.0.0.0 Mask:255.255.255.252 + inet6 addr: fe80::a058:dcff:fe4d:ddca/64 Scope:Link + UP BROADCAST RUNNING NOARP MULTICAST MTU:1500 Metric:1 + RX packets:0 errors:0 dropped:0 overruns:0 frame:0 + TX packets:8 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:0 + RX bytes:0 (0.0 B) TX bytes:720 (720.0 B) + +root@ZhuoTK:/# ip ro del 8.8.8.8/32 +RTNETLINK answers: No such process +root@ZhuoTK:/# ip ro add 8.8.8.8/32 dev wwan0.1 +root@ZhuoTK:/# ping 8.8.8.8 +PING 8.8.8.8 (8.8.8.8): 56 data bytes +64 bytes from 8.8.8.8: seq=0 ttl=52 time=98.584 ms + +root@ZhuoTK:/# ip ro del 8.8.8.8/32 +root@ZhuoTK:/# ip ro del 8.8.8.8/32 +RTNETLINK answers: No such process +root@ZhuoTK:/# ip ro add 8.8.8.8/32 dev wwan0.2 +root@ZhuoTK:/# ping 8.8.8.8 +PING 8.8.8.8 (8.8.8.8): 56 data bytes +64 bytes from 8.8.8.8: seq=0 ttl=111 time=101.770 ms \ No newline at end of file diff --git a/wwan/app/quectel-cm/src/log/ecm_ncm_rndis.txt b/wwan/app/quectel-cm/src/log/ecm_ncm_rndis.txt new file mode 100644 index 0000000..2ae7e6b --- /dev/null +++ b/wwan/app/quectel-cm/src/log/ecm_ncm_rndis.txt @@ -0,0 +1,129 @@ +# ./quectel-CM -s cmnet & +[04-21_17:35:14:362] Quectel_QConnectManager_Linux_V1.6.0.26 +[04-21_17:35:14:363] Find /sys/bus/usb/devices/2-4 idVendor=0x2c7c idProduct=0x8101, bus=0x002, dev=0x016 +[04-21_17:35:14:363] Auto find qmichannel = /dev/ttyUSB0 +[04-21_17:35:14:363] Auto find usbnet_adapter = usb0 +[04-21_17:35:14:363] netcard driver = cdc_ncm, driver version = 22-Aug-2005 +[04-21_17:35:14:363] Modem works in ECM_RNDIS_NCM mode +[04-21_17:35:14:371] atc_fd = 7 +[04-21_17:35:14:371] AT> ATE0Q0V1 +[04-21_17:35:14:372] AT< RDATE0Q0V1 +[04-21_17:35:14:372] AT< COMMAND NOT SUPPORT +[04-21_17:35:15:373] AT> AT+QCFG="usbnet" +[04-21_17:35:15:373] AT< +QCFG: "usbnet",5 +[04-21_17:35:15:373] AT< OK +[04-21_17:35:15:373] AT> AT+QNETDEVCTL=? +[04-21_17:35:15:374] AT< +QNETDEVCTL: (1-11),(0,1),(0,1) +[04-21_17:35:15:374] AT< OK +[04-21_17:35:15:374] AT> AT+CGREG=2 +[04-21_17:35:15:376] AT< OK +[04-21_17:35:15:376] AT> AT+CEREG=2 +[04-21_17:35:15:381] AT< OK +[04-21_17:35:15:381] AT> AT+C5GREG=2 +[04-21_17:35:15:384] AT< OK +[04-21_17:35:15:384] AT> AT+QNETDEVSTATUS=? +[04-21_17:35:15:385] AT< +QNETDEVSTATUS: (1-11) +[04-21_17:35:15:385] AT< OK +[04-21_17:35:15:385] AT> AT+QCFG="NAT" +[04-21_17:35:15:385] AT< +QCFG: "nat",0 +[04-21_17:35:15:385] AT< OK +[04-21_17:35:15:385] AT> AT+CGMR +[04-21_17:35:15:386] AT< RG801HEAAAR03A01M8G +[04-21_17:35:15:386] AT< OK +[04-21_17:35:15:386] AT> AT+CPIN? +[04-21_17:35:15:388] AT< +CPIN: READY +[04-21_17:35:15:388] AT< OK +[04-21_17:35:15:389] AT> AT+QCCID +[04-21_17:35:15:393] AT< +QCCID: 89860015120716380461 +[04-21_17:35:15:393] AT< OK +[04-21_17:35:15:393] requestGetICCID 89860015120716380461 +[04-21_17:35:15:393] AT> AT+CIMI +[04-21_17:35:15:409] AT< 460028563800461 +[04-21_17:35:15:409] AT< OK +[04-21_17:35:15:409] requestGetIMSI 460028563800461 +[04-21_17:35:15:409] AT> AT+QICSGP=1 +[04-21_17:35:15:411] AT< +QICSGP: 1,1,"cment","","",0,,0, +[04-21_17:35:15:411] AT< OK +[04-21_17:35:15:411] AT> AT+QICSGP=1 +[04-21_17:35:15:415] AT< +QICSGP: 1,1,"cment","","",0,,0, +[04-21_17:35:15:415] AT< OK +[04-21_17:35:15:415] AT> AT+COPS=3,0;+COPS?;+COPS=3,1;+COPS?;+COPS=3,2;+COPS? +[04-21_17:35:15:421] AT< +COPS: 0,0,"CHINA MOBILE",12 +[04-21_17:35:15:421] AT< +COPS: 0,1,"CMCC",12 +[04-21_17:35:15:421] AT< +COPS: 0,2,"46000",12 +[04-21_17:35:15:421] AT< OK +[04-21_17:35:15:421] AT> AT+C5GREG? +[04-21_17:35:15:424] AT< +C5GREG: 2,1,"46550B","0000000170C23000",11,1,"01" +[04-21_17:35:15:424] AT< OK +[04-21_17:35:15:424] AT> at+cops? +[04-21_17:35:15:427] AT< +COPS: 0,2,"46000",12 +[04-21_17:35:15:427] AT< OK +[04-21_17:35:15:427] AT> at+qeng="servingcell" +[04-21_17:35:15:441] AT< +QENG: "servingcell","NOCONN","NR5G-SA","TDD",460,00,170C23000,901,46550B,504990,41,-,-54,-10,16,-,- +[04-21_17:35:15:441] AT< OK +[04-21_17:35:15:441] AT> AT+QNETDEVSTATUS=1 +[04-21_17:35:15:445] AT< ERROR +[04-21_17:35:15:445] ifconfig usb0 0.0.0.0 +[04-21_17:35:15:446] ifconfig usb0 down +[04-21_17:35:15:448] AT> AT+QNETDEVCTL=1,1,0 +[04-21_17:35:15:454] AT< OK +[04-21_17:35:15:456] AT> AT+QNETDEVSTATUS=1 +[04-21_17:35:15:458] AT< ERROR +[04-21_17:35:15:989] AT< +QNETDEVSTATUS:1,1,"IPV4" +[04-21_17:35:16:459] AT> AT+QNETDEVSTATUS=1 +[04-21_17:35:16:461] AT< +QNETDEVSTATUS: 4F10190A,E0FFFFFF,4110190A,4110190A,02B48AD3,03B48AD3, 85600, 85600 +[04-21_17:35:16:461] AT< OK +[04-21_17:35:16:461] AT> AT+QNETDEVSTATUS=1 +[04-21_17:35:16:462] AT< +QNETDEVSTATUS: 4F10190A,E0FFFFFF,4110190A,4110190A,02B48AD3,03B48AD3, 85600, 85600 +[04-21_17:35:16:462] AT< OK +[04-21_17:35:16:462] requestGetIPAddress 10.25.16.79 +[04-21_17:35:16:462] AT> at+cops? +[04-21_17:35:16:463] AT< +COPS: 0,2,"46000",12 +[04-21_17:35:16:463] AT< OK +[04-21_17:35:16:463] AT> at+qeng="servingcell" +[04-21_17:35:16:465] AT< +QENG: "servingcell","CONNECT","NR5G-SA","TDD",460,00,170C23000,901,46550B,504990,41,-,-52,-11,15,-,- +[04-21_17:35:16:465] AT< OK +[04-21_17:35:16:465] AT> AT+QNETDEVSTATUS=1 +[04-21_17:35:16:466] AT< +QNETDEVSTATUS: 4F10190A,E0FFFFFF,4110190A,4110190A,02B48AD3,03B48AD3, 85600, 85600 +[04-21_17:35:16:466] AT< OK +[04-21_17:35:16:466] ifconfig usb0 up +[04-21_17:35:16:470] busybox udhcpc -f -n -q -t 5 -i usb0 +udhcpc: started, v1.30.1 +udhcpc: sending discover +udhcpc: sending select for 10.25.16.79 +udhcpc: lease of 10.25.16.79 obtained, lease time 518400 +[04-21_17:35:16:602] /etc/udhcpc/default.script: Resetting default routes +SIOCDELRT: No such process +SIOCADDRT: Network is unreachable +[04-21_17:35:16:606] /etc/udhcpc/default.script: Adding DNS 211.138.180.2 +[04-21_17:35:16:606] /etc/udhcpc/default.script: Adding DNS 211.138.180.3 +[04-21_17:35:16:655] AT> at+cops? +[04-21_17:35:16:656] AT< +COPS: 0,2,"46000",12 +[04-21_17:35:16:656] AT< OK +[04-21_17:35:16:656] AT> at+qeng="servingcell" +[04-21_17:35:16:657] AT< +QENG: "servingcell","CONNECT","NR5G-SA","TDD",460,00,170C23000,901,46550B,504990,41,-,-50,-11,17,-,- +[04-21_17:35:16:658] AT< OK +err = 16 +[04-21_17:35:16:658] AT> AT+QNETDEVSTATUS=1 +[04-21_17:35:16:659] AT< +QNETDEVSTATUS: 4F10190A,E0FFFFFF,4110190A,4110190A,02B48AD3,03B48AD3, 85600, 85600 +[04-21_17:35:16:659] AT< OK + +root@carl-ThinkPad-X1-Carbon-7th:/home/carl/q/quectel-CM# ifconfig usb0 +usb0: flags=4163 mtu 1500 + inet 10.25.16.79 netmask 255.255.255.224 broadcast 10.25.16.95 + inet6 fe80::5c98:e9d4:c82d:5f prefixlen 64 scopeid 0x20 + ether 0c:5b:8f:27:9a:64 txqueuelen 1000 (Ethernet) + RX packets 7 bytes 1656 (1.6 KB) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 32 bytes 5112 (5.1 KB) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + +root@carl-ThinkPad-X1-Carbon-7th:/home/carl/q/quectel-CM# [04-21_17:35:31:670] AT> at+cops? +[04-21_17:35:31:671] AT< +COPS: 0,2,"46000",12 +[04-21_17:35:31:671] AT< OK +[04-21_17:35:31:671] AT> at+qeng="servingcell" +[04-21_17:35:31:673] AT< +QENG: "servingcell","CONNECT","NR5G-SA","TDD",460,00,170C23000,901,46550B,504990,41,-,-48,-10,17,-,- +[04-21_17:35:31:673] AT< OK +[04-21_17:35:31:673] AT> AT+QNETDEVSTATUS=1 +[04-21_17:35:31:674] AT< +QNETDEVSTATUS: 4F10190A,E0FFFFFF,4110190A,4110190A,02B48AD3,03B48AD3, 85600, 85600 +[04-21_17:35:31:674] AT< OK diff --git a/wwan/app/quectel-cm/src/log/gobinet.txt b/wwan/app/quectel-cm/src/log/gobinet.txt new file mode 100644 index 0000000..2b286de --- /dev/null +++ b/wwan/app/quectel-cm/src/log/gobinet.txt @@ -0,0 +1,62 @@ +root@ZhuoTK:/# dmesg +[ 230.590000] GobiNet 1-1.3:1.4 usb0: register 'GobiNet' at usb-101c0000.ehci-1.3, GobiNet Ethernet Device, 02:50:f4:00:00:00 +[ 230.600000] creating qcqmi0 + +root@ZhuoTK:/# quectel-CM -s cmnet & +[04-13_03:24:58:213] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-13_03:24:58:216] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x004 +[04-13_03:24:58:218] Auto find qmichannel = /dev/qcqmi0 +[04-13_03:24:58:218] Auto find usbnet_adapter = usb0 +[04-13_03:24:58:218] netcard driver = GobiNet, driver version = V1.6.2.13 +[04-13_03:24:58:219] Modem works in QMI mode +[04-13_03:24:58:260] Get clientWDS = 7 +[04-13_03:24:58:292] Get clientDMS = 8 +[04-13_03:24:58:324] Get clientNAS = 9 +[04-13_03:24:58:355] Get clientUIM = 10 +[04-13_03:24:58:388] Get clientWDA = 11 +[04-13_03:24:58:420] requestBaseBandVersion EC25EFAR06A11M4G +[04-13_03:24:58:548] requestGetSIMStatus SIMStatus: SIM_READY +[04-13_03:24:58:549] requestSetProfile[1] cmnet///0 +[04-13_03:24:58:613] requestGetProfile[1] cmnet///0 +[04-13_03:24:58:645] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE +[04-13_03:24:58:677] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED +[04-13_03:24:58:677] ifconfig usb0 0.0.0.0 +[04-13_03:24:58:696] ifconfig usb0 down +[04-13_03:24:59:028] requestSetupDataCall WdsConnectionIPv4Handle: 0x87245bd0 +[04-13_03:24:59:189] ifconfig usb0 up +[04-13_03:24:59:214] you are use OpenWrt? +[04-13_03:24:59:215] should not calling udhcpc manually? +[04-13_03:24:59:215] should modify /etc/config/network as below? +[04-13_03:24:59:215] config interface wan +[04-13_03:24:59:215] option ifname usb0 +[04-13_03:24:59:215] option proto dhcp +[04-13_03:24:59:215] should use "/sbin/ifstaus wan" to check usb0 's status? +[04-13_03:24:59:216] busybox udhcpc -f -n -q -t 5 -i usb0 +[04-13_03:24:59:226] udhcpc (v1.23.2) started +[04-13_03:24:59:238] Sending discover... +[04-13_03:24:59:248] Sending select for 10.198.78.154... +[04-13_03:24:59:251] Lease of 10.198.78.154 obtained, lease time 7200 +[04-13_03:24:59:257] udhcpc: ifconfig usb0 10.198.78.154 netmask 255.255.255.252 broadcast + +[04-13_03:24:59:266] udhcpc: setting default routers: 10.198.78.153 + +root@ZhuoTK:/# ifconfig usb0 +usb0 Link encap:Ethernet HWaddr 02:50:F4:00:00:00 + inet addr:10.198.78.154 Mask:255.255.255.252 + inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link + UP RUNNING NOARP MTU:1500 Metric:1 + RX packets:6 errors:0 dropped:0 overruns:0 frame:0 + TX packets:6 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:916 (916.0 B) TX bytes:960 (960.0 B) + +root@ZhuoTK:/# ip ro show +default via 10.198.78.153 dev usb0 +10.198.78.152/30 dev usb0 proto kernel scope link src 10.198.78.154 +192.168.1.0/24 dev br-lan proto kernel scope link src 192.168.1.251 + +root@ZhuoTK:/# killall quectel-CM +[04-13_03:25:38:779] requestDeactivateDefaultPDP WdsConnectionIPv4Handle +[04-13_03:25:39:061] ifconfig usb0 0.0.0.0 +[04-13_03:25:39:072] ifconfig usb0 down +[04-13_03:25:39:284] GobiNetThread exit +[04-13_03:25:39:285] qmi_main exit diff --git a/wwan/app/quectel-cm/src/log/gobinet_bridge.txt b/wwan/app/quectel-cm/src/log/gobinet_bridge.txt new file mode 100644 index 0000000..7ed229e --- /dev/null +++ b/wwan/app/quectel-cm/src/log/gobinet_bridge.txt @@ -0,0 +1,60 @@ +root@ZhuoTK:/# insmod GobiNet.ko +[ 80.460000] GobiNet: Quectel_Linux&Android_GobiNet_Driver_V1.6.2.13 +[ 80.460000] usbcore: registered new interface driver GobiNet +[ 97.710000] usb 1-1.3: new high-speed USB device number 3 using ehci-platform +[ 97.930000] usb 1-1.3: GSM modem (1-port) converter now attached to ttyUSB103 +[ 97.950000] GobiNet 1-1.3:1.4 usb0: register 'GobiNet' at usb-101c0000.ehci-1.3, GobiNet Ethernet Device, 02:50:f4:00:00:00 +[ 97.960000] creating qcqmi0 + +root@ZhuoTK:/# brctl addbr br0 +root@ZhuoTK:/# brctl addif br0 eth0.1 +root@ZhuoTK:/# brctl addif br0 usb0 +root@ZhuoTK:/# brctl show +bridge name bridge id STP enabled interfaces +br0 8000.00ca019197b9 no eth0.1 + usb0 + +root@ZhuoTK:/# quectel-CM -s cment -b & +[04-13_05:13:18:213] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-13_05:13:18:216] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x003 +[ 122.270000] net usb0: bridge_mode change to 0x1 +[04-13_05:13:18:218] Auto find qmichannel = /dev/qcqmi0 +[04-13_05:13:18:218] Auto find usbnet_adapter = usb0 +[04-13_05:13:18:218] netcard driver = GobiNet, driver version = V1.6.2.13 +[04-13_05:13:18:224] Modem works in QMI mode +[04-13_05:13:18:251] Get clientWDS = 7 +[04-13_05:13:18:282] Get clientDMS = 8 +[04-13_05:13:18:316] Get clientNAS = 9 +[04-13_05:13:18:347] Get clientUIM = 10 +[04-13_05:13:18:379] Get clientWDA = 11 +[04-13_05:13:18:411] requestBaseBandVersion EC25EFAR06A11M4G +[04-13_05:13:18:539] requestGetSIMStatus SIMStatus: SIM_READY +[04-13_05:13:18:540] requestSetProfile[1] cment///0 +[04-13_05:13:18:603] requestGetProfile[1] cment///0 +[04-13_05:13:18:637] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE +[04-13_05:13:18:666] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED +[04-13_05:13:18:667] ifconfig usb0 0.0.0.0 +[04-13_05:13:18:687] ifconfig usb0 down +[04-13_05:13:19:083] requestSetupDataCall WdsConnectionIPv4Handle: 0x8724d220 +[04-13_05:13:19:243] ifconfig usb0 up +[04-13_05:13:19:270] echo '0xa218480' > /sys/class/net/usb0/bridge_ipv4 + +root@ZhuoTK:/# ifconfig br0 up +[ 135.530000] usb0 PC Mac Address: 00:0e:c6:a6:6c:f1 +[ 135.570000] usb0 PC Mac Address: 00:0e:c6:a6:6c:f1 +[ 135.580000] usb0 PC Mac Address: 00:0e:c6:a6:6c:f1 +[ 135.610000] usb0 sip = 10.33.132.128, tip=10.33.132.129, ipv4=10.33.132.128 +[ 135.620000] usb0 sip = 10.33.132.128, tip=10.33.132.129, ipv4=10.33.132.128 +[ 135.910000] usb0 sip = 0.0.0.0, tip=10.33.132.128, ipv4=10.33.132.128 +[ 136.000000] usb0 sip = 10.33.132.128, tip=10.33.132.129, ipv4=10.33.132.128 +[ 136.910000] usb0 sip = 0.0.0.0, tip=10.33.132.128, ipv4=10.33.132.128 +[ 137.910000] usb0 sip = 0.0.0.0, tip=10.33.132.128, ipv4=10.33.132.128 +[ 138.740000] usb0 sip = 10.33.132.128, tip=10.33.132.129, ipv4=10.33.132.128 +[ 138.910000] usb0 sip = 10.33.132.128, tip=10.33.132.128, ipv4=10.33.132.128 +[ 139.000000] usb0 sip = 10.33.132.128, tip=10.33.132.129, ipv4=10.33.132.128 +[ 140.860000] usb0 sip = 10.33.132.128, tip=10.33.132.129, ipv4=10.33.132.128 +[ 143.160000] br0: port 2(usb0) entered forwarding state +[ 143.160000] br0: port 1(eth0.1) entered forwarding state +[ 148.870000] usb0 sip = 10.33.132.128, tip=10.33.132.129, ipv4=10.33.132.128 +[ 149.010000] usb0 sip = 10.33.132.128, tip=10.33.132.129, ipv4=10.33.132.128 +[ 165.630000] usb0 sip = 10.33.132.128, tip=10.33.132.129, ipv4=10.33.132.128 diff --git a/wwan/app/quectel-cm/src/log/gobinet_qmap=1.txt b/wwan/app/quectel-cm/src/log/gobinet_qmap=1.txt new file mode 100644 index 0000000..83cedd9 --- /dev/null +++ b/wwan/app/quectel-cm/src/log/gobinet_qmap=1.txt @@ -0,0 +1,45 @@ +root@ZhuoTK:/# insmod GobiNet.ko qmap_mode=1 +[ 798.480000] GobiNet: Quectel_Linux&Android_GobiNet_Driver_V1.6.2.13 +[ 798.490000] GobiNet 1-1.3:1.4 usb0: register 'GobiNet' at usb-101c0000.ehci-1.3, GobiNet Ethernet Device, 02:50:f4:00:00:00 +[ 798.510000] creating qcqmi0 +[ 798.510000] usbcore: registered new interface driver GobiNet +[ 799.620000] GobiNet::QMIWDASetDataFormat qmap settings qmap_version=5, rx_size=4096, tx_size=4096 +[ 799.630000] GobiNet::QMIWDASetDataFormat qmap settings ul_data_aggregation_max_size=4096, ul_data_aggregation_max_datagrams=16 + +root@ZhuoTK:/# quectel-CM -s cmnet & +[04-13_03:32:31:248] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-13_03:32:31:251] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x005 +[04-13_03:32:31:253] Auto find qmichannel = /dev/qcqmi0 +[04-13_03:32:31:253] Auto find usbnet_adapter = usb0 +[04-13_03:32:31:253] netcard driver = GobiNet, driver version = V1.6.2.13 +[04-13_03:32:31:253] qmap_mode = 1, qmap_version = 5, qmap_size = 4096, muxid = 0x81, qmap_netcard = usb0 +[04-13_03:32:31:254] Modem works in QMI mode +[04-13_03:32:31:289] Get clientWDS = 7 +[04-13_03:32:31:320] Get clientDMS = 8 +[04-13_03:32:31:353] Get clientNAS = 9 +[04-13_03:32:31:385] Get clientUIM = 10 +[04-13_03:32:31:417] requestBaseBandVersion EC25EFAR06A11M4G +[04-13_03:32:31:545] requestGetSIMStatus SIMStatus: SIM_READY +[04-13_03:32:31:545] requestSetProfile[1] cmnet///0 +[04-13_03:32:31:609] requestGetProfile[1] cmnet///0 +[04-13_03:32:31:641] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE +[04-13_03:32:31:673] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED +[04-13_03:32:31:674] ifconfig usb0 0.0.0.0 +[04-13_03:32:31:698] ifconfig usb0 down +[04-13_03:32:31:770] requestSetupDataCall WdsConnectionIPv4Handle: 0x872481a0 +[ 857.000000] net usb0: link_state 0x0 -> 0x1 +[04-13_03:32:31:902] ifconfig usb0 up +[04-13_03:32:31:928] you are use OpenWrt? +[04-13_03:32:31:928] should not calling udhcpc manually? +[04-13_03:32:31:928] should modify /etc/config/network as below? +[04-13_03:32:31:928] config interface wan +[04-13_03:32:31:928] option ifname usb0 +[04-13_03:32:31:929] option proto dhcp +[04-13_03:32:31:929] should use "/sbin/ifstaus wan" to check usb0 's status? +[04-13_03:32:31:929] busybox udhcpc -f -n -q -t 5 -i usb0 +[04-13_03:32:31:939] udhcpc (v1.23.2) started +[04-13_03:32:31:951] Sending discover... +[04-13_03:32:31:956] Sending select for 10.199.102.71... +[04-13_03:32:31:959] Lease of 10.199.102.71 obtained, lease time 7200 +[04-13_03:32:31:964] udhcpc: ifconfig usb0 10.199.102.71 netmask 255.255.255.240 broadcast + +[04-13_03:32:31:974] udhcpc: setting default routers: 10.199.102.72 diff --git a/wwan/app/quectel-cm/src/log/gobinet_qmap=1_bridge.txt b/wwan/app/quectel-cm/src/log/gobinet_qmap=1_bridge.txt new file mode 100644 index 0000000..64a8374 --- /dev/null +++ b/wwan/app/quectel-cm/src/log/gobinet_qmap=1_bridge.txt @@ -0,0 +1,62 @@ +root@ZhuoTK:/# insmod GobiNet.ko qmap_mode=1 +[ 41.540000] GobiNet: Quectel_Linux&Android_GobiNet_Driver_V1.6.2.13 +[ 41.550000] GobiNet 1-1.3:1.4 usb0: register 'GobiNet' at usb-101c0000.ehci-1.3, GobiNet Ethernet Device, 02:50:f4:00:00:00 +[ 41.570000] creating qcqmi0 +[ 41.570000] usbcore: registered new interface driver GobiNet +[ 42.700000] GobiNet::QMIWDASetDataFormat qmap settings qmap_version=5, rx_size=4096, tx_size=4096 +[ 42.710000] GobiNet::QMIWDASetDataFormat qmap settings ul_data_aggregation_max_size=4096, ul_data_aggregation_max_datagrams=16 + +root@ZhuoTK:/# brctl addbr br0 +root@ZhuoTK:/# brctl addif br0 eth0.1 +root@ZhuoTK:/# brctl addif br0 usb0 +root@ZhuoTK:/# brctl show +bridge name bridge id STP enabled interfaces +br0 8000.00ca019197b9 no eth0.1 + usb0 + +root@ZhuoTK:/# quectel-CM -s cmnet -b & +# [04-13_05:12:29:338] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-13_05:12:29:340] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x003 +[ 73.380000] net usb0: bridge_mode change to 0x1 +[04-13_05:12:29:342] Auto find qmichannel = /dev/qcqmi0 +[04-13_05:12:29:342] Auto find usbnet_adapter = usb0 +[04-13_05:12:29:342] netcard driver = GobiNet, driver version = V1.6.2.13 +[04-13_05:12:29:343] qmap_mode = 1, qmap_version = 5, qmap_size = 4096, muxid = 0x81, qmap_netcard = usb0 +[04-13_05:12:29:348] Modem works in QMI mode +[04-13_05:12:29:382] Get clientWDS = 7 +[04-13_05:12:29:414] Get clientDMS = 8 +[04-13_05:12:29:447] Get clientNAS = 9 +[04-13_05:12:29:479] Get clientUIM = 10 +[04-13_05:12:29:512] requestBaseBandVersion EC25EFAR06A11M4G +[04-13_05:12:29:640] requestGetSIMStatus SIMStatus: SIM_READY +[04-13_05:12:29:640] requestSetProfile[1] cmnet///0 +[04-13_05:12:29:704] requestGetProfile[1] cmnet///0 +[04-13_05:12:29:735] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE +[04-13_05:12:29:767] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED +[04-13_05:12:29:768] ifconfig usb0 0.0.0.0 +[04-13_05:12:29:792] ifconfig usb0 down +[04-13_05:12:29:863] requestSetupDataCall WdsConnectionIPv4Handle: 0x8724d820 +[ 74.030000] net usb0: link_state 0x0 -> 0x1 +[04-13_05:12:29:996] ifconfig usb0 up +[04-13_05:12:30:022] echo '0xa16b769' > /sys/class/net/usb0/bridge_ipv4 + +root@ZhuoTK:/# ifconfig br0 up +[ 82.210000] br0: port 2(usb0) entered forwarding state +[ 82.210000] br0: port 2(usb0) entered forwarding state +[ 82.220000] br0: port 1(eth0.1) entered forwarding state +[ 82.220000] br0: port 1(eth0.1) entered forwarding state +[ 88.830000] rt305x-esw 10110000.esw: link changed 0x01 +[ 89.010000] usb0 PC Mac Address: 00:0e:c6:a6:6c:f1 +[ 89.040000] usb0 PC Mac Address: 00:0e:c6:a6:6c:f1 +[ 89.050000] usb0 PC Mac Address: 00:0e:c6:a6:6c:f1 +[ 89.120000] usb0 sip = 10.22.183.105, tip=10.22.183.106, ipv4=10.22.183.105 +[ 89.350000] usb0 sip = 0.0.0.0, tip=10.22.183.105, ipv4=10.22.183.105 +[ 89.400000] usb0 sip = 10.22.183.105, tip=10.22.183.106, ipv4=10.22.183.105 +[ 89.520000] usb0 sip = 10.22.183.105, tip=10.22.183.106, ipv4=10.22.183.105 +[ 90.350000] usb0 sip = 0.0.0.0, tip=10.22.183.105, ipv4=10.22.183.105 +[ 91.350000] usb0 sip = 0.0.0.0, tip=10.22.183.105, ipv4=10.22.183.105 +[ 92.350000] usb0 sip = 10.22.183.105, tip=10.22.183.105, ipv4=10.22.183.105 +[ 92.430000] usb0 sip = 10.22.183.105, tip=10.22.183.106, ipv4=10.22.183.105 +[ 92.660000] usb0 sip = 10.22.183.105, tip=10.22.183.106, ipv4=10.22.183.105 +[ 97.240000] br0: port 2(usb0) entered forwarding state +[ 97.240000] br0: port 1(eth0.1) entered forwarding state diff --git a/wwan/app/quectel-cm/src/log/gobinet_qmap=4.txt b/wwan/app/quectel-cm/src/log/gobinet_qmap=4.txt new file mode 100644 index 0000000..5ec02bf --- /dev/null +++ b/wwan/app/quectel-cm/src/log/gobinet_qmap=4.txt @@ -0,0 +1,146 @@ +root@ZhuoTK:/# insmod GobiNet.ko qmap_mode=4 +[ 970.380000] GobiNet: Quectel_Linux&Android_GobiNet_Driver_V1.6.2.13 +[ 970.380000] usbcore: registered new interface driver GobiNet +[ 989.620000] usb 1-1.3: new high-speed USB device number 6 using ehci-platform +[ 989.860000] GobiNet 1-1.3:1.4 usb0: register 'GobiNet' at usb-101c0000.ehci-1.3, GobiNet Ethernet Device, 02:50:f4:00:00:00 +[ 989.870000] creating qcqmi0 +[ 989.880000] GobiNet::qmap_register_device usb0.1 +[ 989.880000] GobiNet::qmap_register_device usb0.2 +[ 989.890000] GobiNet::qmap_register_device usb0.3 +[ 989.890000] GobiNet::qmap_register_device usb0.4 +[ 994.820000] GobiNet::QMIWDASetDataFormat qmap settings qmap_version=5, rx_size=4096, tx_size=4096 +[ 994.830000] GobiNet::QMIWDASetDataFormat qmap settings ul_data_aggregation_max_size=4096, ul_data_aggregation_max_datagrams=16 + +root@ZhuoTK:/# quectel-CM -n 1 -s cmnet & +[04-13_03:35:31:878] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-13_03:35:31:881] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x006 +[04-13_03:35:31:882] Auto find qmichannel = /dev/qcqmi0 +[04-13_03:35:31:882] Auto find usbnet_adapter = usb0 +[04-13_03:35:31:883] netcard driver = GobiNet, driver version = V1.6.2.13 +[04-13_03:35:31:883] qmap_mode = 4, qmap_version = 5, qmap_size = 4096, muxid = 0x81, qmap_netcard = usb0.1 +[04-13_03:35:31:883] Modem works in QMI mode +[04-13_03:35:31:896] Get clientWDS = 7 +[04-13_03:35:31:927] Get clientDMS = 8 +[04-13_03:35:31:959] Get clientNAS = 9 +[04-13_03:35:31:992] Get clientUIM = 10 +[04-13_03:35:32:024] requestBaseBandVersion EC25EFAR06A11M4G +[04-13_03:35:32:152] requestGetSIMStatus SIMStatus: SIM_READY +[04-13_03:35:32:152] requestSetProfile[1] cmnet///0 +[04-13_03:35:32:216] requestGetProfile[1] cmnet///0 +[04-13_03:35:32:248] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE +[04-13_03:35:32:279] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED +[04-13_03:35:32:280] ifconfig usb0 down +[04-13_03:35:32:290] ifconfig usb0.1 0.0.0.0 +[04-13_03:35:32:301] ifconfig usb0.1 down +[04-13_03:35:32:344] requestSetupDataCall WdsConnectionIPv4Handle: 0x8723eef0 +[ 1037.570000] net usb0: link_state 0x0 -> 0x1 +[04-13_03:35:32:477] ifconfig usb0 up +[04-13_03:35:32:496] ifconfig usb0.1 up +[04-13_03:35:32:508] you are use OpenWrt? +[04-13_03:35:32:509] should not calling udhcpc manually? +[04-13_03:35:32:509] should modify /etc/config/network as below? +[04-13_03:35:32:509] config interface wan +[04-13_03:35:32:509] option ifname usb0.1 +[04-13_03:35:32:509] option proto dhcp +[04-13_03:35:32:509] should use "/sbin/ifstaus wan" to check usb0.1 's status? +[04-13_03:35:32:510] busybox udhcpc -f -n -q -t 5 -i usb0.1 +[04-13_03:35:32:520] udhcpc (v1.23.2) started +[04-13_03:35:32:532] Sending discover... +[04-13_03:35:32:540] Sending select for 10.187.142.20... +[04-13_03:35:32:545] Lease of 10.187.142.20 obtained, lease time 7200 +[04-13_03:35:32:550] udhcpc: ifconfig usb0.1 10.187.142.20 netmask 255.255.255.248 broadcast + +[04-13_03:35:32:560] udhcpc: setting default routers: 10.187.142.21 + +root@ZhuoTK:/# quectel-CM -n 2 -s 4gnet & +[04-13_03:35:38:766] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-13_03:35:38:769] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x006 +[04-13_03:35:38:770] Auto find qmichannel = /dev/qcqmi0 +[04-13_03:35:38:770] Auto find usbnet_adapter = usb0 +[04-13_03:35:38:771] netcard driver = GobiNet, driver version = V1.6.2.13 +[04-13_03:35:38:771] qmap_mode = 4, qmap_version = 5, qmap_size = 4096, muxid = 0x82, qmap_netcard = usb0.2 +[04-13_03:35:38:771] Modem works in QMI mode +[04-13_03:35:38:809] Get clientWDS = 7 +[04-13_03:35:38:841] Get clientDMS = 8 +[04-13_03:35:38:873] Get clientNAS = 9 +[04-13_03:35:38:905] Get clientUIM = 10 +[04-13_03:35:38:937] requestBaseBandVersion EC25EFAR06A11M4G +[04-13_03:35:39:065] requestGetSIMStatus SIMStatus: SIM_READY +[04-13_03:35:39:065] requestSetProfile[2] 4gnet///0 +[04-13_03:35:39:129] requestGetProfile[2] 4gnet///0 +[04-13_03:35:39:161] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE +[04-13_03:35:39:193] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED +[04-13_03:35:39:193] ifconfig usb0.2 0.0.0.0 +[04-13_03:35:39:206] ifconfig usb0.2 down +[04-13_03:35:39:417] requestSetupDataCall WdsConnectionIPv4Handle: 0x87252eb0 +[ 1044.650000] net usb0: link_state 0x1 -> 0x3 +[04-13_03:35:39:550] ifconfig usb0 up +[04-13_03:35:39:560] ifconfig usb0.2 up +[04-13_03:35:39:573] you are use OpenWrt? +[04-13_03:35:39:573] should not calling udhcpc manually? +[04-13_03:35:39:573] should modify /etc/config/network as below? +[04-13_03:35:39:573] config interface wan +[04-13_03:35:39:573] option ifname usb0.2 +[04-13_03:35:39:573] option proto dhcp +[04-13_03:35:39:573] should use "/sbin/ifstaus wan" to check usb0.2 's status? +[04-13_03:35:39:574] busybox udhcpc -f -n -q -t 5 -i usb0.2 +[04-13_03:35:39:585] udhcpc (v1.23.2) started +[04-13_03:35:39:597] Sending discover... +[04-13_03:35:39:601] Sending select for 10.197.125.183... +[04-13_03:35:39:606] Lease of 10.197.125.183 obtained, lease time 7200 +[04-13_03:35:39:611] udhcpc: ifconfig usb0.2 10.197.125.183 netmask 255.255.255.240 broadcast + +[04-13_03:35:39:621] udhcpc: setting default routers: 10.197.125.184 + +root@ZhuoTK:/# ifconfig usb0.1 +usb0.1 Link encap:Ethernet HWaddr 02:50:F4:00:00:00 + inet addr:10.187.142.20 Mask:255.255.255.248 + inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link + UP RUNNING NOARP MTU:1500 Metric:1 + RX packets:4 errors:0 dropped:0 overruns:0 frame:0 + TX packets:10 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:764 (764.0 B) TX bytes:1824 (1.7 KiB) + +root@ZhuoTK:/# ifconfig usb0.2 +usb0.2 Link encap:Ethernet HWaddr 02:50:F4:00:00:00 + inet addr:10.197.125.183 Mask:255.255.255.240 + inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link + UP RUNNING NOARP MTU:1500 Metric:1 + RX packets:3 errors:0 dropped:0 overruns:0 frame:0 + TX packets:9 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:688 (688.0 B) TX bytes:1224 (1.1 KiB) + +root@ZhuoTK:/# ip ro add 8.8.8.8/32 dev usb0.1 +root@ZhuoTK:/# ping 8.8.8.8 +PING 8.8.8.8 (8.8.8.8): 56 data bytes +64 bytes from 8.8.8.8: seq=0 ttl=52 time=74.450 ms + +root@ZhuoTK:/# ip ro del 8.8.8.8/32 +root@ZhuoTK:/# ip ro del 8.8.8.8/32 +RTNETLINK answers: No such process + +root@ZhuoTK:/# ip ro add 8.8.8.8/32 dev usb0.2 +root@ZhuoTK:/# ping 8.8.8.8 +PING 8.8.8.8 (8.8.8.8): 56 data bytes +64 bytes from 8.8.8.8: seq=0 ttl=52 time=257.851 ms + +root@ZhuoTK:/# quectel-CM -k 2 +[04-13_03:39:16:986] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-13_03:39:16:988] /proc/2294/cmdline: quectel-CM -n 2 -s 4gnet +[04-13_03:39:16:988] send SIGINT to process 2294 +[04-13_03:39:16:989] requestDeactivateDefaultPDP WdsConnectionIPv4Handle +[ 1262.310000] net usb0: link_state 0x3 -> 0x1 +[04-13_03:39:17:216] ifconfig usb0.2 0.0.0.0 +[04-13_03:39:17:228] ifconfig usb0.2 down +[04-13_03:39:17:370] GobiNetThread exit +[04-13_03:39:17:371] qmi_main exit + +[2]+ Done quectel-CM -n 2 -s 4gnet + +root@ZhuoTK:/# ifconfig usb0.2 +usb0.2 Link encap:Ethernet HWaddr 02:50:F4:00:00:00 + NOARP MTU:1500 Metric:1 + RX packets:30 errors:0 dropped:0 overruns:0 frame:0 + TX packets:35 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:2816 (2.7 KiB) TX bytes:3408 (3.3 KiB) diff --git a/wwan/app/quectel-cm/src/log/gobinet_qmap=4_bridge.txt b/wwan/app/quectel-cm/src/log/gobinet_qmap=4_bridge.txt new file mode 100644 index 0000000..ebfd4fb --- /dev/null +++ b/wwan/app/quectel-cm/src/log/gobinet_qmap=4_bridge.txt @@ -0,0 +1,114 @@ +root@ZhuoTK:/# insmod GobiNet.ko qmap_mode=4 +[ 42.120000] GobiNet: Quectel_Linux&Android_GobiNet_Driver_V1.6.2.13 +[ 42.130000] GobiNet 1-1.3:1.4 usb0: register 'GobiNet' at usb-101c0000.ehci-1.3, GobiNet Ethernet Device, 02:50:f4:00:00:00 +[ 42.140000] creating qcqmi0 +[ 42.150000] GobiNet::qmap_register_device usb0.1 +[ 42.150000] GobiNet::qmap_register_device usb0.2 +[ 42.160000] GobiNet::qmap_register_device usb0.3 +[ 42.160000] GobiNet::qmap_register_device usb0.4 +[ 42.170000] usbcore: registered new interface driver GobiNet +[ 43.270000] GobiNet::QMIWDASetDataFormat qmap settings qmap_version=5, rx_size=4096, tx_size=4096 +[ 43.280000] GobiNet::QMIWDASetDataFormat qmap settings ul_data_aggregation_max_size=4096, ul_data_aggregation_max_datagrams=16 + +root@ZhuoTK:/# brctl addbr br0 +root@ZhuoTK:/# brctl addif br0 eth0.1 +root@ZhuoTK:/# brctl addif br0 usb0.1 +root@ZhuoTK:/# brctl show +bridge name bridge id STP enabled interfaces +br0 8000.00ca019197b9 no eth0.1 + usb0.1 + +root@ZhuoTK:/# quectel-CM -n 1 -s cmnet -b & +[04-13_05:12:42:155] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-13_05:12:42:158] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x003 +[ 86.130000] net usb0.1: bridge_mode change to 0x1 +[04-13_05:12:42:159] Auto find qmichannel = /dev/qcqmi0 +[04-13_05:12:42:160] Auto find usbnet_adapter = usb0 +[04-13_05:12:42:160] netcard driver = GobiNet, driver version = V1.6.2.13 +[04-13_05:12:42:160] qmap_mode = 4, qmap_version = 5, qmap_size = 4096, muxid = 0x81, qmap_netcard = usb0.1 +[04-13_05:12:42:166] Modem works in QMI mode +[04-13_05:12:42:181] Get clientWDS = 7 +[04-13_05:12:42:213] Get clientDMS = 8 +[04-13_05:12:42:246] Get clientNAS = 9 +[04-13_05:12:42:278] Get clientUIM = 10 +[04-13_05:12:42:310] requestBaseBandVersion EC25EFAR06A11M4G +[04-13_05:12:42:438] requestGetSIMStatus SIMStatus: SIM_READY +[04-13_05:12:42:439] requestSetProfile[1] cmnet///0 +[04-13_05:12:42:502] requestGetProfile[1] cmnet///0 +[04-13_05:12:42:534] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE +[04-13_05:12:42:565] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED +[04-13_05:12:42:566] ifconfig usb0 down +[04-13_05:12:42:576] ifconfig usb0.1 0.0.0.0 +[04-13_05:12:42:587] ifconfig usb0.1 down +[04-13_05:12:42:629] requestSetupDataCall WdsConnectionIPv4Handle: 0x8724d740 +[ 86.730000] net usb0: link_state 0x0 -> 0x1 +[04-13_05:12:42:762] ifconfig usb0 up +[04-13_05:12:42:782] ifconfig usb0.1 up +[04-13_05:12:42:794] echo '0xa16b769' > /sys/class/net/usb0.1/bridge_ipv4 + +root@ZhuoTK:/# ifconfig br0 up +[ 98.270000] usb0.1 PC Mac Address: 00:0e:c6:a6:6c:f1 +[ 98.360000] usb0.1 sip = 0.0.0.0, tip=10.22.183.105, ipv4=10.22.183.105 +[ 98.370000] usb0.1 sip = 10.22.183.105, tip=10.22.183.106, ipv4=10.22.183.105 +[ 99.360000] usb0.1 sip = 0.0.0.0, tip=10.22.183.105, ipv4=10.22.183.105 +[ 100.360000] usb0.1 sip = 0.0.0.0, tip=10.22.183.105, ipv4=10.22.183.105 +[ 100.500000] usb0.1 sip = 10.22.183.105, tip=10.22.183.106, ipv4=10.22.183.105 + +root@ZhuoTK:/# quectel-CM -n 2 -s 4gnet & +[04-13_05:13:05:715] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-13_05:13:05:717] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x003 +[04-13_05:13:05:719] Auto find qmichannel = /dev/qcqmi0 +[04-13_05:13:05:719] Auto find usbnet_adapter = usb0 +[04-13_05:13:05:719] netcard driver = GobiNet, driver version = V1.6.2.13 +[04-13_05:13:05:719] qmap_mode = 4, qmap_version = 5, qmap_size = 4096, muxid = 0x82, qmap_netcard = usb0.2 +[04-13_05:13:05:720] Modem works in QMI mode +[04-13_05:13:05:734] Get clientWDS = 7 +[04-13_05:13:05:766] Get clientDMS = 8 +[04-13_05:13:05:798] Get clientNAS = 9 +[04-13_05:13:05:830] Get clientUIM = 10 +[04-13_05:13:05:861] requestBaseBandVersion EC25EFAR06A11M4G +[04-13_05:13:05:990] requestGetSIMStatus SIMStatus: SIM_READY +[04-13_05:13:05:991] requestSetProfile[2] 4gnet///0 +[04-13_05:13:06:054] requestGetProfile[2] 4gnet///0 +[04-13_05:13:06:086] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE +[04-13_05:13:06:118] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED +[04-13_05:13:06:119] ifconfig usb0.2 0.0.0.0 +[04-13_05:13:06:131] ifconfig usb0.2 down +[04-13_05:13:06:375] requestSetupDataCall WdsConnectionIPv4Handle: 0x872b8c50 +[ 110.470000] net usb0: link_state 0x1 -> 0x3 +[04-13_05:13:06:507] ifconfig usb0 up +[04-13_05:13:06:518] ifconfig usb0.2 up +[04-13_05:13:06:539] you are use OpenWrt? +[04-13_05:13:06:540] should not calling udhcpc manually? +[04-13_05:13:06:540] should modify /etc/config/network as below? +[04-13_05:13:06:540] config interface wan +[04-13_05:13:06:540] option ifname usb0.2 +[04-13_05:13:06:540] option proto dhcp +[04-13_05:13:06:540] should use "/sbin/ifstaus wan" to check usb0.2 's status? +[04-13_05:13:06:540] busybox udhcpc -f -n -q -t 5 -i usb0.2 +[04-13_05:13:06:554] udhcpc (v1.23.2) started +[04-13_05:13:06:614] Sending discover... +[04-13_05:13:06:619] Sending select for 10.22.58.141... +[04-13_05:13:06:623] Lease of 10.22.58.141 obtained, lease time 7200 +[04-13_05:13:06:629] udhcpc: ifconfig usb0.2 10.22.58.141 netmask 255.255.255.252 broadcast + +[04-13_05:13:06:638] udhcpc: setting default routers: 10.22.58.142 + +root@ZhuoTK:/# ifconfig usb0.2 +usb0.2 Link encap:Ethernet HWaddr 02:50:F4:00:00:00 + inet addr:10.22.58.141 Mask:255.255.255.252 + inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link + UP RUNNING NOARP MTU:1500 Metric:1 + RX packets:2 errors:0 dropped:0 overruns:0 frame:0 + TX packets:7 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:612 (612.0 B) TX bytes:1064 (1.0 KiB) + +root@ZhuoTK:/# ip ro show +default via 10.22.58.142 dev usb0.2 +10.22.58.140/30 dev usb0.2 proto kernel scope link src 10.22.58.141 +192.168.1.0/24 dev br-lan proto kernel scope link src 192.168.1.251 + +root@ZhuoTK:/# ping 8.8.8.8 +PING 8.8.8.8 (8.8.8.8): 56 data bytes +64 bytes from 8.8.8.8: seq=0 ttl=52 time=69.822 ms + diff --git a/wwan/app/quectel-cm/src/log/pcie_mhi_mbim.txt b/wwan/app/quectel-cm/src/log/pcie_mhi_mbim.txt new file mode 100644 index 0000000..7a988a9 --- /dev/null +++ b/wwan/app/quectel-cm/src/log/pcie_mhi_mbim.txt @@ -0,0 +1,80 @@ +root@OpenWrt:/# lspci +00:00.0 Class 0604: 17cb:1001 +01:00.0 Class ff00: 17cb:0306 + +root@OpenWrt:/# insmod pcie_mhi.ko mhi_mbim_enabled=1 +[ 63.094154] mhi_init Quectel_Linux_PCIE_MHI_Driver_V1.3.0.17 +[ 63.094739] mhi_pci_probe pci_dev->name = 0000:01:00.0, domain=0, bus=1, slot=0, vendor=17CB, device=0306 +[ 63.099373] mhi_q 0000:01:00.0: BAR 0: assigned [mem 0x48000000-0x48000fff 64bit] +[ 63.108476] mhi_q 0000:01:00.0: enabling device (0140 -> 0142) +[ 63.293451] [I][mhi_netdev_enable_iface] Prepare the channels for transfer +[ 63.324757] [I][mhi_netdev_enable_iface] Exited. +[ 63.326265] rmnet_vnd_register_device(rmnet_mhi0.1)=0 + +root@OpenWrt:/# quectel-CM -s cment & +[04-13_09:25:23:910] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-13_09:25:23:912] network interface '' or qmidev '' is not exist +[04-13_09:25:23:912] netcard driver = pcie_mhi, driver version = V1.3.0.17 +[04-13_09:25:23:913] mbim_qmap_mode = 1, vlan_id = 0x00, qmap_netcard = rmnet_mhi0.1 +[04-13_09:25:23:913] Modem works in MBIM mode +[04-13_09:25:23:965] cdc_wdm_fd = 7 +[04-13_09:25:23:965] mbim_open_device() +[04-13_09:25:24:549] mbim_device_caps_query() +[04-13_09:25:24:575] DeviceId: 869710030002905 +[04-13_09:25:24:575] FirmwareInfo: RM500QGLABR10A03M4G_01.001.03 +[04-13_09:25:24:575] HardwareInfo: RM500QGL_VH +[04-13_09:25:24:576] mbim_device_services_query() +[04-13_09:25:24:585] mbim_set_radio_state( 1 ) +[04-13_09:25:24:588] HwRadioState: 1, SwRadioState: 1 +[04-13_09:25:24:588] mbim_subscriber_status_query() +[04-13_09:25:24:612] SubscriberId: 460028563800461 +[04-13_09:25:24:612] SimIccId: 89860015120716380461 +[04-13_09:25:24:613] SubscriberReadyState NotInitialized -> Initialized +[04-13_09:25:24:613] mbim_register_state_query() +[04-13_09:25:24:617] RegisterState Unknown -> Home +[04-13_09:25:24:617] mbim_packet_service_query() +[04-13_09:25:24:619] PacketServiceState Unknown -> Attached +[04-13_09:25:24:619] CurrentDataClass = 5G_NSA +[04-13_09:25:24:620] mbim_query_connect(sessionID=0) +[04-13_09:25:24:631] ActivationState Unknown -> Deactivated +[04-13_09:25:24:631] ifconfig rmnet_mhi0 down +[04-13_09:25:24:657] ifconfig rmnet_mhi0.1 0.0.0.0 +ifconfig: SIOCSIFFLAGS: Network is down +[04-13_09:25:24:681] ifconfig rmnet_mhi0.1 down +[04-13_09:25:24:705] mbim_register_state_query() +[04-13_09:25:24:709] mbim_packet_service_query() +[04-13_09:25:24:713] CurrentDataClass = 5G_NSA +[04-13_09:25:24:713] mbim_set_connect(onoff=1, sessionID=0) +[04-13_09:25:25:096] ActivationState Deactivated -> Activated +[04-13_09:25:25:097] mbim_ip_config(sessionID=0) +[04-13_09:25:25:100] < SessionId = 0 +[04-13_09:25:25:100] < IPv4ConfigurationAvailable = 0xf +[04-13_09:25:25:100] < IPv6ConfigurationAvailable = 0x0 +[04-13_09:25:25:101] < IPv4AddressCount = 0x1 +[04-13_09:25:25:101] < IPv4AddressOffset = 0x3c +[04-13_09:25:25:101] < IPv6AddressCount = 0x0 +[04-13_09:25:25:102] < IPv6AddressOffset = 0x0 +[04-13_09:25:25:102] < IPv4 = 10.190.166.229/30 +[04-13_09:25:25:103] < gw = 10.190.166.230 +[04-13_09:25:25:103] < dns1 = 211.138.180.2 +[04-13_09:25:25:103] < dns2 = 211.138.180.3 +[04-13_09:25:25:104] < ipv4 mtu = 1500 +[04-13_09:25:25:112] ifconfig rmnet_mhi0 up +[04-13_09:25:25:141] ifconfig rmnet_mhi0.1 up +[04-13_09:25:25:170] ip -4 address flush dev rmnet_mhi0.1 +[04-13_09:25:25:190] ip -4 address add 10.190.166.229/30 dev rmnet_mhi0.1 +[04-13_09:25:25:213] ip -4 route add default via 10.190.166.230 dev rmnet_mhi0.1 + +root@OpenWrt:/# ifconfig rmnet_mhi0.1 +rmnet_mhi0.1 Link encap:Ethernet HWaddr 02:50:F4:00:00:00 + inet addr:10.190.166.229 Mask:255.255.255.252 + inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link + UP RUNNING NOARP MTU:1500 Metric:1 + RX packets:19 errors:0 dropped:0 overruns:0 frame:0 + TX packets:29 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:2326 (2.2 KiB) TX bytes:2991 (2.9 KiB) + +root@OpenWrt:/# ping 8.8.8.8 +PING 8.8.8.8 (8.8.8.8): 56 data bytes +64 bytes from 8.8.8.8: seq=0 ttl=52 time=278.561 ms diff --git a/wwan/app/quectel-cm/src/log/pcie_mhi_mbim_qmap=4.txt b/wwan/app/quectel-cm/src/log/pcie_mhi_mbim_qmap=4.txt new file mode 100644 index 0000000..4d6cdf0 --- /dev/null +++ b/wwan/app/quectel-cm/src/log/pcie_mhi_mbim_qmap=4.txt @@ -0,0 +1,170 @@ +root@OpenWrt:/# lspci +00:00.0 Class 0604: 17cb:1001 +01:00.0 Class ff00: 17cb:0304 +root@OpenWrt:/# insmod pcie_mhi.ko mhi_mbim_enabled=1 qmap_mode=4 +[ 76.596827] mhi_init Quectel_Linux_PCIE_MHI_Driver_V1.3.0.17 +[ 76.598596] mhi_pci_probe pci_dev->name = 0000:01:00.0, domain=0, bus=1, slot=0, vendor=17CB, device=0304 +[ 76.602863] mhi_q 0000:01:00.0: BAR 0: assigned [mem 0x48000000-0x48000fff 64bit] +[ 76.611323] mhi_q 0000:01:00.0: enabling device (0140 -> 0142) +[ 76.760239] [I][mhi_netdev_enable_iface] Prepare the channels for transfer +[ 76.828699] [I][mhi_netdev_enable_iface] Exited. +[ 76.832727] rmnet_vnd_register_device(rmnet_mhi0.1)=0 +[ 76.836596] rmnet_vnd_register_device(rmnet_mhi0.2)=0 +[ 76.841170] rmnet_vnd_register_device(rmnet_mhi0.3)=0 +[ 76.846373] rmnet_vnd_register_device(rmnet_mhi0.4)=0 + +root@OpenWrt:~# quectel-mbim-proxy -d /dev/mhi_MBIM & +root@OpenWrt:~# [04-14_03:05:36:296] mbim_dev_fd=3 +[04-14_03:05:36:297] mbim_send_open_msg() +[04-14_03:05:36:669] receive MBIM_OPEN_DONE, status=0 +[04-14_03:05:36:670] mbim_server_fd=4 + +root@OpenWrt:~# quectel-CM -n 1 -s cmnet & +[04-14_03:05:45:955] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-14_03:05:45:956] network interface '' or qmidev '' is not exist +[04-14_03:05:45:957] netcard driver = pcie_mhi, driver version = V1.3.0.17 +[04-14_03:05:45:957] mbim_qmap_mode = 4, vlan_id = 0x01, qmap_netcard = rmnet_mhi0.1 +[04-14_03:05:45:958] Modem works in MBIM mode +[04-14_03:05:45:959] connect to quectel-mbim-proxy sockfd = 7 +[04-14_03:05:45:959] handle_client_connect client_fd=5, client_idx=1 +[04-14_03:05:45:959] cdc_wdm_fd = 7 +[04-14_03:05:45:960] mbim_open_device() +[04-14_03:05:45:961] mbim_device_caps_query() +[04-14_03:05:45:967] DeviceId: 860459050041596 +[04-14_03:05:45:968] FirmwareInfo: EM120RGLAPR02A03M4G_01.001.07 + +[04-14_03:05:45:968] HardwareInfo: EM120R_GL +[04-14_03:05:45:968] mbim_device_services_query() +[04-14_03:05:45:972] mbim_set_radio_state( 1 ) +[04-14_03:05:45:976] HwRadioState: 1, SwRadioState: 1 +[04-14_03:05:45:976] mbim_subscriber_status_query() +[04-14_03:05:45:985] SubscriberId: 460028563800461 +[04-14_03:05:45:985] SimIccId: 89860015120716380461 +[04-14_03:05:45:986] SubscriberReadyState NotInitialized -> Initialized +[04-14_03:05:45:986] mbim_register_state_query() +[04-14_03:05:45:991] RegisterState Unknown -> Home +[04-14_03:05:45:991] mbim_packet_service_query() +[04-14_03:05:45:995] PacketServiceState Unknown -> Attached +[04-14_03:05:45:996] mbim_query_connect(sessionID=1) +[04-14_03:05:46:000] ActivationState Unknown -> Deactivated +[04-14_03:05:46:000] ifconfig rmnet_mhi0 down +[04-14_03:05:46:024] ifconfig rmnet_mhi0.1 0.0.0.0 +ifconfig: SIOCSIFFLAGS: Network is down +[04-14_03:05:46:049] ifconfig rmnet_mhi0.1 down +[04-14_03:05:46:072] mbim_set_connect(onoff=1, sessionID=1) +[04-14_03:05:46:099] ActivationState Deactivated -> Activated +[04-14_03:05:46:099] mbim_ip_config(sessionID=1) +[ 222.484298] net rmnet_mhi0: link_state 0x0 -> 0x1 +[04-14_03:05:46:103] < SessionId = 1 +[04-14_03:05:46:104] < IPv4ConfigurationAvailable = 0xf +[04-14_03:05:46:104] < IPv6ConfigurationAvailable = 0x0 +[04-14_03:05:46:104] < IPv4AddressCount = 0x1 +[04-14_03:05:46:105] < IPv4AddressOffset = 0x3c +[ 222.507775] [I][mhi_netdev_open] Opened net dev interface +[04-14_03:05:46:105] < IPv6AddressCount = 0x0 +[04-14_03:05:46:105] < IPv6AddressOffset = 0x0 +[04-14_03:05:46:106] < IPv4 = 10.38.21.158/30 +[04-14_03:05:46:106] < gw = 10.38.21.157 +[04-14_03:05:46:106] < dns1 = 211.138.180.2 +[04-14_03:05:46:107] < dns2 = 211.138.180.3 +[04-14_03:05:46:107] < ipv4 mtu = 1500 +[04-14_03:05:46:112] ifconfig rmnet_mhi0 up +[04-14_03:05:46:140] ifconfig rmnet_mhi0.1 up +[04-14_03:05:46:168] ip -4 address flush dev rmnet_mhi0.1 +[04-14_03:05:46:190] ip -4 address add 10.38.21.158/30 dev rmnet_mhi0.1 +[04-14_03:05:46:212] ip -4 route add default via 10.38.21.157 dev rmnet_mhi0.1 +[04-14_03:05:50:730] handle_client_connect client_fd=6, client_idx=2 +[ 227.558631] net rmnet_mhi0: link_state 0x1 -> 0x3 + +root@OpenWrt:~# quectel-CM -n 2 -s 4gnet +[04-14_03:05:50:725] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-14_03:05:50:726] network interface '' or qmidev '' is not exist +[04-14_03:05:50:727] netcard driver = pcie_mhi, driver version = V1.3.0.17 +[04-14_03:05:50:728] mbim_qmap_mode = 4, vlan_id = 0x02, qmap_netcard = rmnet_mhi0.2 +[04-14_03:05:50:729] Modem works in MBIM mode +[04-14_03:05:50:730] connect to quectel-mbim-proxy sockfd = 8 +[04-14_03:05:50:730] cdc_wdm_fd = 8 +[04-14_03:05:50:731] mbim_open_device() +[04-14_03:05:50:732] mbim_device_caps_query() +[04-14_03:05:50:738] DeviceId: 860459050041596 +[04-14_03:05:50:739] FirmwareInfo: EM120RGLAPR02A03M4G_01.001.07 + +[04-14_03:05:50:739] HardwareInfo: EM120R_GL +[04-14_03:05:50:740] mbim_device_services_query() +[04-14_03:05:50:744] mbim_set_radio_state( 1 ) +[04-14_03:05:50:747] HwRadioState: 1, SwRadioState: 1 +[04-14_03:05:50:747] mbim_subscriber_status_query() +[04-14_03:05:50:757] SubscriberId: 460028563800461 +[04-14_03:05:50:758] SimIccId: 89860015120716380461 +[04-14_03:05:50:758] SubscriberReadyState NotInitialized -> Initialized +[04-14_03:05:50:759] mbim_register_state_query() +[04-14_03:05:50:763] RegisterState Unknown -> Home +[04-14_03:05:50:764] mbim_packet_service_query() +[04-14_03:05:50:768] PacketServiceState Unknown -> Attached +[04-14_03:05:50:769] mbim_query_connect(sessionID=2) +[04-14_03:05:50:772] ActivationState Unknown -> Deactivated +[04-14_03:05:50:773] ifconfig rmnet_mhi0.2 0.0.0.0 +[04-14_03:05:50:799] ifconfig rmnet_mhi0.2 down +[04-14_03:05:50:834] mbim_set_connect(onoff=1, sessionID=2) +[04-14_03:05:51:170] ActivationState Deactivated -> Activated +[04-14_03:05:51:171] mbim_ip_config(sessionID=2) +[04-14_03:05:51:174] < SessionId = 2 +[04-14_03:05:51:174] < IPv4ConfigurationAvailable = 0xf +[04-14_03:05:51:175] < IPv6ConfigurationAvailable = 0x0 +[04-14_03:05:51:175] < IPv4AddressCount = 0x1 +[04-14_03:05:51:175] < IPv4AddressOffset = 0x3c +[04-14_03:05:51:176] < IPv6AddressCount = 0x0 +[04-14_03:05:51:176] < IPv6AddressOffset = 0x0 +[04-14_03:05:51:176] < IPv4 = 10.36.109.217/30 +[04-14_03:05:51:177] < gw = 10.36.109.218 +[04-14_03:05:51:177] < dns1 = 211.138.180.2 +[04-14_03:05:51:178] < dns2 = 211.138.180.3 +[04-14_03:05:51:178] < ipv4 mtu = 1500 +[04-14_03:05:51:182] ifconfig rmnet_mhi0 up +[04-14_03:05:51:206] ifconfig rmnet_mhi0.2 up +[04-14_03:05:51:233] ip -4 address flush dev rmnet_mhi0.2 +[04-14_03:05:51:254] ip -4 address add 10.36.109.217/30 dev rmnet_mhi0.2 +[04-14_03:05:51:277] ip -4 route add default via 10.36.109.218 dev rmnet_mhi0.2 + +root@OpenWrt:~# ifconfig rmnet_mhi0.1 +rmnet_mhi0.1 Link encap:Ethernet HWaddr 02:50:F4:00:00:00 + inet addr:10.38.21.158 Mask:255.255.255.252 + inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link + UP RUNNING NOARP MTU:1500 Metric:1 + RX packets:37 errors:0 dropped:0 overruns:0 frame:0 + TX packets:29 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:9907 (9.6 KiB) TX bytes:2764 (2.6 KiB) + +root@OpenWrt:~# ifconfig rmnet_mhi0.2 +rmnet_mhi0.2 Link encap:Ethernet HWaddr 02:50:F4:00:00:00 + inet addr:10.36.109.217 Mask:255.255.255.252 + inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link + UP RUNNING NOARP MTU:1500 Metric:1 + RX packets:5 errors:0 dropped:0 overruns:0 frame:0 + TX packets:18 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:344 (344.0 B) TX bytes:1152 (1.1 KiB) + +root@OpenWrt:~# ip ro del 8.8.8.8/32 +RTNETLINK answers: No such process +root@OpenWrt:~# ip ro add 8.8.8.8/32 dev rmnet_mhi0.1 +root@OpenWrt:~# ping 8.8.8.8 +PING 8.8.8.8 (8.8.8.8): 56 data bytes +64 bytes from 8.8.8.8: seq=0 ttl=52 time=73.248 ms + +root@OpenWrt:~# ip ro del 8.8.8.8/32 +root@OpenWrt:~# ip ro del 8.8.8.8/32 +RTNETLINK answers: No such process +root@OpenWrt:~# ip ro add 8.8.8.8/32 dev rmnet_mhi0.2 +root@OpenWrt:~# ping 8.8.8.8 +PING 8.8.8.8 (8.8.8.8): 56 data bytes +64 bytes from 8.8.8.8: seq=0 ttl=52 time=99.637 ms + +root@OpenWrt:~# quectel-CM -k 2 +[04-14_03:06:58:912] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-14_03:06:59:063] /proc/3565/cmdline: quectel-CM -n 2 -s 4gnet +[04-14_03:06:59:064] send SIGINT to process 3565 +[ 295.719442] net rmnet_mhi0: link_state 0x3 -> 0x1 +[04-14_03:06:59:407] proxy_loop poll fd = 6, revents = 0011 +[04-14_03:06:59:408] handle_client_disconnect client_fd=6, client_idx=2 diff --git a/wwan/app/quectel-cm/src/log/pcie_mhi_qmap=1.txt b/wwan/app/quectel-cm/src/log/pcie_mhi_qmap=1.txt new file mode 100644 index 0000000..c93af7e --- /dev/null +++ b/wwan/app/quectel-cm/src/log/pcie_mhi_qmap=1.txt @@ -0,0 +1,127 @@ +root@OpenWrt:/# cat /sys/class/net/rmnet_mhi0/qmap_mode +1 +root@OpenWrt:/# cat /sys/module/pcie_mhi/parameters/mhi_mbim_enabled +0 +root@OpenWrt:/# dmesg | grep mhi +[ 18.442226] mhi_init Quectel_Linux_PCIE_MHI_Driver_V1.3.0.17 +[ 18.443032] mhi_pci_probe pci_dev->name = 0000:01:00.0, domain=0, bus=1, slot=0, vendor=17CB, device=0306 +[ 18.447488] mhi_q 0000:01:00.0: BAR 0: assigned [mem 0x48000000-0x48000fff 64bit] +[ 18.456563] mhi_q 0000:01:00.0: enabling device (0140 -> 0142) +[ 18.464184] [I][mhi_init_pci_dev] msi_required = 5, msi_allocated = 5, msi_irq = 197 +[ 18.464215] [I][mhi_power_up] dev_state:RESET +[ 18.464225] [I][mhi_async_power_up] Requested to power on +[ 18.464432] [I][mhi_alloc_coherent] size = 114688, dma_handle = 8d400000 +[ 18.464445] [I][mhi_init_dev_ctxt] mhi_ctxt->ctrl_seg = d1766000 +[ 18.466003] [I][mhi_async_power_up] dev_state:RESET ee:AMSS +[ 18.466080] [I][mhi_pm_st_worker] Transition to state:READY +[ 18.466109] [I][mhi_pm_st_worker] INVALID_EE -> AMSS +[ 18.466135] [I][mhi_ready_state_transition] Waiting to enter READY state +[ 18.466224] [I][mhi_async_power_up] Power on setup success +[ 18.466265] [I][mhi_pci_probe] Return successful +[ 18.577299] [I][mhi_intvec_threaded_handlr] device ee:AMSS dev_state:READY, pm_state:POR +[ 18.577312] [I][mhi_ready_state_transition] Device in READY State +[ 18.577325] [I][mhi_intvec_threaded_handlr] device ee:AMSS dev_state:READY, INVALID_EE +[ 18.577329] [I][mhi_tryset_pm_state] Transition to pm state from:POR to:POR +[ 18.577337] [I][mhi_init_mmio] Initializing MMIO +[ 18.577344] [I][mhi_init_mmio] CHDBOFF:0x300 +[ 18.577361] [I][mhi_init_mmio] ERDBOFF:0x700 +[ 18.577372] [I][mhi_init_mmio] Programming all MMIO values. +[ 18.690834] [I][mhi_dump_tre] carl_ev evt_state_change mhistate=2 +[ 18.690854] [I][mhi_process_ctrl_ev_ring] MHI state change event to state:M0 +[ 18.690866] [I][mhi_pm_m0_transition] Entered With State:READY PM_STATE:POR +[ 18.690879] [I][mhi_tryset_pm_state] Transition to pm state from:POR to:M0 +[ 18.694229] [I][mhi_dump_tre] carl_ev evt_ee_state execenv=2 +[ 18.694241] [I][mhi_process_ctrl_ev_ring] MHI EE received event:AMSS +[ 18.694293] [I][mhi_pm_st_worker] Transition to state:MISSION MODE +[ 18.694310] [I][mhi_pm_st_worker] INVALID_EE -> AMSS +[ 18.694319] [I][mhi_pm_mission_mode_transition] Processing Mission Mode Transition +[ 18.694341] [I][mhi_init_timesync] No timesync capability found +[ 18.694350] [I][mhi_pm_mission_mode_transition] Adding new devices +[ 18.696365] [I][mhi_dtr_probe] Enter for DTR control channel +[ 18.696383] [I][__mhi_prepare_channel] Entered: preparing channel:18 +[ 18.703113] [I][mhi_dump_tre] carl_ev evt_cmd_comp code=1, type=33 +[ 18.703164] [I][__mhi_prepare_channel] Chan:18 successfully moved to start state +[ 18.703174] [I][__mhi_prepare_channel] Entered: preparing channel:19 +[ 18.710681] [I][mhi_dump_tre] carl_ev evt_cmd_comp code=1, type=33 +[ 18.710734] [I][__mhi_prepare_channel] Chan:19 successfully moved to start state +[ 18.710804] [I][mhi_dtr_probe] Exit with ret:0 +[ 18.711774] [I][mhi_netdev_enable_iface] Prepare the channels for transfer +[ 18.711811] [I][__mhi_prepare_channel] Entered: preparing channel:100 +[ 18.732097] [I][mhi_dump_tre] carl_ev evt_cmd_comp code=1, type=33 +[ 18.732151] [I][__mhi_prepare_channel] Chan:100 successfully moved to start state +[ 18.732162] [I][__mhi_prepare_channel] Entered: preparing channel:101 +[ 18.744170] [I][mhi_dump_tre] carl_ev evt_cmd_comp code=1, type=33 +[ 18.744219] [I][__mhi_prepare_channel] Chan:101 successfully moved to start state +[ 18.749132] [I][mhi_netdev_enable_iface] Exited. +[ 18.750306] rmnet_vnd_register_device(rmnet_mhi0.1)=0 +[ 18.752927] [I][mhi_pm_mission_mode_transition] Exit with ret:0 + +root@OpenWrt:/# busybox microcom /dev/mhi_DUN +at+cpin? ++CPIN: READY + +OK +at+cops? ++COPS: 0,0,"CHINA MOBILE",13 + +OK +at+csq ++csq: 23,99 + +OK + +root@OpenWrt:/# quectel-CM -s cmnet & +[04-13_09:26:58:077] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-13_09:26:58:078] network interface '' or qmidev '' is not exist +[04-13_09:26:58:079] netcard driver = pcie_mhi, driver version = V1.3.0.17 +[04-13_09:26:58:080] qmap_mode = 1, qmap_version = 9, qmap_size = 16384, muxid = 0x81, qmap_netcard = rmnet_mhi0.1 +[04-13_09:26:58:080] Modem works in QMI mode +[04-13_09:26:58:131] cdc_wdm_fd = 7 +[04-13_09:26:59:132] QmiWwanInit message timeout +[04-13_09:27:00:140] Get clientWDS = 15 +[04-13_09:27:00:144] Get clientDMS = 1 +[04-13_09:27:00:147] Get clientNAS = 4 +[04-13_09:27:00:151] Get clientUIM = 1 +[04-13_09:27:00:155] Get clientWDA = 1 +[04-13_09:27:00:158] requestBaseBandVersion RM500QGLABR10A03M4G +[04-13_09:27:00:161] qmap_settings.rx_urb_size = 16384 +[04-13_09:27:00:162] qmap_settings.ul_data_aggregation_max_datagrams = 11 +[04-13_09:27:00:162] qmap_settings.ul_data_aggregation_max_size = 8192 +[04-13_09:27:00:163] qmap_settings.dl_minimum_padding = 0 +[04-13_09:27:00:176] requestGetSIMStatus SIMStatus: SIM_READY +[04-13_09:27:00:177] requestSetProfile[1] cmnet///0 +[04-13_09:27:00:190] requestGetProfile[1] cmnet///0 +[04-13_09:27:00:193] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: 5G_NSA +[04-13_09:27:00:197] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED +[04-13_09:27:00:198] ifconfig rmnet_mhi0 down +[04-13_09:27:00:222] ifconfig rmnet_mhi0.1 0.0.0.0 +[04-13_09:27:00:247] ifconfig rmnet_mhi0.1 down +[04-13_09:27:00:281] requestSetupDataCall WdsConnectionIPv4Handle: 0x1228bb20 +[ 245.284909] net rmnet_mhi0: link_state 0x0 -> 0x1 +[04-13_09:27:00:293] ifconfig rmnet_mhi0 up +[ 245.308696] [I][mhi_netdev_open] Opened net dev interface +[04-13_09:27:00:318] ifconfig rmnet_mhi0.1 up +[04-13_09:27:00:353] you are use OpenWrt? +[04-13_09:27:00:354] should not calling udhcpc manually? +[04-13_09:27:00:354] should modify /etc/config/network as below? +[04-13_09:27:00:355] config interface wan +[04-13_09:27:00:355] option ifname rmnet_mhi0.1 +[04-13_09:27:00:355] option proto dhcp +[04-13_09:27:00:356] should use "/sbin/ifstaus wan" to check rmnet_mhi0.1 's status? +[04-13_09:27:00:356] busybox udhcpc -f -n -q -t 5 -i rmnet_mhi0.1 +udhcpc: started, v1.28.3 +udhcpc: sending discover +udhcpc: sending select for 10.128.73.23 +udhcpc: lease of 10.128.73.23 obtained, lease time 7200 +[04-13_09:27:00:710] udhcpc: ifconfig rmnet_mhi0.1 10.128.73.23 netmask 255.255.255.240 broadcast + +[04-13_09:27:00:742] udhcpc: setting default routers: 10.128.73.24 + +root@OpenWrt:/# ifconfig rmnet_mhi0.1 +rmnet_mhi0.1 Link encap:Ethernet HWaddr 02:50:F4:00:00:00 + inet addr:10.128.73.23 Mask:255.255.255.240 + inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link + UP RUNNING NOARP MTU:1500 Metric:1 + RX packets:2 errors:0 dropped:0 overruns:0 frame:0 + TX packets:2 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:612 (612.0 B) TX bytes:684 (684.0 B) diff --git a/wwan/app/quectel-cm/src/log/pcie_mhi_qmap=1_bridge.txt b/wwan/app/quectel-cm/src/log/pcie_mhi_qmap=1_bridge.txt new file mode 100644 index 0000000..0ab6de7 --- /dev/null +++ b/wwan/app/quectel-cm/src/log/pcie_mhi_qmap=1_bridge.txt @@ -0,0 +1,76 @@ +root@OpenWrt:/# lspci +00:00.0 Class 0604: 17cb:1001 +01:00.0 Class ff00: 17cb:0306 + +root@OpenWrt:~# insmod pcie_mhi.ko +[ 77.949271] mhi_init Quectel_Linux_PCIE_MHI_Driver_V1.3.0.17 +[ 77.950949] mhi_pci_probe pci_dev->name = 0000:01:00.0, domain=0, bus=1, slot=0, vendor=17CB, device=0306 +[ 77.955331] mhi_q 0000:01:00.0: BAR 0: assigned [mem 0x48000000-0x48000fff 64bit] +[ 77.963756] mhi_q 0000:01:00.0: enabling device (0140 -> 0142) +[ 78.048911] [I][mhi_netdev_enable_iface] Prepare the channels for transfer +[ 78.092304] [I][mhi_netdev_enable_iface] Exited. +[ 78.096580] rmnet_vnd_register_device(rmnet_mhi0.1)=0 + +root@OpenWrt:~# brctl addbr br0 +root@OpenWrt:~# brctl addif br0 rmnet_mhi0.1 +root@OpenWrt:~# brctl addif br0 eth1 +[ 250.017213] device eth1 entered promiscuous mode +root@OpenWrt:~# brctl show +bridge name bridge id STP enabled interfaces +br0 8000.00001c353487 no eth1 + rmnet_mhi0.1 + +root@OpenWrt:~# quectel-CM -s cmnet -b & +[04-14_06:43:28:473] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-14_06:43:28:474] network interface '' or qmidev '' is not exist +[04-14_06:43:28:475] netcard driver = pcie_mhi, driver version = V1.3.0.17 +[04-14_06:43:28:476] qmap_mode = 1, qmap_version = 9, qmap_size = 16384, muxid = 0x81, qmap_netcard = rmnet_mhi0.1 +[04-14_06:43:28:477] Modem works in QMI mode +[04-14_06:43:28:531] cdc_wdm_fd = 7 +[04-14_06:43:29:532] QmiWwanInit message timeout +[04-14_06:43:30:540] Get clientWDS = 15 +[04-14_06:43:30:543] Get clientDMS = 1 +[04-14_06:43:30:546] Get clientNAS = 4 +[04-14_06:43:30:550] Get clientUIM = 1 +[04-14_06:43:30:553] Get clientWDA = 1 +[04-14_06:43:30:557] requestBaseBandVersion RM500QGLABR10A03M4G +[04-14_06:43:30:560] qmap_settings.rx_urb_size = 16384 +[04-14_06:43:30:561] qmap_settings.ul_data_aggregation_max_datagrams = 11 +[04-14_06:43:30:561] qmap_settings.ul_data_aggregation_max_size = 8192 +[04-14_06:43:30:561] qmap_settings.dl_minimum_padding = 0 +[04-14_06:43:30:575] requestGetSIMStatus SIMStatus: SIM_READY +[04-14_06:43:30:575] requestSetProfile[1] cmnet///0 +[04-14_06:43:30:588] requestGetProfile[1] cmnet///0 +[04-14_06:43:30:591] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: 5G_NSA +[04-14_06:43:30:595] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED +[04-14_06:43:30:595] ifconfig rmnet_mhi0 down +[04-14_06:43:30:620] ifconfig rmnet_mhi0.1 0.0.0.0 +ifconfig: SIOCSIFFLAGS: Network is down +[04-14_06:43:30:644] ifconfig rmnet_mhi0.1 down +[04-14_06:43:30:679] requestSetupDataCall WdsConnectionIPv4Handle: 0xb41f47d0 +[ 263.869899] net rmnet_mhi0: link_state 0x0 -> 0x1 +[04-14_06:43:30:693] ifconfig rmnet_mhi0 up +[ 263.892647] [I][mhi_netdev_open] Opened net dev interface +[04-14_06:43:30:718] ifconfig rmnet_mhi0.1 up +[04-14_06:43:30:746] echo '0xa59316b' > /sys/class/net/rmnet_mhi0.1/bridge_ipv4 + +root@OpenWrt:~# ifconfig br0 up +[ 268.800026] br0: port 2(eth1) entered forwarding state +[ 268.800336] br0: port 2(eth1) entered forwarding state +[ 268.804251] br0: port 1(rmnet_mhi0.1) entered forwarding state +[ 268.809465] br0: port 1(rmnet_mhi0.1) entered forwarding state +[ 283.845790] br0: port 2(eth1) entered forwarding state + +[ 296.512489] rmnet_mhi0.1 PC Mac Address: 00:0e:c6:a6:6c:f1 +[ 296.515756] rmnet_mhi0.1 PC Mac Address: 00:0e:c6:a6:6c:f1 +[ 296.586584] rmnet_mhi0.1 sip = 10.89.49.107, tip=10.89.49.108, ipv4=10.89.49.107 +[ 296.672356] rmnet_mhi0.1 sip = 10.89.49.107, tip=10.89.49.108, ipv4=10.89.49.107 +[ 296.792061] rmnet_mhi0.1 sip = 10.89.49.107, tip=10.89.49.108, ipv4=10.89.49.107 +[ 296.832822] rmnet_mhi0.1 sip = 10.89.49.107, tip=10.89.49.108, ipv4=10.89.49.107 +[ 296.941073] rmnet_mhi0.1 sip = 0.0.0.0, tip=10.89.49.107, ipv4=10.89.49.107 +[ 297.941310] rmnet_mhi0.1 sip = 0.0.0.0, tip=10.89.49.107, ipv4=10.89.49.107 +[ 298.941528] rmnet_mhi0.1 sip = 0.0.0.0, tip=10.89.49.107, ipv4=10.89.49.107 +[ 299.941704] rmnet_mhi0.1 sip = 10.89.49.107, tip=10.89.49.107, ipv4=10.89.49.107 +[ 300.024484] rmnet_mhi0.1 sip = 10.89.49.107, tip=10.89.49.108, ipv4=10.89.49.107 +[ 300.051995] rmnet_mhi0.1 sip = 10.89.49.107, tip=10.89.49.108, ipv4=10.89.49.107 +[ 303.915933] rmnet_mhi0.1 sip = 10.89.49.107, tip=10.89.49.108, ipv4=10.89.49.107 diff --git a/wwan/app/quectel-cm/src/log/pcie_mhi_qmap=4.txt b/wwan/app/quectel-cm/src/log/pcie_mhi_qmap=4.txt new file mode 100644 index 0000000..5f43a74 --- /dev/null +++ b/wwan/app/quectel-cm/src/log/pcie_mhi_qmap=4.txt @@ -0,0 +1,138 @@ +root@OpenWrt:/# lspci +00:00.0 Class 0604: 17cb:1001 +01:00.0 Class ff00: 17cb:0306 + +root@OpenWrt:/# insmod pcie_mhi.ko qmap_mode=4 +[ 61.988878] mhi_init Quectel_Linux_PCIE_MHI_Driver_V1.3.0.17 +[ 61.989484] mhi_pci_probe pci_dev->name = 0000:01:00.0, domain=0, bus=1, slot=0, vendor=17CB, device=0306 +[ 61.994039] mhi_q 0000:01:00.0: BAR 0: assigned [mem 0x48000000-0x48000fff 64bit] +[ 62.003208] mhi_q 0000:01:00.0: enabling device (0140 -> 0142) +[ 62.191947] [I][mhi_netdev_enable_iface] Prepare the channels for transfer +[ 62.224065] [I][mhi_netdev_enable_iface] Exited. +[ 62.225619] rmnet_vnd_register_device(rmnet_mhi0.1)=0 +[ 62.229289] rmnet_vnd_register_device(rmnet_mhi0.2)=0 +[ 62.234378] rmnet_vnd_register_device(rmnet_mhi0.3)=0 +[ 62.240039] rmnet_vnd_register_device(rmnet_mhi0.4)=0 + +root@OpenWrt:/# quectel-qmi-proxy -d /dev/mhi_QMI0 & +[04-13_09:25:12:278] Will use cdc-wdm='/dev/mhi_QMI0', proxy='quectel-qmi-proxy0' +[04-13_09:25:12:297] qmi_proxy_init enter +[04-13_09:25:12:297] qmi_proxy_loop enter thread_id 0xb6e88d44 +[04-13_09:25:14:298] qmi_proxy_init succful +[04-13_09:25:14:299] local server: quectel-qmi-proxy0 sockfd = 4 +[04-13_09:25:14:299] qmi_proxy_server_fd = 4 + +root@OpenWrt:/# quectel-CM -n 1 -s cmnet & +[04-13_09:25:32:336] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-13_09:25:32:337] network interface '' or qmidev '' is not exist +[04-13_09:25:32:338] netcard driver = pcie_mhi, driver version = V1.3.0.17 +[04-13_09:25:32:339] qmap_mode = 4, qmap_version = 9, qmap_size = 16384, muxid = 0x81, qmap_netcard = rmnet_mhi0.1 +[04-13_09:25:32:340] Modem works in QMI mode +[04-13_09:25:32:341] connect to quectel-qmi-proxy0 sockfd = 7 +[04-13_09:25:32:342] cdc_wdm_fd = 7 +[04-13_09:25:32:380] requestBaseBandVersion RM500QGLABR10A03M4G +[04-13_09:25:32:382] qmap_settings.rx_urb_size = 16384 +[04-13_09:25:32:383] qmap_settings.ul_data_aggregation_max_datagrams = 11 +[04-13_09:25:32:383] qmap_settings.ul_data_aggregation_max_size = 8192 +[04-13_09:25:32:384] qmap_settings.dl_minimum_padding = 0 +[04-13_09:25:32:394] requestGetSIMStatus SIMStatus: SIM_READY +[04-13_09:25:32:395] requestSetProfile[1] cmnet///0 +[04-13_09:25:32:409] requestGetProfile[1] cmnet///0 +[04-13_09:25:32:414] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: 5G_NSA +[04-13_09:25:32:418] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED +[04-13_09:25:32:419] ifconfig rmnet_mhi0 down +[04-13_09:25:32:448] ifconfig rmnet_mhi0.1 0.0.0.0 +[04-13_09:25:32:473] ifconfig rmnet_mhi0.1 down +[04-13_09:25:32:514] requestSetupDataCall WdsConnectionIPv4Handle: 0x2313a2a0 +[ 121.648172] net rmnet_mhi0: link_state 0x0 -> 0x1 +[04-13_09:25:32:525] ifconfig rmnet_mhi0 up +[ 121.671210] [I][mhi_netdev_open] Opened net dev interface +[04-13_09:25:32:551] ifconfig rmnet_mhi0.1 up +[04-13_09:25:32:586] you are use OpenWrt? +[04-13_09:25:32:587] should not calling udhcpc manually? +[04-13_09:25:32:587] should modify /etc/config/network as below? +[04-13_09:25:32:587] config interface wan +[04-13_09:25:32:588] option ifname rmnet_mhi0.1 +[04-13_09:25:32:588] option proto dhcp +[04-13_09:25:32:589] should use "/sbin/ifstaus wan" to check rmnet_mhi0.1 's status? +[04-13_09:25:32:589] busybox udhcpc -f -n -q -t 5 -i rmnet_mhi0.1 +udhcpc: started, v1.28.3 +udhcpc: sending discover +udhcpc: sending select for 10.174.91.70 +udhcpc: lease of 10.174.91.70 obtained, lease time 7200 +[04-13_09:25:32:980] udhcpc: ifconfig rmnet_mhi0.1 10.174.91.70 netmask 255.255.255.252 broadcast + +[04-13_09:25:33:007] udhcpc: setting default routers: 10.174.91.69 + +root@OpenWrt:/# quectel-CM -n 2 -s 4gnet & +[04-13_09:25:42:976] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-13_09:25:42:977] network interface '' or qmidev '' is not exist +[04-13_09:25:42:978] netcard driver = pcie_mhi, driver version = V1.3.0.17 +[04-13_09:25:42:978] qmap_mode = 4, qmap_version = 9, qmap_size = 16384, muxid = 0x82, qmap_netcard = rmnet_mhi0.2 +[04-13_09:25:42:979] Modem works in QMI mode +[04-13_09:25:42:981] connect to quectel-qmi-proxy0 sockfd = 7 +[04-13_09:25:42:982] cdc_wdm_fd = 7 +[04-13_09:25:43:010] requestBaseBandVersion RM500QGLABR10A03M4G +[04-13_09:25:43:013] qmap_settings.rx_urb_size = 16384 +[04-13_09:25:43:014] qmap_settings.ul_data_aggregation_max_datagrams = 11 +[04-13_09:25:43:014] qmap_settings.ul_data_aggregation_max_size = 8192 +[04-13_09:25:43:015] qmap_settings.dl_minimum_padding = 0 +[04-13_09:25:43:030] requestGetSIMStatus SIMStatus: SIM_READY +[04-13_09:25:43:030] requestSetProfile[2] 4gnet///0 +[04-13_09:25:43:046] requestGetProfile[2] 4gnet///0 +[04-13_09:25:43:050] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: 5G_NSA +[04-13_09:25:43:054] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED +[04-13_09:25:43:055] ifconfig rmnet_mhi0.2 0.0.0.0 +[04-13_09:25:43:082] ifconfig rmnet_mhi0.2 down +[04-13_09:25:43:507] requestSetupDataCall WdsConnectionIPv4Handle: 0x2332a780 +[ 132.641313] net rmnet_mhi0: link_state 0x1 -> 0x3 +[04-13_09:25:43:519] ifconfig rmnet_mhi0 up +[04-13_09:25:43:543] ifconfig rmnet_mhi0.2 up +[04-13_09:25:43:570] you are use OpenWrt? +[04-13_09:25:43:570] should not calling udhcpc manually? +[04-13_09:25:43:571] should modify /etc/config/network as below? +[04-13_09:25:43:571] config interface wan +[04-13_09:25:43:571] option ifname rmnet_mhi0.2 +[04-13_09:25:43:572] option proto dhcp +[04-13_09:25:43:572] should use "/sbin/ifstaus wan" to check rmnet_mhi0.2 's status? +[04-13_09:25:43:573] busybox udhcpc -f -n -q -t 5 -i rmnet_mhi0.2 +udhcpc: started, v1.28.3 +udhcpc: sending discover +udhcpc: sending select for 10.163.253.197 +udhcpc: lease of 10.163.253.197 obtained, lease time 7200 +[04-13_09:25:43:810] udhcpc: ifconfig rmnet_mhi0.2 10.163.253.197 netmask 255.255.255.252 broadcast + +[04-13_09:25:43:836] udhcpc: setting default routers: 10.163.253.198 + +root@OpenWrt:/# ifconfig rmnet_mhi0.1 +rmnet_mhi0.1 Link encap:Ethernet HWaddr 02:50:F4:00:00:00 + inet addr:10.174.91.70 Mask:255.255.255.252 + inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link + UP RUNNING NOARP MTU:1500 Metric:1 + RX packets:2 errors:0 dropped:0 overruns:0 frame:0 + TX packets:4 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:612 (612.0 B) TX bytes:1380 (1.3 KiB) + +root@OpenWrt:/# ifconfig rmnet_mhi0.2 +rmnet_mhi0.2 Link encap:Ethernet HWaddr 02:50:F4:00:00:00 + inet addr:10.163.253.197 Mask:255.255.255.252 + inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link + UP RUNNING NOARP MTU:1500 Metric:1 + RX packets:2 errors:0 dropped:0 overruns:0 frame:0 + TX packets:2 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:612 (612.0 B) TX bytes:684 (684.0 B) + +root@OpenWrt:/# ip ro del 8.8.8.8/32 +RTNETLINK answers: No such process +root@OpenWrt:/# ip ro add 8.8.8.8/32 dev rmnet_mhi0.1 +root@OpenWrt:/# ping 8.8.8.8 +PING 8.8.8.8 (8.8.8.8): 56 data bytes +64 bytes from 8.8.8.8: seq=0 ttl=52 time=390.869 ms + +root@OpenWrt:/# ip ro del 8.8.8.8/32 +root@OpenWrt:/# ip ro del 8.8.8.8/32 +RTNETLINK answers: No such process +root@OpenWrt:/# ip ro add 8.8.8.8/32 dev rmnet_mhi0.2 +root@OpenWrt:/# ping 8.8.8.8 +PING 8.8.8.8 (8.8.8.8): 56 data bytes +64 bytes from 8.8.8.8: seq=0 ttl=111 time=314.395 ms \ No newline at end of file diff --git a/wwan/app/quectel-cm/src/log/pcie_mhi_qmap=4_bridge.txt b/wwan/app/quectel-cm/src/log/pcie_mhi_qmap=4_bridge.txt new file mode 100644 index 0000000..0af5ff0 --- /dev/null +++ b/wwan/app/quectel-cm/src/log/pcie_mhi_qmap=4_bridge.txt @@ -0,0 +1,147 @@ +root@OpenWrt:~# lspci +00:00.0 Class 0604: 17cb:1001 +01:00.0 Class ff00: 17cb:0306 +root@OpenWrt:~# + +root@OpenWrt:~# insmod pcie_mhi.ko qmap_mode=4 +[ 200.906104] mhi_init Quectel_Linux_PCIE_MHI_Driver_V1.3.0.17 +[ 200.907913] mhi_pci_probe pci_dev->name = 0000:01:00.0, domain=0, bus=1, slot=0, vendor=17CB, device=0306 +[ 200.912164] mhi_q 0000:01:00.0: BAR 0: assigned [mem 0x48000000-0x48000fff 64bit] +[ 200.920593] mhi_q 0000:01:00.0: enabling device (0140 -> 0142) +root@OpenWrt:~# [ 201.112214] [I][mhi_netdev_enable_iface] Prepare the channels for transfer +[ 201.154640] [I][mhi_netdev_enable_iface] Exited. +[ 201.159271] rmnet_vnd_register_device(rmnet_mhi0.1)=0 +[ 201.162953] rmnet_vnd_register_device(rmnet_mhi0.2)=0 +[ 201.167698] rmnet_vnd_register_device(rmnet_mhi0.3)=0 +[ 201.172178] rmnet_vnd_register_device(rmnet_mhi0.4)=0 + +root@OpenWrt:~# brctl addbr br0 +root@OpenWrt:~# brctl addif br0 eth1 +root@OpenWrt:~# brctl addif br0 rmnet_mhi0.2 +root@OpenWrt:~# brctl show +bridge name bridge id STP enabled interfaces +br0 8000.00001c353487 no eth1 + rmnet_mhi0.2 + +root@OpenWrt:~# quectel-qmi-proxy -d /dev/mhi_QMI0 & +[04-14_06:44:01:556] Will use cdc-wdm='/dev/mhi_QMI0', proxy='quectel-qmi-proxy0' +[04-14_06:44:01:573] qmi_proxy_init enter +[04-14_06:44:01:573] qmi_proxy_loop enter thread_id 0xb6f20d44 +[04-14_06:44:03:574] qmi_proxy_init succful +[04-14_06:44:03:574] local server: quectel-qmi-proxy0 sockfd = 4 +[04-14_06:44:03:575] qmi_proxy_server_fd = 4 + + +root@OpenWrt:~# quectel-CM -n 1 -s cmnet & +[04-14_06:47:53:303] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-14_06:47:53:314] network interface '' or qmidev '' is not exist +[04-14_06:47:53:315] netcard driver = pcie_mhi, driver version = V1.3.0.17 +[04-14_06:47:53:316] qmap_mode = 4, qmap_version = 9, qmap_size = 16384, muxid = 0x81, qmap_netcard = rmnet_mhi0.1 +[04-14_06:47:53:316] Modem works in QMI mode +[04-14_06:47:53:318] connect to quectel-qmi-proxy0 sockfd = 7 +[04-14_06:47:53:318] cdc_wdm_fd = 7 +[04-14_06:47:53:326] Get clientWDS = 15 +[04-14_06:47:53:329] Get clientDMS = 2 +[04-14_06:47:53:334] Get clientNAS = 4 +[04-14_06:47:53:338] Get clientUIM = 1 +[04-14_06:47:53:343] Get clientWDA = 1 +[04-14_06:47:53:347] requestBaseBandVersion RM500QGLABR10A03M4G +[04-14_06:47:53:351] qmap_settings.rx_urb_size = 16384 +[04-14_06:47:53:352] qmap_settings.ul_data_aggregation_max_datagrams = 11 +[04-14_06:47:53:352] qmap_settings.ul_data_aggregation_max_size = 8192 +[04-14_06:47:53:352] qmap_settings.dl_minimum_padding = 0 +[04-14_06:47:53:369] requestGetSIMStatus SIMStatus: SIM_READY +[04-14_06:47:53:370] requestSetProfile[1] cmnet///0 +[04-14_06:47:53:402] requestGetProfile[1] cmnet///0 +[04-14_06:47:53:407] requestRegistrationState2 MCC: 0, MNC: 0, PS: Detached, DataCap: UNKNOW +[04-14_06:47:53:411] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED +[04-14_06:47:53:412] ifconfig rmnet_mhi0 down +[04-14_06:47:53:436] ifconfig rmnet_mhi0.1 0.0.0.0 +[04-14_06:47:53:460] ifconfig rmnet_mhi0.1 down +[04-14_06:48:26:399] requestRegistrationState2 MCC: 460, MNC: 0, PS: Detached, DataCap: UNKNOW +[04-14_06:48:26:405] requestRegistrationState2 MCC: 460, MNC: 0, PS: Detached, DataCap: UNKNOW +[04-14_06:48:26:411] requestRegistrationState2 MCC: 460, MNC: 0, PS: Detached, DataCap: UNKNOW +[04-14_06:48:26:970] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: 5G_NSA +[04-14_06:48:26:992] requestSetupDataCall WdsConnectionIPv4Handle: 0x34176710 +[04-14_06:48:27:005] ifconfig rmnet_mhi0 up +[04-14_06:48:27:031] ifconfig rmnet_mhi0.1 up +[04-14_06:48:27:057] you are use OpenWrt? +[04-14_06:48:27:057] should not calling udhcpc manually? +[04-14_06:48:27:080] should use "/sbin/ifstaus wan" to check rmnet_mhi0.1 's status? +[04-14_06:48:27:081] busybox udhcpc -f -n -q -t 5 -i rmnet_mhi0.1 +[04-14_06:48:27:363] udhcpc: ifconfig rmnet_mhi0.1 10.245.22.3 netmask 255.255.255.248 broadcast + +[04-14_06:48:27:398] udhcpc: setting default routers: 10.245.22.4 +[04-14_06:48:27:491] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: 5G_NSA + +root@OpenWrt:~# quectel-CM -n 2 -s 4gnet -b & +[04-14_06:48:06:842] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-14_06:48:06:853] network interface '' or qmidev '' is not exist +[04-14_06:48:06:854] netcard driver = pcie_mhi, driver version = V1.3.0.17 +[04-14_06:48:06:855] qmap_mode = 4, qmap_version = 9, qmap_size = 16384, muxid = 0x82, qmap_netcard = rmnet_mhi0.2 +[04-14_06:48:06:855] Modem works in QMI mode +[04-14_06:48:06:857] connect to quectel-qmi-proxy0 sockfd = 7 +[04-14_06:48:06:858] cdc_wdm_fd = 7 +[04-14_06:48:06:864] Get clientWDS = 16 +[04-14_06:48:06:867] Get clientDMS = 3 +[04-14_06:48:06:871] Get clientNAS = 5 +[04-14_06:48:06:874] Get clientUIM = 2 +[04-14_06:48:06:879] Get clientWDA = 2 +[04-14_06:48:06:886] requestBaseBandVersion RM500QGLABR10A03M4G +[04-14_06:48:06:891] qmap_settings.rx_urb_size = 16384 +[04-14_06:48:06:891] qmap_settings.ul_data_aggregation_max_datagrams = 11 +[04-14_06:48:06:892] qmap_settings.ul_data_aggregation_max_size = 8192 +[04-14_06:48:06:892] qmap_settings.dl_minimum_padding = 0 +[04-14_06:48:06:909] requestGetSIMStatus SIMStatus: SIM_READY +[04-14_06:48:06:909] requestSetProfile[2] 4gnet///0 +[04-14_06:48:06:940] requestGetProfile[2] 4gnet///0 +[04-14_06:48:06:944] requestRegistrationState2 MCC: 0, MNC: 0, PS: Detached, DataCap: UNKNOW +[04-14_06:48:06:949] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED +[04-14_06:48:06:949] ifconfig rmnet_mhi0 down +[04-14_06:48:06:973] ifconfig rmnet_mhi0.2 0.0.0.0 +[04-14_06:48:06:998] ifconfig rmnet_mhi0.2 down +[04-14_06:48:26:400] requestRegistrationState2 MCC: 460, MNC: 0, PS: Detached, DataCap: UNKNOW +[04-14_06:48:26:405] requestRegistrationState2 MCC: 460, MNC: 0, PS: Detached, DataCap: UNKNOW +[04-14_06:48:26:411] requestRegistrationState2 MCC: 460, MNC: 0, PS: Detached, DataCap: UNKNOW +[04-14_06:48:26:970] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: 5G_NSA +[04-14_06:48:27:220] requestSetupDataCall WdsConnectionIPv4Handle: 0x341450a0 +[04-14_06:48:27:228] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: 5G_NSA +[04-14_06:48:27:238] ifconfig rmnet_mhi0 up +[04-14_06:48:27:263] ifconfig rmnet_mhi0.2 up +[04-14_06:48:27:313] echo '0xaf51be9' > /sys/class/net/rmnet_mhi0.2/bridge_ipv4 + +root@OpenWrt:~# ifconfig rmnet_mhi0.1 +rmnet_mhi0.1 Link encap:Ethernet HWaddr 02:50:F4:00:00:00 + inet addr:10.245.22.3 Mask:255.255.255.248 + inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link + UP RUNNING NOARP MTU:1500 Metric:1 + RX packets:6 errors:0 dropped:0 overruns:0 frame:0 + TX packets:6 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:1836 (1.7 KiB) TX bytes:2052 (2.0 KiB) + +root@OpenWrt:~# ifconfig rmnet_mhi0.2 +rmnet_mhi0.2 Link encap:Ethernet HWaddr 02:50:F4:00:00:00 + inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link + UP RUNNING NOARP MTU:1500 Metric:1 + RX packets:347 errors:0 dropped:0 overruns:0 frame:0 + TX packets:795 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:119871 (117.0 KiB) TX bytes:121254 (118.4 KiB) + +root@OpenWrt:~# ifconfig br0 up +[ 520.005476] rmnet_mhi0.2 PC Mac Address: 00:0e:c6:a6:6c:f1 +[ 520.025896] rmnet_mhi0.2 PC Mac Address: 00:0e:c6:a6:6c:f1 +[ 520.028002] rmnet_mhi0.2 PC Mac Address: 00:0e:c6:a6:6c:f1 +[ 520.144371] rmnet_mhi0.2 sip = 10.245.27.233, tip=10.245.27.234, ipv4=10.245.27.233 +[ 520.410052] rmnet_mhi0.2 sip = 0.0.0.0, tip=10.245.27.233, ipv4=10.245.27.233 +[ 520.414504] rmnet_mhi0.2 sip = 10.245.27.233, tip=10.245.27.234, ipv4=10.245.27.233 +[ 520.847074] rmnet_mhi0.2 sip = 10.245.27.233, tip=10.245.27.234, ipv4=10.245.27.233 +[ 521.410241] rmnet_mhi0.2 sip = 0.0.0.0, tip=10.245.27.233, ipv4=10.245.27.233 +[ 522.410455] rmnet_mhi0.2 sip = 0.0.0.0, tip=10.245.27.233, ipv4=10.245.27.233 +[ 522.822594] rmnet_mhi0.2 sip = 10.245.27.233, tip=10.245.27.234, ipv4=10.245.27.233 +[ 523.410638] rmnet_mhi0.2 sip = 10.245.27.233, tip=10.245.27.233, ipv4=10.245.27.233 +[ 523.510028] rmnet_mhi0.2 sip = 10.245.27.233, tip=10.245.27.234, ipv4=10.245.27.233 +[ 523.997961] rmnet_mhi0.2 sip = 10.245.27.233, tip=10.245.27.234, ipv4=10.245.27.233 +[ 543.799483] rmnet_mhi0.2 sip = 10.245.27.233, tip=10.245.27.234, ipv4=10.245.27.233 +[ 543.929301] rmnet_mhi0.2 sip = 10.245.27.233, tip=10.245.27.234, ipv4=10.245.27.233 + diff --git a/wwan/app/quectel-cm/src/log/qmi_wwan_q.txt b/wwan/app/quectel-cm/src/log/qmi_wwan_q.txt new file mode 100644 index 0000000..161dbbd --- /dev/null +++ b/wwan/app/quectel-cm/src/log/qmi_wwan_q.txt @@ -0,0 +1,65 @@ +root@ZhuoTK:/# dmesg +[ 15.840000] qmi_wwan_q 1-1.3:1.4: cdc-wdm0: USB WDM device +[ 15.860000] qmi_wwan_q 1-1.3:1.4: Quectel Android work on RawIP mode +[ 15.860000] qmi_wwan_q 1-1.3:1.4: rx_urb_size = 1520 +[ 15.870000] qmi_wwan_q 1-1.3:1.4 wwan0: register 'qmi_wwan_q' at usb-101c0000.ehci-1.3, WWAN/QMI device, da:0b:ce:b2:db:21 + +root@ZhuoTK:/# quectel-CM -s cment & +[04-13_03:20:20:456] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-13_03:20:20:459] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x003 +[04-13_03:20:20:460] Auto find qmichannel = /dev/cdc-wdm0 +[04-13_03:20:20:460] Auto find usbnet_adapter = wwan0 +[04-13_03:20:20:461] netcard driver = qmi_wwan_q, driver version = V1.2.0.23 +[04-13_03:20:20:461] Modem works in QMI mode +[04-13_03:20:20:469] cdc_wdm_fd = 7 +[04-13_03:20:20:547] Get clientWDS = 4 +[04-13_03:20:20:579] Get clientDMS = 1 +[04-13_03:20:20:611] Get clientNAS = 4 +[04-13_03:20:20:643] Get clientUIM = 1 +[04-13_03:20:20:675] Get clientWDA = 1 +[04-13_03:20:20:707] requestBaseBandVersion EC25EFAR06A11M4G +[04-13_03:20:20:836] requestGetSIMStatus SIMStatus: SIM_READY +[04-13_03:20:20:836] requestSetProfile[1] cment///0 +[04-13_03:20:20:899] requestGetProfile[1] cment///0 +[04-13_03:20:20:931] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE +[04-13_03:20:20:963] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED +[04-13_03:20:20:963] ifconfig wwan0 0.0.0.0 +[04-13_03:20:20:976] ifconfig wwan0 down +[04-13_03:20:21:186] requestSetupDataCall WdsConnectionIPv4Handle: 0x8723e780 +[04-13_03:20:21:316] ifconfig wwan0 up +[04-13_03:20:21:329] you are use OpenWrt? +[04-13_03:20:21:330] should not calling udhcpc manually? +[04-13_03:20:21:330] should modify /etc/config/network as below? +[04-13_03:20:21:330] config interface wan +[04-13_03:20:21:330] option ifname wwan0 +[04-13_03:20:21:330] option proto dhcp +[04-13_03:20:21:330] should use "/sbin/ifstaus wan" to check wwan0 's status? +[04-13_03:20:21:331] busybox udhcpc -f -n -q -t 5 -i wwan0 +[04-13_03:20:21:341] udhcpc (v1.23.2) started +[04-13_03:20:21:353] Sending discover... +[04-13_03:20:21:362] Sending select for 10.90.1.113... +[04-13_03:20:21:365] Lease of 10.90.1.113 obtained, lease time 7200 +[04-13_03:20:21:370] udhcpc: ifconfig wwan0 10.90.1.113 netmask 255.255.255.252 broadcast + +[04-13_03:20:21:380] udhcpc: setting default routers: 10.90.1.114 + +root@ZhuoTK:/# ifconfig wwan0 +wwan0 Link encap:Ethernet HWaddr 00:CA:01:91:97:BA + inet addr:10.90.1.113 Mask:255.255.255.252 + inet6 addr: fe80::2ca:1ff:fe91:97ba/64 Scope:Link + UP RUNNING NOARP MTU:1500 Metric:1 + RX packets:38 errors:0 dropped:0 overruns:0 frame:0 + TX packets:46 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:5244 (5.1 KiB) TX bytes:6964 (6.8 KiB) + +root@ZhuoTK:/# ip ro show +default via 10.90.1.114 dev wwan0 +10.90.1.112/30 dev wwan0 proto kernel scope link src 10.90.1.113 +192.168.1.0/24 dev br-lan proto kernel scope link src 192.168.1.251 + +root@ZhuoTK:/# killall quectel-CM +[04-13_03:20:46:130] requestDeactivateDefaultPDP WdsConnectionIPv4Handle +[04-13_03:20:46:406] ifconfig wwan0 0.0.0.0 +[04-13_03:20:46:418] ifconfig wwan0 down +[04-13_03:20:46:600] QmiWwanThread exit +[04-13_03:20:46:600] qmi_main exit diff --git a/wwan/app/quectel-cm/src/log/qmi_wwan_q_bridge.txt b/wwan/app/quectel-cm/src/log/qmi_wwan_q_bridge.txt new file mode 100644 index 0000000..b979af9 --- /dev/null +++ b/wwan/app/quectel-cm/src/log/qmi_wwan_q_bridge.txt @@ -0,0 +1,57 @@ +root@ZhuoTK:/# insmod qmi_wwan_q.ko +[ 116.910000] qmi_wwan_q 1-1.3:1.4: cdc-wdm0: USB WDM device +[ 116.930000] qmi_wwan_q 1-1.3:1.4: Quectel Android work on RawIP mode +[ 116.930000] qmi_wwan_q 1-1.3:1.4: rx_urb_size = 1520 +[ 116.940000] qmi_wwan_q 1-1.3:1.4 wwan0: register 'qmi_wwan_q' at usb-101c0000.ehci-1.3, WWAN/QMI device, 06:fb:51:a3:d6:c5 +[ 116.950000] usbcore: registered new interface driver qmi_wwan_q + +root@ZhuoTK:/# brctl addbr br0 +root@ZhuoTK:/# brctl addif br0 eth0.1 +root@ZhuoTK:/# brctl addif br0 wwan0 +root@ZhuoTK:/# brctl show +bridge name bridge id STP enabled interfaces +br0 8000.00ca019197b9 no eth0.1 + wwan0 + +root@ZhuoTK:/# quectel-CM -s cmnet -b & +root@ZhuoTK:/# [04-13_05:13:39:369] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-13_05:13:39:372] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x003 +[ 143.340000] net wwan0: bridge_mode change to 0x1 +[04-13_05:13:39:373] Auto find qmichannel = /dev/cdc-wdm0 +[04-13_05:13:39:374] Auto find usbnet_adapter = wwan0 +[04-13_05:13:39:374] netcard driver = qmi_wwan_q, driver version = V1.2.0.23 +[04-13_05:13:39:380] Modem works in QMI mode +[04-13_05:13:39:388] cdc_wdm_fd = 7 +[04-13_05:13:39:466] Get clientWDS = 5 +[04-13_05:13:39:496] Get clientDMS = 2 +[04-13_05:13:39:527] Get clientNAS = 4 +[04-13_05:13:39:559] Get clientUIM = 1 +[04-13_05:13:39:592] Get clientWDA = 1 +[04-13_05:13:39:626] requestBaseBandVersion EC25EFAR06A11M4G +[04-13_05:13:39:752] requestGetSIMStatus SIMStatus: SIM_READY +[04-13_05:13:39:752] requestSetProfile[1] cmnet///0 +[04-13_05:13:39:816] requestGetProfile[1] cmnet///0 +[04-13_05:13:39:848] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE +[04-13_05:13:39:879] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED +[04-13_05:13:39:880] ifconfig wwan0 0.0.0.0 +[04-13_05:13:39:893] ifconfig wwan0 down +[04-13_05:13:39:943] requestSetupDataCall WdsConnectionIPv4Handle: 0x872627c0 +[04-13_05:13:40:073] ifconfig wwan0 up +[04-13_05:13:40:085] echo '0xa8d9237' > /sys/class/net/wwan0/bridge_ipv4 + +root@ZhuoTK:/# ifconfig br0 up +[ 165.730000] wwan0 PC Mac Address: 00:0e:c6:a6:6c:f1 +[ 165.750000] wwan0 PC Mac Address: 00:0e:c6:a6:6c:f1 +[ 165.860000] wwan0 sip = 10.141.146.55, tip=10.141.146.56, ipv4=10.141.146.55 +[ 165.870000] wwan0 sip = 10.141.146.55, tip=10.141.146.56, ipv4=10.141.146.55 +[ 165.990000] wwan0 sip = 10.141.146.55, tip=10.141.146.56, ipv4=10.141.146.55 +[ 166.010000] wwan0 sip = 0.0.0.0, tip=10.141.146.55, ipv4=10.141.146.55 +[ 166.070000] wwan0 sip = 10.141.146.55, tip=10.141.146.56, ipv4=10.141.146.55 +[ 167.010000] wwan0 sip = 0.0.0.0, tip=10.141.146.55, ipv4=10.141.146.55 +[ 167.480000] br0: port 2(wwan0) entered forwarding state +[ 167.520000] br0: port 1(eth0.1) entered forwarding state +[ 168.020000] wwan0 sip = 0.0.0.0, tip=10.141.146.55, ipv4=10.141.146.55 +[ 169.010000] wwan0 sip = 10.141.146.55, tip=10.141.146.55, ipv4=10.141.146.55 +[ 169.120000] wwan0 sip = 10.141.146.55, tip=10.141.146.56, ipv4=10.141.146.55 +[ 169.130000] wwan0 sip = 10.141.146.55, tip=10.141.146.56, ipv4=10.141.146.55 +[ 176.620000] wwan0 sip = 10.141.146.55, tip=10.141.146.56, ipv4=10.141.146.55 diff --git a/wwan/app/quectel-cm/src/log/qmi_wwan_q_qmap=1.txt b/wwan/app/quectel-cm/src/log/qmi_wwan_q_qmap=1.txt new file mode 100644 index 0000000..9f088e5 --- /dev/null +++ b/wwan/app/quectel-cm/src/log/qmi_wwan_q_qmap=1.txt @@ -0,0 +1,54 @@ +root@ZhuoTK:/# insmod qmi_wwan_q.ko qmap_mode=1 +[ 1367.200000] usbcore: registered new interface driver qmi_wwan_q +[ 1383.840000] usb 1-1.3: new high-speed USB device number 7 using ehci-platform +[ 1384.080000] qmi_wwan_q 1-1.3:1.4: cdc-wdm0: USB WDM device +[ 1384.080000] qmi_wwan_q 1-1.3:1.4: Quectel Android work on RawIP mode +[ 1384.100000] qmi_wwan_q 1-1.3:1.4: rx_urb_size = 4096 +[ 1384.100000] qmi_wwan_q 1-1.3:1.4 wwan0: register 'qmi_wwan_q' at usb-101c0000.ehci-1.3, WWAN/QMI device, da:0b:ce:b2:db:21 + +root@ZhuoTK:/# quectel-CM -s cmnet & +[04-13_03:41:28:144] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-13_03:41:28:146] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x007 +[04-13_03:41:28:148] Auto find qmichannel = /dev/cdc-wdm0 +[04-13_03:41:28:148] Auto find usbnet_adapter = wwan0 +[04-13_03:41:28:148] netcard driver = qmi_wwan_q, driver version = V1.2.0.23 +[04-13_03:41:28:149] qmap_mode = 1, qmap_version = 5, qmap_size = 4096, muxid = 0x81, qmap_netcard = wwan0 +[04-13_03:41:28:150] Modem works in QMI mode +[04-13_03:41:28:158] cdc_wdm_fd = 7 +[04-13_03:41:28:238] Get clientWDS = 4 +[04-13_03:41:28:271] Get clientDMS = 1 +[04-13_03:41:28:302] Get clientNAS = 4 +[04-13_03:41:28:334] Get clientUIM = 1 +[04-13_03:41:28:365] Get clientWDA = 1 +[04-13_03:41:28:397] requestBaseBandVersion EC25EFAR06A11M4G +[04-13_03:41:28:430] qmap_settings.rx_urb_size = 4096 +[ 1393.530000] net wwan0: ul_data_aggregation_max_datagrams=11, ul_data_aggregation_max_size=4096, dl_minimum_padding=0 +[04-13_03:41:28:431] qmap_settings.ul_data_aggregation_max_datagrams = 11 +[04-13_03:41:28:431] qmap_settings.ul_data_aggregation_max_size = 4096 +[04-13_03:41:28:431] qmap_settings.dl_minimum_padding = 0 +[04-13_03:41:28:557] requestGetSIMStatus SIMStatus: SIM_READY +[04-13_03:41:28:558] requestSetProfile[1] cmnet///0 +[04-13_03:41:28:622] requestGetProfile[1] cmnet///0 +[04-13_03:41:28:654] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE +[04-13_03:41:28:685] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED +[ 1393.790000] net wwan0: link_state 0x1 -> 0x0 +[04-13_03:41:28:692] ifconfig wwan0 0.0.0.0 +[04-13_03:41:28:703] ifconfig wwan0 down +[04-13_03:41:28:751] requestSetupDataCall WdsConnectionIPv4Handle: 0x8729a6b0 +[ 1393.980000] net wwan0: link_state 0x0 -> 0x1 +[04-13_03:41:28:882] ifconfig wwan0 up +[04-13_03:41:28:895] you are use OpenWrt? +[04-13_03:41:28:895] should not calling udhcpc manually? +[04-13_03:41:28:895] should modify /etc/config/network as below? +[04-13_03:41:28:896] config interface wan +[04-13_03:41:28:896] option ifname wwan0 +[04-13_03:41:28:896] option proto dhcp +[04-13_03:41:28:896] should use "/sbin/ifstaus wan" to check wwan0 's status? +[04-13_03:41:28:896] busybox udhcpc -f -n -q -t 5 -i wwan0 +[04-13_03:41:28:907] udhcpc (v1.23.2) started +[04-13_03:41:28:919] Sending discover... +[04-13_03:41:28:925] Sending select for 10.129.198.20... +[04-13_03:41:28:929] Lease of 10.129.198.20 obtained, lease time 7200 +[04-13_03:41:28:934] udhcpc: ifconfig wwan0 10.129.198.20 netmask 255.255.255.248 broadcast + +[04-13_03:41:28:949] udhcpc: setting default routers: 10.129.198.21 + diff --git a/wwan/app/quectel-cm/src/log/qmi_wwan_q_qmap=1_bridge.txt b/wwan/app/quectel-cm/src/log/qmi_wwan_q_qmap=1_bridge.txt new file mode 100644 index 0000000..05919d6 --- /dev/null +++ b/wwan/app/quectel-cm/src/log/qmi_wwan_q_qmap=1_bridge.txt @@ -0,0 +1,86 @@ +root@ZhuoTK:/# insmod qmi_wwan_q.ko qmap_mode=1 +[ 49.000000] qmi_wwan_q 1-1.3:1.4: cdc-wdm0: USB WDM device +[ 49.000000] qmi_wwan_q 1-1.3:1.4: Quectel Android work on RawIP mode +[ 49.020000] qmi_wwan_q 1-1.3:1.4: rx_urb_size = 4096 +[ 49.020000] qmi_wwan_q 1-1.3:1.4 wwan0: register 'qmi_wwan_q' at usb-101c0000.ehci-1.3, WWAN/QMI device, de:ae:5c:82:b5:b2 +[ 49.030000] usbcore: registered new interface driver qmi_wwan_q + +root@ZhuoTK:/# brctl addbr br0 +root@ZhuoTK:/# brctl addif br0 eth0.1 +root@ZhuoTK:/# brctl addif br0 wwan0 +root@ZhuoTK:/# brctl show +bridge name bridge id STP enabled interfaces +br0 8000.00ca019197b9 no eth0.1 + wwan0 + +root@ZhuoTK:/# quectel-CM -s cmnet -b & +[04-13_05:11:46:442] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-13_05:11:46:444] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x003 +[ 84.340000] net wwan0: bridge_mode change to 0x1 +[04-13_05:11:46:446] Auto find qmichannel = /dev/cdc-wdm0 +[04-13_05:11:46:446] Auto find usbnet_adapter = wwan0 +[04-13_05:11:46:446] netcard driver = qmi_wwan_q, driver version = V1.2.0.23 +[04-13_05:11:46:447] qmap_mode = 1, qmap_version = 5, qmap_size = 4096, muxid = 0x81, qmap_netcard = wwan0 +[04-13_05:11:46:454] Modem works in QMI mode +[04-13_05:11:46:462] cdc_wdm_fd = 7 +[04-13_05:11:46:537] Get clientWDS = 5 +[04-13_05:11:46:569] Get clientDMS = 1 +[04-13_05:11:46:601] Get clientNAS = 4 +[04-13_05:11:46:633] Get clientUIM = 1 +[04-13_05:11:46:666] Get clientWDA = 1 +[04-13_05:11:46:697] requestBaseBandVersion EC25EFAR06A11M4G +[04-13_05:11:46:730] qmap_settings.rx_urb_size = 4096 +[ 84.620000] net wwan0: ul_data_aggregation_max_datagrams=11, ul_data_aggregation_max_size=4096, dl_minimum_padding=0 +[04-13_05:11:46:730] qmap_settings.ul_data_aggregation_max_datagrams = 11 +[04-13_05:11:46:730] qmap_settings.ul_data_aggregation_max_size = 4096 +[04-13_05:11:46:730] qmap_settings.dl_minimum_padding = 0 +[04-13_05:11:46:859] requestGetSIMStatus SIMStatus: SIM_READY +[04-13_05:11:46:859] requestSetProfile[1] cmnet///0 +[04-13_05:11:46:922] requestGetProfile[1] cmnet///0 +[04-13_05:11:46:954] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE +[04-13_05:11:46:986] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED +[ 84.880000] net wwan0: link_state 0x1 -> 0x0 +[04-13_05:11:46:992] ifconfig wwan0 0.0.0.0 +[04-13_05:11:47:005] ifconfig wwan0 down +[04-13_05:11:47:050] requestSetupDataCall WdsConnectionIPv4Handle: 0x872a5830 +[ 85.070000] net wwan0: link_state 0x0 -> 0x1 +[04-13_05:11:47:183] ifconfig wwan0 up +[04-13_05:11:47:195] echo '0xa54a78b' > /sys/class/net/wwan0/bridge_ipv4 + +root@ZhuoTK:/# ifconfig wwan0 +wwan0 Link encap:Ethernet HWaddr DE:AE:5C:82:B5:B2 + inet6 addr: fe80::dcae:5cff:fe82:b5b2/64 Scope:Link + UP RUNNING NOARP MTU:1500 Metric:1 + RX packets:3792 errors:0 dropped:0 overruns:0 frame:0 + TX packets:3271 errors:0 dropped:36 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:2271762 (2.1 MiB) TX bytes:565184 (551.9 KiB) + +root@ZhuoTK:/# ifconfig br0 up +[ 89.530000] br0: port 2(wwan0) entered forwarding state +[ 89.530000] br0: port 2(wwan0) entered forwarding state +[ 89.540000] br0: port 1(eth0.1) entered forwarding state +[ 89.540000] br0: port 1(eth0.1) entered forwarding state + +root@ZhuoTK:/# +[ 93.720000] wwan0 sip = 192.168.1.153, tip=10.84.167.140, ipv4=10.84.167.139 +[ 104.560000] br0: port 2(wwan0) entered forwarding state +[ 104.560000] br0: port 1(eth0.1) entered forwarding state +[ 111.750000] rt305x-esw 10110000.esw: link changed 0x00 +[ 116.440000] rt305x-esw 10110000.esw: link changed 0x01 +[ 116.620000] wwan0 PC Mac Address: 00:0e:c6:a6:6c:f1 +[ 116.680000] wwan0 PC Mac Address: 00:0e:c6:a6:6c:f1 +[ 116.690000] wwan0 PC Mac Address: 00:0e:c6:a6:6c:f1 +[ 116.760000] wwan0 sip = 10.84.167.139, tip=10.84.167.140, ipv4=10.84.167.139 +[ 117.050000] wwan0 sip = 10.84.167.139, tip=10.84.167.140, ipv4=10.84.167.139 +[ 117.220000] wwan0 sip = 0.0.0.0, tip=10.84.167.139, ipv4=10.84.167.139 +[ 117.820000] wwan0 sip = 10.84.167.139, tip=10.84.167.140, ipv4=10.84.167.139 +[ 118.220000] wwan0 sip = 0.0.0.0, tip=10.84.167.139, ipv4=10.84.167.139 +[ 118.300000] wwan0 sip = 10.84.167.139, tip=10.84.167.140, ipv4=10.84.167.139 +[ 119.220000] wwan0 sip = 0.0.0.0, tip=10.84.167.139, ipv4=10.84.167.139 +[ 120.220000] wwan0 sip = 10.84.167.139, tip=10.84.167.139, ipv4=10.84.167.139 +[ 120.300000] wwan0 sip = 10.84.167.139, tip=10.84.167.140, ipv4=10.84.167.139 +[ 121.430000] wwan0 sip = 10.84.167.139, tip=10.84.167.140, ipv4=10.84.167.139 +[ 141.730000] wwan0 sip = 10.84.167.139, tip=10.84.167.140, ipv4=10.84.167.139 +[ 144.390000] wwan0 sip = 10.84.167.139, tip=10.84.167.140, ipv4=10.84.167.139 +[ 144.510000] wwan0 sip = 10.84.167.139, tip=10.84.167.140, ipv4=10.84.167.139 diff --git a/wwan/app/quectel-cm/src/log/qmi_wwan_q_qmap=4.txt b/wwan/app/quectel-cm/src/log/qmi_wwan_q_qmap=4.txt new file mode 100644 index 0000000..6464f27 --- /dev/null +++ b/wwan/app/quectel-cm/src/log/qmi_wwan_q_qmap=4.txt @@ -0,0 +1,185 @@ +root@ZhuoTK:/# insmod qmi_wwan_q.ko qmap_mode=4 +[ 1515.180000] usbcore: registered new interface driver qmi_wwan_q +[ 1530.260000] usb 1-1.3: new high-speed USB device number 8 using ehci-platform +[ 1530.500000] qmi_wwan_q 1-1.3:1.4: cdc-wdm0: USB WDM device +[ 1530.500000] qmi_wwan_q 1-1.3:1.4: Quectel Android work on RawIP mode +[ 1530.520000] qmi_wwan_q 1-1.3:1.4: rx_urb_size = 4096 +[ 1530.520000] qmi_wwan_q 1-1.3:1.4 wwan0: register 'qmi_wwan_q' at usb-101c0000.ehci-1.3, RMNET/USB device, da:0b:ce:b2:db:21 +[ 1530.530000] net wwan0: qmap_register_device wwan0_1 +[ 1530.540000] net wwan0: qmap_register_device wwan0_2 +[ 1530.550000] net wwan0: qmap_register_device wwan0_3 +[ 1530.550000] net wwan0: qmap_register_device wwan0_4 + +root@ZhuoTK:~# quectel-qmi-proxy & +[04-13_03:44:53:958] Will use cdc-wdm='/dev/cdc-wdm0', proxy='quectel-qmi-proxy0' +[04-13_03:44:53:959] qmi_proxy_init enter +[04-13_03:44:53:960] qmi_proxy_loop enter thread_id 0x77c07530 +[04-13_03:44:54:960] qmi_proxy_init succful +[04-13_03:44:54:960] local server: quectel-qmi-proxy0 sockfd = 4 +[04-13_03:44:54:960] qmi_proxy_server_fd = 4 +[04-13_03:45:04:346] +++ ClientFd=5 +[04-13_03:45:04:410] +++ ClientFd=5 QMIType=1 ClientId=4 +[04-13_03:45:04:442] +++ ClientFd=5 QMIType=2 ClientId=1 +[04-13_03:45:04:474] +++ ClientFd=5 QMIType=3 ClientId=4 +[04-13_03:45:04:506] +++ ClientFd=5 QMIType=11 ClientId=1 +[04-13_03:45:04:539] +++ ClientFd=5 QMIType=26 ClientId=1 +[04-13_03:45:10:770] +++ ClientFd=6 +[04-13_03:45:10:811] +++ ClientFd=6 QMIType=1 ClientId=21 +[04-13_03:45:10:843] +++ ClientFd=6 QMIType=2 ClientId=2 +[04-13_03:45:10:875] +++ ClientFd=6 QMIType=3 ClientId=5 +[04-13_03:45:10:907] +++ ClientFd=6 QMIType=11 ClientId=2 +[04-13_03:46:31:419] --- ClientFd=6 QMIType=1 ClientId=21 +[04-13_03:46:31:451] --- ClientFd=6 QMIType=2 ClientId=2 +[04-13_03:46:31:484] --- ClientFd=6 QMIType=3 ClientId=5 +[04-13_03:46:31:517] --- ClientFd=6 QMIType=11 ClientId=2 +[04-13_03:46:31:518] qmi_proxy_loop poll fd = 6, revents = 0011 +[04-13_03:46:31:519] --- ClientFd=6 + +root@ZhuoTK:/# quectel-CM -n 1 -s cmnet & +root@ZhuoTK:/# [04-13_03:45:04:340] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-13_03:45:04:343] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x008 +[04-13_03:45:04:344] Auto find qmichannel = /dev/cdc-wdm0 +[04-13_03:45:04:344] Auto find usbnet_adapter = wwan0 +[04-13_03:45:04:345] netcard driver = qmi_wwan_q, driver version = V1.2.0.23 +[04-13_03:45:04:345] qmap_mode = 4, qmap_version = 5, qmap_size = 4096, muxid = 0x81, qmap_netcard = wwan0_1 +[04-13_03:45:04:345] Modem works in QMI mode +[04-13_03:45:04:347] connect to quectel-qmi-proxy0 sockfd = 7 +[04-13_03:45:04:347] cdc_wdm_fd = 7 +[04-13_03:45:04:411] Get clientWDS = 4 +[04-13_03:45:04:443] Get clientDMS = 1 +[04-13_03:45:04:475] Get clientNAS = 4 +[04-13_03:45:04:507] Get clientUIM = 1 +[04-13_03:45:04:540] Get clientWDA = 1 +[04-13_03:45:04:571] requestBaseBandVersion EC25EFAR06A11M4G +[04-13_03:45:04:602] qmap_settings.rx_urb_size = 4096 +[ 1609.700000] net wwan0: ul_data_aggregation_max_datagrams=11, ul_data_aggregation_max_size=4096, dl_minimum_padding=0 +[04-13_03:45:04:603] qmap_settings.ul_data_aggregation_max_datagrams = 11 +[04-13_03:45:04:603] qmap_settings.ul_data_aggregation_max_size = 4096 +[04-13_03:45:04:603] qmap_settings.dl_minimum_padding = 0 +[04-13_03:45:04:731] requestGetSIMStatus SIMStatus: SIM_READY +[04-13_03:45:04:731] requestSetProfile[1] cmnet///0 +[04-13_03:45:04:795] requestGetProfile[1] cmnet///0 +[04-13_03:45:04:827] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE +[04-13_03:45:04:858] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED +[ 1609.960000] net wwan0: link_state 0x1 -> 0x0 +[04-13_03:45:04:865] ifconfig wwan0 down +[04-13_03:45:04:879] ifconfig wwan0_1 0.0.0.0 +[04-13_03:45:04:889] ifconfig wwan0_1 down +[04-13_03:45:04:955] requestSetupDataCall WdsConnectionIPv4Handle: 0x87253410 +[ 1610.180000] net wwan0: link_state 0x0 -> 0x1 +[04-13_03:45:05:087] ifconfig wwan0 up +[ 1610.200000] IPv6: ADDRCONF(NETDEV_UP): wwan0: link is not ready +[04-13_03:45:05:105] ifconfig wwan0_1 up +[ 1610.220000] IPv6: ADDRCONF(NETDEV_CHANGE): wwan0: link becomes ready +[04-13_03:45:05:125] you are use OpenWrt? +[04-13_03:45:05:125] should not calling udhcpc manually? +[04-13_03:45:05:125] should modify /etc/config/network as below? +[04-13_03:45:05:125] config interface wan +[04-13_03:45:05:125] option ifname wwan0_1 +[04-13_03:45:05:125] option proto dhcp +[04-13_03:45:05:126] should use "/sbin/ifstaus wan" to check wwan0_1 's status? +[04-13_03:45:05:126] busybox udhcpc -f -n -q -t 5 -i wwan0_1 +[04-13_03:45:05:136] udhcpc (v1.23.2) started +[04-13_03:45:05:148] Sending discover... +[04-13_03:45:05:155] Sending select for 10.244.10.206... +[04-13_03:45:05:160] Lease of 10.244.10.206 obtained, lease time 7200 +[04-13_03:45:05:165] udhcpc: ifconfig wwan0_1 10.244.10.206 netmask 255.255.255.252 broadcast + +[04-13_03:45:05:174] udhcpc: setting default routers: 10.244.10.205 + +root@ZhuoTK:/# quectel-CM -n 2 -s 4gnet & +[04-13_03:45:10:764] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-13_03:45:10:767] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x008 +[04-13_03:45:10:768] Auto find qmichannel = /dev/cdc-wdm0 +[04-13_03:45:10:768] Auto find usbnet_adapter = wwan0 +[04-13_03:45:10:768] netcard driver = qmi_wwan_q, driver version = V1.2.0.23 +[04-13_03:45:10:769] qmap_mode = 4, qmap_version = 5, qmap_size = 4096, muxid = 0x82, qmap_netcard = wwan0_2 +[04-13_03:45:10:769] Modem works in QMI mode +[04-13_03:45:10:771] connect to quectel-qmi-proxy0 sockfd = 7 +[04-13_03:45:10:771] cdc_wdm_fd = 7 +[04-13_03:45:10:812] Get clientWDS = 21 +[04-13_03:45:10:844] Get clientDMS = 2 +[04-13_03:45:10:876] Get clientNAS = 5 +[04-13_03:45:10:908] Get clientUIM = 2 +[04-13_03:45:10:971] requestBaseBandVersion EC25EFAR06A11M4G +[04-13_03:45:11:099] requestGetSIMStatus SIMStatus: SIM_READY +[04-13_03:45:11:099] requestSetProfile[2] 4gnet///0 +[04-13_03:45:11:163] requestGetProfile[2] 4gnet///0 +[04-13_03:45:11:195] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE +[04-13_03:45:11:227] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED +[04-13_03:45:11:227] ifconfig wwan0_2 0.0.0.0 +[ 1616.340000] IPv6: ADDRCONF(NETDEV_UP): wwan0_2: link is not ready +[04-13_03:45:11:246] ifconfig wwan0_2 down +[04-13_03:45:11:642] requestSetupDataCall WdsConnectionIPv4Handle: 0x87254580 +[ 1616.870000] net wwan0: link_state 0x1 -> 0x3 +[04-13_03:45:11:775] ifconfig wwan0 up +[04-13_03:45:11:785] ifconfig wwan0_2 up +[04-13_03:45:11:798] you are use OpenWrt? +[04-13_03:45:11:798] should not calling udhcpc manually? +[04-13_03:45:11:798] should modify /etc/config/network as below? +[04-13_03:45:11:798] config interface wan +[04-13_03:45:11:798] option ifname wwan0_2 +[04-13_03:45:11:798] option proto dhcp +[04-13_03:45:11:798] should use "/sbin/ifstaus wan" to check wwan0_2 's status? +[04-13_03:45:11:799] busybox udhcpc -f -n -q -t 5 -i wwan0_2 +[04-13_03:45:11:809] udhcpc (v1.23.2) started +[04-13_03:45:11:821] Sending discover... +[04-13_03:45:11:830] Sending select for 10.245.78.212... +[04-13_03:45:11:836] Lease of 10.245.78.212 obtained, lease time 7200 +[04-13_03:45:11:842] udhcpc: ifconfig wwan0_2 10.245.78.212 netmask 255.255.255.248 broadcast + +[04-13_03:45:11:852] udhcpc: setting default routers: 10.245.78.213 + +root@ZhuoTK:/# ifconfig wwan0_1 +wwan0_1 Link encap:Ethernet HWaddr DA:0B:CE:B2:DB:21 + inet addr:10.244.10.206 Mask:255.255.255.252 + inet6 addr: fe80::d80b:ceff:feb2:db21/64 Scope:Link + UP RUNNING NOARP MTU:1500 Metric:1 + RX packets:2 errors:0 dropped:0 overruns:0 frame:0 + TX packets:4 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:640 (640.0 B) TX bytes:1344 (1.3 KiB) + +root@ZhuoTK:/# ifconfig wwan0_2 +wwan0_2 Link encap:Ethernet HWaddr DA:0B:CE:B2:DB:21 + inet addr:10.245.78.212 Mask:255.255.255.248 + inet6 addr: fe80::d80b:ceff:feb2:db21/64 Scope:Link + UP RUNNING NOARP MTU:1500 Metric:1 + RX packets:8 errors:0 dropped:0 overruns:0 frame:0 + TX packets:7 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:1193 (1.1 KiB) TX bytes:1028 (1.0 KiB) + +root@ZhuoTK:/# ip ro del 8.8.8.8/32 +RTNETLINK answers: No such process + +root@ZhuoTK:/# ip ro add 8.8.8.8/32 dev wwan0_1 +root@ZhuoTK:/# ping 8.8.8.8 +PING 8.8.8.8 (8.8.8.8): 56 data bytes +64 bytes from 8.8.8.8: seq=0 ttl=52 time=113.508 ms + +root@ZhuoTK:/# ip ro del 8.8.8.8/32 +root@ZhuoTK:/# ip ro del 8.8.8.8/32 +RTNETLINK answers: No such process + +root@ZhuoTK:/# ip ro add 8.8.8.8/32 dev wwan0_2 +root@ZhuoTK:/# ping 8.8.8.8 +PING 8.8.8.8 (8.8.8.8): 56 data bytes +64 bytes from 8.8.8.8: seq=0 ttl=111 time=123.651 ms + +root@ZhuoTK:/# quectel-CM -k 2 +[04-13_03:46:30:808] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-13_03:46:30:811] /proc/2834/cmdline: quectel-CM -n 2 -s 4gnet +[04-13_03:46:30:811] send SIGINT to process 2834 +[04-13_03:46:30:811] requestDeactivateDefaultPDP WdsConnectionIPv4Handle +[ 1696.460000] net wwan0: link_state 0x3 -> 0x1 +[04-13_03:46:31:361] ifconfig wwan0_2 0.0.0.0 +[04-13_03:46:31:373] ifconfig wwan0_2 down +[04-13_03:46:31:516] QmiWwanThread exit +[04-13_03:46:31:516] qmi_main exit + +root@ZhuoTK:/# ifconfig wwan0_2 +wwan0_2 Link encap:Ethernet HWaddr DA:0B:CE:B2:DB:21 + NOARP MTU:1500 Metric:1 + RX packets:16 errors:0 dropped:0 overruns:0 frame:0 + TX packets:15 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:1865 (1.8 KiB) TX bytes:1620 (1.5 KiB) diff --git a/wwan/app/quectel-cm/src/log/qmi_wwan_q_qmap=4_bridge.txt b/wwan/app/quectel-cm/src/log/qmi_wwan_q_qmap=4_bridge.txt new file mode 100644 index 0000000..504d11a --- /dev/null +++ b/wwan/app/quectel-cm/src/log/qmi_wwan_q_qmap=4_bridge.txt @@ -0,0 +1,132 @@ +root@ZhuoTK:/# brctl addbr br0 +brctl: bridge br0: File exists +root@ZhuoTK:/# brctl delbr br0 +root@ZhuoTK:/# brctl addbr br0 +root@ZhuoTK:/# brctl addif br0 eth0.1 + +root@ZhuoTK:/# insmod qmi_wwan_q.ko qmap_mode=4 +[ 365.340000] usbcore: registered new interface driver qmi_wwan_q +[ 380.860000] usb 1-1.3: new high-speed USB device number 4 using ehci-platform +[ 381.100000] qmi_wwan_q 1-1.3:1.4: cdc-wdm0: USB WDM device +[ 381.100000] qmi_wwan_q 1-1.3:1.4: Quectel Android work on RawIP mode +[ 381.120000] qmi_wwan_q 1-1.3:1.4: rx_urb_size = 4096 +[ 381.120000] qmi_wwan_q 1-1.3:1.4 wwan0: register 'qmi_wwan_q' at usb-101c0000.ehci-1.3, RMNET/USB device, fa:24:73:b5:39:a8 +[ 381.130000] net wwan0: qmap_register_device wwan0_1 +[ 381.140000] net wwan0: qmap_register_device wwan0_2 +[ 381.150000] net wwan0: qmap_register_device wwan0_3 +[ 381.150000] net wwan0: qmap_register_device wwan0_4 + +root@ZhuoTK:/# brctl addbr br0 +root@ZhuoTK:/# brctl addif br0 eth0.1 +root@ZhuoTK:/# brctl addif br0 wwan0_2 +root@ZhuoTK:/# brctl show +bridge name bridge id STP enabled interfaces +br0 8000.00ca019197b9 no eth0.1 + wwan0_2 + +root@ZhuoTK:/# quectel-qmi-proxy & +[04-13_05:18:10:832] Will use cdc-wdm='/dev/cdc-wdm0', proxy='quectel-qmi-proxy0' +[04-13_05:18:10:833] qmi_proxy_init enter +[04-13_05:18:10:833] qmi_proxy_loop enter thread_id 0x77995530 +[04-13_05:18:11:833] qmi_proxy_init succful +[04-13_05:18:11:833] local server: quectel-qmi-proxy0 sockfd = 4 +[04-13_05:18:11:833] qmi_proxy_server_fd = 4 + +root@ZhuoTK:/# quectel-CM -n 2 -s 4gnet -b & +[04-13_05:18:20:144] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-13_05:18:20:146] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x004 +[04-13_05:18:20:147] Auto find qmichannel = /dev/cdc-wdm0 +[04-13_05:18:20:148] Auto find usbnet_adapter = wwan0 +[04-13_05:18:20:148] netcard driver = qmi_wwan_q, driver version = V1.2.0.23 +[04-13_05:18:20:148] qmap_mode = 4, qmap_version = 5, qmap_size = 4096, muxid = 0x82, qmap_netcard = wwan0_2 +[04-13_05:18:20:149] Modem works in QMI mode +[04-13_05:18:20:150] connect to quectel-qmi-proxy0 sockfd = 7 +[04-13_05:18:20:150] cdc_wdm_fd = 7 +[04-13_05:18:20:370] requestBaseBandVersion EC25EFAR06A11M4G +[04-13_05:18:20:403] qmap_settings.rx_urb_size = 4096 +[04-13_05:18:20:404] qmap_settings.ul_data_aggregation_max_datagrams = 11 +[04-13_05:18:20:404] qmap_settings.ul_data_aggregation_max_size = 4096 +[04-13_05:18:20:404] qmap_settings.dl_minimum_padding = 0 +[04-13_05:18:20:530] requestGetSIMStatus SIMStatus: SIM_READY +[04-13_05:18:20:530] requestSetProfile[2] 4gnet///0 +[04-13_05:18:20:594] requestGetProfile[2] 4gnet///0 +[04-13_05:18:20:626] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE +[04-13_05:18:20:657] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED +[04-13_05:18:20:658] ifconfig wwan0_2 0.0.0.0 +[04-13_05:18:20:669] ifconfig wwan0_2 down +[04-13_05:18:21:010] requestSetupDataCall WdsConnectionIPv4Handle: 0x87249650 +[ 425.100000] net wwan0: link_state 0x1 -> 0x3 +[04-13_05:18:21:143] ifconfig wwan0 up +[04-13_05:18:21:156] ifconfig wwan0_2 up +[04-13_05:18:21:168] echo '0xa8ceec7' > /sys/class/net/wwan0_2/bridge_ipv4 + +root@ZhuoTK:/# ifconfig br0 up + +[ 450.520000] br0: port 2(wwan0_2) entered forwarding state +[ 450.520000] br0: port 1(eth0.1) entered forwarding state +[ 450.770000] wwan0_2 PC Mac Address: 00:0e:c6:a6:6c:f1 +[ 450.790000] wwan0_2 PC Mac Address: 00:0e:c6:a6:6c:f1 +[ 450.840000] wwan0_2 sip = 10.140.238.199, tip=10.140.238.200, ipv4=10.140.238.199 +[ 450.950000] wwan0_2 sip = 10.140.238.199, tip=10.140.238.200, ipv4=10.140.238.199 +[ 450.950000] wwan0_2 sip = 10.140.238.199, tip=10.140.238.200, ipv4=10.140.238.199 +[ 451.120000] wwan0_2 sip = 0.0.0.0, tip=10.140.238.199, ipv4=10.140.238.199 +[ 451.180000] wwan0_2 sip = 10.140.238.199, tip=10.140.238.200, ipv4=10.140.238.199 +[ 452.120000] wwan0_2 sip = 0.0.0.0, tip=10.140.238.199, ipv4=10.140.238.199 +[ 453.080000] wwan0_2 sip = 10.140.238.199, tip=10.140.238.200, ipv4=10.140.238.199 +[ 453.120000] wwan0_2 sip = 0.0.0.0, tip=10.140.238.199, ipv4=10.140.238.199 +[ 454.120000] wwan0_2 sip = 10.140.238.199, tip=10.140.238.199, ipv4=10.140.238.199 +[ 454.220000] wwan0_2 sip = 10.140.238.199, tip=10.140.238.200, ipv4=10.140.238.199 +[ 456.200000] wwan0_2 sip = 10.140.238.199, tip=10.140.238.200, ipv4=10.140.238.199 +[ 458.120000] wwan0_2 sip = 10.140.238.199, tip=10.140.238.200, ipv4=10.140.238.199 +[ 459.240000] wwan0_2 sip = 10.140.238.199, tip=10.140.238.200, ipv4=10.140.238.199 + +root@ZhuoTK:/# quectel-CM -n 1 -s cmnet & +[04-13_05:19:21:122] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-13_05:19:21:125] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x004 +[04-13_05:19:21:126] Auto find qmichannel = /dev/cdc-wdm0 +[04-13_05:19:21:126] Auto find usbnet_adapter = wwan0 +[04-13_05:19:21:127] netcard driver = qmi_wwan_q, driver version = V1.2.0.23 +[04-13_05:19:21:127] qmap_mode = 4, qmap_version = 5, qmap_size = 4096, muxid = 0x81, qmap_netcard = wwan0_1 +[04-13_05:19:21:127] Modem works in QMI mode +[04-13_05:19:21:128] connect to quectel-qmi-proxy0 sockfd = 7 +[04-13_05:19:21:129] cdc_wdm_fd = 7 +[04-13_05:19:21:331] requestBaseBandVersion EC25EFAR06A11M4G +[04-13_05:19:21:459] requestGetSIMStatus SIMStatus: SIM_READY +[04-13_05:19:21:459] requestSetProfile[1] cmnet///0 +[04-13_05:19:21:522] requestGetProfile[1] cmnet///0 +[04-13_05:19:21:554] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE +[04-13_05:19:21:585] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED +[ 485.550000] net wwan0: link_state 0x3 -> 0x2 +[04-13_05:19:21:592] ifconfig wwan0_1 0.0.0.0 +[ 485.570000] IPv6: ADDRCONF(NETDEV_UP): wwan0_1: link is not ready +[04-13_05:19:21:610] ifconfig wwan0_1 down +[04-13_05:19:21:682] requestSetupDataCall WdsConnectionIPv4Handle: 0x8725ed70 +[ 485.780000] net wwan0: link_state 0x2 -> 0x3 +[04-13_05:19:21:815] ifconfig wwan0 up +[04-13_05:19:21:826] ifconfig wwan0_1 up +[04-13_05:19:21:845] you are use OpenWrt? +[04-13_05:19:21:845] should not calling udhcpc manually? +[04-13_05:19:21:845] should modify /etc/config/network as below? +[04-13_05:19:21:845] config interface wan +[04-13_05:19:21:845] option ifname wwan0_1 +[04-13_05:19:21:845] option proto dhcp +[04-13_05:19:21:845] should use "/sbin/ifstaus wan" to check wwan0_1 's status? +[04-13_05:19:21:846] busybox udhcpc -f -n -q -t 5 -i wwan0_1 +[04-13_05:19:21:863] udhcpc (v1.23.2) started +[04-13_05:19:21:923] Sending discover... +[04-13_05:19:21:927] Sending select for 10.141.146.55... +[04-13_05:19:21:932] Lease of 10.141.146.55 obtained, lease time 7200 +[04-13_05:19:21:938] udhcpc: ifconfig wwan0_1 10.141.146.55 netmask 255.255.255.240 broadcast + +[04-13_05:19:21:949] udhcpc: setting default routers: 10.141.146.56 + +root@ZhuoTK:/# ip ro show +default via 10.141.146.56 dev wwan0_1 +10.141.146.48/28 dev wwan0_1 proto kernel scope link src 10.141.146.55 +192.168.1.0/24 dev br-lan proto kernel scope link src 192.168.1.251 + +root@ZhuoTK:/# ping 8.8.8.8 +PING 8.8.8.8 (8.8.8.8): 56 data bytes +64 bytes from 8.8.8.8: seq=0 ttl=111 time=86.006 ms +64 bytes from 8.8.8.8: seq=1 ttl=111 time=74.763 ms +64 bytes from 8.8.8.8: seq=2 ttl=111 time=85.501 ms +64 bytes from 8.8.8.8: seq=3 ttl=111 time=74.231 ms diff --git a/wwan/app/quectel-cm/src/log/qmi_wwan_qmap=4.txt b/wwan/app/quectel-cm/src/log/qmi_wwan_qmap=4.txt new file mode 100644 index 0000000..c0067bf --- /dev/null +++ b/wwan/app/quectel-cm/src/log/qmi_wwan_qmap=4.txt @@ -0,0 +1,55 @@ +# dmesg +[ 1737.738025] usb 1-1.2: new high-speed USB device number 5 using xhci-hcd +[ 1737.838917] usb 1-1.2: New USB device found, idVendor=2c7c, idProduct=0512, bcdDevice= 3.18 +[ 1737.838948] usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3 +[ 1737.838963] usb 1-1.2: Product: EG12-EA +[ 1737.838975] usb 1-1.2: Manufacturer: Quectel +[ 1737.838986] usb 1-1.2: SerialNumber: 0123456789ABCDE +[ 1737.994955] option 1-1.2:1.0: GSM modem (1-port) converter detected +[ 1737.995430] usb 1-1.2: GSM modem (1-port) converter now attached to ttyUSB0 +[ 1737.995978] option 1-1.2:1.1: GSM modem (1-port) converter detected +[ 1737.996409] usb 1-1.2: GSM modem (1-port) converter now attached to ttyUSB1 +[ 1737.996963] option 1-1.2:1.2: GSM modem (1-port) converter detected +[ 1737.997351] usb 1-1.2: GSM modem (1-port) converter now attached to ttyUSB2 +[ 1737.997909] option 1-1.2:1.3: GSM modem (1-port) converter detected +[ 1737.998976] usb 1-1.2: GSM modem (1-port) converter now attached to ttyUSB3 +[ 1825.835796] qmi_wwan 1-1.2:1.4: cdc-wdm0: USB WDM device +[ 1825.839685] qmi_wwan 1-1.2:1.4 wwan0: register 'qmi_wwan' at usb-fe9c0000.xhci-1.2, WWAN/QMI device, 0e:80:14:b1:f6:b9 +[ 1825.840062] usbcore: registered new interface driver qmi_wwan + +# ifconfig wwan0 down +# echo Y > /sys/class/net/wwan0/qmi/raw_ip + +# echo 1 > /sys/class/net/wwan0/qmi/add_mux +# ifconfig qmimux0 +qmimux0: flags=4240 mtu 1500 + unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 1000 (UNSPEC) + RX packets 0 bytes 0 (0.0 B) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 0 bytes 0 (0.0 B) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + +# echo 2 > /sys/class/net/wwan0/qmi/add_mux +# echo 3 > /sys/class/net/wwan0/qmi/add_mux +# echo 4 > /sys/class/net/wwan0/qmi/add_mux +# ifconfig qmimux3 +qmimux3: flags=4240 mtu 1500 + unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 1000 (UNSPEC) + RX packets 0 bytes 0 (0.0 B) + RX errors 0 dropped 0 overruns 0 frame 0 + TX packets 0 bytes 0 (0.0 B) + TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 + +set wwan0's mtu to max qmap packet size, for usbnet.c:usbnet_change_mtu() do not accept +# ifconfig wwan0 mtu 16385 + +run qmi proxy programm, +# quectel-CM/quectel-qmi-proxy -d /dev/cdc-wdm0 +or libqmi's qmi-proxy, if use libqmi's qmi-proxy, you can use qmicli to setup data call. +# /usr/libexec/qmi-proxy --verbose --no-exit + +use quectel-CM to setup data call, if use libqmi's qmi-proxy, use '-p qmi-proxy' instead of '-p quectel-qmi-proxy' +# quectel-CM -p quectel-qmi-proxy -n 4 -s cmnet4 +# quectel-CM -p quectel-qmi-proxy -n 1 -s cmnet + +for how to use libqmi to setup data call, please refer to https://knowledge.quectel.com/display/SWSYSTLinuxAndroid/libqmi_How+to+using+QMAP+multiplexing \ No newline at end of file diff --git a/wwan/app/quectel-cm/src/log/usage_of_argument/6.txt b/wwan/app/quectel-cm/src/log/usage_of_argument/6.txt new file mode 100644 index 0000000..5ab9533 --- /dev/null +++ b/wwan/app/quectel-cm/src/log/usage_of_argument/6.txt @@ -0,0 +1,68 @@ +root@OpenWrt:~# quectel-CM -s cmnet -4 -6 +[04-14_06:56:51:778] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-14_06:56:51:779] network interface '' or qmidev '' is not exist +[04-14_06:56:51:780] netcard driver = pcie_mhi, driver version = V1.3.0.17 +[04-14_06:56:51:781] qmap_mode = 4, qmap_version = 9, qmap_size = 16384, muxid = 0x81, qmap_netcard = rmnet_mhi0.1 +[04-14_06:56:51:782] Modem works in QMI mode +[04-14_06:56:51:783] connect to quectel-qmi-proxy0 sockfd = 7 +[04-14_06:56:51:783] cdc_wdm_fd = 7 +[04-14_06:56:51:789] Get clientWDS = 15 +[04-14_06:56:51:792] Get clientWDS = 16 +[04-14_06:56:51:794] Get clientDMS = 3 +[04-14_06:56:51:798] Get clientNAS = 4 +[04-14_06:56:51:801] Get clientUIM = 1 +[04-14_06:56:51:805] Get clientWDA = 1 +[04-14_06:56:51:809] requestBaseBandVersion RM500QGLABR10A03M4G +[04-14_06:56:51:813] qmap_settings.rx_urb_size = 16384 +[04-14_06:56:51:813] qmap_settings.ul_data_aggregation_max_datagrams = 11 +[04-14_06:56:51:814] qmap_settings.ul_data_aggregation_max_size = 8192 +[04-14_06:56:51:814] qmap_settings.dl_minimum_padding = 0 +[04-14_06:56:51:835] requestGetSIMStatus SIMStatus: SIM_READY +[04-14_06:56:51:836] requestSetProfile[1] cmnet///0 +[04-14_06:56:51:848] requestGetProfile[1] cmnet///0 +[04-14_06:56:51:852] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: 5G_NSA +[04-14_06:56:51:857] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED +[04-14_06:56:51:860] requestQueryDataCall IPv6ConnectionStatus: DISCONNECTED +[04-14_06:56:51:861] ifconfig rmnet_mhi0 down +[04-14_06:56:51:885] ifconfig rmnet_mhi0.1 0.0.0.0 +ifconfig: SIOCSIFFLAGS: Network is down +[04-14_06:56:51:909] ifconfig rmnet_mhi0.1 down +[04-14_06:56:51:943] requestSetupDataCall WdsConnectionIPv4Handle: 0x341450a0 +[04-14_06:56:52:423] requestSetupDataCall WdsConnectionIPv6Handle: 0x341439f0 +[ 1001.561353] net rmnet_mhi0: link_state 0x0 -> 0x1 +[04-14_06:56:52:441] ifconfig rmnet_mhi0 up +[ 1001.584623] [I][mhi_netdev_open] Opened net dev interface +[04-14_06:56:52:467] ifconfig rmnet_mhi0.1 up +[04-14_06:56:52:495] you are use OpenWrt? +[04-14_06:56:52:496] should not calling udhcpc manually? +[04-14_06:56:52:496] should modify /etc/config/network as below? +[04-14_06:56:52:497] config interface wan +[04-14_06:56:52:497] option ifname rmnet_mhi0.1 +[04-14_06:56:52:497] option proto dhcp +[04-14_06:56:52:498] should use "/sbin/ifstaus wan" to check rmnet_mhi0.1 's status? +[04-14_06:56:52:498] busybox udhcpc -f -n -q -t 5 -i rmnet_mhi0.1 +udhcpc: started, v1.28.3 +udhcpc: sending discover +udhcpc: sending select for 10.245.22.3 +udhcpc: lease of 10.245.22.3 obtained, lease time 7200 +[04-14_06:56:52:713] udhcpc: ifconfig rmnet_mhi0.1 10.245.22.3 netmask 255.255.255.248 broadcast + +[04-14_06:56:52:754] udhcpc: setting default routers: 10.245.22.4 +[04-14_06:56:52:838] ip -6 address flush dev rmnet_mhi0.1 +[04-14_06:56:52:861] ip -6 address add 2409:8930:463:3daa:7c8e:429a:c902:c6cc/64 dev rmnet_mhi0.1 +[04-14_06:56:52:884] ip -6 route add default dev rmnet_mhi0.1 + +root@OpenWrt:~# cat /etc/resolv.conf +nameserver 2409:8030:2000:0:0:0:0:1 # IPV6 rmnet_mhi0.1 +nameserver 2409:8030:2000:0:0:0:0:2 # IPV6 rmnet_mhi0.1 +search lan +nameserver 127.0.0.1 + +root@OpenWrt:~# ip -6 ro show +2409:8930:463:96df::/64 dev rmnet_mhi0.1 proto kernel metric 256 +fe80::/64 dev br-lan proto kernel metric 256 +fe80::/64 dev br0 proto kernel metric 256 +default dev rmnet_mhi0.1 metric 1024 + +root@OpenWrt:~# ping6 www.qq.com +PING www.qq.com (2402:4e00:1430:1301::9227:79cc:76f2): 56 data bytes +64 bytes from 2402:4e00:1430:1301::9227:79cc:76f2: seq=0 ttl=51 time=97.230 ms diff --git a/wwan/app/quectel-cm/src/log/usage_of_argument/m.txt b/wwan/app/quectel-cm/src/log/usage_of_argument/m.txt new file mode 100644 index 0000000..c4c46b8 --- /dev/null +++ b/wwan/app/quectel-cm/src/log/usage_of_argument/m.txt @@ -0,0 +1,58 @@ +root@ZhuoTK:/# quectel-CM -n 1 -m 4 -s cmnet & +[04-13_05:12:07:455] Quectel_QConnectManager_Linux_V1.6.0.25 +[04-13_05:12:07:458] Find /sys/bus/usb/devices/1-1.3 idVendor=0x2c7c idProduct=0x125, bus=0x001, dev=0x003 +[04-13_05:12:07:459] Auto find qmichannel = /dev/qcqmi0 +[04-13_05:12:07:459] Auto find usbnet_adapter = usb0 +[04-13_05:12:07:467] netcard driver = GobiNet, driver version = V1.6.2.13 +[04-13_05:12:07:467] qmap_mode = 4, qmap_version = 5, qmap_size = 4096, muxid = 0x84, qmap_netcard = usb0.4 +[04-13_05:12:07:467] Modem works in QMI mode +[04-13_05:12:07:495] Get clientWDS = 7 +[04-13_05:12:07:529] Get clientDMS = 8 +[04-13_05:12:07:561] Get clientNAS = 9 +[04-13_05:12:07:591] Get clientUIM = 10 +[04-13_05:12:07:623] requestBaseBandVersion EC25EFAR06A11M4G +[04-13_05:12:07:752] requestGetSIMStatus SIMStatus: SIM_READY +[04-13_05:12:07:752] requestSetProfile[1] cmnet///0 +[04-13_05:12:07:817] requestGetProfile[1] cmnet///0 +[04-13_05:12:07:849] requestRegistrationState2 MCC: 460, MNC: 0, PS: Attached, DataCap: LTE +[04-13_05:12:07:881] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED +[04-13_05:12:07:881] ifconfig usb0 down +[04-13_05:12:07:892] ifconfig usb0.4 0.0.0.0 +[04-13_05:12:07:903] ifconfig usb0.4 down +[04-13_05:12:07:944] requestSetupDataCall WdsConnectionIPv4Handle: 0x87265c40 +[ 52.020000] net usb0: link_state 0x0 -> 0x8 +[04-13_05:12:08:077] ifconfig usb0 up +[04-13_05:12:08:096] ifconfig usb0.4 up +[04-13_05:12:08:116] you are use OpenWrt? +[04-13_05:12:08:116] should not calling udhcpc manually? +[04-13_05:12:08:116] should modify /etc/config/network as below? +[04-13_05:12:08:116] config interface wan +[04-13_05:12:08:116] option ifname usb0.4 +[04-13_05:12:08:116] option proto dhcp +[04-13_05:12:08:116] should use "/sbin/ifstaus wan" to check usb0.4 's status? +[04-13_05:12:08:117] busybox udhcpc -f -n -q -t 5 -i usb0.4 +[04-13_05:12:08:134] udhcpc (v1.23.2) started +[04-13_05:12:08:193] Sending discover... +[04-13_05:12:08:197] Sending select for 10.84.241.180... +[04-13_05:12:08:203] Lease of 10.84.241.180 obtained, lease time 7200 +[04-13_05:12:08:208] udhcpc: ifconfig usb0.4 10.84.241.180 netmask 255.255.255.248 broadcast + +[04-13_05:12:08:221] udhcpc: setting default routers: 10.84.241.181 + +root@ZhuoTK:/# ifconfig usb0.4 +usb0.4 Link encap:Ethernet HWaddr 02:50:F4:00:00:00 + inet addr:10.84.241.180 Mask:255.255.255.248 + inet6 addr: fe80::50:f4ff:fe00:0/64 Scope:Link + UP RUNNING NOARP MTU:1500 Metric:1 + RX packets:2 errors:0 dropped:0 overruns:0 frame:0 + TX packets:6 errors:0 dropped:0 overruns:0 carrier:0 + collisions:0 txqueuelen:1000 + RX bytes:612 (612.0 B) TX bytes:984 (984.0 B) + +root@ZhuoTK:/# ip ro show +default via 10.84.241.181 dev usb0.4 +10.84.241.176/29 dev usb0.4 proto kernel scope link src 10.84.241.180 +192.168.1.0/24 dev br-lan proto kernel scope link src 192.168.1.251 + +root@ZhuoTK:/# ping 8.8.8.8 +PING 8.8.8.8 (8.8.8.8): 56 data bytes +64 bytes from 8.8.8.8: seq=0 ttl=52 time=99.431 ms diff --git a/wwan/app/quectel_cm_5G/src/main.c b/wwan/app/quectel-cm/src/main.c similarity index 100% rename from wwan/app/quectel_cm_5G/src/main.c rename to wwan/app/quectel-cm/src/main.c diff --git a/wwan/app/quectel_cm_5G/src/mbim-cm.c b/wwan/app/quectel-cm/src/mbim-cm.c similarity index 97% rename from wwan/app/quectel_cm_5G/src/mbim-cm.c rename to wwan/app/quectel-cm/src/mbim-cm.c index 15ae772..0d10f1f 100644 --- a/wwan/app/quectel_cm_5G/src/mbim-cm.c +++ b/wwan/app/quectel-cm/src/mbim-cm.c @@ -1,2426 +1,2426 @@ -/****************************************************************************** - @file mbim-cm.c - @brief MIBIM drivers. - - 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "QMIThread.h" - -#define mbim_debug dbg_time - -#define UUID_BASIC_CONNECT "a289cc33-bcbb-8b4f-b6b0-133ec2aae6df" -//https://docs.microsoft.com/en-us/windows-hardware/drivers/network/mb-5g-data-class-support -#define UUID_BASIC_CONNECT_EXT "3d01dcc5-fef5-4d05-0d3a-bef7058e9aaf" -#define UUID_SMS "533fbeeb-14fe-4467-9f90-33a223e56c3f" -#define UUID_USSD "e550a0c8-5e82-479e-82f7-10abf4c3351f" -#define UUID_PHONEBOOK "4bf38476-1e6a-41db-b1d8-bed289c25bdb" -#define UUID_STK "d8f20131-fcb5-4e17-8602-d6ed3816164c" -#define UUID_AUTH "1d2b5ff7-0aa1-48b2-aa52-50f15767174e" -#define UUID_DSS "c08a26dd-7718-4382-8482-6e0d583c4d0e" -#define uuid_ext_qmux "d1a30bc2-f97a-6e43-bf65-c7e24fb0f0d3" -#define uuid_mshsd "883b7c26-985f-43fa-9804-27d7fb80959c" -#define uuid_qmbe "2d0c12c9-0e6a-495a-915c-8d174fe5d63c" -#define UUID_MSFWID "e9f7dea2-feaf-4009-93ce-90a3694103b6" -#define uuid_atds "5967bdcc-7fd2-49a2-9f5c-b2e70e527db3" -#define uuid_qdu "6427015f-579d-48f5-8c54-f43ed1e76f83" -#define UUID_MS_UICC_LOW_LEVEL "c2f6588e-f037-4bc9-8665-f4d44bd09367" -#define UUID_MS_SARControl "68223D04-9F6C-4E0F-822D-28441FB72340" -#define UUID_VOICEEXTENSIONS "8d8b9eba-37be-449b-8f1e-61cb034a702e" +/****************************************************************************** + @file mbim-cm.c + @brief MIBIM drivers. + + 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "QMIThread.h" + +#define mbim_debug dbg_time + +#define UUID_BASIC_CONNECT "a289cc33-bcbb-8b4f-b6b0-133ec2aae6df" +//https://docs.microsoft.com/en-us/windows-hardware/drivers/network/mb-5g-data-class-support +#define UUID_BASIC_CONNECT_EXT "3d01dcc5-fef5-4d05-0d3a-bef7058e9aaf" +#define UUID_SMS "533fbeeb-14fe-4467-9f90-33a223e56c3f" +#define UUID_USSD "e550a0c8-5e82-479e-82f7-10abf4c3351f" +#define UUID_PHONEBOOK "4bf38476-1e6a-41db-b1d8-bed289c25bdb" +#define UUID_STK "d8f20131-fcb5-4e17-8602-d6ed3816164c" +#define UUID_AUTH "1d2b5ff7-0aa1-48b2-aa52-50f15767174e" +#define UUID_DSS "c08a26dd-7718-4382-8482-6e0d583c4d0e" +#define uuid_ext_qmux "d1a30bc2-f97a-6e43-bf65-c7e24fb0f0d3" +#define uuid_mshsd "883b7c26-985f-43fa-9804-27d7fb80959c" +#define uuid_qmbe "2d0c12c9-0e6a-495a-915c-8d174fe5d63c" +#define UUID_MSFWID "e9f7dea2-feaf-4009-93ce-90a3694103b6" +#define uuid_atds "5967bdcc-7fd2-49a2-9f5c-b2e70e527db3" +#define uuid_qdu "6427015f-579d-48f5-8c54-f43ed1e76f83" +#define UUID_MS_UICC_LOW_LEVEL "c2f6588e-f037-4bc9-8665-f4d44bd09367" +#define UUID_MS_SARControl "68223D04-9F6C-4E0F-822D-28441FB72340" +#define UUID_VOICEEXTENSIONS "8d8b9eba-37be-449b-8f1e-61cb034a702e" #define UUID_LIBMBIM_PROXY "838cf7fb-8d0d-4d7f-871e-d71dbefbb39b" - -#define UUID_MBIMContextTypeInternet "7E5E2A7E-4E6F-7272-736B-656E7E5E2A7E" - -typedef unsigned char UINT8; -typedef unsigned short UINT16; -typedef unsigned int UINT32; -typedef unsigned long long UINT64; - -#pragma pack(4) -typedef enum { - MBIM_CID_CMD_TYPE_QUERY = 0, - MBIM_CID_CMD_TYPE_SET = 1, -} MBIM_CID_CMD_TYPE_E; - -typedef enum { - MBIM_CID_DEVICE_CAPS = 1, - MBIM_CID_SUBSCRIBER_READY_STATUS = 2, - MBIM_CID_RADIO_STATE = 3, MBIM_CID_PIN = 4, - MBIM_CID_PIN_LIS = 5, - MBIM_CID_HOME_PROVIDER = 6, - MBIM_CID_PREFERRED_PROVIDERS = 7, - MBIM_CID_VISIBLE_PROVIDERS = 8, - MBIM_CID_REGISTER_STATE = 9, - MBIM_CID_PACKET_SERVICE = 10, - MBIM_CID_SIGNAL_STATE = 11, - MBIM_CID_CONNECT = 12, - MBIM_CID_PROVISIONED_CONTEXTS = 13, - MBIM_CID_SERVICE_ACTIVATION = 14, - MBIM_CID_IP_CONFIGURATION = 15, - MBIM_CID_DEVICE_SERVICES = 16, - MBIM_CID_DEVICE_SERVICE_SUBSCRIBE_LIST = 19, - MBIM_CID_PACKET_STATISTICS = 20, - MBIM_CID_NETWORK_IDLE_HINT = 21, - MBIM_CID_EMERGENCY_MODE = 22, - MBIM_CID_IP_PACKET_FILTERS = 23, - MBIM_CID_MULTICARRIER_PROVIDERS = 24, -} UUID_BASIC_CONNECT_CID_E; - -typedef enum{ - MBIM_CID_MS_PROVISIONED_CONTEXT_V2 = 1, - MBIM_CID_MS_NETWORK_BLACKLIST = 2, - MBIM_CID_MS_LTE_ATTACH_CONFIG = 3, - MBIM_CID_MS_LTE_ATTACH_STATUS = 4, - MBIM_CID_MS_SYS_CAPS = 5, - MBIM_CID_MS_DEVICE_CAPS_V2 = 6, - MBIM_CID_MS_DEVICE_SLOT_MAPPING = 7, - MBIM_CID_MS_SLOT_INFO_STATUS = 8, - MBIM_CID_MS_PCO = 9, - MBIM_CID_MS_DEVICE_RESET = 10, - MBIM_CID_MS_BASE_STATIONS_INFO = 11, - MBIM_CID_MS_LOCATION_INFO_STATUS = 12, - MBIM_CID_NOT_DEFINED = 13, - MBIM_CID_MS_PIN_EX = 14, - MBIM_CID_MS_VERSION = 15, -} UUID_BASIC_CONNECT_EXT_CID_E; - -typedef enum { - MBIM_CID_SMS_CONFIGURATION = 1, // Y Y Y - MBIM_CID_SMS_READ = 2, // N Y Y - MBIM_CID_SMS_SEND = 3, // Y N N - MBIM_CID_SMS_DELETE = 4, // Y N N - MBIM_CID_SMS_MESSAGE_STORE_STATUS = 5, // N Y Y -} UUID_SMS_CID_E; - -typedef enum { - MBIM_CID_DSS_CONNECT = 1, // Y N N -} UUID_DSS_CID_E; - -typedef enum{ - MBIM_OPEN_MSG = 1, - MBIM_CLOSE_MSG = 2, - MBIM_COMMAND_MSG = 3, - MBIM_HOST_ERROR_MSG = 4, - MBIM_OPEN_DONE = 0x80000001, - MBIM_CLOSE_DONE = 0x80000002, - MBIM_COMMAND_DONE = 0x80000003, - MBIM_FUNCTION_ERROR_MSG = 0x80000004, - MBIM_INDICATE_STATUS_MSG = 0x80000007, -} MBIM_MSG_Type_E; - + +#define UUID_MBIMContextTypeInternet "7E5E2A7E-4E6F-7272-736B-656E7E5E2A7E" + +typedef unsigned char UINT8; +typedef unsigned short UINT16; +typedef unsigned int UINT32; +typedef unsigned long long UINT64; + +#pragma pack(4) +typedef enum { + MBIM_CID_CMD_TYPE_QUERY = 0, + MBIM_CID_CMD_TYPE_SET = 1, +} MBIM_CID_CMD_TYPE_E; + +typedef enum { + MBIM_CID_DEVICE_CAPS = 1, + MBIM_CID_SUBSCRIBER_READY_STATUS = 2, + MBIM_CID_RADIO_STATE = 3, MBIM_CID_PIN = 4, + MBIM_CID_PIN_LIS = 5, + MBIM_CID_HOME_PROVIDER = 6, + MBIM_CID_PREFERRED_PROVIDERS = 7, + MBIM_CID_VISIBLE_PROVIDERS = 8, + MBIM_CID_REGISTER_STATE = 9, + MBIM_CID_PACKET_SERVICE = 10, + MBIM_CID_SIGNAL_STATE = 11, + MBIM_CID_CONNECT = 12, + MBIM_CID_PROVISIONED_CONTEXTS = 13, + MBIM_CID_SERVICE_ACTIVATION = 14, + MBIM_CID_IP_CONFIGURATION = 15, + MBIM_CID_DEVICE_SERVICES = 16, + MBIM_CID_DEVICE_SERVICE_SUBSCRIBE_LIST = 19, + MBIM_CID_PACKET_STATISTICS = 20, + MBIM_CID_NETWORK_IDLE_HINT = 21, + MBIM_CID_EMERGENCY_MODE = 22, + MBIM_CID_IP_PACKET_FILTERS = 23, + MBIM_CID_MULTICARRIER_PROVIDERS = 24, +} UUID_BASIC_CONNECT_CID_E; + +typedef enum{ + MBIM_CID_MS_PROVISIONED_CONTEXT_V2 = 1, + MBIM_CID_MS_NETWORK_BLACKLIST = 2, + MBIM_CID_MS_LTE_ATTACH_CONFIG = 3, + MBIM_CID_MS_LTE_ATTACH_STATUS = 4, + MBIM_CID_MS_SYS_CAPS = 5, + MBIM_CID_MS_DEVICE_CAPS_V2 = 6, + MBIM_CID_MS_DEVICE_SLOT_MAPPING = 7, + MBIM_CID_MS_SLOT_INFO_STATUS = 8, + MBIM_CID_MS_PCO = 9, + MBIM_CID_MS_DEVICE_RESET = 10, + MBIM_CID_MS_BASE_STATIONS_INFO = 11, + MBIM_CID_MS_LOCATION_INFO_STATUS = 12, + MBIM_CID_NOT_DEFINED = 13, + MBIM_CID_MS_PIN_EX = 14, + MBIM_CID_MS_VERSION = 15, +} UUID_BASIC_CONNECT_EXT_CID_E; + +typedef enum { + MBIM_CID_SMS_CONFIGURATION = 1, // Y Y Y + MBIM_CID_SMS_READ = 2, // N Y Y + MBIM_CID_SMS_SEND = 3, // Y N N + MBIM_CID_SMS_DELETE = 4, // Y N N + MBIM_CID_SMS_MESSAGE_STORE_STATUS = 5, // N Y Y +} UUID_SMS_CID_E; + +typedef enum { + MBIM_CID_DSS_CONNECT = 1, // Y N N +} UUID_DSS_CID_E; + +typedef enum{ + MBIM_OPEN_MSG = 1, + MBIM_CLOSE_MSG = 2, + MBIM_COMMAND_MSG = 3, + MBIM_HOST_ERROR_MSG = 4, + MBIM_OPEN_DONE = 0x80000001, + MBIM_CLOSE_DONE = 0x80000002, + MBIM_COMMAND_DONE = 0x80000003, + MBIM_FUNCTION_ERROR_MSG = 0x80000004, + MBIM_INDICATE_STATUS_MSG = 0x80000007, +} MBIM_MSG_Type_E; + typedef enum { /*< since=1.10 >*/ MBIM_CID_PROXY_CONTROL_UNKNOWN = 0, MBIM_CID_PROXY_CONTROL_CONFIGURATION = 1 -} UUID_LIBMBIM_PROXY_CID_E; - -typedef enum { - MBIM_CID_MS_UICC_ATR = 1, - MBIM_CID_MS_UICC_OPEN_CHANNEL = 2, - MBIM_CID_MS_UICC_CLOSE_CHANNEL = 3, - MBIM_CID_MS_UICC_APDU = 4, - MBIM_CID_MS_UICC_TERMINAL_CAPABILITY = 5, - MBIM_CID_MS_UICC_RESET = 6, - MBIM_CID_MS_APP_LIST = 7, -} UUID_MS_UICC_CID_E; - -typedef enum { - MBIM_ERROR_TIMEOUT_FRAGMENT = 1, - MBIM_ERROR_FRAGMENT_OUT_OF_SEQUENCE = 2, - MBIM_ERROR_LENGTH_MISMATCH = 3, - MBIM_ERROR_DUPLICATED_TID = 4, - MBIM_ERROR_NOT_OPENED = 5, - MBIM_ERROR_UNKNOWN = 6, - MBIM_ERROR_CANCEL = 7, - MBIM_ERROR_MAX_TRANSFER = 8, -} MBIM_ERROR_E; - -typedef enum { - MBIM_STATUS_SUCCESS = 0, - MBIM_STATUS_BUSY = 1, - MBIM_STATUS_FAILURE = 2, - MBIM_STATUS_SIM_NOT_INSERTED = 3, - MBIM_STATUS_BAD_SIM = 4, - MBIM_STATUS_PIN_REQUIRED = 5, - MBIM_STATUS_PIN_DISABLED = 6, - MBIM_STATUS_NOT_REGISTERED = 7, - MBIM_STATUS_PROVIDERS_NOT_FOUND = 8, - MBIM_STATUS_NO_DEVICE_SUPPORT = 9, - MBIM_STATUS_PROVIDER_NOT_VISIBLE = 10, - MBIM_STATUS_DATA_CLASS_NOT_AVAILABL = 11, - MBIM_STATUS_PACKET_SERVICE_DETACHED = 12, -} MBIM_STATUS_CODES_E; - -typedef enum { - MBIMPacketServiceActionAttach = 0, - MBIMPacketServiceActionDetach = 1, -} MBIM_PACKET_SERVICE_ACTION_E; - -typedef enum { - MBIMPacketServiceStateUnknown = 0, - MBIMPacketServiceStateAttaching = 1, - MBIMPacketServiceStateAttached = 2, - MBIMPacketServiceStateDetaching = 3, - MBIMPacketServiceStateDetached = 4, -} MBIM_PACKET_SERVICE_STATE_E; - -static const char *MBIMPacketServiceStateStr(int _val) { - struct { int val;char *name;} _enumstr[] = { - {MBIMPacketServiceStateUnknown, "Unknown"}, - {MBIMPacketServiceStateAttaching, "Attaching"}, - {MBIMPacketServiceStateAttached, "Attached"}, - {MBIMPacketServiceStateDetaching, "Detaching"}, - {MBIMPacketServiceStateDetached, "Detached"}, - }; - int idx; - - for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { - if (_val == _enumstr[idx].val) - return _enumstr[idx].name; - } - - return "Undefined"; -}; - -typedef enum { - MBIMDataClassNone = 0x0, - MBIMDataClassGPRS = 0x1, - MBIMDataClassEDGE = 0x2, - MBIMDataClassUMTS = 0x4, - MBIMDataClassHSDPA = 0x8, - MBIMDataClassHSUPA = 0x10, - MBIMDataClassLTE = 0x20, - MBIMDataClass5G_NSA = 0x40, - MBIMDataClass5G_SA = 0x80, - MBIMDataClass1XRTT = 0x10000, - MBIMDataClass1XEVDO = 0x20000, - MBIMDataClass1XEVDORevA = 0x40000, - MBIMDataClass1XEVDV = 0x80000, - MBIMDataClass3XRTT = 0x100000, - MBIMDataClass1XEVDORevB = 0x200000, - MBIMDataClassUMB = 0x400000, - MBIMDataClassCustom = 0x80000000, -} MBIM_DATA_CLASS_E; - -static const char *MBIMDataClassStr(int _val) { - struct { int val;char *name;} _enumstr[] = { - {MBIMDataClassNone, "None"}, - {MBIMDataClassGPRS, "GPRS"}, - {MBIMDataClassEDGE, "EDGE"}, - {MBIMDataClassUMTS, "UMTS"}, - {MBIMDataClassHSDPA, "HSDPA"}, - {MBIMDataClassHSUPA, "HSUPA"}, - {MBIMDataClassLTE, "LTE"}, - {MBIMDataClass5G_NSA, "5G_NSA"}, - {MBIMDataClass5G_SA, "5G_SA"}, - {MBIMDataClass1XRTT, "1XRTT"}, - {MBIMDataClass1XEVDO, "1XEVDO"}, - {MBIMDataClass1XEVDORevA, "1XEVDORevA"}, - {MBIMDataClass1XEVDV, "1XEVDV"}, - {MBIMDataClass3XRTT, "3XRTT"}, - {MBIMDataClass1XEVDORevB, "1XEVDORevB"}, - {MBIMDataClassUMB, "UMB"}, - {MBIMDataClassCustom, "Custom"}, - }; - int idx; - - for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { - if (_val == _enumstr[idx].val) - return _enumstr[idx].name; - } - - return "Unknow"; -}; - -typedef struct { - UINT32 NwError; - UINT32 PacketServiceState; //MBIM_PACKET_SERVICE_STATE_E - UINT32 HighestAvailableDataClass; //MBIM_DATA_CLASS_E - UINT64 UplinkSpeed; - UINT64 DownlinkSpeed; -} MBIM_PACKET_SERVICE_INFO_T; - -typedef struct { - UINT32 NwError; - UINT32 PacketServiceState; //MBIM_PACKET_SERVICE_STATE_E - UINT32 CurrentDataClass; //MBIM_DATA_CLASS_E - UINT64 UplinkSpeed; - UINT64 DownlinkSpeed; - UINT32 FrequencyRange; -} MBIM_PACKET_SERVICE_INFO_V2_T; - -typedef enum { - MBIMSubscriberReadyStateNotInitialized = 0, - MBIMSubscriberReadyStateInitialized = 1, - MBIMSubscriberReadyStateSimNotInserted = 2, - MBIMSubscriberReadyStateBadSim = 3, - MBIMSubscriberReadyStateFailure = 4, - MBIMSubscriberReadyStateNotActivated = 5, - MBIMSubscriberReadyStateDeviceLocked = 6, -}MBIM_SUBSCRIBER_READY_STATE_E; - -static const char *MBIMSubscriberReadyStateStr(int _val) { - struct { int val;char *name;} _enumstr[] = { - {MBIMSubscriberReadyStateNotInitialized, "NotInitialized"}, - {MBIMSubscriberReadyStateInitialized, "Initialized"}, - {MBIMSubscriberReadyStateSimNotInserted, "NotInserted"}, - {MBIMSubscriberReadyStateBadSim, "BadSim"}, - {MBIMSubscriberReadyStateFailure, "Failure"}, - {MBIMSubscriberReadyStateNotActivated, "NotActivated"}, - {MBIMSubscriberReadyStateDeviceLocked, "DeviceLocked"}, - }; - int idx; - - for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { - if (_val == _enumstr[idx].val) - return _enumstr[idx].name; - } - - return "Undefined"; -}; - -typedef struct { - UINT32 DeviceType; //MBIM_DEVICE_TYPE - UINT32 CellularClass; //MBIM_CELLULAR_CLASS - UINT32 VoiceClass; //MBIM_VOICE_CLASS - UINT32 SimClass; //MBIM_SIM_CLASS - UINT32 DataClass; //MBIM_DATA_CLASS - UINT32 SmsCaps; //MBIM_SMS_CAPS - UINT32 ControlCaps; //MBIM_CTRL_CAPS - UINT32 MaxSessions; - UINT32 CustomDataClassOffset; - UINT32 CustomDataClassSize; - UINT32 DeviceIdOffset; - UINT32 DeviceIdSize; - UINT32 FirmwareInfoOffset; - UINT32 FirmwareInfoSize; - UINT32 HardwareInfoOffset; - UINT32 HardwareInfoSize; - UINT8 DataBuffer[0]; //DeviceId FirmwareInfo HardwareInfo -} MBIM_DEVICE_CAPS_INFO_T; - -typedef enum { - MBIMRadioOff = 0, - MBIMRadioOn = 1, -} MBIM_RADIO_SWITCH_STATE_E; - -typedef struct { - MBIM_RADIO_SWITCH_STATE_E RadioState; -} MBIM_SET_RADIO_STATE_T; - -typedef struct { - MBIM_RADIO_SWITCH_STATE_E HwRadioState; - MBIM_RADIO_SWITCH_STATE_E SwRadioState; -} MBIM_RADIO_STATE_INFO_T; - -typedef enum { - MBIMReadyInfoFlagsNone, - MBIMReadyInfoFlagsProtectUniqueID, -}MBIM_UNIQUE_ID_FLAGS; - -typedef struct { - UINT32 ReadyState; - UINT32 SubscriberIdOffset; - UINT32 SubscriberIdSize; - UINT32 SimIccIdOffset; - UINT32 SimIccIdSize; - UINT32 ReadyInfo; - UINT32 ElementCount; - UINT8 *TelephoneNumbersRefList; - UINT8 *DataBuffer; -} MBIM_SUBSCRIBER_READY_STATUS_T; - -typedef enum { - MBIMRegisterActionAutomatic, - MBIMRegisterActionManual, -}MBIM_REGISTER_ACTION_E; - -typedef enum { - MBIMRegisterStateUnknown = 0, - MBIMRegisterStateDeregistered = 1, - MBIMRegisterStateSearching = 2, - MBIMRegisterStateHome = 3, - MBIMRegisterStateRoaming = 4, - MBIMRegisterStatePartner = 5, - MBIMRegisterStateDenied = 6, -}MBIM_REGISTER_STATE_E; - -typedef enum { - MBIMRegisterModeUnknown = 0, - MBIMRegisterModeAutomatic = 1, - MBIMRegisterModeManual = 2, -}MBIM_REGISTER_MODE_E; - -static const char *MBIMRegisterStateStr(int _val) { - struct { int val;char *name;} _enumstr[] ={ - {MBIMRegisterStateUnknown, "Unknown"}, - {MBIMRegisterStateDeregistered, "Deregistered"}, - {MBIMRegisterStateSearching, "Searching"}, - {MBIMRegisterStateHome, "Home"}, - {MBIMRegisterStateRoaming, "Roaming"}, - {MBIMRegisterStatePartner, "Partner"}, - {MBIMRegisterStateDenied, "Denied"}, - }; - int idx; - - for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { - if (_val == _enumstr[idx].val) - return _enumstr[idx].name; - } - - return "Undefined"; -}; - -static const char *MBIMRegisterModeStr(int _val) { - struct { int val;char *name;} _enumstr[] = { - {MBIMRegisterModeUnknown, "Unknown"}, - {MBIMRegisterModeAutomatic, "Automatic"}, - {MBIMRegisterModeManual, "Manual"}, - }; - int idx; - - for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { - if (_val == _enumstr[idx].val) - return _enumstr[idx].name; - } - - return "Undefined"; -}; - -typedef enum { - MBIM_REGISTRATION_NONE, - MBIM_REGISTRATION_MANUAL_SELECTION_NOT_AVAILABLE, - MBIM_REGISTRATION_PACKET_SERVICE_AUTOMATIC_ATTACH, -}MBIM_REGISTRATION_FLAGS_E; - -typedef struct { - UINT32 NwError; - UINT32 RegisterState; //MBIM_REGISTER_STATE_E - UINT32 RegisterMode; - UINT32 AvailableDataClasses; - UINT32 CurrentCellularClass; - UINT32 ProviderIdOffset; - UINT32 ProviderIdSize; - UINT32 ProviderNameOffset; - UINT32 ProviderNameSize; - UINT32 RoamingTextOffset; - UINT32 RoamingTextSize; - UINT32 RegistrationFlag; - UINT8 *DataBuffer; -} MBIM_REGISTRATION_STATE_INFO_T; - -typedef struct { - UINT32 NwError; - UINT32 RegisterState; //MBIM_REGISTER_STATE_E - UINT32 RegisterMode; - UINT32 AvailableDataClasses; - UINT32 CurrentCellularClass; - UINT32 ProviderIdOffset; - UINT32 ProviderIdSize; - UINT32 ProviderNameOffset; - UINT32 ProviderNameSize; - UINT32 RoamingTextOffset; - UINT32 RoamingTextSize; - UINT32 RegistrationFlag; - UINT32 PreferredDataClass; - UINT8 *DataBuffer; -} MBIM_REGISTRATION_STATE_INFO_V2_T; - -typedef struct { - UINT32 MessageType; //Specifies the MBIM message type. - UINT32 MessageLength; //Specifies the total length of this MBIM message in bytes. - /* Specifies the MBIM message id value. This value is used to match host sent messages with function responses. - This value must be unique among all outstanding transactions. - For notifications, the TransactionId must be set to 0 by the function */ - UINT32 TransactionId; -} MBIM_MESSAGE_HEADER; - -typedef struct { - UINT32 TotalFragments; //this field indicates how many fragments there are intotal. - UINT32 CurrentFragment; //This field indicates which fragment this message is. Values are 0 to TotalFragments?\1 -} MBIM_FRAGMENT_HEADER; - -typedef struct { - MBIM_MESSAGE_HEADER MessageHeader; - UINT32 MaxControlTransfer; -} MBIM_OPEN_MSG_T; - -typedef struct { - MBIM_MESSAGE_HEADER MessageHeader; - UINT32 Status; //MBIM_STATUS_CODES_E -} MBIM_OPEN_DONE_T; - -typedef struct { - MBIM_MESSAGE_HEADER MessageHeader; -} MBIM_CLOSE_MSG_T; - -typedef struct { - MBIM_MESSAGE_HEADER MessageHeader; - UINT32 Status; -} MBIM_CLOSE_DONE_T; - -typedef struct { - UINT8 uuid[16]; -} UUID_T; - -typedef struct { - MBIM_MESSAGE_HEADER MessageHeader; - MBIM_FRAGMENT_HEADER FragmentHeader; - UUID_T DeviceServiceId; //A 16 byte UUID that identifies the device service the following CID value applies. - UINT32 CID; //Specifies the CID that identifies the parameter being queried for - UINT32 CommandType; //0 for a query operation, 1 for a Set operation - UINT32 InformationBufferLength; //Size of the Total InformationBuffer, may be larger than current message if fragmented. - UINT8 InformationBuffer[0]; //Data supplied to device specific to the CID -} MBIM_COMMAND_MSG_T; - -typedef struct { - MBIM_MESSAGE_HEADER MessageHeader; - MBIM_FRAGMENT_HEADER FragmentHeader; - UUID_T DeviceServiceId; //A 16 byte UUID that identifies the device service the following CID value applies. - UINT32 CID; //Specifies the CID that identifies the parameter being queried for - UINT32 Status; - UINT32 InformationBufferLength; //Size of the Total InformationBuffer, may be larger than current message if fragmented. - UINT8 InformationBuffer[0]; //Data supplied to device specific to the CID -} MBIM_COMMAND_DONE_T; - -typedef struct { - MBIM_MESSAGE_HEADER MessageHeader; - UINT32 ErrorStatusCode; -} MBIM_HOST_ERROR_MSG_T; - -typedef struct { - MBIM_MESSAGE_HEADER MessageHeader; - UINT32 ErrorStatusCode; -} MBIM_FUNCTION_ERROR_MSG_T; - -typedef struct { - MBIM_MESSAGE_HEADER MessageHeader; - MBIM_FRAGMENT_HEADER FragmentHeader; - UUID_T DeviceServiceId; //A 16 byte UUID that identifies the device service the following CID value applies. - UINT32 CID; //Specifies the CID that identifies the parameter being queried for - UINT32 InformationBufferLength; //Size of the Total InformationBuffer, may be larger than current message if fragmented. - UINT8 InformationBuffer[0]; //Data supplied to device specific to the CID -} MBIM_INDICATE_STATUS_MSG_T; - -typedef struct { - UINT32 offset; - UINT32 size; -} OL_PAIR_LIST; - -typedef struct { - UUID_T DeviceServiceId; - UINT32 DssPayload; - UINT32 MaxDssInstances; - UINT32 CidCount; - UINT32 CidList[]; -} MBIM_DEVICE_SERVICE_ELEMENT_T; - -typedef struct { - UINT32 DeviceServicesCount; - UINT32 MaxDssSessions; - OL_PAIR_LIST DeviceServicesRefList[]; -} MBIM_DEVICE_SERVICES_INFO_T; - -typedef enum { - MBIMActivationCommandDeactivate = 0, - MBIMActivationCommandActivate = 1, -} MBIM_ACTIVATION_COMMAND_E; - -typedef enum { - MBIMCompressionNone = 0, - MBIMCompressionEnable = 1, -} MBIM_COMPRESSION_E; - -typedef enum { - MBIMAuthProtocolNone = 0, - MBIMAuthProtocolPap = 1, - MBIMAuthProtocolChap = 2, - MBIMAuthProtocolMsChapV2 = 3, -} MBIM_AUTH_PROTOCOL_E; - -typedef enum { - MBIMContextIPTypeDefault = 0, - MBIMContextIPTypeIPv4 = 1, - MBIMContextIPTypeIPv6 = 2, - MBIMContextIPTypeIPv4v6 = 3, - MBIMContextIPTypeIPv4AndIPv6 = 4, -} MBIM_CONTEXT_IP_TYPE_E; - -typedef enum { - MBIMActivationStateUnknown = 0, - MBIMActivationStateActivated = 1, - MBIMActivationStateActivating = 2, - MBIMActivationStateDeactivated = 3, - MBIMActivationStateDeactivating = 4, -} MBIM_ACTIVATION_STATE_E; - -typedef enum { - MBIMVoiceCallStateNone = 0, - MBIMVoiceCallStateInProgress = 1, - MBIMVoiceCallStateHangUp = 2, -} MBIM_VOICECALL_STATE_E; - -static const char *MBIMMSGTypeStr(int _val) { - struct { int val;char *name;} _enumstr[] = { - {MBIM_OPEN_MSG, "MBIM_OPEN_MSG"}, - {MBIM_CLOSE_MSG, "MBIM_CLOSE_MSG"}, - {MBIM_COMMAND_MSG, "MBIM_COMMAND_MSG"}, - {MBIM_HOST_ERROR_MSG, "MBIM_HOST_ERROR_MSG"}, - {MBIM_OPEN_DONE, "MBIM_OPEN_DONE"}, - {MBIM_CLOSE_DONE, "MBIM_CLOSE_DONE"}, - {MBIM_COMMAND_DONE, "MBIM_COMMAND_DONE"}, - {MBIM_FUNCTION_ERROR_MSG, "MBIM_FUNCTION_ERROR_MSG"}, - {MBIM_INDICATE_STATUS_MSG, "MBIM_INDICATE_STATUS_MSG"}, - }; - int idx; - - for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { - if (_val == _enumstr[idx].val) - return _enumstr[idx].name; - } - - return "MBIMMSGTypeUnknow"; -}; - -static const char *MBIMContextIPTypeStr(int _val) { - struct { int val;char *name;} _enumstr[] = { - {MBIMContextIPTypeDefault, "MBIMContextIPTypeDefault"}, - {MBIMContextIPTypeIPv4, "MBIMContextIPTypeIPv4"}, - {MBIMContextIPTypeIPv6, "MBIMContextIPTypeIPv6"}, - {MBIMContextIPTypeIPv4v6, "MBIMContextIPTypeIPv4v6"}, - {MBIMContextIPTypeIPv4AndIPv6, "MBIMContextIPTypeIPv4AndIPv6"}, - }; - int idx; - - for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { - if (_val == _enumstr[idx].val) - return _enumstr[idx].name; - } - - return "MBIMContextIPTypeUnknow"; -} - -static const char *MBIMActivationStateStr(int _val) { - struct { int val;char *name;} _enumstr[] = { - {MBIMActivationStateUnknown, "Unknown"}, - {MBIMActivationStateActivated, "Activated"}, - {MBIMActivationStateActivating, "Activating"}, - {MBIMActivationStateDeactivated, "Deactivated"}, - {MBIMActivationStateDeactivating, "Deactivating"}, - }; - int idx; - - for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { - if (_val == _enumstr[idx].val) - return _enumstr[idx].name; - } - - return "Undefined"; -}; - -static const char *MBIMVoiceCallStateStr(int _val) { - struct { int val;char *name;} _enumstr[] = { - {MBIMVoiceCallStateNone, "None"}, - {MBIMVoiceCallStateInProgress, "InProgress"}, - {MBIMVoiceCallStateHangUp, "HangUp"}, - }; - int idx; - - for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { - if (_val == _enumstr[idx].val) - return _enumstr[idx].name; - } - - return "Undefined"; -}; - -typedef struct { - const char *uuid; - UINT32 cid; - const char *name; -} UUID_CID_STR; - -static const UUID_CID_STR uuid_cid_string[] = { - {UUID_BASIC_CONNECT, MBIM_CID_DEVICE_CAPS, "MBIM_CID_DEVICE_CAPS"}, - {UUID_BASIC_CONNECT, MBIM_CID_SUBSCRIBER_READY_STATUS, "MBIM_CID_SUBSCRIBER_READY_STATUS"}, - {UUID_BASIC_CONNECT, MBIM_CID_RADIO_STATE, "MBIM_CID_RADIO_STATE"}, - {UUID_BASIC_CONNECT, MBIM_CID_PIN, "MBIM_CID_PIN"}, - {UUID_BASIC_CONNECT, MBIM_CID_PIN_LIS, "MBIM_CID_PIN_LIS"}, - {UUID_BASIC_CONNECT, MBIM_CID_HOME_PROVIDER, "MBIM_CID_HOME_PROVIDER"}, - {UUID_BASIC_CONNECT, MBIM_CID_PREFERRED_PROVIDERS, "MBIM_CID_PREFERRED_PROVIDERS"}, - {UUID_BASIC_CONNECT, MBIM_CID_VISIBLE_PROVIDERS, "MBIM_CID_VISIBLE_PROVIDERS"}, - {UUID_BASIC_CONNECT, MBIM_CID_REGISTER_STATE, "MBIM_CID_REGISTER_STATE"}, - {UUID_BASIC_CONNECT, MBIM_CID_PACKET_SERVICE, "MBIM_CID_PACKET_SERVICE"}, - {UUID_BASIC_CONNECT, MBIM_CID_SIGNAL_STATE, "MBIM_CID_SIGNAL_STATE"}, - {UUID_BASIC_CONNECT, MBIM_CID_CONNECT, "MBIM_CID_CONNECT"}, - {UUID_BASIC_CONNECT, MBIM_CID_PROVISIONED_CONTEXTS, "MBIM_CID_PROVISIONED_CONTEXTS"}, - {UUID_BASIC_CONNECT, MBIM_CID_SERVICE_ACTIVATION, "MBIM_CID_SERVICE_ACTIVATION"}, - {UUID_BASIC_CONNECT, MBIM_CID_IP_CONFIGURATION, "MBIM_CID_IP_CONFIGURATION"}, - {UUID_BASIC_CONNECT, MBIM_CID_DEVICE_SERVICES, "MBIM_CID_DEVICE_SERVICES"}, - {UUID_BASIC_CONNECT, MBIM_CID_DEVICE_SERVICE_SUBSCRIBE_LIST, "MBIM_CID_DEVICE_SERVICE_SUBSCRIBE_LIST"}, - {UUID_BASIC_CONNECT, MBIM_CID_PACKET_STATISTICS, "MBIM_CID_PACKET_STATISTICS"}, - {UUID_BASIC_CONNECT, MBIM_CID_NETWORK_IDLE_HINT, "MBIM_CID_NETWORK_IDLE_HINT"}, - {UUID_BASIC_CONNECT, MBIM_CID_EMERGENCY_MODE, "MBIM_CID_EMERGENCY_MODE"}, - {UUID_BASIC_CONNECT, MBIM_CID_IP_PACKET_FILTERS, "MBIM_CID_IP_PACKET_FILTERS"}, - {UUID_BASIC_CONNECT, MBIM_CID_MULTICARRIER_PROVIDERS, "MBIM_CID_MULTICARRIER_PROVIDERS"}, - - {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_PROVISIONED_CONTEXT_V2, "MBIM_CID_MS_PROVISIONED_CONTEXT_V2"}, - {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_NETWORK_BLACKLIST, "MBIM_CID_MS_NETWORK_BLACKLIST"}, - {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_LTE_ATTACH_CONFIG, "MBIM_CID_MS_LTE_ATTACH_CONFIG"}, - {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_LTE_ATTACH_STATUS, "MBIM_CID_MS_LTE_ATTACH_STATUS"}, - {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_SYS_CAPS, "MBIM_CID_MS_SYS_CAPS"}, - {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_DEVICE_CAPS_V2, "MBIM_CID_MS_DEVICE_CAPS_V2"}, - {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_DEVICE_SLOT_MAPPING, "MBIM_CID_MS_DEVICE_SLOT_MAPPING"}, - {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_SLOT_INFO_STATUS, "MBIM_CID_MS_SLOT_INFO_STATUS"}, - {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_PCO, "MBIM_CID_MS_PCO"}, - {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_DEVICE_RESET, "MBIM_CID_MS_DEVICE_RESET"}, - {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_BASE_STATIONS_INFO, "MBIM_CID_MS_BASE_STATIONS_INFO"}, - {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_LOCATION_INFO_STATUS, "MBIM_CID_MS_LOCATION_INFO_STATUS"}, - {UUID_BASIC_CONNECT_EXT, MBIM_CID_NOT_DEFINED, "MBIM_CID_NOT_DEFINED"}, - {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_PIN_EX, "MBIM_CID_MS_PIN_EX"}, - {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_VERSION, "MBIM_CID_MS_VERSION"}, - - {UUID_MS_UICC_LOW_LEVEL, MBIM_CID_MS_UICC_ATR, "MBIM_CID_MS_UICC_ATR"}, - {UUID_MS_UICC_LOW_LEVEL, MBIM_CID_MS_UICC_OPEN_CHANNEL, "MBIM_CID_MS_UICC_OPEN_CHANNEL"}, - {UUID_MS_UICC_LOW_LEVEL, MBIM_CID_MS_UICC_CLOSE_CHANNEL, "MBIM_CID_MS_UICC_CLOSE_CHANNEL"}, - {UUID_MS_UICC_LOW_LEVEL, MBIM_CID_MS_UICC_APDU, "MBIM_CID_MS_UICC_APDU"}, - {UUID_MS_UICC_LOW_LEVEL, MBIM_CID_MS_UICC_TERMINAL_CAPABILITY, "MBIM_CID_MS_UICC_TERMINAL_CAPABILITY"}, - {UUID_MS_UICC_LOW_LEVEL, MBIM_CID_MS_UICC_RESET, "MBIM_CID_MS_UICC_RESET"}, - {UUID_MS_UICC_LOW_LEVEL, MBIM_CID_MS_APP_LIST, "MBIM_CID_MS_APP_LIST"}, -}; - -typedef struct { - UINT32 SessionId; - UINT32 ActivationCommand; //MBIM_ACTIVATION_COMMAND_E - UINT32 AccessStringOffset; - UINT32 AccessStringSize; - UINT32 UserNameOffset; - UINT32 UserNameSize; - UINT32 PasswordOffset; - UINT32 PasswordSize; - UINT32 Compression; //MBIM_COMPRESSION_E - UINT32 AuthProtocol; //MBIM_AUTH_PROTOCOL_E - UINT32 IPType; //MBIM_CONTEXT_IP_TYPE_E - UUID_T ContextType; - UINT8 DataBuffer[0]; /* apn, username, password */ -} MBIM_SET_CONNECT_T; - -typedef struct { - UINT32 SessionId; - UINT32 ActivationState; //MBIM_ACTIVATION_STATE_E - UINT32 VoiceCallState; - UINT32 IPType; //MBIM_CONTEXT_IP_TYPE_E - UUID_T ContextType; - UINT32 NwError; -} MBIM_CONNECT_T; - -typedef struct { - UINT32 OnLinkPrefixLength; - UINT8 IPv4Address[4]; -} MBIM_IPV4_ELEMENT_T; - -typedef struct { - UINT32 OnLinkPrefixLength; - UINT8 IPv6Address[16]; -} MBIM_IPV6_ELEMENT_T; - -typedef struct { - UINT32 SessionId; - UINT32 IPv4ConfigurationAvailable; //bit0~Address, bit1~gateway, bit2~DNS, bit3~MTU - UINT32 IPv6ConfigurationAvailable; //bit0~Address, bit1~gateway, bit2~DNS, bit3~MTU - UINT32 IPv4AddressCount; - UINT32 IPv4AddressOffset; - UINT32 IPv6AddressCount; - UINT32 IPv6AddressOffset; - UINT32 IPv4GatewayOffset; - UINT32 IPv6GatewayOffset; - UINT32 IPv4DnsServerCount; - UINT32 IPv4DnsServerOffset; - UINT32 IPv6DnsServerCount; - UINT32 IPv6DnsServerOffset; - UINT32 IPv4Mtu; - UINT32 IPv6Mtu; - UINT8 DataBuffer[]; -} MBIM_IP_CONFIGURATION_INFO_T; - -typedef struct { - UINT32 RSRP; - UINT32 SNR; - UINT32 RSRPThreshold; - UINT32 SNRThreshold; - UINT32 SystemType; -} MBIM_RSRP_SNR_INFO_T; - -typedef struct { - UINT32 Elementcount; - MBIM_RSRP_SNR_INFO_T RsrpSnr[0]; -} MBIM_RSRP_SNR_T; - -typedef struct { - UINT32 Rssi; - UINT32 ErrorRate; - UINT32 SignalStrengthInterval; - UINT32 RssiThreshold; - UINT32 ErrorRateThreshold; -} MBIM_SIGNAL_STATE_INFO_T; - -typedef struct { - UINT32 Rssi; - UINT32 ErrorRate; - UINT32 SignalStrengthInterval; - UINT32 RssiThreshold; - UINT32 ErrorRateThreshold; - UINT32 RsrpSnrOffset; - UINT32 RsrpSnrSize; - UINT8 DataBuffer[]; -} MBIM_SIGNAL_STATE_INFO_V2_T; - -typedef struct { - UINT32 SignalStrengthInterval; - UINT32 RssiThreshold; - UINT32 ErrorRateThreshold; -} MBIM_SET_SIGNAL_STATE_T; - +} UUID_LIBMBIM_PROXY_CID_E; + +typedef enum { + MBIM_CID_MS_UICC_ATR = 1, + MBIM_CID_MS_UICC_OPEN_CHANNEL = 2, + MBIM_CID_MS_UICC_CLOSE_CHANNEL = 3, + MBIM_CID_MS_UICC_APDU = 4, + MBIM_CID_MS_UICC_TERMINAL_CAPABILITY = 5, + MBIM_CID_MS_UICC_RESET = 6, + MBIM_CID_MS_APP_LIST = 7, +} UUID_MS_UICC_CID_E; + +typedef enum { + MBIM_ERROR_TIMEOUT_FRAGMENT = 1, + MBIM_ERROR_FRAGMENT_OUT_OF_SEQUENCE = 2, + MBIM_ERROR_LENGTH_MISMATCH = 3, + MBIM_ERROR_DUPLICATED_TID = 4, + MBIM_ERROR_NOT_OPENED = 5, + MBIM_ERROR_UNKNOWN = 6, + MBIM_ERROR_CANCEL = 7, + MBIM_ERROR_MAX_TRANSFER = 8, +} MBIM_ERROR_E; + +typedef enum { + MBIM_STATUS_SUCCESS = 0, + MBIM_STATUS_BUSY = 1, + MBIM_STATUS_FAILURE = 2, + MBIM_STATUS_SIM_NOT_INSERTED = 3, + MBIM_STATUS_BAD_SIM = 4, + MBIM_STATUS_PIN_REQUIRED = 5, + MBIM_STATUS_PIN_DISABLED = 6, + MBIM_STATUS_NOT_REGISTERED = 7, + MBIM_STATUS_PROVIDERS_NOT_FOUND = 8, + MBIM_STATUS_NO_DEVICE_SUPPORT = 9, + MBIM_STATUS_PROVIDER_NOT_VISIBLE = 10, + MBIM_STATUS_DATA_CLASS_NOT_AVAILABL = 11, + MBIM_STATUS_PACKET_SERVICE_DETACHED = 12, +} MBIM_STATUS_CODES_E; + +typedef enum { + MBIMPacketServiceActionAttach = 0, + MBIMPacketServiceActionDetach = 1, +} MBIM_PACKET_SERVICE_ACTION_E; + +typedef enum { + MBIMPacketServiceStateUnknown = 0, + MBIMPacketServiceStateAttaching = 1, + MBIMPacketServiceStateAttached = 2, + MBIMPacketServiceStateDetaching = 3, + MBIMPacketServiceStateDetached = 4, +} MBIM_PACKET_SERVICE_STATE_E; + +static const char *MBIMPacketServiceStateStr(int _val) { + struct { int val;char *name;} _enumstr[] = { + {MBIMPacketServiceStateUnknown, "Unknown"}, + {MBIMPacketServiceStateAttaching, "Attaching"}, + {MBIMPacketServiceStateAttached, "Attached"}, + {MBIMPacketServiceStateDetaching, "Detaching"}, + {MBIMPacketServiceStateDetached, "Detached"}, + }; + int idx; + + for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { + if (_val == _enumstr[idx].val) + return _enumstr[idx].name; + } + + return "Undefined"; +}; + +typedef enum { + MBIMDataClassNone = 0x0, + MBIMDataClassGPRS = 0x1, + MBIMDataClassEDGE = 0x2, + MBIMDataClassUMTS = 0x4, + MBIMDataClassHSDPA = 0x8, + MBIMDataClassHSUPA = 0x10, + MBIMDataClassLTE = 0x20, + MBIMDataClass5G_NSA = 0x40, + MBIMDataClass5G_SA = 0x80, + MBIMDataClass1XRTT = 0x10000, + MBIMDataClass1XEVDO = 0x20000, + MBIMDataClass1XEVDORevA = 0x40000, + MBIMDataClass1XEVDV = 0x80000, + MBIMDataClass3XRTT = 0x100000, + MBIMDataClass1XEVDORevB = 0x200000, + MBIMDataClassUMB = 0x400000, + MBIMDataClassCustom = 0x80000000, +} MBIM_DATA_CLASS_E; + +static const char *MBIMDataClassStr(int _val) { + struct { int val;char *name;} _enumstr[] = { + {MBIMDataClassNone, "None"}, + {MBIMDataClassGPRS, "GPRS"}, + {MBIMDataClassEDGE, "EDGE"}, + {MBIMDataClassUMTS, "UMTS"}, + {MBIMDataClassHSDPA, "HSDPA"}, + {MBIMDataClassHSUPA, "HSUPA"}, + {MBIMDataClassLTE, "LTE"}, + {MBIMDataClass5G_NSA, "5G_NSA"}, + {MBIMDataClass5G_SA, "5G_SA"}, + {MBIMDataClass1XRTT, "1XRTT"}, + {MBIMDataClass1XEVDO, "1XEVDO"}, + {MBIMDataClass1XEVDORevA, "1XEVDORevA"}, + {MBIMDataClass1XEVDV, "1XEVDV"}, + {MBIMDataClass3XRTT, "3XRTT"}, + {MBIMDataClass1XEVDORevB, "1XEVDORevB"}, + {MBIMDataClassUMB, "UMB"}, + {MBIMDataClassCustom, "Custom"}, + }; + int idx; + + for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { + if (_val == _enumstr[idx].val) + return _enumstr[idx].name; + } + + return "Unknow"; +}; + typedef struct { - UINT32 DevicePathOffset; - UINT32 DevicePathSize; - UINT32 Timeout; - UINT8 DataBuffer[]; -} MBIM_LIBQMI_PROXY_CONFIG_T; - -typedef struct { - UINT32 AtrSize; - UINT32 AtrOffset; - UINT8 DataBuffer[]; -} MBIM_MS_ATR_INFO_T; - -#pragma pack() - -static pthread_t s_tid_reader = 0; -static int mbim_verbose = 0; -static UINT32 TransactionId = 1; -static unsigned mbim_default_timeout = 30000; -static const char *mbim_apn = NULL; -static const char *mbim_user = NULL; -static const char *mbim_passwd = NULL; -static int mbim_iptype = MBIMContextIPTypeDefault; -static int mbim_auth = MBIMAuthProtocolNone; -static int mbim_sessionID = 0; -static int mbim_fd = -1; -static MBIM_MESSAGE_HEADER *mbim_pRequest; -static MBIM_MESSAGE_HEADER *mbim_pResponse; - -static unsigned int qmi_over_mbim_support = 0; -static int qmi_over_mbim_sk[2] = {-1, -1}; -static pthread_mutex_t mbim_command_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t mbim_command_cond = PTHREAD_COND_INITIALIZER; -static int mbim_ms_version = 1; -static uint8_t qmi_over_mbim_nas = 0; -int qmi_over_mbim_qmidev_send(PQCQMIMSG pQMI); - -static const UUID_T * str2uuid(const char *str) { - static UUID_T uuid; - UINT32 d[16]; - char tmp[16*2+4+1]; - unsigned i = 0; - - while (str[i]) { - tmp[i] = tolower(str[i]); - i++; - } - tmp[i] = '\0'; - - sscanf(tmp, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", - &d[0], &d[1], &d[2], &d[3], &d[4], &d[5], &d[6], &d[7], - &d[8], &d[9], &d[10], &d[11], &d[12], &d[13], &d[14], &d[15]); - - for (i = 0; i < 16; i++) { - uuid.uuid[i] = d[i]&0xFF; - } - - return &uuid; -} - -static void wchar2char(const char *src, size_t src_size, char *dst, size_t dst_len) { - size_t i; - - for (i = 0; i < (dst_len-1) && i < (src_size/2); i++) - dst[i] = src[i*2]; - dst[i] = 0; -} - -static size_t char2wchar(const char *src, size_t src_len, uint8_t *dst, size_t dst_len) { - size_t i; - - if (src_len > (dst_len/2)) - src_len = (dst_len/2); - - for (i = 0; i < src_len; i++) { - *dst++ = *src++; - *dst++ = 0; - } - - return i*2; -} - -#define mbim_alloc( _size) malloc(_size) -#define mbim_free(_mem) do { if (_mem) { free(_mem); _mem = NULL;}} while(0) - -static int mbim_open_state = 0; -static MBIM_SUBSCRIBER_READY_STATE_E ReadyState = MBIMSubscriberReadyStateNotInitialized; -static MBIM_REGISTER_STATE_E RegisterState = MBIMRegisterStateUnknown; -static MBIM_PACKET_SERVICE_STATE_E PacketServiceState = MBIMPacketServiceStateUnknown; -static MBIM_ACTIVATION_STATE_E ActivationState = MBIMActivationStateUnknown; -static MBIM_SUBSCRIBER_READY_STATE_E oldReadyState = MBIMSubscriberReadyStateNotInitialized; -static MBIM_REGISTER_STATE_E oldRegisterState = MBIMRegisterStateUnknown; -static MBIM_PACKET_SERVICE_STATE_E oldPacketServiceState = MBIMPacketServiceStateUnknown; -static MBIM_ACTIVATION_STATE_E oldActivationState = MBIMActivationStateUnknown; -static int mbim_update_state(void); - -static __inline uint32_t mbim2qmi_ipv4addr(uint32_t addr) { - return (addr>>24) | (addr>>8&0xff00) | (addr<<8&0xff0000) | (addr<<24); -} - -static __inline void mbim2qmi_ipv6addr(const unsigned char *src, unsigned char *dst) { - int i; - - for (i = 0; i < 16 ; i++) { - dst[i] = src[i]; - } -} - -static MBIM_MESSAGE_HEADER *compose_open_command(UINT32 MaxControlTransfer) -{ - MBIM_OPEN_MSG_T *pRequest = (MBIM_OPEN_MSG_T *)mbim_alloc(sizeof(MBIM_OPEN_MSG_T)); - - if(!pRequest) - return NULL; - - pRequest->MessageHeader.MessageType = htole32(MBIM_OPEN_MSG); - pRequest->MessageHeader.MessageLength = htole32(sizeof(MBIM_OPEN_MSG_T)); - pRequest->MessageHeader.TransactionId = htole32(TransactionId++); - pRequest->MaxControlTransfer = htole32(MaxControlTransfer); - - return &pRequest->MessageHeader; -} - -static MBIM_MESSAGE_HEADER *compose_close_command(void) -{ - MBIM_CLOSE_MSG_T *pRequest = (MBIM_CLOSE_MSG_T *)mbim_alloc(sizeof(MBIM_CLOSE_MSG_T)); - - if(!pRequest) - return NULL; - - pRequest->MessageHeader.MessageType = htole32(MBIM_CLOSE_MSG); - pRequest->MessageHeader.MessageLength = htole32(sizeof(MBIM_CLOSE_MSG_T)); - pRequest->MessageHeader.TransactionId = htole32(TransactionId++); - - return &pRequest->MessageHeader; -} - -static MBIM_MESSAGE_HEADER *compose_basic_connect_command(UINT32 CID, UINT32 CommandType, void *pInformationBuffer, UINT32 InformationBufferLength) -{ - MBIM_COMMAND_MSG_T *pRequest = (MBIM_COMMAND_MSG_T *)mbim_alloc(sizeof(MBIM_COMMAND_MSG_T) + InformationBufferLength); - - if (!pRequest) - return NULL; - - pRequest->MessageHeader.MessageType = htole32(MBIM_COMMAND_MSG); - pRequest->MessageHeader.MessageLength = htole32((sizeof(MBIM_COMMAND_MSG_T) + InformationBufferLength)); - pRequest->MessageHeader.TransactionId = htole32(TransactionId++); - - pRequest->FragmentHeader.TotalFragments = htole32(1); - pRequest->FragmentHeader.CurrentFragment= htole32(0); - - memcpy(pRequest->DeviceServiceId.uuid, str2uuid(UUID_BASIC_CONNECT), 16); - - pRequest->CID = htole32(CID); - pRequest->CommandType = htole32(CommandType); - if (InformationBufferLength && pInformationBuffer) { - pRequest->InformationBufferLength = htole32(InformationBufferLength); - memcpy(pRequest->InformationBuffer, pInformationBuffer, InformationBufferLength); - } else { - pRequest->InformationBufferLength = htole32(0); - } - - return &pRequest->MessageHeader; -} - -static MBIM_MESSAGE_HEADER *compose_basic_connect_ext_command(UINT32 CID, UINT32 CommandType, void *pInformationBuffer, UINT32 InformationBufferLength) -{ - MBIM_COMMAND_MSG_T *pRequest = (MBIM_COMMAND_MSG_T *)compose_basic_connect_command(CID, CommandType, pInformationBuffer, InformationBufferLength); - - if (!pRequest) - return NULL; - - memcpy(pRequest->DeviceServiceId.uuid, str2uuid(UUID_BASIC_CONNECT_EXT), 16); - - return &pRequest->MessageHeader; -} - -static MBIM_MESSAGE_HEADER *compose_qmi_over_mbim_command(UINT32 CID, UINT32 CommandType, void *pInformationBuffer, UINT32 InformationBufferLength) -{ - MBIM_COMMAND_MSG_T *pRequest = (MBIM_COMMAND_MSG_T *)compose_basic_connect_command(CID, CommandType, pInformationBuffer, InformationBufferLength); - - if (!pRequest) - return NULL; - - memcpy(pRequest->DeviceServiceId.uuid, str2uuid(uuid_ext_qmux), 16); - - return &pRequest->MessageHeader; -} - -static const char * uuid2str(const UUID_T *pUUID) { - static char str[16*2+4+1]; - const UINT8 *d = pUUID->uuid; - - snprintf(str, sizeof(str), "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", - d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], - d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); - - return str; -} - -static const char *DeviceServiceId2str(const UUID_T *pUUID) { - const char *str = uuid2str(pUUID); - - struct { char *val;char *name;} _enumstr[] = { - {UUID_BASIC_CONNECT, "UUID_BASIC_CONNECT"}, - {UUID_BASIC_CONNECT_EXT, "UUID_BASIC_CONNECT_EXT"}, - {UUID_SMS, "UUID_SMS"}, - {UUID_USSD, "UUID_USSD"}, - {UUID_PHONEBOOK, "UUID_PHONEBOOK"}, - {UUID_STK, "UUID_STK"}, - {UUID_AUTH, "UUID_AUTH"}, - {UUID_DSS, "UUID_DSS"}, - {uuid_ext_qmux, "uuid_ext_qmux"}, - {uuid_mshsd, "uuid_mshsd"}, - {uuid_qmbe, "uuid_qmbe"}, - {UUID_MSFWID, "UUID_MSFWID"}, - {uuid_atds, "uuid_atds"}, - {uuid_qdu, "uuid_qdu"}, - {UUID_MS_UICC_LOW_LEVEL, "UUID_MS_UICC_LOW_LEVEL"}, - {UUID_MS_SARControl, "UUID_MS_SARControl"}, - {UUID_VOICEEXTENSIONS, "UUID_VOICEEXTENSIONS"}, - {UUID_LIBMBIM_PROXY, "UUID_LIBMBIM_PROXY"}, - }; - int idx; - - for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { - if (!strcasecmp(str, _enumstr[idx].val)) - return _enumstr[idx].name; - } - - return str; -} - -static const char *mbim_get_segment(void *_pMsg, UINT32 offset, UINT32 len) -{ - int idx; - static char buff[256] = {'\0'}; - UINT8 *pMsg = (UINT8*)_pMsg; - - for (idx = 0; idx < (int)(len/2); idx++) - buff[idx] = pMsg[offset+idx*2]; - buff[idx] = '\0'; - return buff; -} - -static void mbim_dump_header(MBIM_MESSAGE_HEADER *pMsg, const char *direction) { - mbim_debug("%s Header:", direction); - mbim_debug("%s MessageLength = %u", direction, le32toh(pMsg->MessageLength)); - mbim_debug("%s MessageType = %s (0x%08x)", direction, MBIMMSGTypeStr(le32toh(pMsg->MessageType)), le32toh(pMsg->MessageType)); - mbim_debug("%s TransactionId = %u", direction, le32toh(pMsg->TransactionId)); - mbim_debug("%s Contents:", direction); -} - -static void mbim_dump_uuid_cid(const UUID_T *pUUID, UINT32 CID, const char *direction) { - size_t idx; - const char *uuidStr = uuid2str(pUUID); - const char *cidStr = "unknow"; - - for (idx = 0; idx < (sizeof(uuid_cid_string)/sizeof(uuid_cid_string[0])); idx++) { - if (!strcmp(uuidStr, uuid_cid_string[idx].uuid) && uuid_cid_string[idx].cid == CID) { - cidStr = uuid_cid_string[idx].name; - } - } - - mbim_debug("%s DeviceServiceId = %s (%s)", direction, DeviceServiceId2str(pUUID), uuidStr); - mbim_debug("%s CID = %s (%u)", direction, cidStr, le32toh(CID)); -} - - -static void mbim_dump_command_msg(MBIM_COMMAND_MSG_T *pCmdMsg, const char *direction) { - mbim_dump_uuid_cid(&pCmdMsg->DeviceServiceId, le32toh(pCmdMsg->CID), direction); - mbim_debug("%s CommandType = %s (%u)", direction, le32toh(pCmdMsg->CommandType) ? "set" : "query", le32toh(pCmdMsg->CommandType)); - mbim_debug("%s InformationBufferLength = %u", direction, le32toh(pCmdMsg->InformationBufferLength)); -} - -static void mbim_dump_command_done(MBIM_COMMAND_DONE_T *pCmdDone, const char *direction) { - mbim_dump_uuid_cid(&pCmdDone->DeviceServiceId, le32toh(pCmdDone->CID), direction); - mbim_debug("%s Status = %u", direction, le32toh(pCmdDone->Status)); - mbim_debug("%s InformationBufferLength = %u", direction, le32toh(pCmdDone->InformationBufferLength)); -} - -static void mbim_dump_indicate_msg(MBIM_INDICATE_STATUS_MSG_T *pIndMsg, const char *direction) { - mbim_dump_uuid_cid(&pIndMsg->DeviceServiceId, le32toh(pIndMsg->CID), direction); - mbim_debug("%s InformationBufferLength = %u", direction, le32toh(pIndMsg->InformationBufferLength)); -} - -static void mbim_dump_connect(MBIM_CONNECT_T *pInfo, const char *direction) { - mbim_debug("%s SessionId = %u", direction, le32toh(pInfo->SessionId)); - mbim_debug("%s ActivationState = %s (%u)", direction, MBIMActivationStateStr(le32toh(pInfo->ActivationState)), le32toh(pInfo->ActivationState)); - mbim_debug("%s IPType = %s", direction, MBIMContextIPTypeStr(le32toh(pInfo->IPType))); - mbim_debug("%s VoiceCallState = %s", direction, MBIMVoiceCallStateStr(le32toh(pInfo->VoiceCallState))); - mbim_debug("%s ContextType = %s", direction, uuid2str(&pInfo->ContextType)); - mbim_debug("%s NwError = %u", direction, le32toh(pInfo->NwError)); -} - -static void mbim_dump_signal_state(MBIM_SIGNAL_STATE_INFO_T *pInfo, const char *direction) -{ - mbim_debug("%s Rssi = %u", direction, le32toh(pInfo->Rssi)); - mbim_debug("%s ErrorRate = %u", direction, le32toh(pInfo->ErrorRate)); - mbim_debug("%s SignalStrengthInterval = %u", direction, le32toh(pInfo->SignalStrengthInterval)); - mbim_debug("%s RssiThreshold = %u", direction, le32toh(pInfo->RssiThreshold)); - mbim_debug("%s ErrorRateThreshold = %u", direction, le32toh(pInfo->ErrorRateThreshold)); -} - -static void mbim_dump_packet_service(MBIM_PACKET_SERVICE_INFO_T *pInfo, const char *direction) -{ - mbim_debug("%s NwError = %u", direction, le32toh(pInfo->NwError)); - mbim_debug("%s PacketServiceState = %s", direction, MBIMPacketServiceStateStr(le32toh(pInfo->PacketServiceState))); - mbim_debug("%s HighestAvailableDataClass = %s", direction, MBIMDataClassStr(le32toh(pInfo->HighestAvailableDataClass))); - mbim_debug("%s UplinkSpeed = %ld", direction, (long)le64toh(pInfo->UplinkSpeed)); - mbim_debug("%s DownlinkSpeed = %ld", direction, (long)le64toh(pInfo->DownlinkSpeed)); -} - -static void mbim_dump_subscriber_status(MBIM_SUBSCRIBER_READY_STATUS_T *pInfo, const char *direction) -{ - mbim_debug("%s ReadyState = %s", direction, MBIMSubscriberReadyStateStr(le32toh(pInfo->ReadyState))); - mbim_debug("%s SIMICCID = %s", direction, mbim_get_segment(pInfo, le32toh(pInfo->SimIccIdOffset), le32toh(pInfo->SimIccIdSize))); - mbim_debug("%s SubscriberID = %s", direction, mbim_get_segment(pInfo, le32toh(pInfo->SubscriberIdOffset), le32toh(pInfo->SubscriberIdSize))); - /* maybe more than one number */ - uint32_t idx; - for (idx = 0; idx < le32toh(pInfo->ElementCount); idx++) { - UINT32 offset = ((UINT32*)((UINT8*)pInfo+offsetof(MBIM_SUBSCRIBER_READY_STATUS_T, TelephoneNumbersRefList)))[0]; - UINT32 length = ((UINT32*)((UINT8*)pInfo+offsetof(MBIM_SUBSCRIBER_READY_STATUS_T, TelephoneNumbersRefList)))[1]; - mbim_debug("%s Number = %s", direction, mbim_get_segment(pInfo, le32toh(offset), le32toh(length))); - } -} - -static void mbim_dump_regiester_status(MBIM_REGISTRATION_STATE_INFO_T *pInfo, const char *direction) -{ - mbim_debug("%s NwError = %u", direction, le32toh(pInfo->NwError)); - mbim_debug("%s RegisterState = %s", direction, MBIMRegisterStateStr(le32toh(pInfo->RegisterState))); - mbim_debug("%s RegisterMode = %s", direction, MBIMRegisterModeStr(le32toh(pInfo->RegisterMode))); -} - -static void mbim_dump_ipconfig(MBIM_IP_CONFIGURATION_INFO_T *pInfo, const char *direction) -{ - UINT8 prefix = 0, *ipv4=NULL, *ipv6=NULL, *gw=NULL, *dns1=NULL, *dns2=NULL; - - mbim_debug("%s SessionId = %u", direction, le32toh(pInfo->SessionId)); - mbim_debug("%s IPv4ConfigurationAvailable = 0x%x", direction, le32toh(pInfo->IPv4ConfigurationAvailable)); - mbim_debug("%s IPv6ConfigurationAvailable = 0x%x", direction, le32toh(pInfo->IPv6ConfigurationAvailable)); - mbim_debug("%s IPv4AddressCount = 0x%x", direction, le32toh(pInfo->IPv4AddressCount)); - mbim_debug("%s IPv4AddressOffset = 0x%x", direction, le32toh(pInfo->IPv4AddressOffset)); - mbim_debug("%s IPv6AddressCount = 0x%x", direction, le32toh(pInfo->IPv6AddressCount)); - mbim_debug("%s IPv6AddressOffset = 0x%x", direction, le32toh(pInfo->IPv6AddressOffset)); - - /* IPv4 */ - if (le32toh(pInfo->IPv4ConfigurationAvailable)&0x1) { - MBIM_IPV4_ELEMENT_T *pAddress = (MBIM_IPV4_ELEMENT_T *)(&pInfo->DataBuffer[le32toh(pInfo->IPv4AddressOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); - prefix = le32toh(pAddress->OnLinkPrefixLength); - ipv4 = pAddress->IPv4Address; - mbim_debug("%s IPv4 = %u.%u.%u.%u/%u", direction, ipv4[0], ipv4[1], ipv4[2], ipv4[3], prefix); - } - if (le32toh(pInfo->IPv4ConfigurationAvailable)&0x2) { - gw = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv4GatewayOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); - mbim_debug("%s gw = %u.%u.%u.%u", direction, gw[0], gw[1], gw[2], gw[3]); - } - if (le32toh(pInfo->IPv4ConfigurationAvailable)&0x3) { - dns1 = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv4DnsServerOffset) -sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); - mbim_debug("%s dns1 = %u.%u.%u.%u", direction, dns1[0], dns1[1], dns1[2], dns1[3]); - if (le32toh(pInfo->IPv4DnsServerCount) == 2) { - dns2 = dns1 + 4; - mbim_debug("%s dns2 = %u.%u.%u.%u", direction, dns2[0], dns2[1], dns2[2], dns2[3]); - } - } - if (le32toh(pInfo->IPv4Mtu)) mbim_debug("%s ipv4 mtu = %u", direction, le32toh(pInfo->IPv4Mtu)); - - /* IPv6 */ - if (le32toh(pInfo->IPv6ConfigurationAvailable)&0x1) { - MBIM_IPV6_ELEMENT_T *pAddress = (MBIM_IPV6_ELEMENT_T *)(&pInfo->DataBuffer[le32toh(pInfo->IPv6AddressOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); - prefix = le32toh(pAddress->OnLinkPrefixLength); - ipv6 = pAddress->IPv6Address; - mbim_debug("%s IPv6 = %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x/%d", \ - direction, ipv6[0], ipv6[1], ipv6[2], ipv6[3], ipv6[4], ipv6[5], ipv6[6], ipv6[7], \ - ipv6[8], ipv6[9], ipv6[10], ipv6[11], ipv6[12], ipv6[13], ipv6[14], ipv6[15], prefix); - } - if (le32toh(pInfo->IPv6ConfigurationAvailable)&0x2) { - gw = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv6GatewayOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); - mbim_debug("%s gw = %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", \ - direction, gw[0], gw[1], gw[2], gw[3], gw[4], gw[5], gw[6], gw[7], \ - gw[8], gw[9], gw[10], gw[11], gw[12], gw[13], gw[14], gw[15]); - } - if (le32toh(pInfo->IPv6ConfigurationAvailable)&0x3) { - dns1 = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv6DnsServerOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); - mbim_debug("%s dns1 = %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", \ - direction, dns1[0], dns1[1], dns1[2], dns1[3], dns1[4], dns1[5], dns1[6], dns1[7], \ - dns1[8], dns1[9], dns1[10], dns1[11], dns1[12], dns1[13], dns1[14], dns1[15]); - if (le32toh(pInfo->IPv6DnsServerCount) == 2) { - dns2 = dns1 + 16; - mbim_debug("%s dns2 = %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", \ - direction, dns2[0], dns2[1], dns2[2], dns2[3], dns1[4], dns1[5], dns1[6], dns1[7], - dns2[8], dns2[9], dns2[10], dns2[11], dns2[12], dns2[13], dns2[14], dns2[15]); - } - } - if (le32toh(pInfo->IPv6Mtu)) mbim_debug("%s ipv6 mtu = %u", direction, le32toh(pInfo->IPv6Mtu)); -} - -static void mbim_dump(MBIM_MESSAGE_HEADER *pMsg, int mbim_verbose) { - unsigned char *data = (unsigned char *)pMsg; - const char *direction = (le32toh(pMsg->MessageType) & 0x80000000) ? "<" : ">"; - - if (!mbim_verbose) - return; - - if (mbim_verbose) { - unsigned i; - static char *_tmp = NULL; - - if (!_tmp) - _tmp = (char *)malloc(4096); - - if (_tmp) { - _tmp[0] = (le32toh(pMsg->MessageType) & 0x80000000) ? '<' : '>'; - _tmp[1] = '\0'; - for (i = 0; i < le32toh(pMsg->MessageLength) && i < 4096; i++) - snprintf(_tmp + strlen(_tmp), 4096 - strlen(_tmp), "%02X:", data[i]); - mbim_debug("%s", _tmp); - } - } - - mbim_dump_header(pMsg, direction); - - switch (le32toh(pMsg->MessageType)) { - case MBIM_OPEN_MSG: { - MBIM_OPEN_MSG_T *pOpenMsg = (MBIM_OPEN_MSG_T *)pMsg; - mbim_debug("%s MaxControlTransfer = %u", direction, le32toh(pOpenMsg->MaxControlTransfer)); - } - break; - case MBIM_OPEN_DONE: { - MBIM_OPEN_DONE_T *pOpenDone = (MBIM_OPEN_DONE_T *)pMsg; - mbim_debug("%s Status = %u", direction, le32toh(pOpenDone->Status)); - } - break; - case MBIM_CLOSE_MSG: { - - } - break; - case MBIM_CLOSE_DONE: { - MBIM_CLOSE_DONE_T *pCloseDone = (MBIM_CLOSE_DONE_T *)pMsg; - mbim_debug("%s Status = %u", direction, le32toh(pCloseDone->Status)); - } - break; - case MBIM_COMMAND_MSG: { - MBIM_COMMAND_MSG_T *pCmdMsg = (MBIM_COMMAND_MSG_T *)pMsg; - - mbim_dump_command_msg(pCmdMsg, direction); - if (!memcmp(pCmdMsg->DeviceServiceId.uuid, str2uuid(UUID_BASIC_CONNECT), 16)) { - switch (le32toh(pCmdMsg->CID)) { - case MBIM_CID_CONNECT: { - MBIM_SET_CONNECT_T *pInfo = (MBIM_SET_CONNECT_T *)pCmdMsg->InformationBuffer; - mbim_debug("%s SessionId = %u", direction, le32toh(pInfo->SessionId)); - } - break; - case MBIM_CID_IP_CONFIGURATION: { - MBIM_IP_CONFIGURATION_INFO_T *pInfo = (MBIM_IP_CONFIGURATION_INFO_T *)pCmdMsg->InformationBuffer; - mbim_debug("%s SessionId = %u", direction, le32toh(pInfo->SessionId)); - } - break; - default: - break; - } - } - } - break; - case MBIM_COMMAND_DONE: { - MBIM_COMMAND_DONE_T *pCmdDone = (MBIM_COMMAND_DONE_T *)pMsg; - - mbim_dump_command_done(pCmdDone, direction); - if (le32toh(pCmdDone->InformationBufferLength) == 0) - return; - - if (!memcmp(pCmdDone->DeviceServiceId.uuid, str2uuid(UUID_BASIC_CONNECT), 16)) { - switch (le32toh(pCmdDone->CID)) { - case MBIM_CID_CONNECT: { - MBIM_CONNECT_T *pInfo = (MBIM_CONNECT_T *)pCmdDone->InformationBuffer; - mbim_dump_connect(pInfo, direction); - } - break; - case MBIM_CID_IP_CONFIGURATION: { - //MBIM_IP_CONFIGURATION_INFO_T *pInfo = (MBIM_IP_CONFIGURATION_INFO_T *)pCmdDone->InformationBuffer; - //mbim_dump_ipconfig(pInfo, direction); - } - break; - case MBIM_CID_PACKET_SERVICE: { - MBIM_PACKET_SERVICE_INFO_T *pInfo = (MBIM_PACKET_SERVICE_INFO_T *)pCmdDone->InformationBuffer; - mbim_dump_packet_service(pInfo, direction); - } - break; - case MBIM_CID_SUBSCRIBER_READY_STATUS: { - MBIM_SUBSCRIBER_READY_STATUS_T *pInfo = (MBIM_SUBSCRIBER_READY_STATUS_T *)pCmdDone->InformationBuffer; - mbim_dump_subscriber_status(pInfo, direction); - } - break; - case MBIM_CID_REGISTER_STATE: { - MBIM_REGISTRATION_STATE_INFO_T *pInfo = (MBIM_REGISTRATION_STATE_INFO_T *)pCmdDone->InformationBuffer; - mbim_dump_regiester_status(pInfo, direction); - } - break; - default: - break; - } - } - } - break; - case MBIM_INDICATE_STATUS_MSG: { - MBIM_INDICATE_STATUS_MSG_T *pIndMsg = (MBIM_INDICATE_STATUS_MSG_T *)pMsg; - - mbim_dump_indicate_msg(pIndMsg, direction); - if (le32toh(pIndMsg->InformationBufferLength) == 0) - return; - - if (!memcmp(pIndMsg->DeviceServiceId.uuid, str2uuid(UUID_BASIC_CONNECT), 16)) { - switch (le32toh(pIndMsg->CID)) { - case MBIM_CID_CONNECT: { - MBIM_CONNECT_T *pInfo = (MBIM_CONNECT_T *)pIndMsg->InformationBuffer; - mbim_dump_connect(pInfo, direction); - } - break; - case MBIM_CID_SIGNAL_STATE: { - MBIM_SIGNAL_STATE_INFO_T *pInfo = (MBIM_SIGNAL_STATE_INFO_T *)pIndMsg->InformationBuffer; - mbim_dump_signal_state(pInfo, direction); - } - break; - case MBIM_CID_SUBSCRIBER_READY_STATUS: { - MBIM_SUBSCRIBER_READY_STATUS_T *pInfo = (MBIM_SUBSCRIBER_READY_STATUS_T *)pIndMsg->InformationBuffer; - mbim_dump_subscriber_status(pInfo, direction); - } - break; - case MBIM_CID_REGISTER_STATE: { - MBIM_REGISTRATION_STATE_INFO_T *pInfo = (MBIM_REGISTRATION_STATE_INFO_T *)pIndMsg->InformationBuffer; - mbim_dump_regiester_status(pInfo, direction); - } - break; - case MBIM_CID_PACKET_SERVICE: { - MBIM_PACKET_SERVICE_INFO_T *pInfo = (MBIM_PACKET_SERVICE_INFO_T *)pIndMsg->InformationBuffer; - mbim_dump_packet_service(pInfo, direction); - } - break; - default: - break; - } - } - else if (!memcmp(pIndMsg->DeviceServiceId.uuid, str2uuid(UUID_BASIC_CONNECT_EXT), 16)) { - } - } - break; - case MBIM_FUNCTION_ERROR_MSG: { - MBIM_FUNCTION_ERROR_MSG_T *pErrMsg = (MBIM_FUNCTION_ERROR_MSG_T*)pMsg; - mbim_debug("%s ErrorStatusCode = %u", direction, le32toh(pErrMsg->ErrorStatusCode)); - } - break; - default: - break; - } -} - -static void mbim_recv_command(MBIM_MESSAGE_HEADER *pResponse, unsigned size) -{ - (void)size; - pthread_mutex_lock(&mbim_command_mutex); - - if (pResponse) - mbim_dump(pResponse, mbim_verbose); - - if (pResponse == NULL) { - pthread_cond_signal(&mbim_command_cond); - } - else if (mbim_pRequest && le32toh(mbim_pRequest->TransactionId) == le32toh(pResponse->TransactionId)) { - mbim_pResponse = mbim_alloc(le32toh(pResponse->MessageLength)); - if (mbim_pResponse) - memcpy(mbim_pResponse, pResponse, le32toh(pResponse->MessageLength)); - pthread_cond_signal(&mbim_command_cond); - } - else if (le32toh(pResponse->MessageType) == MBIM_INDICATE_STATUS_MSG) { - MBIM_INDICATE_STATUS_MSG_T *pIndMsg = (MBIM_INDICATE_STATUS_MSG_T *)pResponse; - - if (!memcmp(pIndMsg->DeviceServiceId.uuid, str2uuid(UUID_BASIC_CONNECT), 16)) - { - switch (le32toh(pIndMsg->CID)) { - case MBIM_CID_SUBSCRIBER_READY_STATUS: { - MBIM_SUBSCRIBER_READY_STATUS_T *pInfo = (MBIM_SUBSCRIBER_READY_STATUS_T *)pIndMsg->InformationBuffer; - if (oldReadyState != le32toh(pInfo->ReadyState)) - qmidevice_send_event_to_main(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED); - } - break; - case MBIM_CID_REGISTER_STATE: { - MBIM_REGISTRATION_STATE_INFO_T *pInfo = (MBIM_REGISTRATION_STATE_INFO_T *)pIndMsg->InformationBuffer; - if (oldRegisterState != le32toh(pInfo->RegisterState)) - qmidevice_send_event_to_main(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED); - } - break; - case MBIM_CID_PACKET_SERVICE: { - MBIM_PACKET_SERVICE_INFO_T *pInfo = (MBIM_PACKET_SERVICE_INFO_T *)pIndMsg->InformationBuffer; - MBIM_PACKET_SERVICE_STATE_E state = le32toh(pInfo->PacketServiceState); - - if (oldPacketServiceState != state - && (1 || MBIMPacketServiceStateAttached == state || MBIMPacketServiceStateDetached == state)) - qmidevice_send_event_to_main(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED); - } - break; - case MBIM_CID_CONNECT: { - MBIM_CONNECT_T *pInfo = (MBIM_CONNECT_T *)pIndMsg->InformationBuffer; - if (pInfo->SessionId == (uint32_t)mbim_sessionID) { - MBIM_ACTIVATION_STATE_E state = le32toh(pInfo->ActivationState); - - if (oldActivationState != state - && (1 || MBIMActivationStateActivated == state || MBIMActivationStateDeactivated == state)) - qmidevice_send_event_to_main(RIL_UNSOL_DATA_CALL_LIST_CHANGED); - } - } - break; - default: - break; - } - } - } - - pthread_mutex_unlock(&mbim_command_mutex); -} - -static int mbim_send_command(MBIM_MESSAGE_HEADER *pRequest, MBIM_COMMAND_DONE_T **ppCmdDone, unsigned msecs) { - int ret; - - if (ppCmdDone) - *ppCmdDone = NULL; - - if (mbim_fd <= 0) - return -ENODEV; - - if (s_tid_reader == 0) - return -EINVAL; - - if (!pRequest) - return -ENOMEM; - - pthread_mutex_lock(&mbim_command_mutex); - - if (pRequest) { - if (pRequest->TransactionId == (0xFFFFFF + 1)) { //quectel-mbim-proxy need 0xFF000000 to indicat client - TransactionId = 1; - pRequest->TransactionId = htole32(TransactionId++); - } - mbim_dump(pRequest, mbim_verbose); - } - - mbim_pRequest = pRequest; - mbim_pResponse = NULL; - - ret = write(mbim_fd, pRequest, le32toh(pRequest->MessageLength)); - - if (ret > 0 && (uint32_t)ret == le32toh(pRequest->MessageLength)) { - ret = pthread_cond_timeout_np(&mbim_command_cond, &mbim_command_mutex, msecs); - if (!ret) { - if (mbim_pResponse && ppCmdDone) { - *ppCmdDone = (MBIM_COMMAND_DONE_T *)mbim_pResponse; - } - } - } else { - mbim_debug("%s pthread_cond_timeout_np=%d", __func__, ret); - } - - mbim_pRequest = mbim_pResponse = NULL; - - pthread_mutex_unlock(&mbim_command_mutex); - - return ret; -} - -static ssize_t mbim_proxy_read (int fd, MBIM_MESSAGE_HEADER *pResponse, size_t size) { - ssize_t nreads; - - nreads = read(fd, pResponse, sizeof(MBIM_MESSAGE_HEADER)); - if (nreads == sizeof(MBIM_MESSAGE_HEADER) && le32toh(pResponse->MessageLength) <= size) { - nreads += read(fd, pResponse+1, le32toh(pResponse->MessageLength) - sizeof(MBIM_MESSAGE_HEADER)); - } - - return nreads; -} - -static void * mbim_read_thread(void *param) { - PROFILE_T *profile = (PROFILE_T *)param; - const char *cdc_wdm = (const char *)profile->qmichannel; - int wait_for_request_quit = 0; - - mbim_verbose = debug_qmi; - s_tid_reader = pthread_self(); - - if (profile->qmap_mode > 1 && profile->qmapnet_adapter[0]) { - if (!profile->proxy[0]) - sprintf(profile->proxy, "%s", QUECTEL_MBIM_PROXY); - mbim_sessionID = profile->pdp; - } - - if (profile->proxy[0]) { - mbim_fd = cm_open_proxy(profile->proxy); - } - else { - mbim_fd = cm_open_dev(cdc_wdm); - } - - if (mbim_fd <= 0) { - mbim_debug("fail to open (%s), errno: %d (%s)", cdc_wdm, errno, strerror(errno)); - goto __quit; - } - - dbg_time("cdc_wdm_fd = %d", mbim_fd); - - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_CONNECTED); - - while (mbim_fd > 0) { - struct pollfd pollfds[] = {{mbim_fd, POLLIN, 0}, {qmidevice_control_fd[1], POLLIN, 0}, {qmi_over_mbim_sk[1], POLLIN, 0}}; - int ne, ret, nevents = 2; - - if (pollfds[nevents].fd != -1) - nevents++; - - ret = poll(pollfds, nevents, wait_for_request_quit ? 1000 : -1); - - if (ret == 0 && wait_for_request_quit) { - break; - } - - if (ret < 0) { - mbim_debug("%s poll=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno)); - break; - } - - for (ne = 0; ne < nevents; ne++) { - int fd = pollfds[ne].fd; - short revents = pollfds[ne].revents; - - if (revents & (POLLERR | POLLHUP | POLLNVAL)) { - mbim_debug("%s poll err/hup/inval", __func__); - mbim_debug("epoll fd = %d, events = 0x%04x", fd, revents); - if (revents & (POLLERR | POLLHUP | POLLNVAL)) - goto __quit; - } - - if ((revents & POLLIN) == 0) - continue; - - if (mbim_fd == fd) { - ssize_t nreads; - MBIM_MESSAGE_HEADER *pResponse = (MBIM_MESSAGE_HEADER *) cm_recv_buf; - - if (profile->proxy[0]) - nreads = mbim_proxy_read(fd, pResponse, sizeof(cm_recv_buf)); - else - nreads = read(fd, pResponse, sizeof(cm_recv_buf)); - - if (nreads <= 0) { - mbim_debug("%s read=%d errno: %d (%s)", __func__, (int)nreads, errno, strerror(errno)); - break; - } - - mbim_recv_command(pResponse, nreads); - } - else if (fd == qmidevice_control_fd[1]) { - int triger_event; - if (read(fd, &triger_event, sizeof(triger_event)) == sizeof(triger_event)) { - //mbim_debug("triger_event = 0x%x", triger_event); - switch (triger_event) { - case RIL_REQUEST_QUIT: - goto __quit; - break; - case SIG_EVENT_STOP: - wait_for_request_quit = 1; - break; - default: - break; - } - } - } - else if (fd == qmi_over_mbim_sk[1]) { - ssize_t nreads = read(fd, cm_recv_buf, sizeof(cm_recv_buf)); - if (nreads > 0) - QmiThreadRecvQMI((PQCQMIMSG)cm_recv_buf); - } - } - } - -__quit: - if (mbim_fd != -1) { close(mbim_fd); mbim_fd = -1; } - mbim_recv_command(NULL, 0); - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED); - mbim_debug("%s exit", __func__); - s_tid_reader = 0; - - return NULL; -} - -static int mbim_status_code(MBIM_MESSAGE_HEADER *pMsgHdr) { - int status = 0; - - if (!pMsgHdr) - return 0; - - switch (le32toh(pMsgHdr->MessageType)) { - case MBIM_OPEN_DONE: { - MBIM_OPEN_DONE_T *pOpenDone = (MBIM_OPEN_DONE_T *)pMsgHdr; - status = le32toh(pOpenDone->Status); - } - break; - case MBIM_CLOSE_DONE: { - MBIM_CLOSE_DONE_T *pCloseDone = (MBIM_CLOSE_DONE_T *)pMsgHdr; - status = le32toh(pCloseDone->Status); - } - break; - case MBIM_COMMAND_DONE: { - MBIM_COMMAND_DONE_T *pCmdDone = (MBIM_COMMAND_DONE_T *)pMsgHdr; - status = le32toh(pCmdDone->Status); - } - break; - case MBIM_FUNCTION_ERROR_MSG: { - MBIM_FUNCTION_ERROR_MSG_T *pErrMsg = (MBIM_FUNCTION_ERROR_MSG_T *)pMsgHdr; - status = le32toh(pErrMsg->ErrorStatusCode); - if (status == MBIM_ERROR_NOT_OPENED) - mbim_open_state = 0; //EM06ELAR03A05M4G when suspend/resume, may get this error - } - break; - default: - break; - } - - return status; -} - -#define mbim_check_err(err, pRequest, pCmdDone) do { \ - int _status = mbim_status_code(pCmdDone ? &pCmdDone->MessageHeader : NULL); \ - if (err || _status || !pCmdDone) { \ - if (pCmdDone) { mbim_dump(&pCmdDone->MessageHeader, (mbim_verbose == 0)); } \ - mbim_free(pRequest); mbim_free(pCmdDone); \ - mbim_debug("%s:%d err=%d, Status=%d", __func__, __LINE__, err, _status); \ - if (err) return err; \ - if (_status) return _status; \ - return 8888; \ - } \ -} while(0) - -/* - * MBIM device can be open repeatly without error - * So, we can call the function, no matter it have been opened or not - */ -static int mbim_open_device(uint32_t MaxControlTransfer) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_OPEN_DONE_T *pOpenDone = NULL; - int err = 0; - - mbim_debug("%s()", __func__); - pRequest = compose_open_command(MaxControlTransfer); - err = mbim_send_command(pRequest, (MBIM_COMMAND_DONE_T **)&pOpenDone, 3*1000); //EM06ELAR03A09M4G take about 2.5 seconds - mbim_check_err(err, pRequest, pOpenDone); - - err = le32toh(pOpenDone->Status); - mbim_free(pRequest); mbim_free(pOpenDone); - - return err; -} - -static int mbim_close_device(void) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_CLOSE_DONE_T *pCloseDone = NULL; - int err = 0; - - mbim_debug("%s()", __func__); - pRequest = compose_close_command(); - err = mbim_send_command(pRequest, (MBIM_COMMAND_DONE_T **)&pCloseDone, mbim_default_timeout); - mbim_check_err(err, pRequest, pCloseDone); - - err = le32toh(pCloseDone->Status); - mbim_free(pRequest); mbim_free(pCloseDone); - - return err; -} - -static int mbim_query_connect(int sessionID) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_COMMAND_DONE_T *pCmdDone = NULL; - MBIM_SET_CONNECT_T set_connect; - int err; - - if (ActivationState != MBIMActivationStateActivated || mbim_verbose) - mbim_debug("%s(sessionID=%d)", __func__, sessionID); //avoid two many log - set_connect.SessionId = htole32(sessionID); - pRequest = compose_basic_connect_command(MBIM_CID_CONNECT, MBIM_CID_CMD_TYPE_QUERY, &set_connect, sizeof(set_connect)); - err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); - mbim_check_err(err, pRequest, pCmdDone); - - if (le32toh(pCmdDone->InformationBufferLength)) - { - MBIM_CONNECT_T *pInfo = (MBIM_CONNECT_T *)pCmdDone->InformationBuffer; - ActivationState = le32toh(pInfo->ActivationState); - mbim_update_state(); - } - mbim_free(pRequest); mbim_free(pCmdDone); - return err; -} - -static int mbim_ms_version_query(void) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_COMMAND_DONE_T *pCmdDone = NULL; - int err; - - struct _bc_ext_version { - UINT8 ver_minor; - UINT8 ver_major; - UINT8 ext_ver_minor; - UINT8 ext_ver_major; - } __attribute__ ((packed)) bc_ext_version; - - bc_ext_version.ver_major = 1; - bc_ext_version.ver_minor = 0; - bc_ext_version.ext_ver_major = 2; - bc_ext_version.ext_ver_minor = 0; - - pRequest = compose_basic_connect_ext_command(MBIM_CID_MS_VERSION, MBIM_CID_CMD_TYPE_QUERY, &bc_ext_version, sizeof(bc_ext_version)); - err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); - mbim_check_err(err, pRequest, pCmdDone); - - if (le32toh(pCmdDone->InformationBufferLength)) { - struct _bc_ext_version *pInfo = (struct _bc_ext_version *)pCmdDone->InformationBuffer; - //mbim_debug("%s ext_rel_ver major=%d, minor=%d", __func__, pInfo->ext_ver_major, pInfo->ext_ver_minor); - mbim_ms_version = pInfo->ext_ver_major; - } - - mbim_free(pRequest); mbim_free(pCmdDone); - return err; -} - -static int mbim_device_services_query(void) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_COMMAND_DONE_T *pCmdDone = NULL; - int err; - int mbim_v2_support = 0; - - mbim_debug("%s()", __func__); - pRequest = compose_basic_connect_command(MBIM_CID_DEVICE_SERVICES, MBIM_CID_CMD_TYPE_QUERY, NULL, 0); - err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); - mbim_check_err(err, pRequest, pCmdDone); - - if (pCmdDone->InformationBufferLength) { - MBIM_DEVICE_SERVICES_INFO_T *pInfo = (MBIM_DEVICE_SERVICES_INFO_T *)pCmdDone->InformationBuffer; - UINT32 i; - - for (i = 0; i < le32toh(pInfo->DeviceServicesCount) ; i++) { - //UINT32 size = pInfo->DeviceServicesRefList[i].size; - UINT32 offset = le32toh(pInfo->DeviceServicesRefList[i].offset); - MBIM_DEVICE_SERVICE_ELEMENT_T *pSrvEle = (MBIM_DEVICE_SERVICE_ELEMENT_T *)((void *)pInfo + offset); - - //mbim_debug("\t[%2d] %s (%s)", i, DeviceServiceId2str(&pSrvEle->DeviceServiceId), uuid2str(&pSrvEle->DeviceServiceId)); - if (!strcasecmp(UUID_BASIC_CONNECT_EXT, uuid2str(&pSrvEle->DeviceServiceId))) { - UINT32 cid = 0; - - for (cid = 0; cid < le32toh(pSrvEle->CidCount); cid++) { - if (MBIM_CID_MS_VERSION == le32toh(pSrvEle->CidList[cid])) { - mbim_v2_support = 1; - } - } - } - else if (!strcasecmp(uuid_ext_qmux, uuid2str(&pSrvEle->DeviceServiceId))) { - qmi_over_mbim_support = 1; - } - } - } - mbim_free(pRequest); mbim_free(pCmdDone); - - if (mbim_v2_support) { - mbim_ms_version_query(); - } - - return err; -} - -static int mbim_device_caps_query(PROFILE_T *profile) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_COMMAND_DONE_T *pCmdDone = NULL; - int err; - - mbim_debug("%s()", __func__); - pRequest = compose_basic_connect_command(MBIM_CID_DEVICE_CAPS, MBIM_CID_CMD_TYPE_QUERY, NULL, 0); - err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); - mbim_check_err(err, pRequest, pCmdDone); - - if (le32toh(pCmdDone->InformationBufferLength)) { - MBIM_DEVICE_CAPS_INFO_T *pInfo = (MBIM_DEVICE_CAPS_INFO_T *)pCmdDone->InformationBuffer; - char tmp[32]; - - if (le32toh(pInfo->DeviceIdOffset) && le32toh(pInfo->DeviceIdSize)) { - wchar2char((const char *)pInfo + le32toh(pInfo->DeviceIdOffset), le32toh(pInfo->DeviceIdSize), tmp, sizeof(tmp)); - mbim_debug("DeviceId: %s", tmp); - } - if (le32toh(pInfo->FirmwareInfoOffset) && le32toh(pInfo->FirmwareInfoSize)) { - wchar2char((const char *)pInfo + le32toh(pInfo->FirmwareInfoOffset), le32toh(pInfo->FirmwareInfoSize), tmp, sizeof(tmp)); - strncpy(profile->BaseBandVersion, tmp, sizeof(profile->BaseBandVersion)); - mbim_debug("FirmwareInfo: %s", tmp); - } - if (le32toh(pInfo->HardwareInfoOffset) && le32toh(pInfo->HardwareInfoSize)) { - wchar2char((const char *)pInfo + le32toh(pInfo->HardwareInfoOffset), le32toh(pInfo->HardwareInfoSize), tmp, sizeof(tmp)); - mbim_debug("HardwareInfo: %s", tmp); - } - } - mbim_free(pRequest); mbim_free(pCmdDone); - return err; -} - -#if 0 -static int mbim_radio_state_query(void) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_COMMAND_DONE_T *pCmdDone = NULL; - int err; - - mbim_debug("%s()", __func__); - pRequest = compose_basic_connect_command(MBIM_CID_RADIO_STATE, MBIM_CID_CMD_TYPE_QUERY, NULL, 0); - err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); - mbim_check_err(err, pRequest, pCmdDone); - - if (pCmdDone->InformationBufferLength) { - MBIM_RADIO_STATE_INFO_T *pInfo = (MBIM_RADIO_STATE_INFO_T *)pCmdDone->InformationBuffer; - mbim_debug("HwRadioState: %d, SwRadioState: %d", pInfo->HwRadioState, pInfo->SwRadioState); - } - mbim_free(pRequest); mbim_free(pCmdDone); - return err; -} -#endif - -static int mbim_set_radio_state(MBIM_RADIO_SWITCH_STATE_E RadioState) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_COMMAND_DONE_T *pCmdDone = NULL; - UINT32 value = htole32(RadioState); - int err; - - mbim_debug("%s( %d )", __func__, RadioState); - pRequest = compose_basic_connect_command(MBIM_CID_RADIO_STATE, MBIM_CID_CMD_TYPE_SET, &value, sizeof(value)); - err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); - mbim_check_err(err, pRequest, pCmdDone); - - if (le32toh(pCmdDone->InformationBufferLength)) { - MBIM_RADIO_STATE_INFO_T *pInfo = (MBIM_RADIO_STATE_INFO_T *)pCmdDone->InformationBuffer; - mbim_debug("HwRadioState: %d, SwRadioState: %d", le32toh(pInfo->HwRadioState), le32toh(pInfo->SwRadioState)); - } - mbim_free(pRequest); mbim_free(pCmdDone); - return err; -} - -static int mbim_subscriber_status_query(void) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_COMMAND_DONE_T *pCmdDone = NULL; - int err; - - mbim_debug("%s()", __func__); - pRequest = compose_basic_connect_command(MBIM_CID_SUBSCRIBER_READY_STATUS, MBIM_CID_CMD_TYPE_QUERY, NULL, 0); - err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); - mbim_check_err(err, pRequest, pCmdDone); - - if (le32toh(pCmdDone->InformationBufferLength)) { - MBIM_SUBSCRIBER_READY_STATUS_T *pInfo = (MBIM_SUBSCRIBER_READY_STATUS_T *)pCmdDone->InformationBuffer; - char tmp[32]; - - wchar2char((const char *)pInfo + le32toh(pInfo->SubscriberIdOffset), le32toh(pInfo->SubscriberIdSize), tmp, sizeof(tmp)); - mbim_debug("SubscriberId: %s", tmp); - wchar2char((const char *)pInfo + le32toh(pInfo->SimIccIdOffset), le32toh(pInfo->SimIccIdSize), tmp, sizeof(tmp)); - mbim_debug("SimIccId: %s", tmp); - ReadyState = le32toh(pInfo->ReadyState); - mbim_update_state(); - } - mbim_free(pRequest); mbim_free(pCmdDone); - return err; -} - -static int mbim_register_state_query(void) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_COMMAND_DONE_T *pCmdDone = NULL; - int err; - - mbim_debug("%s()", __func__); - pRequest = compose_basic_connect_command(MBIM_CID_REGISTER_STATE, MBIM_CID_CMD_TYPE_QUERY, NULL, 0); - err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); - mbim_check_err(err, pRequest, pCmdDone); - - if (le32toh(pCmdDone->InformationBufferLength)) { - MBIM_REGISTRATION_STATE_INFO_T *pInfo = (MBIM_REGISTRATION_STATE_INFO_T *)pCmdDone->InformationBuffer;; - RegisterState = le32toh(pInfo->RegisterState); - mbim_update_state(); - } - mbim_free(pRequest); mbim_free(pCmdDone); - return err; -} - -static int mbim_packet_service_query(void) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_COMMAND_DONE_T *pCmdDone = NULL; - int err; - - mbim_debug("%s()", __func__); - pRequest = compose_basic_connect_command(MBIM_CID_PACKET_SERVICE, MBIM_CID_CMD_TYPE_QUERY, NULL, 0); - err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); - mbim_check_err(err, pRequest, pCmdDone); - - if (le32toh(pCmdDone->InformationBufferLength)) { - MBIM_PACKET_SERVICE_INFO_T *pInfo = (MBIM_PACKET_SERVICE_INFO_T *)pCmdDone->InformationBuffer; - PacketServiceState = le32toh(pInfo->PacketServiceState); - mbim_update_state(); - - if (le32toh(pCmdDone->InformationBufferLength) == sizeof(MBIM_PACKET_SERVICE_INFO_V2_T)) { - MBIM_PACKET_SERVICE_INFO_V2_T *pInfo = (MBIM_PACKET_SERVICE_INFO_V2_T *)pCmdDone->InformationBuffer; - mbim_debug("CurrentDataClass = %s", MBIMDataClassStr(le32toh(pInfo->CurrentDataClass))); - } - } - mbim_free(pRequest); mbim_free(pCmdDone); - return err; -} - -static int mbim_packet_service_set(MBIM_PACKET_SERVICE_ACTION_E action) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_COMMAND_DONE_T *pCmdDone = NULL; - UINT32 value = htole32(action); - int err; - - mbim_debug("%s()", __func__); - pRequest = compose_basic_connect_command(MBIM_CID_PACKET_SERVICE, MBIM_CID_CMD_TYPE_SET, &value, sizeof(value)); - err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); - mbim_check_err(err, pRequest, pCmdDone); - - if (le32toh(pCmdDone->InformationBufferLength)) { - MBIM_PACKET_SERVICE_INFO_T *pInfo = (MBIM_PACKET_SERVICE_INFO_T *)pCmdDone->InformationBuffer; - PacketServiceState = le32toh(pInfo->PacketServiceState); - mbim_update_state(); - } - mbim_free(pRequest); mbim_free(pCmdDone); - return err; -} - -#define _align_32(len) {len += (len % 4) ? (4 - (len % 4)) : 0;} -static int mbim_populate_connect_data(MBIM_SET_CONNECT_T **connect_req_ptr) { - int offset; - int buflen = 0; - - if (mbim_apn && strlen(mbim_apn) > 0) buflen += 2*strlen(mbim_apn) ; - _align_32(buflen); - if (mbim_user && strlen(mbim_user) > 0) buflen += 2*strlen(mbim_user); - _align_32(buflen); - if (mbim_passwd && strlen(mbim_passwd) > 0) buflen += 2*strlen(mbim_passwd); - _align_32(buflen); - - *connect_req_ptr = (MBIM_SET_CONNECT_T*)malloc(sizeof(MBIM_SET_CONNECT_T) + buflen); - if (! *connect_req_ptr) { - mbim_debug("not enough memory\n"); - return -1; - } - memset(*connect_req_ptr, 0, sizeof(MBIM_SET_CONNECT_T) + buflen); - - offset = 0; - if (mbim_apn && strlen(mbim_apn) > 0) { - (*connect_req_ptr)->AccessStringSize = htole32(2*strlen(mbim_apn)); - (*connect_req_ptr)->AccessStringOffset = htole32(offset + sizeof(MBIM_SET_CONNECT_T)); - offset = char2wchar(mbim_apn, strlen(mbim_apn), &(*connect_req_ptr)->DataBuffer[offset], buflen - offset); - _align_32(offset); - } - - if (mbim_user && strlen(mbim_user) > 0) { - (*connect_req_ptr)->UserNameSize = htole32(2*strlen(mbim_user)); - (*connect_req_ptr)->UserNameOffset = htole32(offset + sizeof(MBIM_SET_CONNECT_T)); - offset = char2wchar(mbim_user, strlen(mbim_user), &(*connect_req_ptr)->DataBuffer[offset], buflen - offset); - _align_32(offset); - } - - if (mbim_passwd && strlen(mbim_passwd) > 0) { - (*connect_req_ptr)->PasswordSize = htole32(2*strlen(mbim_passwd)); - (*connect_req_ptr)->PasswordOffset = htole32(offset + sizeof(MBIM_SET_CONNECT_T)); - offset = char2wchar(mbim_passwd, strlen(mbim_passwd), &(*connect_req_ptr)->DataBuffer[offset], buflen - offset); - } - - return buflen; -} - -static int mbim_set_connect(int onoff, int sessionID) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_COMMAND_DONE_T *pCmdDone = NULL; - MBIM_SET_CONNECT_T *set_connect = NULL; - int err; - - mbim_debug("%s(onoff=%d, sessionID=%d)", __func__, onoff, sessionID); - /* alloc memory then populate APN USERNAME PASSWORD */ - int buflen = mbim_populate_connect_data(&set_connect); - if (buflen < 0) { - return ENOMEM; - } - - set_connect->SessionId = htole32(sessionID); - if (onoff == 0) - set_connect->ActivationCommand = htole32(MBIMActivationCommandDeactivate); - else - set_connect->ActivationCommand = htole32(MBIMActivationCommandActivate); - - set_connect->Compression = htole32(MBIMCompressionNone); - set_connect->AuthProtocol = htole32(mbim_auth); - set_connect->IPType = htole32(mbim_iptype); - memcpy(set_connect->ContextType.uuid, str2uuid(UUID_MBIMContextTypeInternet), 16); - - pRequest = compose_basic_connect_command(MBIM_CID_CONNECT, MBIM_CID_CMD_TYPE_SET, set_connect, sizeof(MBIM_SET_CONNECT_T) + buflen); - mbim_free(set_connect); - err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout*10); - mbim_check_err(err, pRequest, pCmdDone); - - if (le32toh(pCmdDone->InformationBufferLength)) { - MBIM_CONNECT_T *pInfo = (MBIM_CONNECT_T *)pCmdDone->InformationBuffer; - ActivationState = le32toh(pInfo->ActivationState); - mbim_update_state(); - } - - mbim_free(pRequest); mbim_free(pCmdDone); - return err; -} - -static int mbim_ip_config(PROFILE_T *profile, int sessionID) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_COMMAND_DONE_T *pCmdDone = NULL; - MBIM_IP_CONFIGURATION_INFO_T ip_info; - int err; - - if (profile->ipv4.Address == 0 || mbim_verbose) - mbim_debug("%s(sessionID=%d)", __func__, sessionID); - ip_info.SessionId = htole32(sessionID); - pRequest = compose_basic_connect_command(MBIM_CID_IP_CONFIGURATION, MBIM_CID_CMD_TYPE_QUERY, &ip_info, sizeof(ip_info)); - err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); - mbim_check_err(err, pRequest, pCmdDone); - - if (le32toh(pCmdDone->InformationBufferLength)) { - UINT8 prefix, *ipv4=NULL, *ipv6=NULL, *gw=NULL, *dns1=NULL, *dns2=NULL; - UINT32 mtu = 1500; - MBIM_IP_CONFIGURATION_INFO_T *pInfo = (MBIM_IP_CONFIGURATION_INFO_T *)pCmdDone->InformationBuffer; - - /* IPv4 network configration */ - if (le32toh(pInfo->IPv4ConfigurationAvailable)&0x1) { - MBIM_IPV4_ELEMENT_T *pAddress = (MBIM_IPV4_ELEMENT_T *)(&pInfo->DataBuffer[le32toh(pInfo->IPv4AddressOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); - prefix = le32toh(pAddress->OnLinkPrefixLength); - ipv4 = pAddress->IPv4Address; - - if (le32toh(pInfo->IPv4ConfigurationAvailable)&0x2) - gw = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv4GatewayOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); - - if (le32toh(pInfo->IPv4ConfigurationAvailable)&0x4) { - dns1 = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv4DnsServerOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); - if (le32toh(pInfo->IPv4DnsServerCount) == 2) - dns2 = dns1 + 4; - } - - if (le32toh(pInfo->IPv4ConfigurationAvailable)&0x8) - mtu = le32toh(pInfo->IPv4Mtu); - - if (profile->ipv4.Address != mbim2qmi_ipv4addr(*(uint32_t *)ipv4) || mbim_verbose) { - mbim_dump_ipconfig(pInfo, "<"); - profile->ipv4.Address = mbim2qmi_ipv4addr(*(uint32_t *)ipv4); - } - - if(gw != NULL) - profile->ipv4.Gateway = mbim2qmi_ipv4addr(*(uint32_t *)gw); - profile->ipv4.SubnetMask = mbim2qmi_ipv4addr(0xFFFFFFFF>>(32-prefix)<<(32-prefix)); - if(dns1 != NULL) - profile->ipv4.DnsPrimary = mbim2qmi_ipv4addr(*(uint32_t *)dns1); - if(dns2 != NULL) - profile->ipv4.DnsSecondary = mbim2qmi_ipv4addr(*(uint32_t *)dns2); - profile->ipv4.Mtu = mbim2qmi_ipv4addr(mtu); - } - - /* IPv6 network configration */ - if (le32toh(pInfo->IPv6ConfigurationAvailable)&0x1) { - gw = NULL; dns1 = NULL; dns2 = NULL; - MBIM_IPV6_ELEMENT_T *pAddress = (MBIM_IPV6_ELEMENT_T *)(&pInfo->DataBuffer[le32toh(pInfo->IPv6AddressOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); - prefix = le32toh(pAddress->OnLinkPrefixLength); - ipv6 = pAddress->IPv6Address; - - if (le32toh(pInfo->IPv6ConfigurationAvailable)&0x2) - gw = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv6GatewayOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); - - if (le32toh(pInfo->IPv6ConfigurationAvailable)&0x4) { - dns1 = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv6DnsServerOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); - if (le32toh(pInfo->IPv6DnsServerCount) == 2) - dns2 = dns1 + 16; - } - - if (le32toh(pInfo->IPv6ConfigurationAvailable)&0x8) - mtu = le32toh(pInfo->IPv6Mtu); - - if(ipv6 != NULL) - mbim2qmi_ipv6addr(ipv6, profile->ipv6.Address); - if(gw != NULL) - mbim2qmi_ipv6addr(gw, profile->ipv6.Gateway); - if(dns1 != NULL) - mbim2qmi_ipv6addr(dns1, profile->ipv6.DnsPrimary); - if(dns2 != NULL) - mbim2qmi_ipv6addr(dns2, profile->ipv6.DnsSecondary); - profile->ipv6.PrefixLengthIPAddr = prefix; - profile->ipv6.PrefixLengthGateway = prefix; - profile->ipv6.Mtu = mbim2qmi_ipv4addr(mtu); - } - } - return err; -} - -int mbim_proxy_configure(const char *dev) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_COMMAND_DONE_T *pCmdDone = NULL; - MBIM_LIBQMI_PROXY_CONFIG_T *cfg; - int err; - - pRequest = compose_basic_connect_command( - MBIM_CID_PROXY_CONTROL_CONFIGURATION, - MBIM_CID_CMD_TYPE_SET, - NULL, - sizeof(*cfg) + strlen(dev)*2); - if (pRequest) { - memcpy(((MBIM_COMMAND_MSG_T *)pRequest)->DeviceServiceId.uuid, str2uuid(UUID_LIBMBIM_PROXY), 16); - cfg = (MBIM_LIBQMI_PROXY_CONFIG_T *)((MBIM_COMMAND_MSG_T *)pRequest)->InformationBuffer; - - cfg->DevicePathOffset = sizeof(*cfg); - cfg->DevicePathSize = char2wchar(dev, strlen(dev), cfg->DataBuffer, strlen(dev)*2); - cfg->Timeout = 15; - } - - err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); - mbim_check_err(err, pRequest, pCmdDone); - - mbim_free(pRequest); mbim_free(pCmdDone); - return err; -} - -static int mbim_update_state(void) { - int chages = 0; - - if (oldReadyState != ReadyState) { - mbim_debug("SubscriberReadyState %s -> %s ", MBIMSubscriberReadyStateStr(oldReadyState), MBIMSubscriberReadyStateStr(ReadyState)); - oldReadyState = ReadyState; chages++; - } - if (oldRegisterState != RegisterState) { - mbim_debug("RegisterState %s -> %s ", MBIMRegisterStateStr(oldRegisterState), MBIMRegisterStateStr(RegisterState)); - oldRegisterState = RegisterState; chages++; - } - if (oldPacketServiceState != PacketServiceState) { - mbim_debug("PacketServiceState %s -> %s ", MBIMPacketServiceStateStr(oldPacketServiceState), MBIMPacketServiceStateStr(PacketServiceState)); - oldPacketServiceState = PacketServiceState; chages++; - } - if (oldActivationState != ActivationState) { - mbim_debug("ActivationState %s -> %s ", MBIMActivationStateStr(oldActivationState), MBIMActivationStateStr(ActivationState)); - oldActivationState = ActivationState; chages++; - } - - return chages; -} - -static int mbim_init(PROFILE_T *profile) { - int retval; - int t = 0; - - if (profile->proxy[0] && !strcmp(profile->proxy, LIBMBIM_PROXY)) { - retval = mbim_proxy_configure(profile->qmichannel); - if (retval) goto exit; - } - - while (t++ < 10) { - retval = mbim_open_device(4096); - if (retval != ETIMEDOUT) - break; - } - if (retval) goto exit; - retval = mbim_device_caps_query(profile); - if (retval) goto exit; - mbim_update_state(); - retval = mbim_device_services_query(); - if (retval) goto exit; - mbim_update_state(); - retval = mbim_set_radio_state(MBIMRadioOn); - if (retval) goto exit; - mbim_update_state(); - - if (qmi_over_mbim_support) { - if (!socketpair( AF_LOCAL, SOCK_STREAM, 0, qmi_over_mbim_sk)) { - qmidev_send = qmi_over_mbim_qmidev_send; -#ifdef CONFIG_CELLINFO //by now, only this function need QMI OVER MBIM - qmi_over_mbim_nas = qmi_over_mbim_get_client_id(QMUX_TYPE_NAS); -#endif - } - } - - return 0; - -exit: - return retval; -} - -static int mbim_deinit(void) { - if (qmi_over_mbim_nas) { - qmi_over_mbim_release_client_id(QMUX_TYPE_NAS, qmi_over_mbim_nas); - qmi_over_mbim_nas = 0; - } - - mbim_close_device(); - - if (qmi_over_mbim_sk[0] != -1) { - close(qmi_over_mbim_sk[0]); - close(qmi_over_mbim_sk[1]); - } - - return 0; -} - -const struct qmi_device_ops mbim_dev_ops = { - .init = mbim_init, - .deinit = mbim_deinit, - .read = mbim_read_thread, -}; - -static int requestBaseBandVersion(PROFILE_T *profile) { - (void)profile; - return 0; -} - -static int requestGetSIMStatus(SIM_Status *pSIMStatus) -{ - int retval; - - *pSIMStatus = SIM_ABSENT; - retval = mbim_subscriber_status_query(); - if (retval) - goto exit; - mbim_update_state(); - - switch(ReadyState) { - case MBIMSubscriberReadyStateNotInitialized: *pSIMStatus = SIM_NOT_READY; break; - case MBIMSubscriberReadyStateInitialized: *pSIMStatus = SIM_READY; break; - case MBIMSubscriberReadyStateSimNotInserted: *pSIMStatus = SIM_ABSENT; break; - case MBIMSubscriberReadyStateBadSim: *pSIMStatus = SIM_BAD; break; - case MBIMSubscriberReadyStateFailure: *pSIMStatus = SIM_ABSENT; break; - case MBIMSubscriberReadyStateNotActivated: *pSIMStatus = SIM_ABSENT; break; - case MBIMSubscriberReadyStateDeviceLocked: *pSIMStatus = SIM_PIN; break; - default: *pSIMStatus = SIM_ABSENT; break; - } - -exit: - return retval; -} - -static int requestRegistrationState(UCHAR *pPSAttachedState) { - int retval; - - *pPSAttachedState = 0; - retval = mbim_register_state_query(); - if (retval) - goto exit; - mbim_update_state(); - - switch (RegisterState) { - case MBIMRegisterStateUnknown: *pPSAttachedState = 0; break; - case MBIMRegisterStateDeregistered: *pPSAttachedState = 0; break; - case MBIMRegisterStateSearching: *pPSAttachedState = 0; break; - case MBIMRegisterStateHome: *pPSAttachedState = 1; break; - case MBIMRegisterStateRoaming: *pPSAttachedState = 1; break; - case MBIMRegisterStatePartner: *pPSAttachedState = 0; break; - case MBIMRegisterStateDenied: *pPSAttachedState = 0; break; - default: *pPSAttachedState = 0; break; - } - - if (*pPSAttachedState == 0) - goto exit; - - retval = mbim_packet_service_query(); - if (retval) - goto exit; - - switch (PacketServiceState) { - case MBIMPacketServiceStateUnknown: *pPSAttachedState = 0; break; - case MBIMPacketServiceStateAttaching: *pPSAttachedState = 0; break; - case MBIMPacketServiceStateAttached: *pPSAttachedState = 1; break; - case MBIMPacketServiceStateDetaching: *pPSAttachedState = 0; break; - case MBIMPacketServiceStateDetached: *pPSAttachedState = 0; break; - default: *pPSAttachedState = 0; break; - } - - if (*pPSAttachedState == 0) - mbim_packet_service_set(MBIMPacketServiceActionAttach); - -exit: - return retval; -} - -static int requestSetupDataCall(PROFILE_T *profile, int curIpFamily) { - int retval; - - (void)curIpFamily; - - if (profile->apn) - mbim_apn = profile->apn; - if (profile->user) - mbim_user = profile->user; - if (profile->password) - mbim_passwd = profile->password; - if (profile->auth) - mbim_auth = profile->auth; - if (profile->enable_ipv4) - mbim_iptype = MBIMContextIPTypeIPv4; - if (profile->enable_ipv6) - mbim_iptype = MBIMContextIPTypeIPv6; - if (profile->enable_ipv4 && profile->enable_ipv6) - mbim_iptype = MBIMContextIPTypeIPv4AndIPv6; - - retval = mbim_set_connect(1, mbim_sessionID); - if (retval) - goto exit; - -exit: - return retval; -} - -static int requestQueryDataCall(UCHAR *pConnectionStatus, int curIpFamily) { - int retval; - - (void)curIpFamily; - - *pConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; - - retval = mbim_query_connect(mbim_sessionID); - if (retval) - goto exit; - - switch(ActivationState) { - case MBIMActivationStateUnknown: *pConnectionStatus = QWDS_PKT_DATA_UNKNOW; break; - case MBIMActivationStateActivated: *pConnectionStatus = QWDS_PKT_DATA_CONNECTED; break; - case MBIMActivationStateActivating: *pConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; break; - case MBIMActivationStateDeactivated: *pConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; break; - case MBIMActivationStateDeactivating: *pConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; break; - default: *pConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; break; - } - -exit: - return retval; -} - -static int requestDeactivateDefaultPDP(PROFILE_T *profile, int curIpFamily) { - int retval; - - (void)profile; - (void)curIpFamily; - - retval = mbim_set_connect(0, mbim_sessionID); - if (retval) - goto exit; - -exit: - return retval; -} - -static int requestGetIPAddress(PROFILE_T *profile, int curIpFamily) { - int retval; - - (void)curIpFamily; - retval = mbim_ip_config(profile, mbim_sessionID); - if (retval) - goto exit; - -exit: - return retval; -} - -#ifdef CONFIG_CELLINFO -static int requestGetCellInfoList(void) { - if (qmi_over_mbim_nas) { - if (qmi_request_ops.requestGetCellInfoList) - return qmi_request_ops.requestGetCellInfoList(); - } - - return 0; -} -#endif - -const struct request_ops mbim_request_ops = { - .requestBaseBandVersion = requestBaseBandVersion, - .requestGetSIMStatus = requestGetSIMStatus, - .requestRegistrationState = requestRegistrationState, - .requestSetupDataCall = requestSetupDataCall, - .requestQueryDataCall = requestQueryDataCall, - .requestDeactivateDefaultPDP = requestDeactivateDefaultPDP, - .requestGetIPAddress = requestGetIPAddress, -#ifdef CONFIG_CELLINFO - .requestGetCellInfoList = requestGetCellInfoList, -#endif -}; - -int qmi_over_mbim_qmidev_send(PQCQMIMSG pQMI) { - MBIM_MESSAGE_HEADER *pRequest = NULL; - MBIM_COMMAND_DONE_T *pCmdDone = NULL; - int err; - size_t len = le16toh(pQMI->QMIHdr.Length) + 1; - - if (pQMI->QMIHdr.QMIType != QMUX_TYPE_CTL) { - if (pQMI->QMIHdr.QMIType == QMUX_TYPE_NAS) - pQMI->QMIHdr.ClientId = qmi_over_mbim_nas; - - if (pQMI->QMIHdr.ClientId == 0) { - dbg_time("QMIType %d has no clientID", pQMI->QMIHdr.QMIType); - return -ENODEV; - } - } - - pRequest = compose_qmi_over_mbim_command(1, MBIM_CID_CMD_TYPE_SET, pQMI, len); - err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); - mbim_check_err(err, pRequest, pCmdDone); - - err = -1; - len = le32toh(pCmdDone->InformationBufferLength); - if (len) { - if (write(qmi_over_mbim_sk[0], pCmdDone->InformationBuffer, len) == (long)len) { - err = 0; - }; - } - - mbim_free(pRequest); mbim_free(pCmdDone); - return err; -} + UINT32 NwError; + UINT32 PacketServiceState; //MBIM_PACKET_SERVICE_STATE_E + UINT32 HighestAvailableDataClass; //MBIM_DATA_CLASS_E + UINT64 UplinkSpeed; + UINT64 DownlinkSpeed; +} MBIM_PACKET_SERVICE_INFO_T; + +typedef struct { + UINT32 NwError; + UINT32 PacketServiceState; //MBIM_PACKET_SERVICE_STATE_E + UINT32 CurrentDataClass; //MBIM_DATA_CLASS_E + UINT64 UplinkSpeed; + UINT64 DownlinkSpeed; + UINT32 FrequencyRange; +} MBIM_PACKET_SERVICE_INFO_V2_T; + +typedef enum { + MBIMSubscriberReadyStateNotInitialized = 0, + MBIMSubscriberReadyStateInitialized = 1, + MBIMSubscriberReadyStateSimNotInserted = 2, + MBIMSubscriberReadyStateBadSim = 3, + MBIMSubscriberReadyStateFailure = 4, + MBIMSubscriberReadyStateNotActivated = 5, + MBIMSubscriberReadyStateDeviceLocked = 6, +}MBIM_SUBSCRIBER_READY_STATE_E; + +static const char *MBIMSubscriberReadyStateStr(int _val) { + struct { int val;char *name;} _enumstr[] = { + {MBIMSubscriberReadyStateNotInitialized, "NotInitialized"}, + {MBIMSubscriberReadyStateInitialized, "Initialized"}, + {MBIMSubscriberReadyStateSimNotInserted, "NotInserted"}, + {MBIMSubscriberReadyStateBadSim, "BadSim"}, + {MBIMSubscriberReadyStateFailure, "Failure"}, + {MBIMSubscriberReadyStateNotActivated, "NotActivated"}, + {MBIMSubscriberReadyStateDeviceLocked, "DeviceLocked"}, + }; + int idx; + + for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { + if (_val == _enumstr[idx].val) + return _enumstr[idx].name; + } + + return "Undefined"; +}; + +typedef struct { + UINT32 DeviceType; //MBIM_DEVICE_TYPE + UINT32 CellularClass; //MBIM_CELLULAR_CLASS + UINT32 VoiceClass; //MBIM_VOICE_CLASS + UINT32 SimClass; //MBIM_SIM_CLASS + UINT32 DataClass; //MBIM_DATA_CLASS + UINT32 SmsCaps; //MBIM_SMS_CAPS + UINT32 ControlCaps; //MBIM_CTRL_CAPS + UINT32 MaxSessions; + UINT32 CustomDataClassOffset; + UINT32 CustomDataClassSize; + UINT32 DeviceIdOffset; + UINT32 DeviceIdSize; + UINT32 FirmwareInfoOffset; + UINT32 FirmwareInfoSize; + UINT32 HardwareInfoOffset; + UINT32 HardwareInfoSize; + UINT8 DataBuffer[0]; //DeviceId FirmwareInfo HardwareInfo +} MBIM_DEVICE_CAPS_INFO_T; + +typedef enum { + MBIMRadioOff = 0, + MBIMRadioOn = 1, +} MBIM_RADIO_SWITCH_STATE_E; + +typedef struct { + MBIM_RADIO_SWITCH_STATE_E RadioState; +} MBIM_SET_RADIO_STATE_T; + +typedef struct { + MBIM_RADIO_SWITCH_STATE_E HwRadioState; + MBIM_RADIO_SWITCH_STATE_E SwRadioState; +} MBIM_RADIO_STATE_INFO_T; + +typedef enum { + MBIMReadyInfoFlagsNone, + MBIMReadyInfoFlagsProtectUniqueID, +}MBIM_UNIQUE_ID_FLAGS; + +typedef struct { + UINT32 ReadyState; + UINT32 SubscriberIdOffset; + UINT32 SubscriberIdSize; + UINT32 SimIccIdOffset; + UINT32 SimIccIdSize; + UINT32 ReadyInfo; + UINT32 ElementCount; + UINT8 *TelephoneNumbersRefList; + UINT8 *DataBuffer; +} MBIM_SUBSCRIBER_READY_STATUS_T; + +typedef enum { + MBIMRegisterActionAutomatic, + MBIMRegisterActionManual, +}MBIM_REGISTER_ACTION_E; + +typedef enum { + MBIMRegisterStateUnknown = 0, + MBIMRegisterStateDeregistered = 1, + MBIMRegisterStateSearching = 2, + MBIMRegisterStateHome = 3, + MBIMRegisterStateRoaming = 4, + MBIMRegisterStatePartner = 5, + MBIMRegisterStateDenied = 6, +}MBIM_REGISTER_STATE_E; + +typedef enum { + MBIMRegisterModeUnknown = 0, + MBIMRegisterModeAutomatic = 1, + MBIMRegisterModeManual = 2, +}MBIM_REGISTER_MODE_E; + +static const char *MBIMRegisterStateStr(int _val) { + struct { int val;char *name;} _enumstr[] ={ + {MBIMRegisterStateUnknown, "Unknown"}, + {MBIMRegisterStateDeregistered, "Deregistered"}, + {MBIMRegisterStateSearching, "Searching"}, + {MBIMRegisterStateHome, "Home"}, + {MBIMRegisterStateRoaming, "Roaming"}, + {MBIMRegisterStatePartner, "Partner"}, + {MBIMRegisterStateDenied, "Denied"}, + }; + int idx; + + for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { + if (_val == _enumstr[idx].val) + return _enumstr[idx].name; + } + + return "Undefined"; +}; + +static const char *MBIMRegisterModeStr(int _val) { + struct { int val;char *name;} _enumstr[] = { + {MBIMRegisterModeUnknown, "Unknown"}, + {MBIMRegisterModeAutomatic, "Automatic"}, + {MBIMRegisterModeManual, "Manual"}, + }; + int idx; + + for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { + if (_val == _enumstr[idx].val) + return _enumstr[idx].name; + } + + return "Undefined"; +}; + +typedef enum { + MBIM_REGISTRATION_NONE, + MBIM_REGISTRATION_MANUAL_SELECTION_NOT_AVAILABLE, + MBIM_REGISTRATION_PACKET_SERVICE_AUTOMATIC_ATTACH, +}MBIM_REGISTRATION_FLAGS_E; + +typedef struct { + UINT32 NwError; + UINT32 RegisterState; //MBIM_REGISTER_STATE_E + UINT32 RegisterMode; + UINT32 AvailableDataClasses; + UINT32 CurrentCellularClass; + UINT32 ProviderIdOffset; + UINT32 ProviderIdSize; + UINT32 ProviderNameOffset; + UINT32 ProviderNameSize; + UINT32 RoamingTextOffset; + UINT32 RoamingTextSize; + UINT32 RegistrationFlag; + UINT8 *DataBuffer; +} MBIM_REGISTRATION_STATE_INFO_T; + +typedef struct { + UINT32 NwError; + UINT32 RegisterState; //MBIM_REGISTER_STATE_E + UINT32 RegisterMode; + UINT32 AvailableDataClasses; + UINT32 CurrentCellularClass; + UINT32 ProviderIdOffset; + UINT32 ProviderIdSize; + UINT32 ProviderNameOffset; + UINT32 ProviderNameSize; + UINT32 RoamingTextOffset; + UINT32 RoamingTextSize; + UINT32 RegistrationFlag; + UINT32 PreferredDataClass; + UINT8 *DataBuffer; +} MBIM_REGISTRATION_STATE_INFO_V2_T; + +typedef struct { + UINT32 MessageType; //Specifies the MBIM message type. + UINT32 MessageLength; //Specifies the total length of this MBIM message in bytes. + /* Specifies the MBIM message id value. This value is used to match host sent messages with function responses. + This value must be unique among all outstanding transactions. + For notifications, the TransactionId must be set to 0 by the function */ + UINT32 TransactionId; +} MBIM_MESSAGE_HEADER; + +typedef struct { + UINT32 TotalFragments; //this field indicates how many fragments there are intotal. + UINT32 CurrentFragment; //This field indicates which fragment this message is. Values are 0 to TotalFragments?\1 +} MBIM_FRAGMENT_HEADER; + +typedef struct { + MBIM_MESSAGE_HEADER MessageHeader; + UINT32 MaxControlTransfer; +} MBIM_OPEN_MSG_T; + +typedef struct { + MBIM_MESSAGE_HEADER MessageHeader; + UINT32 Status; //MBIM_STATUS_CODES_E +} MBIM_OPEN_DONE_T; + +typedef struct { + MBIM_MESSAGE_HEADER MessageHeader; +} MBIM_CLOSE_MSG_T; + +typedef struct { + MBIM_MESSAGE_HEADER MessageHeader; + UINT32 Status; +} MBIM_CLOSE_DONE_T; + +typedef struct { + UINT8 uuid[16]; +} UUID_T; + +typedef struct { + MBIM_MESSAGE_HEADER MessageHeader; + MBIM_FRAGMENT_HEADER FragmentHeader; + UUID_T DeviceServiceId; //A 16 byte UUID that identifies the device service the following CID value applies. + UINT32 CID; //Specifies the CID that identifies the parameter being queried for + UINT32 CommandType; //0 for a query operation, 1 for a Set operation + UINT32 InformationBufferLength; //Size of the Total InformationBuffer, may be larger than current message if fragmented. + UINT8 InformationBuffer[0]; //Data supplied to device specific to the CID +} MBIM_COMMAND_MSG_T; + +typedef struct { + MBIM_MESSAGE_HEADER MessageHeader; + MBIM_FRAGMENT_HEADER FragmentHeader; + UUID_T DeviceServiceId; //A 16 byte UUID that identifies the device service the following CID value applies. + UINT32 CID; //Specifies the CID that identifies the parameter being queried for + UINT32 Status; + UINT32 InformationBufferLength; //Size of the Total InformationBuffer, may be larger than current message if fragmented. + UINT8 InformationBuffer[0]; //Data supplied to device specific to the CID +} MBIM_COMMAND_DONE_T; + +typedef struct { + MBIM_MESSAGE_HEADER MessageHeader; + UINT32 ErrorStatusCode; +} MBIM_HOST_ERROR_MSG_T; + +typedef struct { + MBIM_MESSAGE_HEADER MessageHeader; + UINT32 ErrorStatusCode; +} MBIM_FUNCTION_ERROR_MSG_T; + +typedef struct { + MBIM_MESSAGE_HEADER MessageHeader; + MBIM_FRAGMENT_HEADER FragmentHeader; + UUID_T DeviceServiceId; //A 16 byte UUID that identifies the device service the following CID value applies. + UINT32 CID; //Specifies the CID that identifies the parameter being queried for + UINT32 InformationBufferLength; //Size of the Total InformationBuffer, may be larger than current message if fragmented. + UINT8 InformationBuffer[0]; //Data supplied to device specific to the CID +} MBIM_INDICATE_STATUS_MSG_T; + +typedef struct { + UINT32 offset; + UINT32 size; +} OL_PAIR_LIST; + +typedef struct { + UUID_T DeviceServiceId; + UINT32 DssPayload; + UINT32 MaxDssInstances; + UINT32 CidCount; + UINT32 CidList[]; +} MBIM_DEVICE_SERVICE_ELEMENT_T; + +typedef struct { + UINT32 DeviceServicesCount; + UINT32 MaxDssSessions; + OL_PAIR_LIST DeviceServicesRefList[]; +} MBIM_DEVICE_SERVICES_INFO_T; + +typedef enum { + MBIMActivationCommandDeactivate = 0, + MBIMActivationCommandActivate = 1, +} MBIM_ACTIVATION_COMMAND_E; + +typedef enum { + MBIMCompressionNone = 0, + MBIMCompressionEnable = 1, +} MBIM_COMPRESSION_E; + +typedef enum { + MBIMAuthProtocolNone = 0, + MBIMAuthProtocolPap = 1, + MBIMAuthProtocolChap = 2, + MBIMAuthProtocolMsChapV2 = 3, +} MBIM_AUTH_PROTOCOL_E; + +typedef enum { + MBIMContextIPTypeDefault = 0, + MBIMContextIPTypeIPv4 = 1, + MBIMContextIPTypeIPv6 = 2, + MBIMContextIPTypeIPv4v6 = 3, + MBIMContextIPTypeIPv4AndIPv6 = 4, +} MBIM_CONTEXT_IP_TYPE_E; + +typedef enum { + MBIMActivationStateUnknown = 0, + MBIMActivationStateActivated = 1, + MBIMActivationStateActivating = 2, + MBIMActivationStateDeactivated = 3, + MBIMActivationStateDeactivating = 4, +} MBIM_ACTIVATION_STATE_E; + +typedef enum { + MBIMVoiceCallStateNone = 0, + MBIMVoiceCallStateInProgress = 1, + MBIMVoiceCallStateHangUp = 2, +} MBIM_VOICECALL_STATE_E; + +static const char *MBIMMSGTypeStr(int _val) { + struct { int val;char *name;} _enumstr[] = { + {MBIM_OPEN_MSG, "MBIM_OPEN_MSG"}, + {MBIM_CLOSE_MSG, "MBIM_CLOSE_MSG"}, + {MBIM_COMMAND_MSG, "MBIM_COMMAND_MSG"}, + {MBIM_HOST_ERROR_MSG, "MBIM_HOST_ERROR_MSG"}, + {MBIM_OPEN_DONE, "MBIM_OPEN_DONE"}, + {MBIM_CLOSE_DONE, "MBIM_CLOSE_DONE"}, + {MBIM_COMMAND_DONE, "MBIM_COMMAND_DONE"}, + {MBIM_FUNCTION_ERROR_MSG, "MBIM_FUNCTION_ERROR_MSG"}, + {MBIM_INDICATE_STATUS_MSG, "MBIM_INDICATE_STATUS_MSG"}, + }; + int idx; + + for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { + if (_val == _enumstr[idx].val) + return _enumstr[idx].name; + } + + return "MBIMMSGTypeUnknow"; +}; + +static const char *MBIMContextIPTypeStr(int _val) { + struct { int val;char *name;} _enumstr[] = { + {MBIMContextIPTypeDefault, "MBIMContextIPTypeDefault"}, + {MBIMContextIPTypeIPv4, "MBIMContextIPTypeIPv4"}, + {MBIMContextIPTypeIPv6, "MBIMContextIPTypeIPv6"}, + {MBIMContextIPTypeIPv4v6, "MBIMContextIPTypeIPv4v6"}, + {MBIMContextIPTypeIPv4AndIPv6, "MBIMContextIPTypeIPv4AndIPv6"}, + }; + int idx; + + for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { + if (_val == _enumstr[idx].val) + return _enumstr[idx].name; + } + + return "MBIMContextIPTypeUnknow"; +} + +static const char *MBIMActivationStateStr(int _val) { + struct { int val;char *name;} _enumstr[] = { + {MBIMActivationStateUnknown, "Unknown"}, + {MBIMActivationStateActivated, "Activated"}, + {MBIMActivationStateActivating, "Activating"}, + {MBIMActivationStateDeactivated, "Deactivated"}, + {MBIMActivationStateDeactivating, "Deactivating"}, + }; + int idx; + + for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { + if (_val == _enumstr[idx].val) + return _enumstr[idx].name; + } + + return "Undefined"; +}; + +static const char *MBIMVoiceCallStateStr(int _val) { + struct { int val;char *name;} _enumstr[] = { + {MBIMVoiceCallStateNone, "None"}, + {MBIMVoiceCallStateInProgress, "InProgress"}, + {MBIMVoiceCallStateHangUp, "HangUp"}, + }; + int idx; + + for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { + if (_val == _enumstr[idx].val) + return _enumstr[idx].name; + } + + return "Undefined"; +}; + +typedef struct { + const char *uuid; + UINT32 cid; + const char *name; +} UUID_CID_STR; + +static const UUID_CID_STR uuid_cid_string[] = { + {UUID_BASIC_CONNECT, MBIM_CID_DEVICE_CAPS, "MBIM_CID_DEVICE_CAPS"}, + {UUID_BASIC_CONNECT, MBIM_CID_SUBSCRIBER_READY_STATUS, "MBIM_CID_SUBSCRIBER_READY_STATUS"}, + {UUID_BASIC_CONNECT, MBIM_CID_RADIO_STATE, "MBIM_CID_RADIO_STATE"}, + {UUID_BASIC_CONNECT, MBIM_CID_PIN, "MBIM_CID_PIN"}, + {UUID_BASIC_CONNECT, MBIM_CID_PIN_LIS, "MBIM_CID_PIN_LIS"}, + {UUID_BASIC_CONNECT, MBIM_CID_HOME_PROVIDER, "MBIM_CID_HOME_PROVIDER"}, + {UUID_BASIC_CONNECT, MBIM_CID_PREFERRED_PROVIDERS, "MBIM_CID_PREFERRED_PROVIDERS"}, + {UUID_BASIC_CONNECT, MBIM_CID_VISIBLE_PROVIDERS, "MBIM_CID_VISIBLE_PROVIDERS"}, + {UUID_BASIC_CONNECT, MBIM_CID_REGISTER_STATE, "MBIM_CID_REGISTER_STATE"}, + {UUID_BASIC_CONNECT, MBIM_CID_PACKET_SERVICE, "MBIM_CID_PACKET_SERVICE"}, + {UUID_BASIC_CONNECT, MBIM_CID_SIGNAL_STATE, "MBIM_CID_SIGNAL_STATE"}, + {UUID_BASIC_CONNECT, MBIM_CID_CONNECT, "MBIM_CID_CONNECT"}, + {UUID_BASIC_CONNECT, MBIM_CID_PROVISIONED_CONTEXTS, "MBIM_CID_PROVISIONED_CONTEXTS"}, + {UUID_BASIC_CONNECT, MBIM_CID_SERVICE_ACTIVATION, "MBIM_CID_SERVICE_ACTIVATION"}, + {UUID_BASIC_CONNECT, MBIM_CID_IP_CONFIGURATION, "MBIM_CID_IP_CONFIGURATION"}, + {UUID_BASIC_CONNECT, MBIM_CID_DEVICE_SERVICES, "MBIM_CID_DEVICE_SERVICES"}, + {UUID_BASIC_CONNECT, MBIM_CID_DEVICE_SERVICE_SUBSCRIBE_LIST, "MBIM_CID_DEVICE_SERVICE_SUBSCRIBE_LIST"}, + {UUID_BASIC_CONNECT, MBIM_CID_PACKET_STATISTICS, "MBIM_CID_PACKET_STATISTICS"}, + {UUID_BASIC_CONNECT, MBIM_CID_NETWORK_IDLE_HINT, "MBIM_CID_NETWORK_IDLE_HINT"}, + {UUID_BASIC_CONNECT, MBIM_CID_EMERGENCY_MODE, "MBIM_CID_EMERGENCY_MODE"}, + {UUID_BASIC_CONNECT, MBIM_CID_IP_PACKET_FILTERS, "MBIM_CID_IP_PACKET_FILTERS"}, + {UUID_BASIC_CONNECT, MBIM_CID_MULTICARRIER_PROVIDERS, "MBIM_CID_MULTICARRIER_PROVIDERS"}, + + {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_PROVISIONED_CONTEXT_V2, "MBIM_CID_MS_PROVISIONED_CONTEXT_V2"}, + {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_NETWORK_BLACKLIST, "MBIM_CID_MS_NETWORK_BLACKLIST"}, + {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_LTE_ATTACH_CONFIG, "MBIM_CID_MS_LTE_ATTACH_CONFIG"}, + {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_LTE_ATTACH_STATUS, "MBIM_CID_MS_LTE_ATTACH_STATUS"}, + {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_SYS_CAPS, "MBIM_CID_MS_SYS_CAPS"}, + {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_DEVICE_CAPS_V2, "MBIM_CID_MS_DEVICE_CAPS_V2"}, + {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_DEVICE_SLOT_MAPPING, "MBIM_CID_MS_DEVICE_SLOT_MAPPING"}, + {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_SLOT_INFO_STATUS, "MBIM_CID_MS_SLOT_INFO_STATUS"}, + {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_PCO, "MBIM_CID_MS_PCO"}, + {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_DEVICE_RESET, "MBIM_CID_MS_DEVICE_RESET"}, + {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_BASE_STATIONS_INFO, "MBIM_CID_MS_BASE_STATIONS_INFO"}, + {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_LOCATION_INFO_STATUS, "MBIM_CID_MS_LOCATION_INFO_STATUS"}, + {UUID_BASIC_CONNECT_EXT, MBIM_CID_NOT_DEFINED, "MBIM_CID_NOT_DEFINED"}, + {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_PIN_EX, "MBIM_CID_MS_PIN_EX"}, + {UUID_BASIC_CONNECT_EXT, MBIM_CID_MS_VERSION, "MBIM_CID_MS_VERSION"}, + + {UUID_MS_UICC_LOW_LEVEL, MBIM_CID_MS_UICC_ATR, "MBIM_CID_MS_UICC_ATR"}, + {UUID_MS_UICC_LOW_LEVEL, MBIM_CID_MS_UICC_OPEN_CHANNEL, "MBIM_CID_MS_UICC_OPEN_CHANNEL"}, + {UUID_MS_UICC_LOW_LEVEL, MBIM_CID_MS_UICC_CLOSE_CHANNEL, "MBIM_CID_MS_UICC_CLOSE_CHANNEL"}, + {UUID_MS_UICC_LOW_LEVEL, MBIM_CID_MS_UICC_APDU, "MBIM_CID_MS_UICC_APDU"}, + {UUID_MS_UICC_LOW_LEVEL, MBIM_CID_MS_UICC_TERMINAL_CAPABILITY, "MBIM_CID_MS_UICC_TERMINAL_CAPABILITY"}, + {UUID_MS_UICC_LOW_LEVEL, MBIM_CID_MS_UICC_RESET, "MBIM_CID_MS_UICC_RESET"}, + {UUID_MS_UICC_LOW_LEVEL, MBIM_CID_MS_APP_LIST, "MBIM_CID_MS_APP_LIST"}, +}; + +typedef struct { + UINT32 SessionId; + UINT32 ActivationCommand; //MBIM_ACTIVATION_COMMAND_E + UINT32 AccessStringOffset; + UINT32 AccessStringSize; + UINT32 UserNameOffset; + UINT32 UserNameSize; + UINT32 PasswordOffset; + UINT32 PasswordSize; + UINT32 Compression; //MBIM_COMPRESSION_E + UINT32 AuthProtocol; //MBIM_AUTH_PROTOCOL_E + UINT32 IPType; //MBIM_CONTEXT_IP_TYPE_E + UUID_T ContextType; + UINT8 DataBuffer[0]; /* apn, username, password */ +} MBIM_SET_CONNECT_T; + +typedef struct { + UINT32 SessionId; + UINT32 ActivationState; //MBIM_ACTIVATION_STATE_E + UINT32 VoiceCallState; + UINT32 IPType; //MBIM_CONTEXT_IP_TYPE_E + UUID_T ContextType; + UINT32 NwError; +} MBIM_CONNECT_T; + +typedef struct { + UINT32 OnLinkPrefixLength; + UINT8 IPv4Address[4]; +} MBIM_IPV4_ELEMENT_T; + +typedef struct { + UINT32 OnLinkPrefixLength; + UINT8 IPv6Address[16]; +} MBIM_IPV6_ELEMENT_T; + +typedef struct { + UINT32 SessionId; + UINT32 IPv4ConfigurationAvailable; //bit0~Address, bit1~gateway, bit2~DNS, bit3~MTU + UINT32 IPv6ConfigurationAvailable; //bit0~Address, bit1~gateway, bit2~DNS, bit3~MTU + UINT32 IPv4AddressCount; + UINT32 IPv4AddressOffset; + UINT32 IPv6AddressCount; + UINT32 IPv6AddressOffset; + UINT32 IPv4GatewayOffset; + UINT32 IPv6GatewayOffset; + UINT32 IPv4DnsServerCount; + UINT32 IPv4DnsServerOffset; + UINT32 IPv6DnsServerCount; + UINT32 IPv6DnsServerOffset; + UINT32 IPv4Mtu; + UINT32 IPv6Mtu; + UINT8 DataBuffer[]; +} MBIM_IP_CONFIGURATION_INFO_T; + +typedef struct { + UINT32 RSRP; + UINT32 SNR; + UINT32 RSRPThreshold; + UINT32 SNRThreshold; + UINT32 SystemType; +} MBIM_RSRP_SNR_INFO_T; + +typedef struct { + UINT32 Elementcount; + MBIM_RSRP_SNR_INFO_T RsrpSnr[0]; +} MBIM_RSRP_SNR_T; + +typedef struct { + UINT32 Rssi; + UINT32 ErrorRate; + UINT32 SignalStrengthInterval; + UINT32 RssiThreshold; + UINT32 ErrorRateThreshold; +} MBIM_SIGNAL_STATE_INFO_T; + +typedef struct { + UINT32 Rssi; + UINT32 ErrorRate; + UINT32 SignalStrengthInterval; + UINT32 RssiThreshold; + UINT32 ErrorRateThreshold; + UINT32 RsrpSnrOffset; + UINT32 RsrpSnrSize; + UINT8 DataBuffer[]; +} MBIM_SIGNAL_STATE_INFO_V2_T; + +typedef struct { + UINT32 SignalStrengthInterval; + UINT32 RssiThreshold; + UINT32 ErrorRateThreshold; +} MBIM_SET_SIGNAL_STATE_T; + +typedef struct { + UINT32 DevicePathOffset; + UINT32 DevicePathSize; + UINT32 Timeout; + UINT8 DataBuffer[]; +} MBIM_LIBQMI_PROXY_CONFIG_T; + +typedef struct { + UINT32 AtrSize; + UINT32 AtrOffset; + UINT8 DataBuffer[]; +} MBIM_MS_ATR_INFO_T; + +#pragma pack() + +static pthread_t s_tid_reader = 0; +static int mbim_verbose = 0; +static UINT32 TransactionId = 1; +static unsigned mbim_default_timeout = 30000; +static const char *mbim_apn = NULL; +static const char *mbim_user = NULL; +static const char *mbim_passwd = NULL; +static int mbim_iptype = MBIMContextIPTypeDefault; +static int mbim_auth = MBIMAuthProtocolNone; +static int mbim_sessionID = 0; +static int mbim_fd = -1; +static MBIM_MESSAGE_HEADER *mbim_pRequest; +static MBIM_MESSAGE_HEADER *mbim_pResponse; + +static unsigned int qmi_over_mbim_support = 0; +static int qmi_over_mbim_sk[2] = {-1, -1}; +static pthread_mutex_t mbim_command_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t mbim_command_cond = PTHREAD_COND_INITIALIZER; +static int mbim_ms_version = 1; +static uint8_t qmi_over_mbim_nas = 0; +int qmi_over_mbim_qmidev_send(PQCQMIMSG pQMI); + +static const UUID_T * str2uuid(const char *str) { + static UUID_T uuid; + UINT32 d[16]; + char tmp[16*2+4+1]; + unsigned i = 0; + + while (str[i]) { + tmp[i] = tolower(str[i]); + i++; + } + tmp[i] = '\0'; + + sscanf(tmp, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", + &d[0], &d[1], &d[2], &d[3], &d[4], &d[5], &d[6], &d[7], + &d[8], &d[9], &d[10], &d[11], &d[12], &d[13], &d[14], &d[15]); + + for (i = 0; i < 16; i++) { + uuid.uuid[i] = d[i]&0xFF; + } + + return &uuid; +} + +static void wchar2char(const char *src, size_t src_size, char *dst, size_t dst_len) { + size_t i; + + for (i = 0; i < (dst_len-1) && i < (src_size/2); i++) + dst[i] = src[i*2]; + dst[i] = 0; +} + +static size_t char2wchar(const char *src, size_t src_len, uint8_t *dst, size_t dst_len) { + size_t i; + + if (src_len > (dst_len/2)) + src_len = (dst_len/2); + + for (i = 0; i < src_len; i++) { + *dst++ = *src++; + *dst++ = 0; + } + + return i*2; +} + +#define mbim_alloc( _size) malloc(_size) +#define mbim_free(_mem) do { if (_mem) { free(_mem); _mem = NULL;}} while(0) + +static int mbim_open_state = 0; +static MBIM_SUBSCRIBER_READY_STATE_E ReadyState = MBIMSubscriberReadyStateNotInitialized; +static MBIM_REGISTER_STATE_E RegisterState = MBIMRegisterStateUnknown; +static MBIM_PACKET_SERVICE_STATE_E PacketServiceState = MBIMPacketServiceStateUnknown; +static MBIM_ACTIVATION_STATE_E ActivationState = MBIMActivationStateUnknown; +static MBIM_SUBSCRIBER_READY_STATE_E oldReadyState = MBIMSubscriberReadyStateNotInitialized; +static MBIM_REGISTER_STATE_E oldRegisterState = MBIMRegisterStateUnknown; +static MBIM_PACKET_SERVICE_STATE_E oldPacketServiceState = MBIMPacketServiceStateUnknown; +static MBIM_ACTIVATION_STATE_E oldActivationState = MBIMActivationStateUnknown; +static int mbim_update_state(void); + +static __inline uint32_t mbim2qmi_ipv4addr(uint32_t addr) { + return (addr>>24) | (addr>>8&0xff00) | (addr<<8&0xff0000) | (addr<<24); +} + +static __inline void mbim2qmi_ipv6addr(const unsigned char *src, unsigned char *dst) { + int i; + + for (i = 0; i < 16 ; i++) { + dst[i] = src[i]; + } +} + +static MBIM_MESSAGE_HEADER *compose_open_command(UINT32 MaxControlTransfer) +{ + MBIM_OPEN_MSG_T *pRequest = (MBIM_OPEN_MSG_T *)mbim_alloc(sizeof(MBIM_OPEN_MSG_T)); + + if(!pRequest) + return NULL; + + pRequest->MessageHeader.MessageType = htole32(MBIM_OPEN_MSG); + pRequest->MessageHeader.MessageLength = htole32(sizeof(MBIM_OPEN_MSG_T)); + pRequest->MessageHeader.TransactionId = htole32(TransactionId++); + pRequest->MaxControlTransfer = htole32(MaxControlTransfer); + + return &pRequest->MessageHeader; +} + +static MBIM_MESSAGE_HEADER *compose_close_command(void) +{ + MBIM_CLOSE_MSG_T *pRequest = (MBIM_CLOSE_MSG_T *)mbim_alloc(sizeof(MBIM_CLOSE_MSG_T)); + + if(!pRequest) + return NULL; + + pRequest->MessageHeader.MessageType = htole32(MBIM_CLOSE_MSG); + pRequest->MessageHeader.MessageLength = htole32(sizeof(MBIM_CLOSE_MSG_T)); + pRequest->MessageHeader.TransactionId = htole32(TransactionId++); + + return &pRequest->MessageHeader; +} + +static MBIM_MESSAGE_HEADER *compose_basic_connect_command(UINT32 CID, UINT32 CommandType, void *pInformationBuffer, UINT32 InformationBufferLength) +{ + MBIM_COMMAND_MSG_T *pRequest = (MBIM_COMMAND_MSG_T *)mbim_alloc(sizeof(MBIM_COMMAND_MSG_T) + InformationBufferLength); + + if (!pRequest) + return NULL; + + pRequest->MessageHeader.MessageType = htole32(MBIM_COMMAND_MSG); + pRequest->MessageHeader.MessageLength = htole32((sizeof(MBIM_COMMAND_MSG_T) + InformationBufferLength)); + pRequest->MessageHeader.TransactionId = htole32(TransactionId++); + + pRequest->FragmentHeader.TotalFragments = htole32(1); + pRequest->FragmentHeader.CurrentFragment= htole32(0); + + memcpy(pRequest->DeviceServiceId.uuid, str2uuid(UUID_BASIC_CONNECT), 16); + + pRequest->CID = htole32(CID); + pRequest->CommandType = htole32(CommandType); + if (InformationBufferLength && pInformationBuffer) { + pRequest->InformationBufferLength = htole32(InformationBufferLength); + memcpy(pRequest->InformationBuffer, pInformationBuffer, InformationBufferLength); + } else { + pRequest->InformationBufferLength = htole32(0); + } + + return &pRequest->MessageHeader; +} + +static MBIM_MESSAGE_HEADER *compose_basic_connect_ext_command(UINT32 CID, UINT32 CommandType, void *pInformationBuffer, UINT32 InformationBufferLength) +{ + MBIM_COMMAND_MSG_T *pRequest = (MBIM_COMMAND_MSG_T *)compose_basic_connect_command(CID, CommandType, pInformationBuffer, InformationBufferLength); + + if (!pRequest) + return NULL; + + memcpy(pRequest->DeviceServiceId.uuid, str2uuid(UUID_BASIC_CONNECT_EXT), 16); + + return &pRequest->MessageHeader; +} + +static MBIM_MESSAGE_HEADER *compose_qmi_over_mbim_command(UINT32 CID, UINT32 CommandType, void *pInformationBuffer, UINT32 InformationBufferLength) +{ + MBIM_COMMAND_MSG_T *pRequest = (MBIM_COMMAND_MSG_T *)compose_basic_connect_command(CID, CommandType, pInformationBuffer, InformationBufferLength); + + if (!pRequest) + return NULL; + + memcpy(pRequest->DeviceServiceId.uuid, str2uuid(uuid_ext_qmux), 16); + + return &pRequest->MessageHeader; +} + +static const char * uuid2str(const UUID_T *pUUID) { + static char str[16*2+4+1]; + const UINT8 *d = pUUID->uuid; + + snprintf(str, sizeof(str), "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", + d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], + d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); + + return str; +} + +static const char *DeviceServiceId2str(const UUID_T *pUUID) { + const char *str = uuid2str(pUUID); + + struct { char *val;char *name;} _enumstr[] = { + {UUID_BASIC_CONNECT, "UUID_BASIC_CONNECT"}, + {UUID_BASIC_CONNECT_EXT, "UUID_BASIC_CONNECT_EXT"}, + {UUID_SMS, "UUID_SMS"}, + {UUID_USSD, "UUID_USSD"}, + {UUID_PHONEBOOK, "UUID_PHONEBOOK"}, + {UUID_STK, "UUID_STK"}, + {UUID_AUTH, "UUID_AUTH"}, + {UUID_DSS, "UUID_DSS"}, + {uuid_ext_qmux, "uuid_ext_qmux"}, + {uuid_mshsd, "uuid_mshsd"}, + {uuid_qmbe, "uuid_qmbe"}, + {UUID_MSFWID, "UUID_MSFWID"}, + {uuid_atds, "uuid_atds"}, + {uuid_qdu, "uuid_qdu"}, + {UUID_MS_UICC_LOW_LEVEL, "UUID_MS_UICC_LOW_LEVEL"}, + {UUID_MS_SARControl, "UUID_MS_SARControl"}, + {UUID_VOICEEXTENSIONS, "UUID_VOICEEXTENSIONS"}, + {UUID_LIBMBIM_PROXY, "UUID_LIBMBIM_PROXY"}, + }; + int idx; + + for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { + if (!strcasecmp(str, _enumstr[idx].val)) + return _enumstr[idx].name; + } + + return str; +} + +static const char *mbim_get_segment(void *_pMsg, UINT32 offset, UINT32 len) +{ + int idx; + static char buff[256] = {'\0'}; + UINT8 *pMsg = (UINT8*)_pMsg; + + for (idx = 0; idx < (int)(len/2); idx++) + buff[idx] = pMsg[offset+idx*2]; + buff[idx] = '\0'; + return buff; +} + +static void mbim_dump_header(MBIM_MESSAGE_HEADER *pMsg, const char *direction) { + mbim_debug("%s Header:", direction); + mbim_debug("%s MessageLength = %u", direction, le32toh(pMsg->MessageLength)); + mbim_debug("%s MessageType = %s (0x%08x)", direction, MBIMMSGTypeStr(le32toh(pMsg->MessageType)), le32toh(pMsg->MessageType)); + mbim_debug("%s TransactionId = %u", direction, le32toh(pMsg->TransactionId)); + mbim_debug("%s Contents:", direction); +} + +static void mbim_dump_uuid_cid(const UUID_T *pUUID, UINT32 CID, const char *direction) { + size_t idx; + const char *uuidStr = uuid2str(pUUID); + const char *cidStr = "unknow"; + + for (idx = 0; idx < (sizeof(uuid_cid_string)/sizeof(uuid_cid_string[0])); idx++) { + if (!strcmp(uuidStr, uuid_cid_string[idx].uuid) && uuid_cid_string[idx].cid == CID) { + cidStr = uuid_cid_string[idx].name; + } + } + + mbim_debug("%s DeviceServiceId = %s (%s)", direction, DeviceServiceId2str(pUUID), uuidStr); + mbim_debug("%s CID = %s (%u)", direction, cidStr, le32toh(CID)); +} + + +static void mbim_dump_command_msg(MBIM_COMMAND_MSG_T *pCmdMsg, const char *direction) { + mbim_dump_uuid_cid(&pCmdMsg->DeviceServiceId, le32toh(pCmdMsg->CID), direction); + mbim_debug("%s CommandType = %s (%u)", direction, le32toh(pCmdMsg->CommandType) ? "set" : "query", le32toh(pCmdMsg->CommandType)); + mbim_debug("%s InformationBufferLength = %u", direction, le32toh(pCmdMsg->InformationBufferLength)); +} + +static void mbim_dump_command_done(MBIM_COMMAND_DONE_T *pCmdDone, const char *direction) { + mbim_dump_uuid_cid(&pCmdDone->DeviceServiceId, le32toh(pCmdDone->CID), direction); + mbim_debug("%s Status = %u", direction, le32toh(pCmdDone->Status)); + mbim_debug("%s InformationBufferLength = %u", direction, le32toh(pCmdDone->InformationBufferLength)); +} + +static void mbim_dump_indicate_msg(MBIM_INDICATE_STATUS_MSG_T *pIndMsg, const char *direction) { + mbim_dump_uuid_cid(&pIndMsg->DeviceServiceId, le32toh(pIndMsg->CID), direction); + mbim_debug("%s InformationBufferLength = %u", direction, le32toh(pIndMsg->InformationBufferLength)); +} + +static void mbim_dump_connect(MBIM_CONNECT_T *pInfo, const char *direction) { + mbim_debug("%s SessionId = %u", direction, le32toh(pInfo->SessionId)); + mbim_debug("%s ActivationState = %s (%u)", direction, MBIMActivationStateStr(le32toh(pInfo->ActivationState)), le32toh(pInfo->ActivationState)); + mbim_debug("%s IPType = %s", direction, MBIMContextIPTypeStr(le32toh(pInfo->IPType))); + mbim_debug("%s VoiceCallState = %s", direction, MBIMVoiceCallStateStr(le32toh(pInfo->VoiceCallState))); + mbim_debug("%s ContextType = %s", direction, uuid2str(&pInfo->ContextType)); + mbim_debug("%s NwError = %u", direction, le32toh(pInfo->NwError)); +} + +static void mbim_dump_signal_state(MBIM_SIGNAL_STATE_INFO_T *pInfo, const char *direction) +{ + mbim_debug("%s Rssi = %u", direction, le32toh(pInfo->Rssi)); + mbim_debug("%s ErrorRate = %u", direction, le32toh(pInfo->ErrorRate)); + mbim_debug("%s SignalStrengthInterval = %u", direction, le32toh(pInfo->SignalStrengthInterval)); + mbim_debug("%s RssiThreshold = %u", direction, le32toh(pInfo->RssiThreshold)); + mbim_debug("%s ErrorRateThreshold = %u", direction, le32toh(pInfo->ErrorRateThreshold)); +} + +static void mbim_dump_packet_service(MBIM_PACKET_SERVICE_INFO_T *pInfo, const char *direction) +{ + mbim_debug("%s NwError = %u", direction, le32toh(pInfo->NwError)); + mbim_debug("%s PacketServiceState = %s", direction, MBIMPacketServiceStateStr(le32toh(pInfo->PacketServiceState))); + mbim_debug("%s HighestAvailableDataClass = %s", direction, MBIMDataClassStr(le32toh(pInfo->HighestAvailableDataClass))); + mbim_debug("%s UplinkSpeed = %ld", direction, (long)le64toh(pInfo->UplinkSpeed)); + mbim_debug("%s DownlinkSpeed = %ld", direction, (long)le64toh(pInfo->DownlinkSpeed)); +} + +static void mbim_dump_subscriber_status(MBIM_SUBSCRIBER_READY_STATUS_T *pInfo, const char *direction) +{ + mbim_debug("%s ReadyState = %s", direction, MBIMSubscriberReadyStateStr(le32toh(pInfo->ReadyState))); + mbim_debug("%s SIMICCID = %s", direction, mbim_get_segment(pInfo, le32toh(pInfo->SimIccIdOffset), le32toh(pInfo->SimIccIdSize))); + mbim_debug("%s SubscriberID = %s", direction, mbim_get_segment(pInfo, le32toh(pInfo->SubscriberIdOffset), le32toh(pInfo->SubscriberIdSize))); + /* maybe more than one number */ + uint32_t idx; + for (idx = 0; idx < le32toh(pInfo->ElementCount); idx++) { + UINT32 offset = ((UINT32*)((UINT8*)pInfo+offsetof(MBIM_SUBSCRIBER_READY_STATUS_T, TelephoneNumbersRefList)))[0]; + UINT32 length = ((UINT32*)((UINT8*)pInfo+offsetof(MBIM_SUBSCRIBER_READY_STATUS_T, TelephoneNumbersRefList)))[1]; + mbim_debug("%s Number = %s", direction, mbim_get_segment(pInfo, le32toh(offset), le32toh(length))); + } +} + +static void mbim_dump_regiester_status(MBIM_REGISTRATION_STATE_INFO_T *pInfo, const char *direction) +{ + mbim_debug("%s NwError = %u", direction, le32toh(pInfo->NwError)); + mbim_debug("%s RegisterState = %s", direction, MBIMRegisterStateStr(le32toh(pInfo->RegisterState))); + mbim_debug("%s RegisterMode = %s", direction, MBIMRegisterModeStr(le32toh(pInfo->RegisterMode))); +} + +static void mbim_dump_ipconfig(MBIM_IP_CONFIGURATION_INFO_T *pInfo, const char *direction) +{ + UINT8 prefix = 0, *ipv4=NULL, *ipv6=NULL, *gw=NULL, *dns1=NULL, *dns2=NULL; + + mbim_debug("%s SessionId = %u", direction, le32toh(pInfo->SessionId)); + mbim_debug("%s IPv4ConfigurationAvailable = 0x%x", direction, le32toh(pInfo->IPv4ConfigurationAvailable)); + mbim_debug("%s IPv6ConfigurationAvailable = 0x%x", direction, le32toh(pInfo->IPv6ConfigurationAvailable)); + mbim_debug("%s IPv4AddressCount = 0x%x", direction, le32toh(pInfo->IPv4AddressCount)); + mbim_debug("%s IPv4AddressOffset = 0x%x", direction, le32toh(pInfo->IPv4AddressOffset)); + mbim_debug("%s IPv6AddressCount = 0x%x", direction, le32toh(pInfo->IPv6AddressCount)); + mbim_debug("%s IPv6AddressOffset = 0x%x", direction, le32toh(pInfo->IPv6AddressOffset)); + + /* IPv4 */ + if (le32toh(pInfo->IPv4ConfigurationAvailable)&0x1) { + MBIM_IPV4_ELEMENT_T *pAddress = (MBIM_IPV4_ELEMENT_T *)(&pInfo->DataBuffer[le32toh(pInfo->IPv4AddressOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); + prefix = le32toh(pAddress->OnLinkPrefixLength); + ipv4 = pAddress->IPv4Address; + mbim_debug("%s IPv4 = %u.%u.%u.%u/%u", direction, ipv4[0], ipv4[1], ipv4[2], ipv4[3], prefix); + } + if (le32toh(pInfo->IPv4ConfigurationAvailable)&0x2) { + gw = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv4GatewayOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); + mbim_debug("%s gw = %u.%u.%u.%u", direction, gw[0], gw[1], gw[2], gw[3]); + } + if (le32toh(pInfo->IPv4ConfigurationAvailable)&0x3) { + dns1 = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv4DnsServerOffset) -sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); + mbim_debug("%s dns1 = %u.%u.%u.%u", direction, dns1[0], dns1[1], dns1[2], dns1[3]); + if (le32toh(pInfo->IPv4DnsServerCount) == 2) { + dns2 = dns1 + 4; + mbim_debug("%s dns2 = %u.%u.%u.%u", direction, dns2[0], dns2[1], dns2[2], dns2[3]); + } + } + if (le32toh(pInfo->IPv4Mtu)) mbim_debug("%s ipv4 mtu = %u", direction, le32toh(pInfo->IPv4Mtu)); + + /* IPv6 */ + if (le32toh(pInfo->IPv6ConfigurationAvailable)&0x1) { + MBIM_IPV6_ELEMENT_T *pAddress = (MBIM_IPV6_ELEMENT_T *)(&pInfo->DataBuffer[le32toh(pInfo->IPv6AddressOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); + prefix = le32toh(pAddress->OnLinkPrefixLength); + ipv6 = pAddress->IPv6Address; + mbim_debug("%s IPv6 = %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x/%d", \ + direction, ipv6[0], ipv6[1], ipv6[2], ipv6[3], ipv6[4], ipv6[5], ipv6[6], ipv6[7], \ + ipv6[8], ipv6[9], ipv6[10], ipv6[11], ipv6[12], ipv6[13], ipv6[14], ipv6[15], prefix); + } + if (le32toh(pInfo->IPv6ConfigurationAvailable)&0x2) { + gw = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv6GatewayOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); + mbim_debug("%s gw = %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", \ + direction, gw[0], gw[1], gw[2], gw[3], gw[4], gw[5], gw[6], gw[7], \ + gw[8], gw[9], gw[10], gw[11], gw[12], gw[13], gw[14], gw[15]); + } + if (le32toh(pInfo->IPv6ConfigurationAvailable)&0x3) { + dns1 = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv6DnsServerOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); + mbim_debug("%s dns1 = %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", \ + direction, dns1[0], dns1[1], dns1[2], dns1[3], dns1[4], dns1[5], dns1[6], dns1[7], \ + dns1[8], dns1[9], dns1[10], dns1[11], dns1[12], dns1[13], dns1[14], dns1[15]); + if (le32toh(pInfo->IPv6DnsServerCount) == 2) { + dns2 = dns1 + 16; + mbim_debug("%s dns2 = %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", \ + direction, dns2[0], dns2[1], dns2[2], dns2[3], dns1[4], dns1[5], dns1[6], dns1[7], + dns2[8], dns2[9], dns2[10], dns2[11], dns2[12], dns2[13], dns2[14], dns2[15]); + } + } + if (le32toh(pInfo->IPv6Mtu)) mbim_debug("%s ipv6 mtu = %u", direction, le32toh(pInfo->IPv6Mtu)); +} + +static void mbim_dump(MBIM_MESSAGE_HEADER *pMsg, int mbim_verbose) { + unsigned char *data = (unsigned char *)pMsg; + const char *direction = (le32toh(pMsg->MessageType) & 0x80000000) ? "<" : ">"; + + if (!mbim_verbose) + return; + + if (mbim_verbose) { + unsigned i; + static char *_tmp = NULL; + + if (!_tmp) + _tmp = (char *)malloc(4096); + + if (_tmp) { + _tmp[0] = (le32toh(pMsg->MessageType) & 0x80000000) ? '<' : '>'; + _tmp[1] = '\0'; + for (i = 0; i < le32toh(pMsg->MessageLength) && i < 4096; i++) + snprintf(_tmp + strlen(_tmp), 4096 - strlen(_tmp), "%02X:", data[i]); + mbim_debug("%s", _tmp); + } + } + + mbim_dump_header(pMsg, direction); + + switch (le32toh(pMsg->MessageType)) { + case MBIM_OPEN_MSG: { + MBIM_OPEN_MSG_T *pOpenMsg = (MBIM_OPEN_MSG_T *)pMsg; + mbim_debug("%s MaxControlTransfer = %u", direction, le32toh(pOpenMsg->MaxControlTransfer)); + } + break; + case MBIM_OPEN_DONE: { + MBIM_OPEN_DONE_T *pOpenDone = (MBIM_OPEN_DONE_T *)pMsg; + mbim_debug("%s Status = %u", direction, le32toh(pOpenDone->Status)); + } + break; + case MBIM_CLOSE_MSG: { + + } + break; + case MBIM_CLOSE_DONE: { + MBIM_CLOSE_DONE_T *pCloseDone = (MBIM_CLOSE_DONE_T *)pMsg; + mbim_debug("%s Status = %u", direction, le32toh(pCloseDone->Status)); + } + break; + case MBIM_COMMAND_MSG: { + MBIM_COMMAND_MSG_T *pCmdMsg = (MBIM_COMMAND_MSG_T *)pMsg; + + mbim_dump_command_msg(pCmdMsg, direction); + if (!memcmp(pCmdMsg->DeviceServiceId.uuid, str2uuid(UUID_BASIC_CONNECT), 16)) { + switch (le32toh(pCmdMsg->CID)) { + case MBIM_CID_CONNECT: { + MBIM_SET_CONNECT_T *pInfo = (MBIM_SET_CONNECT_T *)pCmdMsg->InformationBuffer; + mbim_debug("%s SessionId = %u", direction, le32toh(pInfo->SessionId)); + } + break; + case MBIM_CID_IP_CONFIGURATION: { + MBIM_IP_CONFIGURATION_INFO_T *pInfo = (MBIM_IP_CONFIGURATION_INFO_T *)pCmdMsg->InformationBuffer; + mbim_debug("%s SessionId = %u", direction, le32toh(pInfo->SessionId)); + } + break; + default: + break; + } + } + } + break; + case MBIM_COMMAND_DONE: { + MBIM_COMMAND_DONE_T *pCmdDone = (MBIM_COMMAND_DONE_T *)pMsg; + + mbim_dump_command_done(pCmdDone, direction); + if (le32toh(pCmdDone->InformationBufferLength) == 0) + return; + + if (!memcmp(pCmdDone->DeviceServiceId.uuid, str2uuid(UUID_BASIC_CONNECT), 16)) { + switch (le32toh(pCmdDone->CID)) { + case MBIM_CID_CONNECT: { + MBIM_CONNECT_T *pInfo = (MBIM_CONNECT_T *)pCmdDone->InformationBuffer; + mbim_dump_connect(pInfo, direction); + } + break; + case MBIM_CID_IP_CONFIGURATION: { + //MBIM_IP_CONFIGURATION_INFO_T *pInfo = (MBIM_IP_CONFIGURATION_INFO_T *)pCmdDone->InformationBuffer; + //mbim_dump_ipconfig(pInfo, direction); + } + break; + case MBIM_CID_PACKET_SERVICE: { + MBIM_PACKET_SERVICE_INFO_T *pInfo = (MBIM_PACKET_SERVICE_INFO_T *)pCmdDone->InformationBuffer; + mbim_dump_packet_service(pInfo, direction); + } + break; + case MBIM_CID_SUBSCRIBER_READY_STATUS: { + MBIM_SUBSCRIBER_READY_STATUS_T *pInfo = (MBIM_SUBSCRIBER_READY_STATUS_T *)pCmdDone->InformationBuffer; + mbim_dump_subscriber_status(pInfo, direction); + } + break; + case MBIM_CID_REGISTER_STATE: { + MBIM_REGISTRATION_STATE_INFO_T *pInfo = (MBIM_REGISTRATION_STATE_INFO_T *)pCmdDone->InformationBuffer; + mbim_dump_regiester_status(pInfo, direction); + } + break; + default: + break; + } + } + } + break; + case MBIM_INDICATE_STATUS_MSG: { + MBIM_INDICATE_STATUS_MSG_T *pIndMsg = (MBIM_INDICATE_STATUS_MSG_T *)pMsg; + + mbim_dump_indicate_msg(pIndMsg, direction); + if (le32toh(pIndMsg->InformationBufferLength) == 0) + return; + + if (!memcmp(pIndMsg->DeviceServiceId.uuid, str2uuid(UUID_BASIC_CONNECT), 16)) { + switch (le32toh(pIndMsg->CID)) { + case MBIM_CID_CONNECT: { + MBIM_CONNECT_T *pInfo = (MBIM_CONNECT_T *)pIndMsg->InformationBuffer; + mbim_dump_connect(pInfo, direction); + } + break; + case MBIM_CID_SIGNAL_STATE: { + MBIM_SIGNAL_STATE_INFO_T *pInfo = (MBIM_SIGNAL_STATE_INFO_T *)pIndMsg->InformationBuffer; + mbim_dump_signal_state(pInfo, direction); + } + break; + case MBIM_CID_SUBSCRIBER_READY_STATUS: { + MBIM_SUBSCRIBER_READY_STATUS_T *pInfo = (MBIM_SUBSCRIBER_READY_STATUS_T *)pIndMsg->InformationBuffer; + mbim_dump_subscriber_status(pInfo, direction); + } + break; + case MBIM_CID_REGISTER_STATE: { + MBIM_REGISTRATION_STATE_INFO_T *pInfo = (MBIM_REGISTRATION_STATE_INFO_T *)pIndMsg->InformationBuffer; + mbim_dump_regiester_status(pInfo, direction); + } + break; + case MBIM_CID_PACKET_SERVICE: { + MBIM_PACKET_SERVICE_INFO_T *pInfo = (MBIM_PACKET_SERVICE_INFO_T *)pIndMsg->InformationBuffer; + mbim_dump_packet_service(pInfo, direction); + } + break; + default: + break; + } + } + else if (!memcmp(pIndMsg->DeviceServiceId.uuid, str2uuid(UUID_BASIC_CONNECT_EXT), 16)) { + } + } + break; + case MBIM_FUNCTION_ERROR_MSG: { + MBIM_FUNCTION_ERROR_MSG_T *pErrMsg = (MBIM_FUNCTION_ERROR_MSG_T*)pMsg; + mbim_debug("%s ErrorStatusCode = %u", direction, le32toh(pErrMsg->ErrorStatusCode)); + } + break; + default: + break; + } +} + +static void mbim_recv_command(MBIM_MESSAGE_HEADER *pResponse, unsigned size) +{ + (void)size; + pthread_mutex_lock(&mbim_command_mutex); + + if (pResponse) + mbim_dump(pResponse, mbim_verbose); + + if (pResponse == NULL) { + pthread_cond_signal(&mbim_command_cond); + } + else if (mbim_pRequest && le32toh(mbim_pRequest->TransactionId) == le32toh(pResponse->TransactionId)) { + mbim_pResponse = mbim_alloc(le32toh(pResponse->MessageLength)); + if (mbim_pResponse) + memcpy(mbim_pResponse, pResponse, le32toh(pResponse->MessageLength)); + pthread_cond_signal(&mbim_command_cond); + } + else if (le32toh(pResponse->MessageType) == MBIM_INDICATE_STATUS_MSG) { + MBIM_INDICATE_STATUS_MSG_T *pIndMsg = (MBIM_INDICATE_STATUS_MSG_T *)pResponse; + + if (!memcmp(pIndMsg->DeviceServiceId.uuid, str2uuid(UUID_BASIC_CONNECT), 16)) + { + switch (le32toh(pIndMsg->CID)) { + case MBIM_CID_SUBSCRIBER_READY_STATUS: { + MBIM_SUBSCRIBER_READY_STATUS_T *pInfo = (MBIM_SUBSCRIBER_READY_STATUS_T *)pIndMsg->InformationBuffer; + if (oldReadyState != le32toh(pInfo->ReadyState)) + qmidevice_send_event_to_main(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED); + } + break; + case MBIM_CID_REGISTER_STATE: { + MBIM_REGISTRATION_STATE_INFO_T *pInfo = (MBIM_REGISTRATION_STATE_INFO_T *)pIndMsg->InformationBuffer; + if (oldRegisterState != le32toh(pInfo->RegisterState)) + qmidevice_send_event_to_main(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED); + } + break; + case MBIM_CID_PACKET_SERVICE: { + MBIM_PACKET_SERVICE_INFO_T *pInfo = (MBIM_PACKET_SERVICE_INFO_T *)pIndMsg->InformationBuffer; + MBIM_PACKET_SERVICE_STATE_E state = le32toh(pInfo->PacketServiceState); + + if (oldPacketServiceState != state + && (1 || MBIMPacketServiceStateAttached == state || MBIMPacketServiceStateDetached == state)) + qmidevice_send_event_to_main(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED); + } + break; + case MBIM_CID_CONNECT: { + MBIM_CONNECT_T *pInfo = (MBIM_CONNECT_T *)pIndMsg->InformationBuffer; + if (pInfo->SessionId == (uint32_t)mbim_sessionID) { + MBIM_ACTIVATION_STATE_E state = le32toh(pInfo->ActivationState); + + if (oldActivationState != state + && (1 || MBIMActivationStateActivated == state || MBIMActivationStateDeactivated == state)) + qmidevice_send_event_to_main(RIL_UNSOL_DATA_CALL_LIST_CHANGED); + } + } + break; + default: + break; + } + } + } + + pthread_mutex_unlock(&mbim_command_mutex); +} + +static int mbim_send_command(MBIM_MESSAGE_HEADER *pRequest, MBIM_COMMAND_DONE_T **ppCmdDone, unsigned msecs) { + int ret; + + if (ppCmdDone) + *ppCmdDone = NULL; + + if (mbim_fd <= 0) + return -ENODEV; + + if (s_tid_reader == 0) + return -EINVAL; + + if (!pRequest) + return -ENOMEM; + + pthread_mutex_lock(&mbim_command_mutex); + + if (pRequest) { + if (pRequest->TransactionId == (0xFFFFFF + 1)) { //quectel-mbim-proxy need 0xFF000000 to indicat client + TransactionId = 1; + pRequest->TransactionId = htole32(TransactionId++); + } + mbim_dump(pRequest, mbim_verbose); + } + + mbim_pRequest = pRequest; + mbim_pResponse = NULL; + + ret = write(mbim_fd, pRequest, le32toh(pRequest->MessageLength)); + + if (ret > 0 && (uint32_t)ret == le32toh(pRequest->MessageLength)) { + ret = pthread_cond_timeout_np(&mbim_command_cond, &mbim_command_mutex, msecs); + if (!ret) { + if (mbim_pResponse && ppCmdDone) { + *ppCmdDone = (MBIM_COMMAND_DONE_T *)mbim_pResponse; + } + } + } else { + mbim_debug("%s pthread_cond_timeout_np=%d", __func__, ret); + } + + mbim_pRequest = mbim_pResponse = NULL; + + pthread_mutex_unlock(&mbim_command_mutex); + + return ret; +} + +static ssize_t mbim_proxy_read (int fd, MBIM_MESSAGE_HEADER *pResponse, size_t size) { + ssize_t nreads; + + nreads = read(fd, pResponse, sizeof(MBIM_MESSAGE_HEADER)); + if (nreads == sizeof(MBIM_MESSAGE_HEADER) && le32toh(pResponse->MessageLength) <= size) { + nreads += read(fd, pResponse+1, le32toh(pResponse->MessageLength) - sizeof(MBIM_MESSAGE_HEADER)); + } + + return nreads; +} + +static void * mbim_read_thread(void *param) { + PROFILE_T *profile = (PROFILE_T *)param; + const char *cdc_wdm = (const char *)profile->qmichannel; + int wait_for_request_quit = 0; + + mbim_verbose = debug_qmi; + s_tid_reader = pthread_self(); + + if (profile->qmap_mode > 1 && profile->qmapnet_adapter[0]) { + if (!profile->proxy[0]) + sprintf(profile->proxy, "%s", QUECTEL_MBIM_PROXY); + mbim_sessionID = profile->pdp; + } + + if (profile->proxy[0]) { + mbim_fd = cm_open_proxy(profile->proxy); + } + else { + mbim_fd = cm_open_dev(cdc_wdm); + } + + if (mbim_fd <= 0) { + mbim_debug("fail to open (%s), errno: %d (%s)", cdc_wdm, errno, strerror(errno)); + goto __quit; + } + + dbg_time("cdc_wdm_fd = %d", mbim_fd); + + qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_CONNECTED); + + while (mbim_fd > 0) { + struct pollfd pollfds[] = {{mbim_fd, POLLIN, 0}, {qmidevice_control_fd[1], POLLIN, 0}, {qmi_over_mbim_sk[1], POLLIN, 0}}; + int ne, ret, nevents = 2; + + if (pollfds[nevents].fd != -1) + nevents++; + + ret = poll(pollfds, nevents, wait_for_request_quit ? 1000 : -1); + + if (ret == 0 && wait_for_request_quit) { + break; + } + + if (ret < 0) { + mbim_debug("%s poll=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno)); + break; + } + + for (ne = 0; ne < nevents; ne++) { + int fd = pollfds[ne].fd; + short revents = pollfds[ne].revents; + + if (revents & (POLLERR | POLLHUP | POLLNVAL)) { + mbim_debug("%s poll err/hup/inval", __func__); + mbim_debug("epoll fd = %d, events = 0x%04x", fd, revents); + if (revents & (POLLERR | POLLHUP | POLLNVAL)) + goto __quit; + } + + if ((revents & POLLIN) == 0) + continue; + + if (mbim_fd == fd) { + ssize_t nreads; + MBIM_MESSAGE_HEADER *pResponse = (MBIM_MESSAGE_HEADER *) cm_recv_buf; + + if (profile->proxy[0]) + nreads = mbim_proxy_read(fd, pResponse, sizeof(cm_recv_buf)); + else + nreads = read(fd, pResponse, sizeof(cm_recv_buf)); + + if (nreads <= 0) { + mbim_debug("%s read=%d errno: %d (%s)", __func__, (int)nreads, errno, strerror(errno)); + break; + } + + mbim_recv_command(pResponse, nreads); + } + else if (fd == qmidevice_control_fd[1]) { + int triger_event; + if (read(fd, &triger_event, sizeof(triger_event)) == sizeof(triger_event)) { + //mbim_debug("triger_event = 0x%x", triger_event); + switch (triger_event) { + case RIL_REQUEST_QUIT: + goto __quit; + break; + case SIG_EVENT_STOP: + wait_for_request_quit = 1; + break; + default: + break; + } + } + } + else if (fd == qmi_over_mbim_sk[1]) { + ssize_t nreads = read(fd, cm_recv_buf, sizeof(cm_recv_buf)); + if (nreads > 0) + QmiThreadRecvQMI((PQCQMIMSG)cm_recv_buf); + } + } + } + +__quit: + if (mbim_fd != -1) { close(mbim_fd); mbim_fd = -1; } + mbim_recv_command(NULL, 0); + qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED); + mbim_debug("%s exit", __func__); + s_tid_reader = 0; + + return NULL; +} + +static int mbim_status_code(MBIM_MESSAGE_HEADER *pMsgHdr) { + int status = 0; + + if (!pMsgHdr) + return 0; + + switch (le32toh(pMsgHdr->MessageType)) { + case MBIM_OPEN_DONE: { + MBIM_OPEN_DONE_T *pOpenDone = (MBIM_OPEN_DONE_T *)pMsgHdr; + status = le32toh(pOpenDone->Status); + } + break; + case MBIM_CLOSE_DONE: { + MBIM_CLOSE_DONE_T *pCloseDone = (MBIM_CLOSE_DONE_T *)pMsgHdr; + status = le32toh(pCloseDone->Status); + } + break; + case MBIM_COMMAND_DONE: { + MBIM_COMMAND_DONE_T *pCmdDone = (MBIM_COMMAND_DONE_T *)pMsgHdr; + status = le32toh(pCmdDone->Status); + } + break; + case MBIM_FUNCTION_ERROR_MSG: { + MBIM_FUNCTION_ERROR_MSG_T *pErrMsg = (MBIM_FUNCTION_ERROR_MSG_T *)pMsgHdr; + status = le32toh(pErrMsg->ErrorStatusCode); + if (status == MBIM_ERROR_NOT_OPENED) + mbim_open_state = 0; //EM06ELAR03A05M4G when suspend/resume, may get this error + } + break; + default: + break; + } + + return status; +} + +#define mbim_check_err(err, pRequest, pCmdDone) do { \ + int _status = mbim_status_code(pCmdDone ? &pCmdDone->MessageHeader : NULL); \ + if (err || _status || !pCmdDone) { \ + if (pCmdDone) { mbim_dump(&pCmdDone->MessageHeader, (mbim_verbose == 0)); } \ + mbim_free(pRequest); mbim_free(pCmdDone); \ + mbim_debug("%s:%d err=%d, Status=%d", __func__, __LINE__, err, _status); \ + if (err) return err; \ + if (_status) return _status; \ + return 8888; \ + } \ +} while(0) + +/* + * MBIM device can be open repeatly without error + * So, we can call the function, no matter it have been opened or not + */ +static int mbim_open_device(uint32_t MaxControlTransfer) { + MBIM_MESSAGE_HEADER *pRequest = NULL; + MBIM_OPEN_DONE_T *pOpenDone = NULL; + int err = 0; + + mbim_debug("%s()", __func__); + pRequest = compose_open_command(MaxControlTransfer); + err = mbim_send_command(pRequest, (MBIM_COMMAND_DONE_T **)&pOpenDone, 3*1000); //EM06ELAR03A09M4G take about 2.5 seconds + mbim_check_err(err, pRequest, pOpenDone); + + err = le32toh(pOpenDone->Status); + mbim_free(pRequest); mbim_free(pOpenDone); + + return err; +} + +static int mbim_close_device(void) { + MBIM_MESSAGE_HEADER *pRequest = NULL; + MBIM_CLOSE_DONE_T *pCloseDone = NULL; + int err = 0; + + mbim_debug("%s()", __func__); + pRequest = compose_close_command(); + err = mbim_send_command(pRequest, (MBIM_COMMAND_DONE_T **)&pCloseDone, mbim_default_timeout); + mbim_check_err(err, pRequest, pCloseDone); + + err = le32toh(pCloseDone->Status); + mbim_free(pRequest); mbim_free(pCloseDone); + + return err; +} + +static int mbim_query_connect(int sessionID) { + MBIM_MESSAGE_HEADER *pRequest = NULL; + MBIM_COMMAND_DONE_T *pCmdDone = NULL; + MBIM_SET_CONNECT_T set_connect; + int err; + + if (ActivationState != MBIMActivationStateActivated || mbim_verbose) + mbim_debug("%s(sessionID=%d)", __func__, sessionID); //avoid two many log + set_connect.SessionId = htole32(sessionID); + pRequest = compose_basic_connect_command(MBIM_CID_CONNECT, MBIM_CID_CMD_TYPE_QUERY, &set_connect, sizeof(set_connect)); + err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); + mbim_check_err(err, pRequest, pCmdDone); + + if (le32toh(pCmdDone->InformationBufferLength)) + { + MBIM_CONNECT_T *pInfo = (MBIM_CONNECT_T *)pCmdDone->InformationBuffer; + ActivationState = le32toh(pInfo->ActivationState); + mbim_update_state(); + } + mbim_free(pRequest); mbim_free(pCmdDone); + return err; +} + +static int mbim_ms_version_query(void) { + MBIM_MESSAGE_HEADER *pRequest = NULL; + MBIM_COMMAND_DONE_T *pCmdDone = NULL; + int err; + + struct _bc_ext_version { + UINT8 ver_minor; + UINT8 ver_major; + UINT8 ext_ver_minor; + UINT8 ext_ver_major; + } __attribute__ ((packed)) bc_ext_version; + + bc_ext_version.ver_major = 1; + bc_ext_version.ver_minor = 0; + bc_ext_version.ext_ver_major = 2; + bc_ext_version.ext_ver_minor = 0; + + pRequest = compose_basic_connect_ext_command(MBIM_CID_MS_VERSION, MBIM_CID_CMD_TYPE_QUERY, &bc_ext_version, sizeof(bc_ext_version)); + err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); + mbim_check_err(err, pRequest, pCmdDone); + + if (le32toh(pCmdDone->InformationBufferLength)) { + struct _bc_ext_version *pInfo = (struct _bc_ext_version *)pCmdDone->InformationBuffer; + //mbim_debug("%s ext_rel_ver major=%d, minor=%d", __func__, pInfo->ext_ver_major, pInfo->ext_ver_minor); + mbim_ms_version = pInfo->ext_ver_major; + } + + mbim_free(pRequest); mbim_free(pCmdDone); + return err; +} + +static int mbim_device_services_query(void) { + MBIM_MESSAGE_HEADER *pRequest = NULL; + MBIM_COMMAND_DONE_T *pCmdDone = NULL; + int err; + int mbim_v2_support = 0; + + mbim_debug("%s()", __func__); + pRequest = compose_basic_connect_command(MBIM_CID_DEVICE_SERVICES, MBIM_CID_CMD_TYPE_QUERY, NULL, 0); + err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); + mbim_check_err(err, pRequest, pCmdDone); + + if (pCmdDone->InformationBufferLength) { + MBIM_DEVICE_SERVICES_INFO_T *pInfo = (MBIM_DEVICE_SERVICES_INFO_T *)pCmdDone->InformationBuffer; + UINT32 i; + + for (i = 0; i < le32toh(pInfo->DeviceServicesCount) ; i++) { + //UINT32 size = pInfo->DeviceServicesRefList[i].size; + UINT32 offset = le32toh(pInfo->DeviceServicesRefList[i].offset); + MBIM_DEVICE_SERVICE_ELEMENT_T *pSrvEle = (MBIM_DEVICE_SERVICE_ELEMENT_T *)((void *)pInfo + offset); + + //mbim_debug("\t[%2d] %s (%s)", i, DeviceServiceId2str(&pSrvEle->DeviceServiceId), uuid2str(&pSrvEle->DeviceServiceId)); + if (!strcasecmp(UUID_BASIC_CONNECT_EXT, uuid2str(&pSrvEle->DeviceServiceId))) { + UINT32 cid = 0; + + for (cid = 0; cid < le32toh(pSrvEle->CidCount); cid++) { + if (MBIM_CID_MS_VERSION == le32toh(pSrvEle->CidList[cid])) { + mbim_v2_support = 1; + } + } + } + else if (!strcasecmp(uuid_ext_qmux, uuid2str(&pSrvEle->DeviceServiceId))) { + qmi_over_mbim_support = 1; + } + } + } + mbim_free(pRequest); mbim_free(pCmdDone); + + if (mbim_v2_support) { + mbim_ms_version_query(); + } + + return err; +} + +static int mbim_device_caps_query(PROFILE_T *profile) { + MBIM_MESSAGE_HEADER *pRequest = NULL; + MBIM_COMMAND_DONE_T *pCmdDone = NULL; + int err; + + mbim_debug("%s()", __func__); + pRequest = compose_basic_connect_command(MBIM_CID_DEVICE_CAPS, MBIM_CID_CMD_TYPE_QUERY, NULL, 0); + err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); + mbim_check_err(err, pRequest, pCmdDone); + + if (le32toh(pCmdDone->InformationBufferLength)) { + MBIM_DEVICE_CAPS_INFO_T *pInfo = (MBIM_DEVICE_CAPS_INFO_T *)pCmdDone->InformationBuffer; + char tmp[32]; + + if (le32toh(pInfo->DeviceIdOffset) && le32toh(pInfo->DeviceIdSize)) { + wchar2char((const char *)pInfo + le32toh(pInfo->DeviceIdOffset), le32toh(pInfo->DeviceIdSize), tmp, sizeof(tmp)); + mbim_debug("DeviceId: %s", tmp); + } + if (le32toh(pInfo->FirmwareInfoOffset) && le32toh(pInfo->FirmwareInfoSize)) { + wchar2char((const char *)pInfo + le32toh(pInfo->FirmwareInfoOffset), le32toh(pInfo->FirmwareInfoSize), tmp, sizeof(tmp)); + strncpy(profile->BaseBandVersion, tmp, sizeof(profile->BaseBandVersion)); + mbim_debug("FirmwareInfo: %s", tmp); + } + if (le32toh(pInfo->HardwareInfoOffset) && le32toh(pInfo->HardwareInfoSize)) { + wchar2char((const char *)pInfo + le32toh(pInfo->HardwareInfoOffset), le32toh(pInfo->HardwareInfoSize), tmp, sizeof(tmp)); + mbim_debug("HardwareInfo: %s", tmp); + } + } + mbim_free(pRequest); mbim_free(pCmdDone); + return err; +} + +#if 0 +static int mbim_radio_state_query(void) { + MBIM_MESSAGE_HEADER *pRequest = NULL; + MBIM_COMMAND_DONE_T *pCmdDone = NULL; + int err; + + mbim_debug("%s()", __func__); + pRequest = compose_basic_connect_command(MBIM_CID_RADIO_STATE, MBIM_CID_CMD_TYPE_QUERY, NULL, 0); + err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); + mbim_check_err(err, pRequest, pCmdDone); + + if (pCmdDone->InformationBufferLength) { + MBIM_RADIO_STATE_INFO_T *pInfo = (MBIM_RADIO_STATE_INFO_T *)pCmdDone->InformationBuffer; + mbim_debug("HwRadioState: %d, SwRadioState: %d", pInfo->HwRadioState, pInfo->SwRadioState); + } + mbim_free(pRequest); mbim_free(pCmdDone); + return err; +} +#endif + +static int mbim_set_radio_state(MBIM_RADIO_SWITCH_STATE_E RadioState) { + MBIM_MESSAGE_HEADER *pRequest = NULL; + MBIM_COMMAND_DONE_T *pCmdDone = NULL; + UINT32 value = htole32(RadioState); + int err; + + mbim_debug("%s( %d )", __func__, RadioState); + pRequest = compose_basic_connect_command(MBIM_CID_RADIO_STATE, MBIM_CID_CMD_TYPE_SET, &value, sizeof(value)); + err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); + mbim_check_err(err, pRequest, pCmdDone); + + if (le32toh(pCmdDone->InformationBufferLength)) { + MBIM_RADIO_STATE_INFO_T *pInfo = (MBIM_RADIO_STATE_INFO_T *)pCmdDone->InformationBuffer; + mbim_debug("HwRadioState: %d, SwRadioState: %d", le32toh(pInfo->HwRadioState), le32toh(pInfo->SwRadioState)); + } + mbim_free(pRequest); mbim_free(pCmdDone); + return err; +} + +static int mbim_subscriber_status_query(void) { + MBIM_MESSAGE_HEADER *pRequest = NULL; + MBIM_COMMAND_DONE_T *pCmdDone = NULL; + int err; + + mbim_debug("%s()", __func__); + pRequest = compose_basic_connect_command(MBIM_CID_SUBSCRIBER_READY_STATUS, MBIM_CID_CMD_TYPE_QUERY, NULL, 0); + err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); + mbim_check_err(err, pRequest, pCmdDone); + + if (le32toh(pCmdDone->InformationBufferLength)) { + MBIM_SUBSCRIBER_READY_STATUS_T *pInfo = (MBIM_SUBSCRIBER_READY_STATUS_T *)pCmdDone->InformationBuffer; + char tmp[32]; + + wchar2char((const char *)pInfo + le32toh(pInfo->SubscriberIdOffset), le32toh(pInfo->SubscriberIdSize), tmp, sizeof(tmp)); + mbim_debug("SubscriberId: %s", tmp); + wchar2char((const char *)pInfo + le32toh(pInfo->SimIccIdOffset), le32toh(pInfo->SimIccIdSize), tmp, sizeof(tmp)); + mbim_debug("SimIccId: %s", tmp); + ReadyState = le32toh(pInfo->ReadyState); + mbim_update_state(); + } + mbim_free(pRequest); mbim_free(pCmdDone); + return err; +} + +static int mbim_register_state_query(void) { + MBIM_MESSAGE_HEADER *pRequest = NULL; + MBIM_COMMAND_DONE_T *pCmdDone = NULL; + int err; + + mbim_debug("%s()", __func__); + pRequest = compose_basic_connect_command(MBIM_CID_REGISTER_STATE, MBIM_CID_CMD_TYPE_QUERY, NULL, 0); + err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); + mbim_check_err(err, pRequest, pCmdDone); + + if (le32toh(pCmdDone->InformationBufferLength)) { + MBIM_REGISTRATION_STATE_INFO_T *pInfo = (MBIM_REGISTRATION_STATE_INFO_T *)pCmdDone->InformationBuffer;; + RegisterState = le32toh(pInfo->RegisterState); + mbim_update_state(); + } + mbim_free(pRequest); mbim_free(pCmdDone); + return err; +} + +static int mbim_packet_service_query(void) { + MBIM_MESSAGE_HEADER *pRequest = NULL; + MBIM_COMMAND_DONE_T *pCmdDone = NULL; + int err; + + mbim_debug("%s()", __func__); + pRequest = compose_basic_connect_command(MBIM_CID_PACKET_SERVICE, MBIM_CID_CMD_TYPE_QUERY, NULL, 0); + err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); + mbim_check_err(err, pRequest, pCmdDone); + + if (le32toh(pCmdDone->InformationBufferLength)) { + MBIM_PACKET_SERVICE_INFO_T *pInfo = (MBIM_PACKET_SERVICE_INFO_T *)pCmdDone->InformationBuffer; + PacketServiceState = le32toh(pInfo->PacketServiceState); + mbim_update_state(); + + if (le32toh(pCmdDone->InformationBufferLength) == sizeof(MBIM_PACKET_SERVICE_INFO_V2_T)) { + MBIM_PACKET_SERVICE_INFO_V2_T *pInfo = (MBIM_PACKET_SERVICE_INFO_V2_T *)pCmdDone->InformationBuffer; + mbim_debug("CurrentDataClass = %s", MBIMDataClassStr(le32toh(pInfo->CurrentDataClass))); + } + } + mbim_free(pRequest); mbim_free(pCmdDone); + return err; +} + +static int mbim_packet_service_set(MBIM_PACKET_SERVICE_ACTION_E action) { + MBIM_MESSAGE_HEADER *pRequest = NULL; + MBIM_COMMAND_DONE_T *pCmdDone = NULL; + UINT32 value = htole32(action); + int err; + + mbim_debug("%s()", __func__); + pRequest = compose_basic_connect_command(MBIM_CID_PACKET_SERVICE, MBIM_CID_CMD_TYPE_SET, &value, sizeof(value)); + err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); + mbim_check_err(err, pRequest, pCmdDone); + + if (le32toh(pCmdDone->InformationBufferLength)) { + MBIM_PACKET_SERVICE_INFO_T *pInfo = (MBIM_PACKET_SERVICE_INFO_T *)pCmdDone->InformationBuffer; + PacketServiceState = le32toh(pInfo->PacketServiceState); + mbim_update_state(); + } + mbim_free(pRequest); mbim_free(pCmdDone); + return err; +} + +#define _align_32(len) {len += (len % 4) ? (4 - (len % 4)) : 0;} +static int mbim_populate_connect_data(MBIM_SET_CONNECT_T **connect_req_ptr) { + int offset; + int buflen = 0; + + if (mbim_apn && strlen(mbim_apn) > 0) buflen += 2*strlen(mbim_apn) ; + _align_32(buflen); + if (mbim_user && strlen(mbim_user) > 0) buflen += 2*strlen(mbim_user); + _align_32(buflen); + if (mbim_passwd && strlen(mbim_passwd) > 0) buflen += 2*strlen(mbim_passwd); + _align_32(buflen); + + *connect_req_ptr = (MBIM_SET_CONNECT_T*)malloc(sizeof(MBIM_SET_CONNECT_T) + buflen); + if (! *connect_req_ptr) { + mbim_debug("not enough memory\n"); + return -1; + } + memset(*connect_req_ptr, 0, sizeof(MBIM_SET_CONNECT_T) + buflen); + + offset = 0; + if (mbim_apn && strlen(mbim_apn) > 0) { + (*connect_req_ptr)->AccessStringSize = htole32(2*strlen(mbim_apn)); + (*connect_req_ptr)->AccessStringOffset = htole32(offset + sizeof(MBIM_SET_CONNECT_T)); + offset = char2wchar(mbim_apn, strlen(mbim_apn), &(*connect_req_ptr)->DataBuffer[offset], buflen - offset); + _align_32(offset); + } + + if (mbim_user && strlen(mbim_user) > 0) { + (*connect_req_ptr)->UserNameSize = htole32(2*strlen(mbim_user)); + (*connect_req_ptr)->UserNameOffset = htole32(offset + sizeof(MBIM_SET_CONNECT_T)); + offset = char2wchar(mbim_user, strlen(mbim_user), &(*connect_req_ptr)->DataBuffer[offset], buflen - offset); + _align_32(offset); + } + + if (mbim_passwd && strlen(mbim_passwd) > 0) { + (*connect_req_ptr)->PasswordSize = htole32(2*strlen(mbim_passwd)); + (*connect_req_ptr)->PasswordOffset = htole32(offset + sizeof(MBIM_SET_CONNECT_T)); + offset = char2wchar(mbim_passwd, strlen(mbim_passwd), &(*connect_req_ptr)->DataBuffer[offset], buflen - offset); + } + + return buflen; +} + +static int mbim_set_connect(int onoff, int sessionID) { + MBIM_MESSAGE_HEADER *pRequest = NULL; + MBIM_COMMAND_DONE_T *pCmdDone = NULL; + MBIM_SET_CONNECT_T *set_connect = NULL; + int err; + + mbim_debug("%s(onoff=%d, sessionID=%d)", __func__, onoff, sessionID); + /* alloc memory then populate APN USERNAME PASSWORD */ + int buflen = mbim_populate_connect_data(&set_connect); + if (buflen < 0) { + return ENOMEM; + } + + set_connect->SessionId = htole32(sessionID); + if (onoff == 0) + set_connect->ActivationCommand = htole32(MBIMActivationCommandDeactivate); + else + set_connect->ActivationCommand = htole32(MBIMActivationCommandActivate); + + set_connect->Compression = htole32(MBIMCompressionNone); + set_connect->AuthProtocol = htole32(mbim_auth); + set_connect->IPType = htole32(mbim_iptype); + memcpy(set_connect->ContextType.uuid, str2uuid(UUID_MBIMContextTypeInternet), 16); + + pRequest = compose_basic_connect_command(MBIM_CID_CONNECT, MBIM_CID_CMD_TYPE_SET, set_connect, sizeof(MBIM_SET_CONNECT_T) + buflen); + mbim_free(set_connect); + err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout*10); + mbim_check_err(err, pRequest, pCmdDone); + + if (le32toh(pCmdDone->InformationBufferLength)) { + MBIM_CONNECT_T *pInfo = (MBIM_CONNECT_T *)pCmdDone->InformationBuffer; + ActivationState = le32toh(pInfo->ActivationState); + mbim_update_state(); + } + + mbim_free(pRequest); mbim_free(pCmdDone); + return err; +} + +static int mbim_ip_config(PROFILE_T *profile, int sessionID) { + MBIM_MESSAGE_HEADER *pRequest = NULL; + MBIM_COMMAND_DONE_T *pCmdDone = NULL; + MBIM_IP_CONFIGURATION_INFO_T ip_info; + int err; + + if (profile->ipv4.Address == 0 || mbim_verbose) + mbim_debug("%s(sessionID=%d)", __func__, sessionID); + ip_info.SessionId = htole32(sessionID); + pRequest = compose_basic_connect_command(MBIM_CID_IP_CONFIGURATION, MBIM_CID_CMD_TYPE_QUERY, &ip_info, sizeof(ip_info)); + err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); + mbim_check_err(err, pRequest, pCmdDone); + + if (le32toh(pCmdDone->InformationBufferLength)) { + UINT8 prefix, *ipv4=NULL, *ipv6=NULL, *gw=NULL, *dns1=NULL, *dns2=NULL; + UINT32 mtu = 1500; + MBIM_IP_CONFIGURATION_INFO_T *pInfo = (MBIM_IP_CONFIGURATION_INFO_T *)pCmdDone->InformationBuffer; + + /* IPv4 network configration */ + if (le32toh(pInfo->IPv4ConfigurationAvailable)&0x1) { + MBIM_IPV4_ELEMENT_T *pAddress = (MBIM_IPV4_ELEMENT_T *)(&pInfo->DataBuffer[le32toh(pInfo->IPv4AddressOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); + prefix = le32toh(pAddress->OnLinkPrefixLength); + ipv4 = pAddress->IPv4Address; + + if (le32toh(pInfo->IPv4ConfigurationAvailable)&0x2) + gw = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv4GatewayOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); + + if (le32toh(pInfo->IPv4ConfigurationAvailable)&0x4) { + dns1 = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv4DnsServerOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); + if (le32toh(pInfo->IPv4DnsServerCount) == 2) + dns2 = dns1 + 4; + } + + if (le32toh(pInfo->IPv4ConfigurationAvailable)&0x8) + mtu = le32toh(pInfo->IPv4Mtu); + + if (profile->ipv4.Address != mbim2qmi_ipv4addr(*(uint32_t *)ipv4) || mbim_verbose) { + mbim_dump_ipconfig(pInfo, "<"); + profile->ipv4.Address = mbim2qmi_ipv4addr(*(uint32_t *)ipv4); + } + + if(gw != NULL) + profile->ipv4.Gateway = mbim2qmi_ipv4addr(*(uint32_t *)gw); + profile->ipv4.SubnetMask = mbim2qmi_ipv4addr(0xFFFFFFFF>>(32-prefix)<<(32-prefix)); + if(dns1 != NULL) + profile->ipv4.DnsPrimary = mbim2qmi_ipv4addr(*(uint32_t *)dns1); + if(dns2 != NULL) + profile->ipv4.DnsSecondary = mbim2qmi_ipv4addr(*(uint32_t *)dns2); + profile->ipv4.Mtu = mbim2qmi_ipv4addr(mtu); + } + + /* IPv6 network configration */ + if (le32toh(pInfo->IPv6ConfigurationAvailable)&0x1) { + gw = NULL; dns1 = NULL; dns2 = NULL; + MBIM_IPV6_ELEMENT_T *pAddress = (MBIM_IPV6_ELEMENT_T *)(&pInfo->DataBuffer[le32toh(pInfo->IPv6AddressOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); + prefix = le32toh(pAddress->OnLinkPrefixLength); + ipv6 = pAddress->IPv6Address; + + if (le32toh(pInfo->IPv6ConfigurationAvailable)&0x2) + gw = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv6GatewayOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); + + if (le32toh(pInfo->IPv6ConfigurationAvailable)&0x4) { + dns1 = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv6DnsServerOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]); + if (le32toh(pInfo->IPv6DnsServerCount) == 2) + dns2 = dns1 + 16; + } + + if (le32toh(pInfo->IPv6ConfigurationAvailable)&0x8) + mtu = le32toh(pInfo->IPv6Mtu); + + if(ipv6 != NULL) + mbim2qmi_ipv6addr(ipv6, profile->ipv6.Address); + if(gw != NULL) + mbim2qmi_ipv6addr(gw, profile->ipv6.Gateway); + if(dns1 != NULL) + mbim2qmi_ipv6addr(dns1, profile->ipv6.DnsPrimary); + if(dns2 != NULL) + mbim2qmi_ipv6addr(dns2, profile->ipv6.DnsSecondary); + profile->ipv6.PrefixLengthIPAddr = prefix; + profile->ipv6.PrefixLengthGateway = prefix; + profile->ipv6.Mtu = mbim2qmi_ipv4addr(mtu); + } + } + return err; +} + +int mbim_proxy_configure(const char *dev) { + MBIM_MESSAGE_HEADER *pRequest = NULL; + MBIM_COMMAND_DONE_T *pCmdDone = NULL; + MBIM_LIBQMI_PROXY_CONFIG_T *cfg; + int err; + + pRequest = compose_basic_connect_command( + MBIM_CID_PROXY_CONTROL_CONFIGURATION, + MBIM_CID_CMD_TYPE_SET, + NULL, + sizeof(*cfg) + strlen(dev)*2); + if (pRequest) { + memcpy(((MBIM_COMMAND_MSG_T *)pRequest)->DeviceServiceId.uuid, str2uuid(UUID_LIBMBIM_PROXY), 16); + cfg = (MBIM_LIBQMI_PROXY_CONFIG_T *)((MBIM_COMMAND_MSG_T *)pRequest)->InformationBuffer; + + cfg->DevicePathOffset = sizeof(*cfg); + cfg->DevicePathSize = char2wchar(dev, strlen(dev), cfg->DataBuffer, strlen(dev)*2); + cfg->Timeout = 15; + } + + err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); + mbim_check_err(err, pRequest, pCmdDone); + + mbim_free(pRequest); mbim_free(pCmdDone); + return err; +} + +static int mbim_update_state(void) { + int chages = 0; + + if (oldReadyState != ReadyState) { + mbim_debug("SubscriberReadyState %s -> %s ", MBIMSubscriberReadyStateStr(oldReadyState), MBIMSubscriberReadyStateStr(ReadyState)); + oldReadyState = ReadyState; chages++; + } + if (oldRegisterState != RegisterState) { + mbim_debug("RegisterState %s -> %s ", MBIMRegisterStateStr(oldRegisterState), MBIMRegisterStateStr(RegisterState)); + oldRegisterState = RegisterState; chages++; + } + if (oldPacketServiceState != PacketServiceState) { + mbim_debug("PacketServiceState %s -> %s ", MBIMPacketServiceStateStr(oldPacketServiceState), MBIMPacketServiceStateStr(PacketServiceState)); + oldPacketServiceState = PacketServiceState; chages++; + } + if (oldActivationState != ActivationState) { + mbim_debug("ActivationState %s -> %s ", MBIMActivationStateStr(oldActivationState), MBIMActivationStateStr(ActivationState)); + oldActivationState = ActivationState; chages++; + } + + return chages; +} + +static int mbim_init(PROFILE_T *profile) { + int retval; + int t = 0; + + if (profile->proxy[0] && !strcmp(profile->proxy, LIBMBIM_PROXY)) { + retval = mbim_proxy_configure(profile->qmichannel); + if (retval) goto exit; + } + + while (t++ < 10) { + retval = mbim_open_device(4096); + if (retval != ETIMEDOUT) + break; + } + if (retval) goto exit; + retval = mbim_device_caps_query(profile); + if (retval) goto exit; + mbim_update_state(); + retval = mbim_device_services_query(); + if (retval) goto exit; + mbim_update_state(); + retval = mbim_set_radio_state(MBIMRadioOn); + if (retval) goto exit; + mbim_update_state(); + + if (qmi_over_mbim_support) { + if (!socketpair( AF_LOCAL, SOCK_STREAM, 0, qmi_over_mbim_sk)) { + qmidev_send = qmi_over_mbim_qmidev_send; +#ifdef CONFIG_CELLINFO //by now, only this function need QMI OVER MBIM + qmi_over_mbim_nas = qmi_over_mbim_get_client_id(QMUX_TYPE_NAS); +#endif + } + } + + return 0; + +exit: + return retval; +} + +static int mbim_deinit(void) { + if (qmi_over_mbim_nas) { + qmi_over_mbim_release_client_id(QMUX_TYPE_NAS, qmi_over_mbim_nas); + qmi_over_mbim_nas = 0; + } + + mbim_close_device(); + + if (qmi_over_mbim_sk[0] != -1) { + close(qmi_over_mbim_sk[0]); + close(qmi_over_mbim_sk[1]); + } + + return 0; +} + +const struct qmi_device_ops mbim_dev_ops = { + .init = mbim_init, + .deinit = mbim_deinit, + .read = mbim_read_thread, +}; + +static int requestBaseBandVersion(PROFILE_T *profile) { + (void)profile; + return 0; +} + +static int requestGetSIMStatus(SIM_Status *pSIMStatus) +{ + int retval; + + *pSIMStatus = SIM_ABSENT; + retval = mbim_subscriber_status_query(); + if (retval) + goto exit; + mbim_update_state(); + + switch(ReadyState) { + case MBIMSubscriberReadyStateNotInitialized: *pSIMStatus = SIM_NOT_READY; break; + case MBIMSubscriberReadyStateInitialized: *pSIMStatus = SIM_READY; break; + case MBIMSubscriberReadyStateSimNotInserted: *pSIMStatus = SIM_ABSENT; break; + case MBIMSubscriberReadyStateBadSim: *pSIMStatus = SIM_BAD; break; + case MBIMSubscriberReadyStateFailure: *pSIMStatus = SIM_ABSENT; break; + case MBIMSubscriberReadyStateNotActivated: *pSIMStatus = SIM_ABSENT; break; + case MBIMSubscriberReadyStateDeviceLocked: *pSIMStatus = SIM_PIN; break; + default: *pSIMStatus = SIM_ABSENT; break; + } + +exit: + return retval; +} + +static int requestRegistrationState(UCHAR *pPSAttachedState) { + int retval; + + *pPSAttachedState = 0; + retval = mbim_register_state_query(); + if (retval) + goto exit; + mbim_update_state(); + + switch (RegisterState) { + case MBIMRegisterStateUnknown: *pPSAttachedState = 0; break; + case MBIMRegisterStateDeregistered: *pPSAttachedState = 0; break; + case MBIMRegisterStateSearching: *pPSAttachedState = 0; break; + case MBIMRegisterStateHome: *pPSAttachedState = 1; break; + case MBIMRegisterStateRoaming: *pPSAttachedState = 1; break; + case MBIMRegisterStatePartner: *pPSAttachedState = 0; break; + case MBIMRegisterStateDenied: *pPSAttachedState = 0; break; + default: *pPSAttachedState = 0; break; + } + + if (*pPSAttachedState == 0) + goto exit; + + retval = mbim_packet_service_query(); + if (retval) + goto exit; + + switch (PacketServiceState) { + case MBIMPacketServiceStateUnknown: *pPSAttachedState = 0; break; + case MBIMPacketServiceStateAttaching: *pPSAttachedState = 0; break; + case MBIMPacketServiceStateAttached: *pPSAttachedState = 1; break; + case MBIMPacketServiceStateDetaching: *pPSAttachedState = 0; break; + case MBIMPacketServiceStateDetached: *pPSAttachedState = 0; break; + default: *pPSAttachedState = 0; break; + } + + if (*pPSAttachedState == 0) + mbim_packet_service_set(MBIMPacketServiceActionAttach); + +exit: + return retval; +} + +static int requestSetupDataCall(PROFILE_T *profile, int curIpFamily) { + int retval; + + (void)curIpFamily; + + if (profile->apn) + mbim_apn = profile->apn; + if (profile->user) + mbim_user = profile->user; + if (profile->password) + mbim_passwd = profile->password; + if (profile->auth) + mbim_auth = profile->auth; + if (profile->enable_ipv4) + mbim_iptype = MBIMContextIPTypeIPv4; + if (profile->enable_ipv6) + mbim_iptype = MBIMContextIPTypeIPv6; + if (profile->enable_ipv4 && profile->enable_ipv6) + mbim_iptype = MBIMContextIPTypeIPv4AndIPv6; + + retval = mbim_set_connect(1, mbim_sessionID); + if (retval) + goto exit; + +exit: + return retval; +} + +static int requestQueryDataCall(UCHAR *pConnectionStatus, int curIpFamily) { + int retval; + + (void)curIpFamily; + + *pConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; + + retval = mbim_query_connect(mbim_sessionID); + if (retval) + goto exit; + + switch(ActivationState) { + case MBIMActivationStateUnknown: *pConnectionStatus = QWDS_PKT_DATA_UNKNOW; break; + case MBIMActivationStateActivated: *pConnectionStatus = QWDS_PKT_DATA_CONNECTED; break; + case MBIMActivationStateActivating: *pConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; break; + case MBIMActivationStateDeactivated: *pConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; break; + case MBIMActivationStateDeactivating: *pConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; break; + default: *pConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; break; + } + +exit: + return retval; +} + +static int requestDeactivateDefaultPDP(PROFILE_T *profile, int curIpFamily) { + int retval; + + (void)profile; + (void)curIpFamily; + + retval = mbim_set_connect(0, mbim_sessionID); + if (retval) + goto exit; + +exit: + return retval; +} + +static int requestGetIPAddress(PROFILE_T *profile, int curIpFamily) { + int retval; + + (void)curIpFamily; + retval = mbim_ip_config(profile, mbim_sessionID); + if (retval) + goto exit; + +exit: + return retval; +} + +#ifdef CONFIG_CELLINFO +static int requestGetCellInfoList(void) { + if (qmi_over_mbim_nas) { + if (qmi_request_ops.requestGetCellInfoList) + return qmi_request_ops.requestGetCellInfoList(); + } + + return 0; +} +#endif + +const struct request_ops mbim_request_ops = { + .requestBaseBandVersion = requestBaseBandVersion, + .requestGetSIMStatus = requestGetSIMStatus, + .requestRegistrationState = requestRegistrationState, + .requestSetupDataCall = requestSetupDataCall, + .requestQueryDataCall = requestQueryDataCall, + .requestDeactivateDefaultPDP = requestDeactivateDefaultPDP, + .requestGetIPAddress = requestGetIPAddress, +#ifdef CONFIG_CELLINFO + .requestGetCellInfoList = requestGetCellInfoList, +#endif +}; + +int qmi_over_mbim_qmidev_send(PQCQMIMSG pQMI) { + MBIM_MESSAGE_HEADER *pRequest = NULL; + MBIM_COMMAND_DONE_T *pCmdDone = NULL; + int err; + size_t len = le16toh(pQMI->QMIHdr.Length) + 1; + + if (pQMI->QMIHdr.QMIType != QMUX_TYPE_CTL) { + if (pQMI->QMIHdr.QMIType == QMUX_TYPE_NAS) + pQMI->QMIHdr.ClientId = qmi_over_mbim_nas; + + if (pQMI->QMIHdr.ClientId == 0) { + dbg_time("QMIType %d has no clientID", pQMI->QMIHdr.QMIType); + return -ENODEV; + } + } + + pRequest = compose_qmi_over_mbim_command(1, MBIM_CID_CMD_TYPE_SET, pQMI, len); + err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout); + mbim_check_err(err, pRequest, pCmdDone); + + err = -1; + len = le32toh(pCmdDone->InformationBufferLength); + if (len) { + if (write(qmi_over_mbim_sk[0], pCmdDone->InformationBuffer, len) == (long)len) { + err = 0; + }; + } + + mbim_free(pRequest); mbim_free(pCmdDone); + return err; +} diff --git a/wwan/app/quectel_cm_5G/src/qendian.h b/wwan/app/quectel-cm/src/qendian.h similarity index 98% rename from wwan/app/quectel_cm_5G/src/qendian.h rename to wwan/app/quectel-cm/src/qendian.h index ba9b766..5e99d5f 100644 --- a/wwan/app/quectel_cm_5G/src/qendian.h +++ b/wwan/app/quectel-cm/src/qendian.h @@ -1,7 +1,7 @@ -#ifndef __QUECTEL_ENDIAN_H__ -#define __QUECTEL_ENDIAN_H__ -#include - +#ifndef __QUECTEL_ENDIAN_H__ +#define __QUECTEL_ENDIAN_H__ +#include + #ifndef htole32 #if __BYTE_ORDER == __LITTLE_ENDIAN #define htole16(x) (uint16_t)(x) @@ -36,17 +36,17 @@ static __inline uint64_t __bswap64(uint64_t __x) { #define le64toh(x) __bswap64(x) #define letoh64(x) __bswap64(x) #endif -#endif - -#define le16_to_cpu(x) le16toh((uint16_t)(x)) -#define le32_to_cpu(x) le32toh((uint32_t)(x)) -#define le64_to_cpu(x) le64toh((uint64_t)(x)) -#define cpu_to_le16(x) htole16((uint16_t)(x)) -#define cpu_to_le32(x) htole32((uint32_t)(x)) -#define cpu_to_le64(x) htole64((uint64_t)(x)) - -static __inline uint32_t ql_swap32(uint32_t __x) { +#endif + +#define le16_to_cpu(x) le16toh((uint16_t)(x)) +#define le32_to_cpu(x) le32toh((uint32_t)(x)) +#define le64_to_cpu(x) le64toh((uint64_t)(x)) +#define cpu_to_le16(x) htole16((uint16_t)(x)) +#define cpu_to_le32(x) htole32((uint32_t)(x)) +#define cpu_to_le64(x) htole64((uint64_t)(x)) + +static __inline uint32_t ql_swap32(uint32_t __x) { return (__x>>24) | (__x>>8&0xff00) | (__x<<8&0xff0000) | (__x<<24); -} -#endif //__QUECTEL_ENDIAN_H__ - +} +#endif //__QUECTEL_ENDIAN_H__ + diff --git a/wwan/app/quectel_cm_5G/src/qlist.h b/wwan/app/quectel-cm/src/qlist.h similarity index 98% rename from wwan/app/quectel_cm_5G/src/qlist.h rename to wwan/app/quectel-cm/src/qlist.h index 4fe86ba..c7f95cf 100644 --- a/wwan/app/quectel_cm_5G/src/qlist.h +++ b/wwan/app/quectel-cm/src/qlist.h @@ -1,6 +1,6 @@ -#ifndef __QUECTEL_LIST_H__ -#define __QUECTEL_LIST_H__ -struct qlistnode +#ifndef __QUECTEL_LIST_H__ +#define __QUECTEL_LIST_H__ +struct qlistnode { struct qlistnode *next; struct qlistnode *prev; @@ -14,8 +14,8 @@ struct qlistnode #define qlist_empty(list) ((list) == (list)->next) #define qlist_head(list) ((list)->next) -#define qlist_tail(list) ((list)->prev) - +#define qlist_tail(list) ((list)->prev) + static void qlist_init(struct qlistnode *node) { node->next = node; @@ -34,5 +34,5 @@ static void qlist_remove(struct qlistnode *item) { item->next->prev = item->prev; item->prev->next = item->next; -} +} #endif \ No newline at end of file diff --git a/wwan/app/quectel_cm_5G/src/qmap_bridge_mode.c b/wwan/app/quectel-cm/src/qmap_bridge_mode.c similarity index 97% rename from wwan/app/quectel_cm_5G/src/qmap_bridge_mode.c rename to wwan/app/quectel-cm/src/qmap_bridge_mode.c index 18e825d..1012bf0 100644 --- a/wwan/app/quectel_cm_5G/src/qmap_bridge_mode.c +++ b/wwan/app/quectel-cm/src/qmap_bridge_mode.c @@ -1,402 +1,402 @@ -/****************************************************************************** - @file qmap_bridge_mode.c - @brief Connectivity bridge manager. - - 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 size_t ql_fread(const char *filename, void *buf, size_t size) { - FILE *fp = fopen(filename , "r"); - size_t n = 0; - - memset(buf, 0x00, size); - - if (fp) { - n = fread(buf, 1, size, fp); - if (n <= 0 || n == size) { - dbg_time("warnning: fail to fread(%s), fread=%zu, buf_size=%zu: (%s)", filename, n, size, strerror(errno)); - } - fclose(fp); - } - - return n > 0 ? n : 0; -} - -static size_t ql_fwrite(const char *filename, const void *buf, size_t size) { - FILE *fp = fopen(filename , "w"); - size_t n = 0; - - if (fp) { - n = fwrite(buf, 1, size, fp); - if (n != size) { - dbg_time("warnning: fail to fwrite(%s), fwrite=%zu, buf_size=%zu: (%s)", filename, n, size, strerror(errno)); - } - fclose(fp); - } - - return n > 0 ? n : 0; -} - -int ql_bridge_mode_detect(PROFILE_T *profile) { - const char *ifname = profile->qmapnet_adapter[0] ? profile->qmapnet_adapter : profile->usbnet_adapter; - const char *driver; - char bridge_mode[128]; - char bridge_ipv4[128]; - char ipv4[128]; - char buf[64]; - size_t n; - int in_bridge = 0; - - driver = profile->driver_name; - snprintf(bridge_mode, sizeof(bridge_mode), "/sys/class/net/%s/bridge_mode", ifname); - snprintf(bridge_ipv4, sizeof(bridge_ipv4), "/sys/class/net/%s/bridge_ipv4", ifname); - - if (access(bridge_ipv4, R_OK)) { - if (errno != ENOENT) { - dbg_time("fail to access %s, errno: %d (%s)", bridge_mode, errno, strerror(errno)); - return 0; - } - - snprintf(bridge_mode, sizeof(bridge_mode), "/sys/module/%s/parameters/bridge_mode", driver); - snprintf(bridge_ipv4, sizeof(bridge_ipv4), "/sys/module/%s/parameters/bridge_ipv4", driver); - - if (access(bridge_mode, R_OK)) { - if (errno != ENOENT) { - dbg_time("fail to access %s, errno: %d (%s)", bridge_mode, errno, strerror(errno)); - } - return 0; - } - } - - n = ql_fread(bridge_mode, buf, sizeof(buf)); - if (n > 0) { - in_bridge = (buf[0] != '0'); - } - if (!in_bridge) - return 0; - - memset(ipv4, 0, sizeof(ipv4)); - - if (strstr(bridge_ipv4, "/sys/class/net/") || profile->qmap_mode == 0 || profile->qmap_mode == 1) { - snprintf(ipv4, sizeof(ipv4), "0x%x", profile->ipv4.Address); - dbg_time("echo '%s' > %s", ipv4, bridge_ipv4); - ql_fwrite(bridge_ipv4, ipv4, strlen(ipv4)); - } - else { - snprintf(ipv4, sizeof(ipv4), "0x%x:%d", profile->ipv4.Address, profile->muxid); - dbg_time("echo '%s' > %s", ipv4, bridge_ipv4); - ql_fwrite(bridge_ipv4, ipv4, strlen(ipv4)); - } - - return in_bridge; -} - -int ql_enable_qmi_wwan_rawip_mode(PROFILE_T *profile) { - char filename[256]; - char buf[4]; - size_t n; - FILE *fp; - - if (!qmidev_is_qmiwwan(profile->qmichannel)) - return 0; - - snprintf(filename, sizeof(filename), "/sys/class/net/%s/qmi/rawip", profile->usbnet_adapter); - n = ql_fread(filename, buf, sizeof(buf)); - - if (n == 0) - return 0; - - if (buf[0] == '1' || buf[0] == 'Y') - return 0; - - fp = fopen(filename , "w"); - if (fp == NULL) { - dbg_time("Fail to fopen(%s, \"w\"), errno: %d (%s)", filename, errno, strerror(errno)); - return 1; - } - - buf[0] = 'Y'; - n = fwrite(buf, 1, 1, fp); - if (n != 1) { - dbg_time("Fail to fwrite(%s), errno: %d (%s)", filename, errno, strerror(errno)); - fclose(fp); - return 1; - } - fclose(fp); - - return 0; -} - -int ql_driver_type_detect(PROFILE_T *profile) { - if (qmidev_is_gobinet(profile->qmichannel)) { - profile->qmi_ops = &gobi_qmidev_ops; - } - else { - profile->qmi_ops = &qmiwwan_qmidev_ops; - } - qmidev_send = profile->qmi_ops->send; - - return 0; -} - -void ql_set_driver_bridge_mode(PROFILE_T *profile) { - char enable[16]; - char filename[256]; - - if(profile->qmap_mode) - snprintf(filename, sizeof(filename), "/sys/class/net/%s/bridge_mode", profile->qmapnet_adapter); - else - snprintf(filename, sizeof(filename), "/sys/class/net/%s/bridge_mode", profile->usbnet_adapter); - snprintf(enable, sizeof(enable), "%02d\n", profile->enable_bridge); - ql_fwrite(filename, enable, sizeof(enable)); -} - -static int ql_qmi_qmap_mode_detect(PROFILE_T *profile) { - char buf[128]; - int n; - struct { - char filename[255 * 2]; - char linkname[255 * 2]; - } *pl; - - pl = (typeof(pl)) malloc(sizeof(*pl)); - - snprintf(pl->linkname, sizeof(pl->linkname), "/sys/class/net/%s/device/driver", profile->usbnet_adapter); - n = readlink(pl->linkname, pl->filename, sizeof(pl->filename)); - pl->filename[n] = '\0'; - while (pl->filename[n] != '/') - n--; - strncpy(profile->driver_name, &pl->filename[n+1], sizeof(profile->driver_name) - 1); - - ql_get_driver_rmnet_info(profile, &profile->rmnet_info); - if (profile->rmnet_info.size) { - profile->qmap_mode = profile->rmnet_info.qmap_mode; - if (profile->qmap_mode) { - int offset_id = (profile->muxid == 0)? profile->pdp - 1 : profile->muxid - 0x81; - - if (profile->qmap_mode == 1) - offset_id = 0; - profile->muxid = profile->rmnet_info.mux_id[offset_id]; - strncpy(profile->qmapnet_adapter, profile->rmnet_info.ifname[offset_id], sizeof(profile->qmapnet_adapter) - 1); - profile->qmap_size = profile->rmnet_info.rx_urb_size; - profile->qmap_version = profile->rmnet_info.qmap_version; - } - - goto _out; - } - - snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/%s/qmap_mode", profile->usbnet_adapter); - if (access(pl->filename, R_OK)) { - if (errno != ENOENT) { - dbg_time("fail to access %s, errno: %d (%s)", pl->filename, errno, strerror(errno)); - goto _out; - } - - snprintf(pl->filename, sizeof(pl->filename), "/sys/module/%s/parameters/qmap_mode", profile->driver_name); - if (access(pl->filename, R_OK)) { - if (errno != ENOENT) { - dbg_time("fail to access %s, errno: %d (%s)", pl->filename, errno, strerror(errno)); - goto _out; - } - - snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/%s/device/driver/module/parameters/qmap_mode", profile->usbnet_adapter); - if (access(pl->filename, R_OK)) { - if (errno != ENOENT) { - dbg_time("fail to access %s, errno: %d (%s)", pl->filename, errno, strerror(errno)); - goto _out; - } - } - } - } - - if (!access(pl->filename, R_OK)) { - n = ql_fread(pl->filename, buf, sizeof(buf)); - if (n > 0) { - profile->qmap_mode = atoi(buf); - - if (profile->qmap_mode > 1) { - if(!profile->muxid) - profile->muxid = profile->pdp + 0x80; //muxis is 0x8X for PDN-X - snprintf(profile->qmapnet_adapter, sizeof(profile->qmapnet_adapter), - "%.16s.%d", profile->usbnet_adapter, profile->muxid - 0x80); - } if (profile->qmap_mode == 1) { - profile->muxid = 0x81; - strncpy(profile->qmapnet_adapter, profile->usbnet_adapter, sizeof(profile->qmapnet_adapter)); - } - } - } - else if (qmidev_is_qmiwwan(profile->qmichannel)) { - snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/qmimux%d", profile->pdp - 1); - if (access(pl->filename, R_OK)) { - if (errno != ENOENT) { - dbg_time("fail to access %s, errno: %d (%s)", pl->filename, errno, strerror(errno)); - } - goto _out; - } - - //upstream Kernel Style QMAP qmi_wwan.c - snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/%s/qmi/add_mux", profile->usbnet_adapter); - n = ql_fread(pl->filename, buf, sizeof(buf)); - if (n >= 5) { - dbg_time("If use QMAP by /sys/class/net/%s/qmi/add_mux", profile->usbnet_adapter); - #if 1 - dbg_time("Please set mtu of wwan0 >= max dl qmap packet size"); - #else - dbg_time("File:%s Line:%d Please make sure add next patch to qmi_wwan.c", __func__, __LINE__); - /* - diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c - index 74bebbd..db8a777 100644 - --- a/drivers/net/usb/qmi_wwan.c - +++ b/drivers/net/usb/qmi_wwan.c - @@ -379,6 +379,24 @@ static ssize_t add_mux_store(struct device *d, struct device_attribute *attr, c - if (!ret) { - info->flags |= QMI_WWAN_FLAG_MUX; - ret = len; - +#if 1 //Add by Quectel - + if (le16_to_cpu(dev->udev->descriptor.idVendor) == 0x2c7c) { - + int idProduct = le16_to_cpu(dev->udev->descriptor.idProduct); - + - + if (idProduct == 0x0121 || idProduct == 0x0125 || idProduct == 0x0435) //MDM9x07 - + dev->rx_urb_size = 4*1024; - + else if (idProduct == 0x0306) //MDM9x40 - + dev->rx_urb_size = 16*1024; - + else if (idProduct == 0x0512) //SDX20 - + dev->rx_urb_size = 32*1024; - + else if (idProduct == 0x0620) //SDX24 - + dev->rx_urb_size = 32*1024; - + else if (idProduct == 0x0800) //SDX55 - + dev->rx_urb_size = 32*1024; - + else - + dev->rx_urb_size = 32*1024; - + } - +#endif - } - err: - rtnl_unlock(); - */ - #endif - profile->qmap_mode = n/5; //0x11\n0x22\n0x33\n - if (profile->qmap_mode > 1) { - //PDN-X map to qmimux-X - if(!profile->muxid) { - profile->muxid = (buf[5*(profile->pdp - 1) + 2] - '0')*16 + (buf[5*(profile->pdp - 1) + 3] - '0'); - snprintf(profile->qmapnet_adapter, sizeof(profile->qmapnet_adapter), "qmimux%d", profile->pdp - 1); - } else { - profile->muxid = (buf[5*(profile->muxid - 0x81) + 2] - '0')*16 + (buf[5*(profile->muxid - 0x81) + 3] - '0'); - snprintf(profile->qmapnet_adapter, sizeof(profile->qmapnet_adapter), "qmimux%d", profile->muxid - 0x81); - } - } else if (profile->qmap_mode == 1) { - profile->muxid = (buf[5*0 + 2] - '0')*16 + (buf[5*0 + 3] - '0'); - snprintf(profile->qmapnet_adapter, sizeof(profile->qmapnet_adapter), - "qmimux%d", 0); - } - } - } - -_out: - if (profile->qmap_mode) { - if (profile->qmap_size == 0) { - profile->qmap_size = 16*1024; - snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/%s/qmap_size", profile->usbnet_adapter); - if (!access(pl->filename, R_OK)) { - size_t n; - char buf[32]; - n = ql_fread(pl->filename, buf, sizeof(buf)); - if (n > 0) { - profile->qmap_size = atoi(buf); - } - } - } - - if (profile->qmap_version == 0) { - profile->qmap_version = WDA_DL_DATA_AGG_QMAP_ENABLED; - } - - dbg_time("qmap_mode = %d, qmap_version = %d, qmap_size = %d, muxid = 0x%02x, qmap_netcard = %s", - profile->qmap_mode, profile->qmap_version, profile->qmap_size, profile->muxid, profile->qmapnet_adapter); - } - ql_set_driver_bridge_mode(profile); - free(pl); - - return 0; -} - -static int ql_mbim_usb_vlan_mode_detect(PROFILE_T *profile) { - char tmp[128]; - - snprintf(tmp, sizeof(tmp), "/sys/class/net/%s.%d", profile->usbnet_adapter, profile->pdp); - if (!access(tmp, F_OK)) { - profile->qmap_mode = 4; - profile->muxid = profile->pdp; - no_trunc_strncpy(profile->qmapnet_adapter, tmp + strlen("/sys/class/net/"), sizeof(profile->qmapnet_adapter) - 1); - - dbg_time("mbim_qmap_mode = %d, vlan_id = 0x%02x, qmap_netcard = %s", - profile->qmap_mode, profile->muxid, profile->qmapnet_adapter); - } - - return 0; -} - -static int ql_mbim_mhi_qmap_mode_detect(PROFILE_T *profile) { - ql_get_driver_rmnet_info(profile, &profile->rmnet_info); - if (profile->rmnet_info.size) { - profile->qmap_mode = profile->rmnet_info.qmap_mode; - if (profile->qmap_mode) { - int offset_id = profile->pdp - 1; - - if (profile->qmap_mode == 1) - offset_id = 0; - profile->muxid = profile->pdp; - strcpy(profile->qmapnet_adapter, profile->rmnet_info.ifname[offset_id]); - profile->qmap_size = profile->rmnet_info.rx_urb_size; - profile->qmap_version = profile->rmnet_info.qmap_version; - - dbg_time("mbim_qmap_mode = %d, vlan_id = 0x%02x, qmap_netcard = %s", - profile->qmap_mode, profile->muxid, profile->qmapnet_adapter); - } - - goto _out; - } - -_out: - return 0; -} - -int ql_qmap_mode_detect(PROFILE_T *profile) { - if (profile->software_interface == SOFTWARE_MBIM) { - if (profile->hardware_interface == HARDWARE_USB) - return ql_mbim_usb_vlan_mode_detect(profile); - else if (profile->hardware_interface == HARDWARE_PCIE) - return ql_mbim_mhi_qmap_mode_detect(profile); - } else if (profile->software_interface == SOFTWARE_QMI) { - return ql_qmi_qmap_mode_detect(profile); - } -#ifdef CONFIG_QRTR - else if(profile->software_interface == SOFTWARE_QRTR) { - char tmp[128]; - - profile->qmap_mode = 4; - profile->qmap_version = WDA_DL_DATA_AGG_QMAP_V5_ENABLED; - profile->qmap_size = 31*1024; - profile->muxid = 0x80 | profile->pdp; - snprintf(profile->qmapnet_adapter, sizeof(profile->qmapnet_adapter), "rmnet_data%d", profile->muxid&0xF); - - snprintf(tmp, sizeof(tmp), "/sys/class/net/%s", profile->qmapnet_adapter); - if (access(tmp, F_OK)) { - rtrmnet_ctl_create_vnd(profile->usbnet_adapter, profile->qmapnet_adapter, - profile->muxid, profile->qmap_version, 11, 4096); - } - } -#endif - return 0; -} +/****************************************************************************** + @file qmap_bridge_mode.c + @brief Connectivity bridge manager. + + 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 size_t ql_fread(const char *filename, void *buf, size_t size) { + FILE *fp = fopen(filename , "r"); + size_t n = 0; + + memset(buf, 0x00, size); + + if (fp) { + n = fread(buf, 1, size, fp); + if (n <= 0 || n == size) { + dbg_time("warnning: fail to fread(%s), fread=%zu, buf_size=%zu: (%s)", filename, n, size, strerror(errno)); + } + fclose(fp); + } + + return n > 0 ? n : 0; +} + +static size_t ql_fwrite(const char *filename, const void *buf, size_t size) { + FILE *fp = fopen(filename , "w"); + size_t n = 0; + + if (fp) { + n = fwrite(buf, 1, size, fp); + if (n != size) { + dbg_time("warnning: fail to fwrite(%s), fwrite=%zu, buf_size=%zu: (%s)", filename, n, size, strerror(errno)); + } + fclose(fp); + } + + return n > 0 ? n : 0; +} + +int ql_bridge_mode_detect(PROFILE_T *profile) { + const char *ifname = profile->qmapnet_adapter[0] ? profile->qmapnet_adapter : profile->usbnet_adapter; + const char *driver; + char bridge_mode[128]; + char bridge_ipv4[128]; + char ipv4[128]; + char buf[64]; + size_t n; + int in_bridge = 0; + + driver = profile->driver_name; + snprintf(bridge_mode, sizeof(bridge_mode), "/sys/class/net/%s/bridge_mode", ifname); + snprintf(bridge_ipv4, sizeof(bridge_ipv4), "/sys/class/net/%s/bridge_ipv4", ifname); + + if (access(bridge_ipv4, R_OK)) { + if (errno != ENOENT) { + dbg_time("fail to access %s, errno: %d (%s)", bridge_mode, errno, strerror(errno)); + return 0; + } + + snprintf(bridge_mode, sizeof(bridge_mode), "/sys/module/%s/parameters/bridge_mode", driver); + snprintf(bridge_ipv4, sizeof(bridge_ipv4), "/sys/module/%s/parameters/bridge_ipv4", driver); + + if (access(bridge_mode, R_OK)) { + if (errno != ENOENT) { + dbg_time("fail to access %s, errno: %d (%s)", bridge_mode, errno, strerror(errno)); + } + return 0; + } + } + + n = ql_fread(bridge_mode, buf, sizeof(buf)); + if (n > 0) { + in_bridge = (buf[0] != '0'); + } + if (!in_bridge) + return 0; + + memset(ipv4, 0, sizeof(ipv4)); + + if (strstr(bridge_ipv4, "/sys/class/net/") || profile->qmap_mode == 0 || profile->qmap_mode == 1) { + snprintf(ipv4, sizeof(ipv4), "0x%x", profile->ipv4.Address); + dbg_time("echo '%s' > %s", ipv4, bridge_ipv4); + ql_fwrite(bridge_ipv4, ipv4, strlen(ipv4)); + } + else { + snprintf(ipv4, sizeof(ipv4), "0x%x:%d", profile->ipv4.Address, profile->muxid); + dbg_time("echo '%s' > %s", ipv4, bridge_ipv4); + ql_fwrite(bridge_ipv4, ipv4, strlen(ipv4)); + } + + return in_bridge; +} + +int ql_enable_qmi_wwan_rawip_mode(PROFILE_T *profile) { + char filename[256]; + char buf[4]; + size_t n; + FILE *fp; + + if (!qmidev_is_qmiwwan(profile->qmichannel)) + return 0; + + snprintf(filename, sizeof(filename), "/sys/class/net/%s/qmi/rawip", profile->usbnet_adapter); + n = ql_fread(filename, buf, sizeof(buf)); + + if (n == 0) + return 0; + + if (buf[0] == '1' || buf[0] == 'Y') + return 0; + + fp = fopen(filename , "w"); + if (fp == NULL) { + dbg_time("Fail to fopen(%s, \"w\"), errno: %d (%s)", filename, errno, strerror(errno)); + return 1; + } + + buf[0] = 'Y'; + n = fwrite(buf, 1, 1, fp); + if (n != 1) { + dbg_time("Fail to fwrite(%s), errno: %d (%s)", filename, errno, strerror(errno)); + fclose(fp); + return 1; + } + fclose(fp); + + return 0; +} + +int ql_driver_type_detect(PROFILE_T *profile) { + if (qmidev_is_gobinet(profile->qmichannel)) { + profile->qmi_ops = &gobi_qmidev_ops; + } + else { + profile->qmi_ops = &qmiwwan_qmidev_ops; + } + qmidev_send = profile->qmi_ops->send; + + return 0; +} + +void ql_set_driver_bridge_mode(PROFILE_T *profile) { + char enable[16]; + char filename[256]; + + if(profile->qmap_mode) + snprintf(filename, sizeof(filename), "/sys/class/net/%s/bridge_mode", profile->qmapnet_adapter); + else + snprintf(filename, sizeof(filename), "/sys/class/net/%s/bridge_mode", profile->usbnet_adapter); + snprintf(enable, sizeof(enable), "%02d\n", profile->enable_bridge); + ql_fwrite(filename, enable, sizeof(enable)); +} + +static int ql_qmi_qmap_mode_detect(PROFILE_T *profile) { + char buf[128]; + int n; + struct { + char filename[255 * 2]; + char linkname[255 * 2]; + } *pl; + + pl = (typeof(pl)) malloc(sizeof(*pl)); + + snprintf(pl->linkname, sizeof(pl->linkname), "/sys/class/net/%s/device/driver", profile->usbnet_adapter); + n = readlink(pl->linkname, pl->filename, sizeof(pl->filename)); + pl->filename[n] = '\0'; + while (pl->filename[n] != '/') + n--; + strncpy(profile->driver_name, &pl->filename[n+1], sizeof(profile->driver_name) - 1); + + ql_get_driver_rmnet_info(profile, &profile->rmnet_info); + if (profile->rmnet_info.size) { + profile->qmap_mode = profile->rmnet_info.qmap_mode; + if (profile->qmap_mode) { + int offset_id = (profile->muxid == 0)? profile->pdp - 1 : profile->muxid - 0x81; + + if (profile->qmap_mode == 1) + offset_id = 0; + profile->muxid = profile->rmnet_info.mux_id[offset_id]; + strncpy(profile->qmapnet_adapter, profile->rmnet_info.ifname[offset_id], sizeof(profile->qmapnet_adapter) - 1); + profile->qmap_size = profile->rmnet_info.rx_urb_size; + profile->qmap_version = profile->rmnet_info.qmap_version; + } + + goto _out; + } + + snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/%s/qmap_mode", profile->usbnet_adapter); + if (access(pl->filename, R_OK)) { + if (errno != ENOENT) { + dbg_time("fail to access %s, errno: %d (%s)", pl->filename, errno, strerror(errno)); + goto _out; + } + + snprintf(pl->filename, sizeof(pl->filename), "/sys/module/%s/parameters/qmap_mode", profile->driver_name); + if (access(pl->filename, R_OK)) { + if (errno != ENOENT) { + dbg_time("fail to access %s, errno: %d (%s)", pl->filename, errno, strerror(errno)); + goto _out; + } + + snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/%s/device/driver/module/parameters/qmap_mode", profile->usbnet_adapter); + if (access(pl->filename, R_OK)) { + if (errno != ENOENT) { + dbg_time("fail to access %s, errno: %d (%s)", pl->filename, errno, strerror(errno)); + goto _out; + } + } + } + } + + if (!access(pl->filename, R_OK)) { + n = ql_fread(pl->filename, buf, sizeof(buf)); + if (n > 0) { + profile->qmap_mode = atoi(buf); + + if (profile->qmap_mode > 1) { + if(!profile->muxid) + profile->muxid = profile->pdp + 0x80; //muxis is 0x8X for PDN-X + snprintf(profile->qmapnet_adapter, sizeof(profile->qmapnet_adapter), + "%.16s.%d", profile->usbnet_adapter, profile->muxid - 0x80); + } if (profile->qmap_mode == 1) { + profile->muxid = 0x81; + strncpy(profile->qmapnet_adapter, profile->usbnet_adapter, sizeof(profile->qmapnet_adapter)); + } + } + } + else if (qmidev_is_qmiwwan(profile->qmichannel)) { + snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/qmimux%d", profile->pdp - 1); + if (access(pl->filename, R_OK)) { + if (errno != ENOENT) { + dbg_time("fail to access %s, errno: %d (%s)", pl->filename, errno, strerror(errno)); + } + goto _out; + } + + //upstream Kernel Style QMAP qmi_wwan.c + snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/%s/qmi/add_mux", profile->usbnet_adapter); + n = ql_fread(pl->filename, buf, sizeof(buf)); + if (n >= 5) { + dbg_time("If use QMAP by /sys/class/net/%s/qmi/add_mux", profile->usbnet_adapter); + #if 1 + dbg_time("Please set mtu of wwan0 >= max dl qmap packet size"); + #else + dbg_time("File:%s Line:%d Please make sure add next patch to qmi_wwan.c", __func__, __LINE__); + /* + diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c + index 74bebbd..db8a777 100644 + --- a/drivers/net/usb/qmi_wwan.c + +++ b/drivers/net/usb/qmi_wwan.c + @@ -379,6 +379,24 @@ static ssize_t add_mux_store(struct device *d, struct device_attribute *attr, c + if (!ret) { + info->flags |= QMI_WWAN_FLAG_MUX; + ret = len; + +#if 1 //Add by Quectel + + if (le16_to_cpu(dev->udev->descriptor.idVendor) == 0x2c7c) { + + int idProduct = le16_to_cpu(dev->udev->descriptor.idProduct); + + + + if (idProduct == 0x0121 || idProduct == 0x0125 || idProduct == 0x0435) //MDM9x07 + + dev->rx_urb_size = 4*1024; + + else if (idProduct == 0x0306) //MDM9x40 + + dev->rx_urb_size = 16*1024; + + else if (idProduct == 0x0512) //SDX20 + + dev->rx_urb_size = 32*1024; + + else if (idProduct == 0x0620) //SDX24 + + dev->rx_urb_size = 32*1024; + + else if (idProduct == 0x0800) //SDX55 + + dev->rx_urb_size = 32*1024; + + else + + dev->rx_urb_size = 32*1024; + + } + +#endif + } + err: + rtnl_unlock(); + */ + #endif + profile->qmap_mode = n/5; //0x11\n0x22\n0x33\n + if (profile->qmap_mode > 1) { + //PDN-X map to qmimux-X + if(!profile->muxid) { + profile->muxid = (buf[5*(profile->pdp - 1) + 2] - '0')*16 + (buf[5*(profile->pdp - 1) + 3] - '0'); + snprintf(profile->qmapnet_adapter, sizeof(profile->qmapnet_adapter), "qmimux%d", profile->pdp - 1); + } else { + profile->muxid = (buf[5*(profile->muxid - 0x81) + 2] - '0')*16 + (buf[5*(profile->muxid - 0x81) + 3] - '0'); + snprintf(profile->qmapnet_adapter, sizeof(profile->qmapnet_adapter), "qmimux%d", profile->muxid - 0x81); + } + } else if (profile->qmap_mode == 1) { + profile->muxid = (buf[5*0 + 2] - '0')*16 + (buf[5*0 + 3] - '0'); + snprintf(profile->qmapnet_adapter, sizeof(profile->qmapnet_adapter), + "qmimux%d", 0); + } + } + } + +_out: + if (profile->qmap_mode) { + if (profile->qmap_size == 0) { + profile->qmap_size = 16*1024; + snprintf(pl->filename, sizeof(pl->filename), "/sys/class/net/%s/qmap_size", profile->usbnet_adapter); + if (!access(pl->filename, R_OK)) { + size_t n; + char buf[32]; + n = ql_fread(pl->filename, buf, sizeof(buf)); + if (n > 0) { + profile->qmap_size = atoi(buf); + } + } + } + + if (profile->qmap_version == 0) { + profile->qmap_version = WDA_DL_DATA_AGG_QMAP_ENABLED; + } + + dbg_time("qmap_mode = %d, qmap_version = %d, qmap_size = %d, muxid = 0x%02x, qmap_netcard = %s", + profile->qmap_mode, profile->qmap_version, profile->qmap_size, profile->muxid, profile->qmapnet_adapter); + } + ql_set_driver_bridge_mode(profile); + free(pl); + + return 0; +} + +static int ql_mbim_usb_vlan_mode_detect(PROFILE_T *profile) { + char tmp[128]; + + snprintf(tmp, sizeof(tmp), "/sys/class/net/%s.%d", profile->usbnet_adapter, profile->pdp); + if (!access(tmp, F_OK)) { + profile->qmap_mode = 4; + profile->muxid = profile->pdp; + no_trunc_strncpy(profile->qmapnet_adapter, tmp + strlen("/sys/class/net/"), sizeof(profile->qmapnet_adapter) - 1); + + dbg_time("mbim_qmap_mode = %d, vlan_id = 0x%02x, qmap_netcard = %s", + profile->qmap_mode, profile->muxid, profile->qmapnet_adapter); + } + + return 0; +} + +static int ql_mbim_mhi_qmap_mode_detect(PROFILE_T *profile) { + ql_get_driver_rmnet_info(profile, &profile->rmnet_info); + if (profile->rmnet_info.size) { + profile->qmap_mode = profile->rmnet_info.qmap_mode; + if (profile->qmap_mode) { + int offset_id = profile->pdp - 1; + + if (profile->qmap_mode == 1) + offset_id = 0; + profile->muxid = profile->pdp; + strcpy(profile->qmapnet_adapter, profile->rmnet_info.ifname[offset_id]); + profile->qmap_size = profile->rmnet_info.rx_urb_size; + profile->qmap_version = profile->rmnet_info.qmap_version; + + dbg_time("mbim_qmap_mode = %d, vlan_id = 0x%02x, qmap_netcard = %s", + profile->qmap_mode, profile->muxid, profile->qmapnet_adapter); + } + + goto _out; + } + +_out: + return 0; +} + +int ql_qmap_mode_detect(PROFILE_T *profile) { + if (profile->software_interface == SOFTWARE_MBIM) { + if (profile->hardware_interface == HARDWARE_USB) + return ql_mbim_usb_vlan_mode_detect(profile); + else if (profile->hardware_interface == HARDWARE_PCIE) + return ql_mbim_mhi_qmap_mode_detect(profile); + } else if (profile->software_interface == SOFTWARE_QMI) { + return ql_qmi_qmap_mode_detect(profile); + } +#ifdef CONFIG_QRTR + else if(profile->software_interface == SOFTWARE_QRTR) { + char tmp[128]; + + profile->qmap_mode = 4; + profile->qmap_version = WDA_DL_DATA_AGG_QMAP_V5_ENABLED; + profile->qmap_size = 31*1024; + profile->muxid = 0x80 | profile->pdp; + snprintf(profile->qmapnet_adapter, sizeof(profile->qmapnet_adapter), "rmnet_data%d", profile->muxid&0xF); + + snprintf(tmp, sizeof(tmp), "/sys/class/net/%s", profile->qmapnet_adapter); + if (access(tmp, F_OK)) { + rtrmnet_ctl_create_vnd(profile->usbnet_adapter, profile->qmapnet_adapter, + profile->muxid, profile->qmap_version, 11, 4096); + } + } +#endif + return 0; +} diff --git a/wwan/app/quectel_cm_5G/src/qrtr.c b/wwan/app/quectel-cm/src/qrtr.c similarity index 96% rename from wwan/app/quectel_cm_5G/src/qrtr.c rename to wwan/app/quectel-cm/src/qrtr.c index 450c6bd..4ddf4a0 100644 --- a/wwan/app/quectel_cm_5G/src/qrtr.c +++ b/wwan/app/quectel-cm/src/qrtr.c @@ -1,657 +1,657 @@ -//https://github.com/andersson/qrtr -/****************************************************************************** - @file QrtrCM.c - @brief GobiNet driver. - - 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 -#include -#include -#include -#include -#include "QMIThread.h" - -typedef struct { - uint32_t service; - uint32_t version; - uint32_t instance; - uint32_t node; - uint32_t port; -} QrtrService; - -#define QRTR_MAX (QMUX_TYPE_WDS_ADMIN + 1) -static QrtrService service_list[QRTR_MAX]; -static int qmiclientId[QRTR_MAX]; -static int get_client(UCHAR QMIType); -static uint32_t node_modem = 3; //IPQ ~ 3, QCM ~ 0 - -#ifdef USE_LINUX_MSM_IPC -#include - -struct xport_ipc_router_server_addr { - uint32_t service; - uint32_t instance; - uint32_t node_id; - uint32_t port_id; -}; - -union ctl_msg { - uint32_t cmd; - struct { - uint32_t cmd; - uint32_t service; - uint32_t instance; - uint32_t node_id; - uint32_t port_id; - } srv; - struct { - uint32_t cmd; - uint32_t node_id; - uint32_t port_id; - } cli; - }; -#define CTL_CMD_NEW_SERVER 4 -#define CTL_CMD_REMOVE_SERVER 5 - -#define VERSION_MASK 0xff -#define GET_VERSION(x) (x & 0xff) -#define GET_XPORT_SVC_INSTANCE(x) GET_VERSION(x) -#define GET_INSTANCE(x) ((x & 0xff00) >> 8) - -static int msm_ipc_socket(const char *name) -{ - int sock; - int flags; - - sock = socket(AF_MSM_IPC, SOCK_DGRAM, 0); - if (sock < 0) { - dbg_time("%s(%s) errno: %d (%s)\n", __func__, name, errno, strerror(errno)); - return -1; - } - - fcntl(sock, F_SETFD, FD_CLOEXEC); - flags = fcntl(sock, F_GETFL, 0); - fcntl(sock, F_SETFL, flags | O_NONBLOCK); - - return sock; -} - -static uint32_t xport_lookup -( - int lookup_sock_fd, - uint32_t service_id, - uint32_t version -) -{ - uint32_t num_servers_found = 0; - uint32_t num_entries_to_fill = 4; - struct server_lookup_args *lookup_arg; - int i; - - lookup_arg = (struct server_lookup_args *)malloc(sizeof(*lookup_arg) - + (num_entries_to_fill * sizeof(struct msm_ipc_server_info))); - if (!lookup_arg) - { - dbg_time("%s: Malloc failed\n", __func__); - return 0; - } - - lookup_arg->port_name.service = service_id; - lookup_arg->port_name.instance = GET_XPORT_SVC_INSTANCE(version); - lookup_arg->num_entries_in_array = num_entries_to_fill; - lookup_arg->lookup_mask = VERSION_MASK; - lookup_arg->num_entries_found = 0; - if (ioctl(lookup_sock_fd, IPC_ROUTER_IOCTL_LOOKUP_SERVER, lookup_arg) < 0) - { - dbg_time("%s: Lookup failed for %08x: %08x\n", __func__, service_id, version); - free(lookup_arg); - return 0; - } - - dbg_time("%s: num_entries_found %d for type=%d instance=%d", __func__, - lookup_arg->num_entries_found, service_id, version); - num_servers_found = 0; - for (i = 0; ((i < (int)num_entries_to_fill) && (i < lookup_arg->num_entries_found)); i++) - { - QrtrService service_info[1]; - - if (lookup_arg->srv_info[i].node_id != node_modem) - continue; - num_servers_found++; - - service_info[0].service = lookup_arg->srv_info[i].service; - service_info[0].version = GET_VERSION(lookup_arg->srv_info[i].instance); - service_info[0].instance = GET_INSTANCE(lookup_arg->srv_info[i].instance); - service_info[0].node = lookup_arg->srv_info[i].node_id; - service_info[0].port = lookup_arg->srv_info[i].port_id; - - service_list[service_id] = service_info[0]; - qmiclientId[service_id] = get_client(service_id); - } - - free(lookup_arg); - return num_servers_found; -} - -static int xport_send(int sock, uint32_t node, uint32_t port, const void *data, unsigned int sz) -{ - struct sockaddr_msm_ipc addr = {}; - int rc; - - addr.family = AF_MSM_IPC; - addr.address.addrtype = MSM_IPC_ADDR_ID; - addr.address.addr.port_addr.node_id = node; - addr.address.addr.port_addr.port_id = port; - - rc = sendto(sock, data, sz, MSG_DONTWAIT, (void *)&addr, sizeof(addr)); - if (rc < 0) { - dbg_time("xport_send errno: %d (%s)\n", errno, strerror(errno)); - return -1; - } - - return 0; -} - -static int xport_recv(int sock, void *data, unsigned int sz, uint32_t *node, uint32_t *port) -{ - struct sockaddr_msm_ipc addr = {}; - socklen_t addr_size = sizeof(struct sockaddr_msm_ipc); - int rc; - - rc = recvfrom(sock, data, sz, MSG_DONTWAIT, (void *)&addr, &addr_size); - if (rc < 0) { - dbg_time("xport_recv errno: %d (%s)\n", errno, strerror(errno)); - } - else if (addr.address.addrtype != MSM_IPC_ADDR_ID) { - dbg_time("xport_recv addrtype is NOT MSM_IPC_ADDR_ID\n"); - rc = -1; - } - - *node = addr.address.addr.port_addr.node_id; - *port = addr.address.addr.port_addr.port_id; - return rc; -} -#define qmi_recv xport_recv - -static int xport_ctrl_init(void) -{ - int ctrl_sock; - int rc; - uint32_t instance = 1; //modem - uint32_t version; - - ctrl_sock = msm_ipc_socket("ctrl_port"); - if (ctrl_sock == -1) - return -1; - - rc = ioctl(ctrl_sock, IPC_ROUTER_IOCTL_GET_VERSION, &version); - if (rc < 0) { - dbg_time("%s: failed to get ipc version\n", __func__); - goto init_close_ctrl_fd; - } - dbg_time("%s ipc_version = %d", __func__, version); - - rc = ioctl(ctrl_sock, IPC_ROUTER_IOCTL_BIND_CONTROL_PORT, NULL); - if (rc < 0) { - dbg_time("%s: failed to bind as control port\n", __func__); - goto init_close_ctrl_fd; - } - - //cat /sys/kernel/debug/msm_ipc_router/dump_servers - rc = 0; - rc += xport_lookup(ctrl_sock, QMUX_TYPE_WDS, instance); - if (service_list[QMUX_TYPE_WDS].port) { - qmiclientId[QMUX_TYPE_WDS_IPV6] = get_client(QMUX_TYPE_WDS); - } - rc += xport_lookup(ctrl_sock, QMUX_TYPE_NAS, instance); - rc += xport_lookup(ctrl_sock, QMUX_TYPE_UIM, instance); - rc += xport_lookup(ctrl_sock, QMUX_TYPE_DMS, instance); - rc += xport_lookup(ctrl_sock, QMUX_TYPE_WDS_ADMIN, instance); - - if (rc == 0) { - dbg_time("%s: failed to lookup qmi service\n", __func__); - goto init_close_ctrl_fd; - } - - return ctrl_sock; - -init_close_ctrl_fd: - close(ctrl_sock); - return -1; -} - -static void handle_ctrl_pkt(int sock) { - union ctl_msg pkt; - uint32_t type; - int rc; - - rc = recvfrom(sock, &pkt, sizeof(pkt), 0, NULL, NULL); - if (rc < 0) - return; - - type = le32toh(pkt.cmd); - if (CTL_CMD_NEW_SERVER == type || CTL_CMD_REMOVE_SERVER == type) { - QrtrService s; - - s.service = le32toh(pkt.srv.service); - s.version = le32toh(pkt.srv.instance) & 0xff; - s.instance = le32toh(pkt.srv.instance) >> 8; - s.node = le32toh(pkt.srv.node_id); - s.port = le32toh(pkt.srv.port_id); - - if (debug_qmi) - dbg_time ("[qrtr] %s server on %u:%u -> service %u, version %u, instance %u", - CTL_CMD_NEW_SERVER == type ? "add" : "remove", - s.node, s.port, s.service, s.version, s.instance); - - if (CTL_CMD_NEW_SERVER == type) { - if (s.service < QRTR_MAX) { - service_list[s.service] = s; - } - } - else if (CTL_CMD_REMOVE_SERVER == type) { - if (s.service < QRTR_MAX) { - memset(&service_list[s.service], 0, sizeof(QrtrService)); - } - } - } -} -#else -#include -#include "qrtr.h" -#endif - -static int qrtr_socket(void) -{ - struct sockaddr_qrtr sq; - socklen_t sl = sizeof(sq); - int sock; - int rc; - - sock = socket(AF_QIPCRTR, SOCK_DGRAM, 0); - if (sock < 0) { - dbg_time("qrtr_socket errno: %d (%s)\n", errno, strerror(errno)); - return -1; - } - - rc = getsockname(sock, (void *)&sq, &sl); - if (rc || sq.sq_family != AF_QIPCRTR || sl != sizeof(sq)) { - dbg_time("getsockname: %d (%s)\n", errno, strerror(errno)); - close(sock); - return -1; - } - - return sock; -} - -static int qrtr_send(int sock, uint32_t node, uint32_t port, const void *data, unsigned int sz) -{ - struct sockaddr_qrtr sq = {}; - int rc; - - sq.sq_family = AF_QIPCRTR; - sq.sq_node = node; - sq.sq_port = port; - - rc = sendto(sock, data, sz, MSG_DONTWAIT, (void *)&sq, sizeof(sq)); - if (rc < 0) { - dbg_time("sendto errno: %d (%s)\n", errno, strerror(errno)); - return -1; - } - - return 0; -} - -static int qrtr_recv(int sock, void *data, unsigned int sz, uint32_t *node, uint32_t *port) -{ - struct sockaddr_qrtr sq = {}; - socklen_t sl = sizeof(sq); - int rc; - - rc = recvfrom(sock, data, sz, MSG_DONTWAIT, (void *)&sq, &sl); - if (rc < 0) { - dbg_time("qrtr_recv errno: %d (%s)\n", errno, strerror(errno)); - } - - *node = sq.sq_node; - *port = sq.sq_port; - return rc; - } -#define qmi_recv qrtr_recv - -static int qrtr_ctrl_init(void) { - int sock; - int rc; - struct qrtr_ctrl_pkt pkt; - struct sockaddr_qrtr sq; - socklen_t sl = sizeof(sq); - - sock = qrtr_socket(); - if (sock == -1) - return -1; - - memset(&pkt, 0, sizeof(pkt)); - pkt.cmd = htole32(QRTR_TYPE_NEW_LOOKUP); - - getsockname(sock, (void *)&sq, &sl); - rc = qrtr_send(sock, sq.sq_node, QRTR_PORT_CTRL, &pkt, sizeof(pkt)); - if (rc == -1) { - dbg_time("qrtr_send errno: %d (%s)\n", errno, strerror(errno)); - close(sock); - return -1; - } - - return sock; -} - -static void handle_server_change(uint32_t type, struct qrtr_ctrl_pkt *ppkt) { - struct qrtr_ctrl_pkt pkt = *ppkt; - QrtrService s; - - s.service = le32toh(pkt.server.service); - s.version = le32toh(pkt.server.instance) & 0xff; - s.instance = le32toh(pkt.server.instance) >> 8; - s.node = le32toh(pkt.server.node); - s.port = le32toh(pkt.server.port); - - if (debug_qmi) - dbg_time ("[qrtr] %s server on %u:%u -> service %u, version %u, instance %u", - QRTR_TYPE_NEW_SERVER == type ? "add" : "remove", - s.node, s.port, s.service, s.version, s.instance); - - if (s.node != node_modem) - return; //we only care modem - - if (QRTR_TYPE_NEW_SERVER == type) { - if (s.service < QRTR_MAX) { - service_list[s.service] = s; - } - } - else if (QRTR_TYPE_DEL_SERVER == type) { - if (s.service < QRTR_MAX) { - memset(&service_list[s.service], 0, sizeof(QrtrService)); - } - } - } - -static void handle_ctrl_pkt(int sock) { - struct qrtr_ctrl_pkt pkt; - struct sockaddr_qrtr sq; - socklen_t sl = sizeof(sq); - uint32_t type; - int rc; - - rc = recvfrom(sock, &pkt, sizeof(pkt), 0, (void *)&sq, &sl); - if (rc < 0) - return; - - type = le32toh(pkt.cmd); - if (debug_qmi) - dbg_time("type %u, node %u, sq.port %x, len: %d", type, sq.sq_node, sq.sq_port, rc); - - if (sq.sq_port != QRTR_PORT_CTRL) - return; - - if (QRTR_TYPE_NEW_SERVER == type || QRTR_TYPE_DEL_SERVER == type) { - handle_server_change(type, &pkt); - } -} - -static int get_client(UCHAR QMIType) { - int ClientId; - QrtrService *s = &service_list[QMIType]; - - if (!s ->service) { - dbg_time("%s service: %d for QMIType: %d", __func__, s ->service, QMIType); - return -ENODEV; - } - -#ifdef USE_LINUX_MSM_IPC - ClientId = msm_ipc_socket("xport"); -#else - ClientId = qrtr_socket(); -#endif - if (ClientId == -1) { - return 0; - } - - switch (QMIType) { - case QMUX_TYPE_WDS: dbg_time("Get clientWDS = %d", ClientId); break; - case QMUX_TYPE_DMS: dbg_time("Get clientDMS = %d", ClientId); break; - case QMUX_TYPE_NAS: dbg_time("Get clientNAS = %d", ClientId); break; - case QMUX_TYPE_QOS: dbg_time("Get clientQOS = %d", ClientId); break; - case QMUX_TYPE_WMS: dbg_time("Get clientWMS = %d", ClientId); break; - case QMUX_TYPE_PDS: dbg_time("Get clientPDS = %d", ClientId); break; - case QMUX_TYPE_UIM: dbg_time("Get clientUIM = %d", ClientId); break; - case QMUX_TYPE_WDS_ADMIN: dbg_time("Get clientWDA = %d", ClientId); - break; - default: break; - } - - return ClientId; -} - -static void handle_alloc_client(PROFILE_T *profile) { - int srv_list[] = {QMUX_TYPE_WDS, QMUX_TYPE_NAS, QMUX_TYPE_UIM, QMUX_TYPE_DMS, QMUX_TYPE_WDS_ADMIN}; - size_t i = 0, srv_ready = 0; - static int report = -1; - - if (report != -1) - return; - - for(i = 0; i < sizeof(srv_list)/sizeof(srv_list[0]); i++) { - int srv = srv_list[i]; - - if (service_list[srv].service) - srv_ready++; - else - continue; - - if (qmiclientId[srv] == 0) { - qmiclientId[srv] = get_client(srv); - - if (qmiclientId[srv] != 0) { - if (srv == QMUX_TYPE_WDS) { - qmiclientId[QMUX_TYPE_WDS_IPV6] = get_client(QMUX_TYPE_WDS); - } - else if (srv == QMUX_TYPE_WDS_ADMIN) { - profile->wda_client = qmiclientId[QMUX_TYPE_WDS_ADMIN]; - } - } - } - } - - if (srv_ready == sizeof(srv_list)/sizeof(srv_list[0])) { - if (qmiclientId[QMUX_TYPE_WDS]) { - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_CONNECTED); - } else { - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED); - } - report = 1; - } -} - -static int qmi_send(PQCQMIMSG pRequest) { - uint8_t QMIType = pRequest->QMIHdr.QMIType; - int sock; - QrtrService *s = &service_list[QMIType == QMUX_TYPE_WDS_IPV6 ? QMUX_TYPE_WDS: QMIType]; - sock = qmiclientId[QMIType]; - - pRequest->QMIHdr.ClientId = 0xaa; - if (!s ->service || !sock) { - dbg_time("%s service: %d, sock: %d for QMIType: %d", __func__, s ->service, sock, QMIType); - return -ENODEV; - } - -#ifdef USE_LINUX_MSM_IPC - return xport_send(sock, s->node, s->port, &pRequest->MUXMsg, - le16_to_cpu(pRequest->QMIHdr.Length) + 1 - sizeof(QCQMI_HDR)); -#else - return qrtr_send(sock, s->node, s->port, &pRequest->MUXMsg, - le16_to_cpu(pRequest->QMIHdr.Length) + 1 - sizeof(QCQMI_HDR)); -#endif -} - -static int qmi_deinit(void) { - unsigned int i; - - for (i = 0; i < sizeof(qmiclientId)/sizeof(qmiclientId[0]); i++) - { - if (qmiclientId[i] != 0) - { - close(qmiclientId[i]); - qmiclientId[i] = 0; - } - } - - return 0; -} - -static void * qmi_read(void *pData) { - PROFILE_T *profile = (PROFILE_T *)pData; - int ctrl_sock; - int wait_for_request_quit = 0; - -#ifdef USE_LINUX_MSM_IPC - ctrl_sock = xport_ctrl_init(); - if (ctrl_sock != -1) - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_CONNECTED); -#else - ctrl_sock = qrtr_ctrl_init(); -#endif - - if (ctrl_sock == -1) - goto _quit; - - while (1) { - struct pollfd pollfds[16] = {{qmidevice_control_fd[1], POLLIN, 0}, {ctrl_sock, POLLIN, 0}}; - int ne, ret, nevents = 2; - unsigned int i; - - for (i = 0; i < sizeof(qmiclientId)/sizeof(qmiclientId[0]); i++) - { - if (qmiclientId[i] != 0) - { - pollfds[nevents].fd = qmiclientId[i]; - pollfds[nevents].events = POLLIN; - pollfds[nevents].revents = 0; - nevents++; - } - } - - do { - ret = poll(pollfds, nevents, wait_for_request_quit ? 1000 : -1); - } while ((ret < 0) && (errno == EINTR)); - - if (ret == 0 && wait_for_request_quit) { - QmiThreadRecvQMI(NULL); //main thread may pending on QmiThreadSendQMI() - continue; - } - - if (ret <= 0) { - dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno)); - break; - } - - for (ne = 0; ne < nevents; ne++) { - int fd = pollfds[ne].fd; - short revents = pollfds[ne].revents; - - if (revents & (POLLERR | POLLHUP | POLLNVAL)) { - dbg_time("%s poll err/hup/inval", __func__); - dbg_time("epoll fd = %d, events = 0x%04x", fd, revents); - if (fd == qmidevice_control_fd[1]) { - } else { - } - if (revents & (POLLERR | POLLHUP | POLLNVAL)) - goto _quit; - } - - if ((revents & POLLIN) == 0) - continue; - - if (fd == qmidevice_control_fd[1]) { - int triger_event; - if (read(fd, &triger_event, sizeof(triger_event)) == sizeof(triger_event)) { - //DBG("triger_event = 0x%x", triger_event); - switch (triger_event) { - case RIL_REQUEST_QUIT: - goto _quit; - break; - case SIG_EVENT_STOP: - wait_for_request_quit = 1; - break; - default: - break; - } - } - } - else if (fd == ctrl_sock) { - handle_ctrl_pkt(ctrl_sock); - handle_alloc_client(profile); - } - else - { - PQCQMIMSG pResponse = (PQCQMIMSG)cm_recv_buf; - int rc; - uint32_t sq_node = 0; - uint32_t sq_port = 0; - - rc = qmi_recv(fd, &pResponse->MUXMsg, sizeof(cm_recv_buf) - sizeof(QCQMI_HDR), &sq_node, &sq_port); - if (debug_qmi) - dbg_time("fd %d, node %u, port %x, len: %d", fd, sq_node, sq_port, rc); - - if (rc <= 0) - { - dbg_time("%s read=%d errno: %d (%s)", __func__, rc, errno, strerror(errno)); - break; - } - - for (i = 0; i < sizeof(qmiclientId)/sizeof(qmiclientId[0]); i++) - { - if (qmiclientId[i] == fd) - { - pResponse->QMIHdr.QMIType = i; - - if (service_list[i].node != sq_node || service_list[i].port != sq_port) { - continue; - } - } - } - - pResponse->QMIHdr.IFType = USB_CTL_MSG_TYPE_QMI; - pResponse->QMIHdr.Length = cpu_to_le16(rc + sizeof(QCQMI_HDR) - 1); - pResponse->QMIHdr.CtlFlags = 0x00; - pResponse->QMIHdr.ClientId = 0xaa; - - QmiThreadRecvQMI(pResponse); - } - } - } - -_quit: - qmi_deinit(); - close(ctrl_sock); - qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED); - QmiThreadRecvQMI(NULL); //main thread may pending on QmiThreadSendQMI() - dbg_time("%s exit", __func__); - pthread_exit(NULL); - return NULL; -} - -const struct qmi_device_ops qrtr_qmidev_ops = { - .deinit = qmi_deinit, - .send = qmi_send, - .read = qmi_read, -}; - +//https://github.com/andersson/qrtr +/****************************************************************************** + @file QrtrCM.c + @brief GobiNet driver. + + 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 +#include +#include +#include +#include +#include "QMIThread.h" + +typedef struct { + uint32_t service; + uint32_t version; + uint32_t instance; + uint32_t node; + uint32_t port; +} QrtrService; + +#define QRTR_MAX (QMUX_TYPE_WDS_ADMIN + 1) +static QrtrService service_list[QRTR_MAX]; +static int qmiclientId[QRTR_MAX]; +static int get_client(UCHAR QMIType); +static uint32_t node_modem = 3; //IPQ ~ 3, QCM ~ 0 + +#ifdef USE_LINUX_MSM_IPC +#include + +struct xport_ipc_router_server_addr { + uint32_t service; + uint32_t instance; + uint32_t node_id; + uint32_t port_id; +}; + +union ctl_msg { + uint32_t cmd; + struct { + uint32_t cmd; + uint32_t service; + uint32_t instance; + uint32_t node_id; + uint32_t port_id; + } srv; + struct { + uint32_t cmd; + uint32_t node_id; + uint32_t port_id; + } cli; + }; +#define CTL_CMD_NEW_SERVER 4 +#define CTL_CMD_REMOVE_SERVER 5 + +#define VERSION_MASK 0xff +#define GET_VERSION(x) (x & 0xff) +#define GET_XPORT_SVC_INSTANCE(x) GET_VERSION(x) +#define GET_INSTANCE(x) ((x & 0xff00) >> 8) + +static int msm_ipc_socket(const char *name) +{ + int sock; + int flags; + + sock = socket(AF_MSM_IPC, SOCK_DGRAM, 0); + if (sock < 0) { + dbg_time("%s(%s) errno: %d (%s)\n", __func__, name, errno, strerror(errno)); + return -1; + } + + fcntl(sock, F_SETFD, FD_CLOEXEC); + flags = fcntl(sock, F_GETFL, 0); + fcntl(sock, F_SETFL, flags | O_NONBLOCK); + + return sock; +} + +static uint32_t xport_lookup +( + int lookup_sock_fd, + uint32_t service_id, + uint32_t version +) +{ + uint32_t num_servers_found = 0; + uint32_t num_entries_to_fill = 4; + struct server_lookup_args *lookup_arg; + int i; + + lookup_arg = (struct server_lookup_args *)malloc(sizeof(*lookup_arg) + + (num_entries_to_fill * sizeof(struct msm_ipc_server_info))); + if (!lookup_arg) + { + dbg_time("%s: Malloc failed\n", __func__); + return 0; + } + + lookup_arg->port_name.service = service_id; + lookup_arg->port_name.instance = GET_XPORT_SVC_INSTANCE(version); + lookup_arg->num_entries_in_array = num_entries_to_fill; + lookup_arg->lookup_mask = VERSION_MASK; + lookup_arg->num_entries_found = 0; + if (ioctl(lookup_sock_fd, IPC_ROUTER_IOCTL_LOOKUP_SERVER, lookup_arg) < 0) + { + dbg_time("%s: Lookup failed for %08x: %08x\n", __func__, service_id, version); + free(lookup_arg); + return 0; + } + + dbg_time("%s: num_entries_found %d for type=%d instance=%d", __func__, + lookup_arg->num_entries_found, service_id, version); + num_servers_found = 0; + for (i = 0; ((i < (int)num_entries_to_fill) && (i < lookup_arg->num_entries_found)); i++) + { + QrtrService service_info[1]; + + if (lookup_arg->srv_info[i].node_id != node_modem) + continue; + num_servers_found++; + + service_info[0].service = lookup_arg->srv_info[i].service; + service_info[0].version = GET_VERSION(lookup_arg->srv_info[i].instance); + service_info[0].instance = GET_INSTANCE(lookup_arg->srv_info[i].instance); + service_info[0].node = lookup_arg->srv_info[i].node_id; + service_info[0].port = lookup_arg->srv_info[i].port_id; + + service_list[service_id] = service_info[0]; + qmiclientId[service_id] = get_client(service_id); + } + + free(lookup_arg); + return num_servers_found; +} + +static int xport_send(int sock, uint32_t node, uint32_t port, const void *data, unsigned int sz) +{ + struct sockaddr_msm_ipc addr = {}; + int rc; + + addr.family = AF_MSM_IPC; + addr.address.addrtype = MSM_IPC_ADDR_ID; + addr.address.addr.port_addr.node_id = node; + addr.address.addr.port_addr.port_id = port; + + rc = sendto(sock, data, sz, MSG_DONTWAIT, (void *)&addr, sizeof(addr)); + if (rc < 0) { + dbg_time("xport_send errno: %d (%s)\n", errno, strerror(errno)); + return -1; + } + + return 0; +} + +static int xport_recv(int sock, void *data, unsigned int sz, uint32_t *node, uint32_t *port) +{ + struct sockaddr_msm_ipc addr = {}; + socklen_t addr_size = sizeof(struct sockaddr_msm_ipc); + int rc; + + rc = recvfrom(sock, data, sz, MSG_DONTWAIT, (void *)&addr, &addr_size); + if (rc < 0) { + dbg_time("xport_recv errno: %d (%s)\n", errno, strerror(errno)); + } + else if (addr.address.addrtype != MSM_IPC_ADDR_ID) { + dbg_time("xport_recv addrtype is NOT MSM_IPC_ADDR_ID\n"); + rc = -1; + } + + *node = addr.address.addr.port_addr.node_id; + *port = addr.address.addr.port_addr.port_id; + return rc; +} +#define qmi_recv xport_recv + +static int xport_ctrl_init(void) +{ + int ctrl_sock; + int rc; + uint32_t instance = 1; //modem + uint32_t version; + + ctrl_sock = msm_ipc_socket("ctrl_port"); + if (ctrl_sock == -1) + return -1; + + rc = ioctl(ctrl_sock, IPC_ROUTER_IOCTL_GET_VERSION, &version); + if (rc < 0) { + dbg_time("%s: failed to get ipc version\n", __func__); + goto init_close_ctrl_fd; + } + dbg_time("%s ipc_version = %d", __func__, version); + + rc = ioctl(ctrl_sock, IPC_ROUTER_IOCTL_BIND_CONTROL_PORT, NULL); + if (rc < 0) { + dbg_time("%s: failed to bind as control port\n", __func__); + goto init_close_ctrl_fd; + } + + //cat /sys/kernel/debug/msm_ipc_router/dump_servers + rc = 0; + rc += xport_lookup(ctrl_sock, QMUX_TYPE_WDS, instance); + if (service_list[QMUX_TYPE_WDS].port) { + qmiclientId[QMUX_TYPE_WDS_IPV6] = get_client(QMUX_TYPE_WDS); + } + rc += xport_lookup(ctrl_sock, QMUX_TYPE_NAS, instance); + rc += xport_lookup(ctrl_sock, QMUX_TYPE_UIM, instance); + rc += xport_lookup(ctrl_sock, QMUX_TYPE_DMS, instance); + rc += xport_lookup(ctrl_sock, QMUX_TYPE_WDS_ADMIN, instance); + + if (rc == 0) { + dbg_time("%s: failed to lookup qmi service\n", __func__); + goto init_close_ctrl_fd; + } + + return ctrl_sock; + +init_close_ctrl_fd: + close(ctrl_sock); + return -1; +} + +static void handle_ctrl_pkt(int sock) { + union ctl_msg pkt; + uint32_t type; + int rc; + + rc = recvfrom(sock, &pkt, sizeof(pkt), 0, NULL, NULL); + if (rc < 0) + return; + + type = le32toh(pkt.cmd); + if (CTL_CMD_NEW_SERVER == type || CTL_CMD_REMOVE_SERVER == type) { + QrtrService s; + + s.service = le32toh(pkt.srv.service); + s.version = le32toh(pkt.srv.instance) & 0xff; + s.instance = le32toh(pkt.srv.instance) >> 8; + s.node = le32toh(pkt.srv.node_id); + s.port = le32toh(pkt.srv.port_id); + + if (debug_qmi) + dbg_time ("[qrtr] %s server on %u:%u -> service %u, version %u, instance %u", + CTL_CMD_NEW_SERVER == type ? "add" : "remove", + s.node, s.port, s.service, s.version, s.instance); + + if (CTL_CMD_NEW_SERVER == type) { + if (s.service < QRTR_MAX) { + service_list[s.service] = s; + } + } + else if (CTL_CMD_REMOVE_SERVER == type) { + if (s.service < QRTR_MAX) { + memset(&service_list[s.service], 0, sizeof(QrtrService)); + } + } + } +} +#else +#include +#include "qrtr.h" +#endif + +static int qrtr_socket(void) +{ + struct sockaddr_qrtr sq; + socklen_t sl = sizeof(sq); + int sock; + int rc; + + sock = socket(AF_QIPCRTR, SOCK_DGRAM, 0); + if (sock < 0) { + dbg_time("qrtr_socket errno: %d (%s)\n", errno, strerror(errno)); + return -1; + } + + rc = getsockname(sock, (void *)&sq, &sl); + if (rc || sq.sq_family != AF_QIPCRTR || sl != sizeof(sq)) { + dbg_time("getsockname: %d (%s)\n", errno, strerror(errno)); + close(sock); + return -1; + } + + return sock; +} + +static int qrtr_send(int sock, uint32_t node, uint32_t port, const void *data, unsigned int sz) +{ + struct sockaddr_qrtr sq = {}; + int rc; + + sq.sq_family = AF_QIPCRTR; + sq.sq_node = node; + sq.sq_port = port; + + rc = sendto(sock, data, sz, MSG_DONTWAIT, (void *)&sq, sizeof(sq)); + if (rc < 0) { + dbg_time("sendto errno: %d (%s)\n", errno, strerror(errno)); + return -1; + } + + return 0; +} + +static int qrtr_recv(int sock, void *data, unsigned int sz, uint32_t *node, uint32_t *port) +{ + struct sockaddr_qrtr sq = {}; + socklen_t sl = sizeof(sq); + int rc; + + rc = recvfrom(sock, data, sz, MSG_DONTWAIT, (void *)&sq, &sl); + if (rc < 0) { + dbg_time("qrtr_recv errno: %d (%s)\n", errno, strerror(errno)); + } + + *node = sq.sq_node; + *port = sq.sq_port; + return rc; + } +#define qmi_recv qrtr_recv + +static int qrtr_ctrl_init(void) { + int sock; + int rc; + struct qrtr_ctrl_pkt pkt; + struct sockaddr_qrtr sq; + socklen_t sl = sizeof(sq); + + sock = qrtr_socket(); + if (sock == -1) + return -1; + + memset(&pkt, 0, sizeof(pkt)); + pkt.cmd = htole32(QRTR_TYPE_NEW_LOOKUP); + + getsockname(sock, (void *)&sq, &sl); + rc = qrtr_send(sock, sq.sq_node, QRTR_PORT_CTRL, &pkt, sizeof(pkt)); + if (rc == -1) { + dbg_time("qrtr_send errno: %d (%s)\n", errno, strerror(errno)); + close(sock); + return -1; + } + + return sock; +} + +static void handle_server_change(uint32_t type, struct qrtr_ctrl_pkt *ppkt) { + struct qrtr_ctrl_pkt pkt = *ppkt; + QrtrService s; + + s.service = le32toh(pkt.server.service); + s.version = le32toh(pkt.server.instance) & 0xff; + s.instance = le32toh(pkt.server.instance) >> 8; + s.node = le32toh(pkt.server.node); + s.port = le32toh(pkt.server.port); + + if (debug_qmi) + dbg_time ("[qrtr] %s server on %u:%u -> service %u, version %u, instance %u", + QRTR_TYPE_NEW_SERVER == type ? "add" : "remove", + s.node, s.port, s.service, s.version, s.instance); + + if (s.node != node_modem) + return; //we only care modem + + if (QRTR_TYPE_NEW_SERVER == type) { + if (s.service < QRTR_MAX) { + service_list[s.service] = s; + } + } + else if (QRTR_TYPE_DEL_SERVER == type) { + if (s.service < QRTR_MAX) { + memset(&service_list[s.service], 0, sizeof(QrtrService)); + } + } + } + +static void handle_ctrl_pkt(int sock) { + struct qrtr_ctrl_pkt pkt; + struct sockaddr_qrtr sq; + socklen_t sl = sizeof(sq); + uint32_t type; + int rc; + + rc = recvfrom(sock, &pkt, sizeof(pkt), 0, (void *)&sq, &sl); + if (rc < 0) + return; + + type = le32toh(pkt.cmd); + if (debug_qmi) + dbg_time("type %u, node %u, sq.port %x, len: %d", type, sq.sq_node, sq.sq_port, rc); + + if (sq.sq_port != QRTR_PORT_CTRL) + return; + + if (QRTR_TYPE_NEW_SERVER == type || QRTR_TYPE_DEL_SERVER == type) { + handle_server_change(type, &pkt); + } +} + +static int get_client(UCHAR QMIType) { + int ClientId; + QrtrService *s = &service_list[QMIType]; + + if (!s ->service) { + dbg_time("%s service: %d for QMIType: %d", __func__, s ->service, QMIType); + return -ENODEV; + } + +#ifdef USE_LINUX_MSM_IPC + ClientId = msm_ipc_socket("xport"); +#else + ClientId = qrtr_socket(); +#endif + if (ClientId == -1) { + return 0; + } + + switch (QMIType) { + case QMUX_TYPE_WDS: dbg_time("Get clientWDS = %d", ClientId); break; + case QMUX_TYPE_DMS: dbg_time("Get clientDMS = %d", ClientId); break; + case QMUX_TYPE_NAS: dbg_time("Get clientNAS = %d", ClientId); break; + case QMUX_TYPE_QOS: dbg_time("Get clientQOS = %d", ClientId); break; + case QMUX_TYPE_WMS: dbg_time("Get clientWMS = %d", ClientId); break; + case QMUX_TYPE_PDS: dbg_time("Get clientPDS = %d", ClientId); break; + case QMUX_TYPE_UIM: dbg_time("Get clientUIM = %d", ClientId); break; + case QMUX_TYPE_WDS_ADMIN: dbg_time("Get clientWDA = %d", ClientId); + break; + default: break; + } + + return ClientId; +} + +static void handle_alloc_client(PROFILE_T *profile) { + int srv_list[] = {QMUX_TYPE_WDS, QMUX_TYPE_NAS, QMUX_TYPE_UIM, QMUX_TYPE_DMS, QMUX_TYPE_WDS_ADMIN}; + size_t i = 0, srv_ready = 0; + static int report = -1; + + if (report != -1) + return; + + for(i = 0; i < sizeof(srv_list)/sizeof(srv_list[0]); i++) { + int srv = srv_list[i]; + + if (service_list[srv].service) + srv_ready++; + else + continue; + + if (qmiclientId[srv] == 0) { + qmiclientId[srv] = get_client(srv); + + if (qmiclientId[srv] != 0) { + if (srv == QMUX_TYPE_WDS) { + qmiclientId[QMUX_TYPE_WDS_IPV6] = get_client(QMUX_TYPE_WDS); + } + else if (srv == QMUX_TYPE_WDS_ADMIN) { + profile->wda_client = qmiclientId[QMUX_TYPE_WDS_ADMIN]; + } + } + } + } + + if (srv_ready == sizeof(srv_list)/sizeof(srv_list[0])) { + if (qmiclientId[QMUX_TYPE_WDS]) { + qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_CONNECTED); + } else { + qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED); + } + report = 1; + } +} + +static int qmi_send(PQCQMIMSG pRequest) { + uint8_t QMIType = pRequest->QMIHdr.QMIType; + int sock; + QrtrService *s = &service_list[QMIType == QMUX_TYPE_WDS_IPV6 ? QMUX_TYPE_WDS: QMIType]; + sock = qmiclientId[QMIType]; + + pRequest->QMIHdr.ClientId = 0xaa; + if (!s ->service || !sock) { + dbg_time("%s service: %d, sock: %d for QMIType: %d", __func__, s ->service, sock, QMIType); + return -ENODEV; + } + +#ifdef USE_LINUX_MSM_IPC + return xport_send(sock, s->node, s->port, &pRequest->MUXMsg, + le16_to_cpu(pRequest->QMIHdr.Length) + 1 - sizeof(QCQMI_HDR)); +#else + return qrtr_send(sock, s->node, s->port, &pRequest->MUXMsg, + le16_to_cpu(pRequest->QMIHdr.Length) + 1 - sizeof(QCQMI_HDR)); +#endif +} + +static int qmi_deinit(void) { + unsigned int i; + + for (i = 0; i < sizeof(qmiclientId)/sizeof(qmiclientId[0]); i++) + { + if (qmiclientId[i] != 0) + { + close(qmiclientId[i]); + qmiclientId[i] = 0; + } + } + + return 0; +} + +static void * qmi_read(void *pData) { + PROFILE_T *profile = (PROFILE_T *)pData; + int ctrl_sock; + int wait_for_request_quit = 0; + +#ifdef USE_LINUX_MSM_IPC + ctrl_sock = xport_ctrl_init(); + if (ctrl_sock != -1) + qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_CONNECTED); +#else + ctrl_sock = qrtr_ctrl_init(); +#endif + + if (ctrl_sock == -1) + goto _quit; + + while (1) { + struct pollfd pollfds[16] = {{qmidevice_control_fd[1], POLLIN, 0}, {ctrl_sock, POLLIN, 0}}; + int ne, ret, nevents = 2; + unsigned int i; + + for (i = 0; i < sizeof(qmiclientId)/sizeof(qmiclientId[0]); i++) + { + if (qmiclientId[i] != 0) + { + pollfds[nevents].fd = qmiclientId[i]; + pollfds[nevents].events = POLLIN; + pollfds[nevents].revents = 0; + nevents++; + } + } + + do { + ret = poll(pollfds, nevents, wait_for_request_quit ? 1000 : -1); + } while ((ret < 0) && (errno == EINTR)); + + if (ret == 0 && wait_for_request_quit) { + QmiThreadRecvQMI(NULL); //main thread may pending on QmiThreadSendQMI() + continue; + } + + if (ret <= 0) { + dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno)); + break; + } + + for (ne = 0; ne < nevents; ne++) { + int fd = pollfds[ne].fd; + short revents = pollfds[ne].revents; + + if (revents & (POLLERR | POLLHUP | POLLNVAL)) { + dbg_time("%s poll err/hup/inval", __func__); + dbg_time("epoll fd = %d, events = 0x%04x", fd, revents); + if (fd == qmidevice_control_fd[1]) { + } else { + } + if (revents & (POLLERR | POLLHUP | POLLNVAL)) + goto _quit; + } + + if ((revents & POLLIN) == 0) + continue; + + if (fd == qmidevice_control_fd[1]) { + int triger_event; + if (read(fd, &triger_event, sizeof(triger_event)) == sizeof(triger_event)) { + //DBG("triger_event = 0x%x", triger_event); + switch (triger_event) { + case RIL_REQUEST_QUIT: + goto _quit; + break; + case SIG_EVENT_STOP: + wait_for_request_quit = 1; + break; + default: + break; + } + } + } + else if (fd == ctrl_sock) { + handle_ctrl_pkt(ctrl_sock); + handle_alloc_client(profile); + } + else + { + PQCQMIMSG pResponse = (PQCQMIMSG)cm_recv_buf; + int rc; + uint32_t sq_node = 0; + uint32_t sq_port = 0; + + rc = qmi_recv(fd, &pResponse->MUXMsg, sizeof(cm_recv_buf) - sizeof(QCQMI_HDR), &sq_node, &sq_port); + if (debug_qmi) + dbg_time("fd %d, node %u, port %x, len: %d", fd, sq_node, sq_port, rc); + + if (rc <= 0) + { + dbg_time("%s read=%d errno: %d (%s)", __func__, rc, errno, strerror(errno)); + break; + } + + for (i = 0; i < sizeof(qmiclientId)/sizeof(qmiclientId[0]); i++) + { + if (qmiclientId[i] == fd) + { + pResponse->QMIHdr.QMIType = i; + + if (service_list[i].node != sq_node || service_list[i].port != sq_port) { + continue; + } + } + } + + pResponse->QMIHdr.IFType = USB_CTL_MSG_TYPE_QMI; + pResponse->QMIHdr.Length = cpu_to_le16(rc + sizeof(QCQMI_HDR) - 1); + pResponse->QMIHdr.CtlFlags = 0x00; + pResponse->QMIHdr.ClientId = 0xaa; + + QmiThreadRecvQMI(pResponse); + } + } + } + +_quit: + qmi_deinit(); + close(ctrl_sock); + qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED); + QmiThreadRecvQMI(NULL); //main thread may pending on QmiThreadSendQMI() + dbg_time("%s exit", __func__); + pthread_exit(NULL); + return NULL; +} + +const struct qmi_device_ops qrtr_qmidev_ops = { + .deinit = qmi_deinit, + .send = qmi_send, + .read = qmi_read, +}; + diff --git a/wwan/app/quectel_cm_5G/src/qrtr.h b/wwan/app/quectel-cm/src/qrtr.h similarity index 100% rename from wwan/app/quectel_cm_5G/src/qrtr.h rename to wwan/app/quectel-cm/src/qrtr.h diff --git a/wwan/app/quectel_cm_5G/src/quectel-atc-proxy.c b/wwan/app/quectel-cm/src/quectel-atc-proxy.c similarity index 100% rename from wwan/app/quectel_cm_5G/src/quectel-atc-proxy.c rename to wwan/app/quectel-cm/src/quectel-atc-proxy.c diff --git a/wwan/app/quectel_cm_5G/src/quectel-mbim-proxy.c b/wwan/app/quectel-cm/src/quectel-mbim-proxy.c similarity index 100% rename from wwan/app/quectel_cm_5G/src/quectel-mbim-proxy.c rename to wwan/app/quectel-cm/src/quectel-mbim-proxy.c diff --git a/wwan/app/quectel_cm_5G/src/quectel-qmi-proxy.c b/wwan/app/quectel-cm/src/quectel-qmi-proxy.c similarity index 100% rename from wwan/app/quectel_cm_5G/src/quectel-qmi-proxy.c rename to wwan/app/quectel-cm/src/quectel-qmi-proxy.c diff --git a/wwan/app/quectel_cm_5G/src/quectel-qrtr-proxy.c b/wwan/app/quectel-cm/src/quectel-qrtr-proxy.c similarity index 100% rename from wwan/app/quectel_cm_5G/src/quectel-qrtr-proxy.c rename to wwan/app/quectel-cm/src/quectel-qrtr-proxy.c diff --git a/wwan/app/quectel_cm_5G/src/rmnetctl.c b/wwan/app/quectel-cm/src/rmnetctl.c similarity index 96% rename from wwan/app/quectel_cm_5G/src/rmnetctl.c rename to wwan/app/quectel-cm/src/rmnetctl.c index 3a9aae9..5b2fb0f 100644 --- a/wwan/app/quectel_cm_5G/src/rmnetctl.c +++ b/wwan/app/quectel-cm/src/rmnetctl.c @@ -1,342 +1,342 @@ -//https://source.codeaurora.org/quic/la/platform/vendor/qcom-opensource/dataservices/tree/rmnetctl -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define RMNETCTL_SUCCESS 0 -#define RMNETCTL_LIB_ERR 1 -#define RMNETCTL_KERNEL_ERR 2 -#define RMNETCTL_INVALID_ARG 3 - -enum rmnetctl_error_codes_e { - RMNETCTL_API_SUCCESS = 0, - - RMNETCTL_API_FIRST_ERR = 1, - RMNETCTL_API_ERR_MESSAGE_SEND = 3, - RMNETCTL_API_ERR_MESSAGE_RECEIVE = 4, - - RMNETCTL_INIT_FIRST_ERR = 5, - RMNETCTL_INIT_ERR_PROCESS_ID = RMNETCTL_INIT_FIRST_ERR, - RMNETCTL_INIT_ERR_NETLINK_FD = 6, - RMNETCTL_INIT_ERR_BIND = 7, - - RMNETCTL_API_SECOND_ERR = 9, - RMNETCTL_API_ERR_HNDL_INVALID = RMNETCTL_API_SECOND_ERR, - RMNETCTL_API_ERR_RETURN_TYPE = 13, -}; - -struct rmnetctl_hndl_s { - uint32_t pid; - uint32_t transaction_id; - int netlink_fd; - struct sockaddr_nl src_addr, dest_addr; -}; -typedef struct rmnetctl_hndl_s rmnetctl_hndl_t; - -#define NLMSG_TAIL(nmsg) \ - ((struct rtattr *) (((char *)(nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) - -struct nlmsg { - struct nlmsghdr nl_addr; - struct ifinfomsg ifmsg; - char data[500]; -}; - -#define MIN_VALID_PROCESS_ID 0 -#define MIN_VALID_SOCKET_FD 0 -#define KERNEL_PROCESS_ID 0 -#define UNICAST 0 - -enum { - IFLA_RMNET_UL_AGG_PARAMS = __IFLA_RMNET_MAX, - __IFLA_RMNET_EXT_MAX, -}; - -struct rmnet_egress_agg_params { - uint16_t agg_size; - uint16_t agg_count; - uint32_t agg_time; -}; - -static int rmnet_get_ack(rmnetctl_hndl_t *hndl, uint16_t *error_code) -{ - struct nlack { - struct nlmsghdr ackheader; - struct nlmsgerr ackdata; - char data[256]; - - } ack; - int i; - - if (!hndl || !error_code) - return RMNETCTL_INVALID_ARG; - - if ((i = recv(hndl->netlink_fd, &ack, sizeof(ack), 0)) < 0) { - *error_code = errno; - return RMNETCTL_API_ERR_MESSAGE_RECEIVE; - } - - /*Ack should always be NLMSG_ERROR type*/ - if (ack.ackheader.nlmsg_type == NLMSG_ERROR) { - if (ack.ackdata.error == 0) { - *error_code = RMNETCTL_API_SUCCESS; - return RMNETCTL_SUCCESS; - } else { - *error_code = -ack.ackdata.error; - return RMNETCTL_KERNEL_ERR; - } - } - - *error_code = RMNETCTL_API_ERR_RETURN_TYPE; - return RMNETCTL_API_FIRST_ERR; -} - -static int rtrmnet_ctl_init(rmnetctl_hndl_t **hndl, uint16_t *error_code) -{ - struct sockaddr_nl __attribute__((__may_alias__)) *saddr_ptr; - int netlink_fd = -1; - pid_t pid = 0; - - if (!hndl || !error_code) - return RMNETCTL_INVALID_ARG; - - *hndl = (rmnetctl_hndl_t *)malloc(sizeof(rmnetctl_hndl_t)); - if (!*hndl) { - *error_code = RMNETCTL_API_ERR_HNDL_INVALID; - return RMNETCTL_LIB_ERR; - } - - memset(*hndl, 0, sizeof(rmnetctl_hndl_t)); - - pid = getpid(); - if (pid < MIN_VALID_PROCESS_ID) { - free(*hndl); - *error_code = RMNETCTL_INIT_ERR_PROCESS_ID; - return RMNETCTL_LIB_ERR; - } - (*hndl)->pid = KERNEL_PROCESS_ID; - netlink_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if (netlink_fd < MIN_VALID_SOCKET_FD) { - free(*hndl); - *error_code = RMNETCTL_INIT_ERR_NETLINK_FD; - return RMNETCTL_LIB_ERR; - } - - (*hndl)->netlink_fd = netlink_fd; - - memset(&(*hndl)->src_addr, 0, sizeof(struct sockaddr_nl)); - - (*hndl)->src_addr.nl_family = AF_NETLINK; - (*hndl)->src_addr.nl_pid = (*hndl)->pid; - - saddr_ptr = &(*hndl)->src_addr; - if (bind((*hndl)->netlink_fd, - (struct sockaddr *)saddr_ptr, - sizeof(struct sockaddr_nl)) < 0) { - close((*hndl)->netlink_fd); - free(*hndl); - *error_code = RMNETCTL_INIT_ERR_BIND; - return RMNETCTL_LIB_ERR; - } - - memset(&(*hndl)->dest_addr, 0, sizeof(struct sockaddr_nl)); - - (*hndl)->dest_addr.nl_family = AF_NETLINK; - (*hndl)->dest_addr.nl_pid = KERNEL_PROCESS_ID; - (*hndl)->dest_addr.nl_groups = UNICAST; - - return RMNETCTL_SUCCESS; -} - -static int rtrmnet_ctl_deinit(rmnetctl_hndl_t *hndl) -{ - if (!hndl) - return RMNETCTL_SUCCESS; - - close(hndl->netlink_fd); - free(hndl); - - return RMNETCTL_SUCCESS; -} - -static int rtrmnet_ctl_newvnd(rmnetctl_hndl_t *hndl, char *devname, char *vndname, - uint16_t *error_code, uint8_t index, - uint32_t flagconfig, uint32_t ul_agg_cnt, uint32_t ul_agg_size) -{ - struct rtattr *attrinfo, *datainfo, *linkinfo; - struct ifla_vlan_flags flags; - int devindex = 0, val = 0; - char *kind = "rmnet"; - struct nlmsg req; - short id; - - if (!hndl || !devname || !vndname || !error_code) - return RMNETCTL_INVALID_ARG; - - memset(&req, 0, sizeof(req)); - req.nl_addr.nlmsg_type = RTM_NEWLINK; - req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); - req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | - NLM_F_ACK; - req.nl_addr.nlmsg_seq = hndl->transaction_id; - hndl->transaction_id++; - - /* Get index of devname*/ - devindex = if_nametoindex(devname); - if (devindex < 0) { - *error_code = errno; - return RMNETCTL_KERNEL_ERR; - } - - /* Setup link attr with devindex as data */ - val = devindex; - attrinfo = (struct rtattr *)(((char *)&req) + - NLMSG_ALIGN(req.nl_addr.nlmsg_len)); - attrinfo->rta_type = IFLA_LINK; - attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(sizeof(val))); - memcpy(RTA_DATA(attrinfo), &val, sizeof(val)); - req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) + - RTA_ALIGN(RTA_LENGTH(sizeof(val))); - - /* Set up IFLA info kind RMNET that has linkinfo and type */ - attrinfo = (struct rtattr *)(((char *)&req) + - NLMSG_ALIGN(req.nl_addr.nlmsg_len)); - attrinfo->rta_type = IFLA_IFNAME; - attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1)); - memcpy(RTA_DATA(attrinfo), vndname, strlen(vndname) + 1); - req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) + - RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1)); - - linkinfo = (struct rtattr *)(((char *)&req) + - NLMSG_ALIGN(req.nl_addr.nlmsg_len)); - linkinfo->rta_type = IFLA_LINKINFO; - linkinfo->rta_len = RTA_ALIGN(RTA_LENGTH(0)); - req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) + - RTA_ALIGN(RTA_LENGTH(0)); - - attrinfo = (struct rtattr *)(((char *)&req) + - NLMSG_ALIGN(req.nl_addr.nlmsg_len)); - attrinfo->rta_type = IFLA_INFO_KIND; - attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(kind))); - memcpy(RTA_DATA(attrinfo), kind, strlen(kind)); - req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) + - RTA_ALIGN(RTA_LENGTH(strlen(kind))); - - datainfo = (struct rtattr *)(((char *)&req) + - NLMSG_ALIGN(req.nl_addr.nlmsg_len)); - datainfo->rta_type = IFLA_INFO_DATA; - datainfo->rta_len = RTA_ALIGN(RTA_LENGTH(0)); - req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) + - RTA_ALIGN(RTA_LENGTH(0)); - - id = index; - attrinfo = (struct rtattr *)(((char *)&req) + - NLMSG_ALIGN(req.nl_addr.nlmsg_len)); - attrinfo->rta_type = IFLA_VLAN_ID; - attrinfo->rta_len = RTA_LENGTH(sizeof(id)); - memcpy(RTA_DATA(attrinfo), &id, sizeof(id)); - req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) + - RTA_ALIGN(RTA_LENGTH(sizeof(id))); - - if (flagconfig != 0) { - flags.mask = flagconfig; - flags.flags = flagconfig; - - attrinfo = (struct rtattr *)(((char *)&req) + - NLMSG_ALIGN(req.nl_addr.nlmsg_len)); - attrinfo->rta_type = IFLA_VLAN_FLAGS; - attrinfo->rta_len = RTA_LENGTH(sizeof(flags)); - memcpy(RTA_DATA(attrinfo), &flags, sizeof(flags)); - req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) + - RTA_ALIGN(RTA_LENGTH(sizeof(flags))); - } - - if (ul_agg_cnt > 1) { - struct rmnet_egress_agg_params agg_params; - - agg_params.agg_size = ul_agg_size; - agg_params.agg_count = ul_agg_cnt; - agg_params.agg_time = 3000000; - - attrinfo = (struct rtattr *)(((char *)&req) + - NLMSG_ALIGN(req.nl_addr.nlmsg_len)); - attrinfo->rta_type = IFLA_RMNET_UL_AGG_PARAMS; - attrinfo->rta_len = RTA_LENGTH(sizeof(agg_params)); - memcpy(RTA_DATA(attrinfo), &agg_params, sizeof(agg_params)); - req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) + - RTA_ALIGN(RTA_LENGTH(sizeof(agg_params))); - } - - datainfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)datainfo; - - linkinfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)linkinfo; - - if (send(hndl->netlink_fd, &req, req.nl_addr.nlmsg_len, 0) < 0) { - *error_code = RMNETCTL_API_ERR_MESSAGE_SEND; - return RMNETCTL_LIB_ERR; - } - - return rmnet_get_ack(hndl, error_code); -} - -int rtrmnet_ctl_create_vnd(char *devname, char *vndname, uint8_t muxid, - uint32_t qmap_version, uint32_t ul_agg_cnt, uint32_t ul_agg_size) -{ - struct rmnetctl_hndl_s *handle; - uint16_t error_code; - int return_code; - uint32_t flagconfig = RMNET_FLAGS_INGRESS_DEAGGREGATION; - - printf("%s devname: %s, vndname: %s, muxid: %d, qmap_version: %d\n", - __func__, devname, vndname, muxid, qmap_version); - - ul_agg_cnt = 0; //TODO - - if (ul_agg_cnt > 1) - flagconfig |= RMNET_EGRESS_FORMAT_AGGREGATION; - - if (qmap_version == 9) { //QMAPV5 -#ifdef RMNET_FLAGS_INGRESS_MAP_CKSUMV5 - flagconfig |= RMNET_FLAGS_INGRESS_MAP_CKSUMV5; - flagconfig |= RMNET_FLAGS_EGRESS_MAP_CKSUMV5; -#else - return -1001; -#endif - } - else if (qmap_version == 8) { //QMAPV4 - flagconfig |= RMNET_FLAGS_INGRESS_MAP_CKSUMV4; - flagconfig |= RMNET_FLAGS_EGRESS_MAP_CKSUMV4; - } - else if (qmap_version == 5) { //QMAPV1 - } - else { - flagconfig = 0; - } - - return_code = rtrmnet_ctl_init(&handle, &error_code); - if (return_code) { - printf("rtrmnet_ctl_init error_code: %d, return_code: %d, errno: %d (%s)\n", - error_code, return_code, errno, strerror(errno)); - } - if (return_code == RMNETCTL_SUCCESS) { - return_code = rtrmnet_ctl_newvnd(handle, devname, vndname, &error_code, - muxid, flagconfig, ul_agg_cnt, ul_agg_size); - if (return_code) { - printf("rtrmnet_ctl_newvnd error_code: %d, return_code: %d, errno: %d (%s)\n", - error_code, return_code, errno, strerror(errno)); - } - rtrmnet_ctl_deinit(handle); - } - - return return_code; -} +//https://source.codeaurora.org/quic/la/platform/vendor/qcom-opensource/dataservices/tree/rmnetctl +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RMNETCTL_SUCCESS 0 +#define RMNETCTL_LIB_ERR 1 +#define RMNETCTL_KERNEL_ERR 2 +#define RMNETCTL_INVALID_ARG 3 + +enum rmnetctl_error_codes_e { + RMNETCTL_API_SUCCESS = 0, + + RMNETCTL_API_FIRST_ERR = 1, + RMNETCTL_API_ERR_MESSAGE_SEND = 3, + RMNETCTL_API_ERR_MESSAGE_RECEIVE = 4, + + RMNETCTL_INIT_FIRST_ERR = 5, + RMNETCTL_INIT_ERR_PROCESS_ID = RMNETCTL_INIT_FIRST_ERR, + RMNETCTL_INIT_ERR_NETLINK_FD = 6, + RMNETCTL_INIT_ERR_BIND = 7, + + RMNETCTL_API_SECOND_ERR = 9, + RMNETCTL_API_ERR_HNDL_INVALID = RMNETCTL_API_SECOND_ERR, + RMNETCTL_API_ERR_RETURN_TYPE = 13, +}; + +struct rmnetctl_hndl_s { + uint32_t pid; + uint32_t transaction_id; + int netlink_fd; + struct sockaddr_nl src_addr, dest_addr; +}; +typedef struct rmnetctl_hndl_s rmnetctl_hndl_t; + +#define NLMSG_TAIL(nmsg) \ + ((struct rtattr *) (((char *)(nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) + +struct nlmsg { + struct nlmsghdr nl_addr; + struct ifinfomsg ifmsg; + char data[500]; +}; + +#define MIN_VALID_PROCESS_ID 0 +#define MIN_VALID_SOCKET_FD 0 +#define KERNEL_PROCESS_ID 0 +#define UNICAST 0 + +enum { + IFLA_RMNET_UL_AGG_PARAMS = __IFLA_RMNET_MAX, + __IFLA_RMNET_EXT_MAX, +}; + +struct rmnet_egress_agg_params { + uint16_t agg_size; + uint16_t agg_count; + uint32_t agg_time; +}; + +static int rmnet_get_ack(rmnetctl_hndl_t *hndl, uint16_t *error_code) +{ + struct nlack { + struct nlmsghdr ackheader; + struct nlmsgerr ackdata; + char data[256]; + + } ack; + int i; + + if (!hndl || !error_code) + return RMNETCTL_INVALID_ARG; + + if ((i = recv(hndl->netlink_fd, &ack, sizeof(ack), 0)) < 0) { + *error_code = errno; + return RMNETCTL_API_ERR_MESSAGE_RECEIVE; + } + + /*Ack should always be NLMSG_ERROR type*/ + if (ack.ackheader.nlmsg_type == NLMSG_ERROR) { + if (ack.ackdata.error == 0) { + *error_code = RMNETCTL_API_SUCCESS; + return RMNETCTL_SUCCESS; + } else { + *error_code = -ack.ackdata.error; + return RMNETCTL_KERNEL_ERR; + } + } + + *error_code = RMNETCTL_API_ERR_RETURN_TYPE; + return RMNETCTL_API_FIRST_ERR; +} + +static int rtrmnet_ctl_init(rmnetctl_hndl_t **hndl, uint16_t *error_code) +{ + struct sockaddr_nl __attribute__((__may_alias__)) *saddr_ptr; + int netlink_fd = -1; + pid_t pid = 0; + + if (!hndl || !error_code) + return RMNETCTL_INVALID_ARG; + + *hndl = (rmnetctl_hndl_t *)malloc(sizeof(rmnetctl_hndl_t)); + if (!*hndl) { + *error_code = RMNETCTL_API_ERR_HNDL_INVALID; + return RMNETCTL_LIB_ERR; + } + + memset(*hndl, 0, sizeof(rmnetctl_hndl_t)); + + pid = getpid(); + if (pid < MIN_VALID_PROCESS_ID) { + free(*hndl); + *error_code = RMNETCTL_INIT_ERR_PROCESS_ID; + return RMNETCTL_LIB_ERR; + } + (*hndl)->pid = KERNEL_PROCESS_ID; + netlink_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + if (netlink_fd < MIN_VALID_SOCKET_FD) { + free(*hndl); + *error_code = RMNETCTL_INIT_ERR_NETLINK_FD; + return RMNETCTL_LIB_ERR; + } + + (*hndl)->netlink_fd = netlink_fd; + + memset(&(*hndl)->src_addr, 0, sizeof(struct sockaddr_nl)); + + (*hndl)->src_addr.nl_family = AF_NETLINK; + (*hndl)->src_addr.nl_pid = (*hndl)->pid; + + saddr_ptr = &(*hndl)->src_addr; + if (bind((*hndl)->netlink_fd, + (struct sockaddr *)saddr_ptr, + sizeof(struct sockaddr_nl)) < 0) { + close((*hndl)->netlink_fd); + free(*hndl); + *error_code = RMNETCTL_INIT_ERR_BIND; + return RMNETCTL_LIB_ERR; + } + + memset(&(*hndl)->dest_addr, 0, sizeof(struct sockaddr_nl)); + + (*hndl)->dest_addr.nl_family = AF_NETLINK; + (*hndl)->dest_addr.nl_pid = KERNEL_PROCESS_ID; + (*hndl)->dest_addr.nl_groups = UNICAST; + + return RMNETCTL_SUCCESS; +} + +static int rtrmnet_ctl_deinit(rmnetctl_hndl_t *hndl) +{ + if (!hndl) + return RMNETCTL_SUCCESS; + + close(hndl->netlink_fd); + free(hndl); + + return RMNETCTL_SUCCESS; +} + +static int rtrmnet_ctl_newvnd(rmnetctl_hndl_t *hndl, char *devname, char *vndname, + uint16_t *error_code, uint8_t index, + uint32_t flagconfig, uint32_t ul_agg_cnt, uint32_t ul_agg_size) +{ + struct rtattr *attrinfo, *datainfo, *linkinfo; + struct ifla_vlan_flags flags; + int devindex = 0, val = 0; + char *kind = "rmnet"; + struct nlmsg req; + short id; + + if (!hndl || !devname || !vndname || !error_code) + return RMNETCTL_INVALID_ARG; + + memset(&req, 0, sizeof(req)); + req.nl_addr.nlmsg_type = RTM_NEWLINK; + req.nl_addr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); + req.nl_addr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL | + NLM_F_ACK; + req.nl_addr.nlmsg_seq = hndl->transaction_id; + hndl->transaction_id++; + + /* Get index of devname*/ + devindex = if_nametoindex(devname); + if (devindex < 0) { + *error_code = errno; + return RMNETCTL_KERNEL_ERR; + } + + /* Setup link attr with devindex as data */ + val = devindex; + attrinfo = (struct rtattr *)(((char *)&req) + + NLMSG_ALIGN(req.nl_addr.nlmsg_len)); + attrinfo->rta_type = IFLA_LINK; + attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(sizeof(val))); + memcpy(RTA_DATA(attrinfo), &val, sizeof(val)); + req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) + + RTA_ALIGN(RTA_LENGTH(sizeof(val))); + + /* Set up IFLA info kind RMNET that has linkinfo and type */ + attrinfo = (struct rtattr *)(((char *)&req) + + NLMSG_ALIGN(req.nl_addr.nlmsg_len)); + attrinfo->rta_type = IFLA_IFNAME; + attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1)); + memcpy(RTA_DATA(attrinfo), vndname, strlen(vndname) + 1); + req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) + + RTA_ALIGN(RTA_LENGTH(strlen(vndname) + 1)); + + linkinfo = (struct rtattr *)(((char *)&req) + + NLMSG_ALIGN(req.nl_addr.nlmsg_len)); + linkinfo->rta_type = IFLA_LINKINFO; + linkinfo->rta_len = RTA_ALIGN(RTA_LENGTH(0)); + req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) + + RTA_ALIGN(RTA_LENGTH(0)); + + attrinfo = (struct rtattr *)(((char *)&req) + + NLMSG_ALIGN(req.nl_addr.nlmsg_len)); + attrinfo->rta_type = IFLA_INFO_KIND; + attrinfo->rta_len = RTA_ALIGN(RTA_LENGTH(strlen(kind))); + memcpy(RTA_DATA(attrinfo), kind, strlen(kind)); + req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) + + RTA_ALIGN(RTA_LENGTH(strlen(kind))); + + datainfo = (struct rtattr *)(((char *)&req) + + NLMSG_ALIGN(req.nl_addr.nlmsg_len)); + datainfo->rta_type = IFLA_INFO_DATA; + datainfo->rta_len = RTA_ALIGN(RTA_LENGTH(0)); + req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) + + RTA_ALIGN(RTA_LENGTH(0)); + + id = index; + attrinfo = (struct rtattr *)(((char *)&req) + + NLMSG_ALIGN(req.nl_addr.nlmsg_len)); + attrinfo->rta_type = IFLA_VLAN_ID; + attrinfo->rta_len = RTA_LENGTH(sizeof(id)); + memcpy(RTA_DATA(attrinfo), &id, sizeof(id)); + req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) + + RTA_ALIGN(RTA_LENGTH(sizeof(id))); + + if (flagconfig != 0) { + flags.mask = flagconfig; + flags.flags = flagconfig; + + attrinfo = (struct rtattr *)(((char *)&req) + + NLMSG_ALIGN(req.nl_addr.nlmsg_len)); + attrinfo->rta_type = IFLA_VLAN_FLAGS; + attrinfo->rta_len = RTA_LENGTH(sizeof(flags)); + memcpy(RTA_DATA(attrinfo), &flags, sizeof(flags)); + req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) + + RTA_ALIGN(RTA_LENGTH(sizeof(flags))); + } + + if (ul_agg_cnt > 1) { + struct rmnet_egress_agg_params agg_params; + + agg_params.agg_size = ul_agg_size; + agg_params.agg_count = ul_agg_cnt; + agg_params.agg_time = 3000000; + + attrinfo = (struct rtattr *)(((char *)&req) + + NLMSG_ALIGN(req.nl_addr.nlmsg_len)); + attrinfo->rta_type = IFLA_RMNET_UL_AGG_PARAMS; + attrinfo->rta_len = RTA_LENGTH(sizeof(agg_params)); + memcpy(RTA_DATA(attrinfo), &agg_params, sizeof(agg_params)); + req.nl_addr.nlmsg_len = NLMSG_ALIGN(req.nl_addr.nlmsg_len) + + RTA_ALIGN(RTA_LENGTH(sizeof(agg_params))); + } + + datainfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)datainfo; + + linkinfo->rta_len = (char *)NLMSG_TAIL(&req.nl_addr) - (char *)linkinfo; + + if (send(hndl->netlink_fd, &req, req.nl_addr.nlmsg_len, 0) < 0) { + *error_code = RMNETCTL_API_ERR_MESSAGE_SEND; + return RMNETCTL_LIB_ERR; + } + + return rmnet_get_ack(hndl, error_code); +} + +int rtrmnet_ctl_create_vnd(char *devname, char *vndname, uint8_t muxid, + uint32_t qmap_version, uint32_t ul_agg_cnt, uint32_t ul_agg_size) +{ + struct rmnetctl_hndl_s *handle; + uint16_t error_code; + int return_code; + uint32_t flagconfig = RMNET_FLAGS_INGRESS_DEAGGREGATION; + + printf("%s devname: %s, vndname: %s, muxid: %d, qmap_version: %d\n", + __func__, devname, vndname, muxid, qmap_version); + + ul_agg_cnt = 0; //TODO + + if (ul_agg_cnt > 1) + flagconfig |= RMNET_EGRESS_FORMAT_AGGREGATION; + + if (qmap_version == 9) { //QMAPV5 +#ifdef RMNET_FLAGS_INGRESS_MAP_CKSUMV5 + flagconfig |= RMNET_FLAGS_INGRESS_MAP_CKSUMV5; + flagconfig |= RMNET_FLAGS_EGRESS_MAP_CKSUMV5; +#else + return -1001; +#endif + } + else if (qmap_version == 8) { //QMAPV4 + flagconfig |= RMNET_FLAGS_INGRESS_MAP_CKSUMV4; + flagconfig |= RMNET_FLAGS_EGRESS_MAP_CKSUMV4; + } + else if (qmap_version == 5) { //QMAPV1 + } + else { + flagconfig = 0; + } + + return_code = rtrmnet_ctl_init(&handle, &error_code); + if (return_code) { + printf("rtrmnet_ctl_init error_code: %d, return_code: %d, errno: %d (%s)\n", + error_code, return_code, errno, strerror(errno)); + } + if (return_code == RMNETCTL_SUCCESS) { + return_code = rtrmnet_ctl_newvnd(handle, devname, vndname, &error_code, + muxid, flagconfig, ul_agg_cnt, ul_agg_size); + if (return_code) { + printf("rtrmnet_ctl_newvnd error_code: %d, return_code: %d, errno: %d (%s)\n", + error_code, return_code, errno, strerror(errno)); + } + rtrmnet_ctl_deinit(handle); + } + + return return_code; +} diff --git a/wwan/app/quectel_cm_5G/src/udhcpc.c b/wwan/app/quectel-cm/src/udhcpc.c similarity index 96% rename from wwan/app/quectel_cm_5G/src/udhcpc.c rename to wwan/app/quectel-cm/src/udhcpc.c index 8ab381e..5c2c12a 100644 --- a/wwan/app/quectel_cm_5G/src/udhcpc.c +++ b/wwan/app/quectel-cm/src/udhcpc.c @@ -1,745 +1,745 @@ -/****************************************************************************** - @file udhcpc.c - @brief call DHCP tools to obtain IP address. - - 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 -#include -#include -#include -#include -#include -#include -#include - -#include "util.h" -#include "QMIThread.h" -extern int ql_get_netcard_carrier_state(const char *devname); - -static __inline in_addr_t qmi2addr(uint32_t __x) { - return (__x>>24) | (__x>>8&0xff00) | (__x<<8&0xff0000) | (__x<<24); -} - -static int ql_system(const char *shell_cmd) { - dbg_time("%s", shell_cmd); - return system(shell_cmd); -} - -static void ifc_init_ifr(const char *name, struct ifreq *ifr) -{ - memset(ifr, 0, sizeof(struct ifreq)); - no_trunc_strncpy(ifr->ifr_name, name, IFNAMSIZ); - ifr->ifr_name[IFNAMSIZ - 1] = 0; -} - -static void ql_set_mtu(const char *ifname, int ifru_mtu) { - int inet_sock; - struct ifreq ifr; - - inet_sock = socket(AF_INET, SOCK_DGRAM, 0); - - if (inet_sock > 0) { - ifc_init_ifr(ifname, &ifr); - - if (!ioctl(inet_sock, SIOCGIFMTU, &ifr)) { - if (ifr.ifr_ifru.ifru_mtu != ifru_mtu) { - dbg_time("change mtu %d -> %d", ifr.ifr_ifru.ifru_mtu , ifru_mtu); - ifr.ifr_ifru.ifru_mtu = ifru_mtu; - ioctl(inet_sock, SIOCSIFMTU, &ifr); - } - } - - close(inet_sock); - } -} - -static int ifc_get_addr(const char *name, in_addr_t *addr) -{ - int inet_sock; - struct ifreq ifr; - int ret = 0; - - inet_sock = socket(AF_INET, SOCK_DGRAM, 0); - - ifc_init_ifr(name, &ifr); - if (addr != NULL) { - ret = ioctl(inet_sock, SIOCGIFADDR, &ifr); - if (ret < 0) { - *addr = 0; - } else { - *addr = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr; - } - } - close(inet_sock); - return ret; -} - -static short ifc_get_flags(const char *ifname) -{ - int inet_sock; - struct ifreq ifr; - int ret = 0; - - inet_sock = socket(AF_INET, SOCK_DGRAM, 0); - - if (inet_sock > 0) { - ifc_init_ifr(ifname, &ifr); - - if (!ioctl(inet_sock, SIOCGIFFLAGS, &ifr)) { - ret = ifr.ifr_ifru.ifru_flags; - } - - close(inet_sock); - } - - 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; - - ifc_get_addr(ifname, &addr); - return addr == ip; -} - -static int ql_raw_ip_mode_check(const char *ifname, uint32_t ip) { - int fd; - char raw_ip[128]; - char mode[2] = "X"; - int mode_change = 0; - - if (ql_netcard_ipv4_address_check(ifname, qmi2addr(ip))) - return 0; - - snprintf(raw_ip, sizeof(raw_ip), "/sys/class/net/%s/qmi/raw_ip", ifname); - if (access(raw_ip, F_OK)) - return 0; - - fd = open(raw_ip, O_RDWR | O_NONBLOCK | O_NOCTTY); - if (fd < 0) { - dbg_time("%s %d fail to open(%s), errno:%d (%s)", __FILE__, __LINE__, raw_ip, errno, strerror(errno)); - return 0; - } - - 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); - 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); - } - - close(fd); - return mode_change; -} - -static void* udhcpc_thread_function(void* arg) { - FILE * udhcpc_fp; - char *udhcpc_cmd = (char *)arg; - - if (udhcpc_cmd == NULL) - return NULL; - - dbg_time("%s", udhcpc_cmd); - udhcpc_fp = popen(udhcpc_cmd, "r"); - free(udhcpc_cmd); - if (udhcpc_fp) { - char buf[0xff]; - - buf[sizeof(buf)-1] = '\0'; - while((fgets(buf, sizeof(buf)-1, udhcpc_fp)) != NULL) { - if ((strlen(buf) > 1) && (buf[strlen(buf) - 1] == '\n')) - buf[strlen(buf) - 1] = '\0'; - dbg_time("%s", buf); - } - - pclose(udhcpc_fp); - } - - return NULL; -} - -//#define USE_DHCLIENT -#ifdef USE_DHCLIENT -static int dhclient_alive = 0; -#endif -static int dibbler_client_alive = 0; - -void ql_set_driver_link_state(PROFILE_T *profile, int link_state) { - char link_file[128]; - int fd; - int new_state = 0; - - snprintf(link_file, sizeof(link_file), "/sys/class/net/%s/link_state", profile->usbnet_adapter); - fd = open(link_file, O_RDWR | O_NONBLOCK | O_NOCTTY); - if (fd == -1) { - if (errno != ENOENT) - dbg_time("Fail to access %s, errno: %d (%s)", link_file, errno, strerror(errno)); - return; - } - - if (profile->qmap_mode <= 1) - new_state = !!link_state; - else { - //0x80 means link off this pdp - new_state = (link_state ? 0x00 : 0x80) + (profile->muxid & 0x7F); - } - - snprintf(link_file, sizeof(link_file), "%d\n", new_state); - if (write(fd, link_file, sizeof(link_file)) == -1) {}; - - if (link_state == 0 && profile->qmapnet_adapter[0] - && strcmp(profile->qmapnet_adapter, profile->usbnet_adapter)) { - size_t rc; - - 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); - } - } - - close(fd); -} - -static const char *ipv4Str(const uint32_t Address) { - static char str[] = {"255.225.255.255"}; - uint8_t *ip = (uint8_t *)&Address; - - snprintf(str, sizeof(str), "%d.%d.%d.%d", ip[3], ip[2], ip[1], ip[0]); - return str; -} - -static const char *ipv6Str(const UCHAR Address[16]) { - static char str[64]; - uint16_t ip[8]; - int i; - for (i = 0; i < 8; i++) { - ip[i] = (Address[i*2]<<8) + Address[i*2+1]; - } - - snprintf(str, sizeof(str), "%x:%x:%x:%x:%x:%x:%x:%x", - ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7]); - - return str; -} - -void update_ipv4_address(const char *ifname, const char *ip, const char *gw, unsigned prefix) -{ - char shell_cmd[128]; - - if (!ifname) - return; - - if (!access("/sbin/ip", X_OK)) { - snprintf(shell_cmd, sizeof(shell_cmd), "ip -%d address flush dev %s", 4, ifname); - ql_system(shell_cmd); - - snprintf(shell_cmd, sizeof(shell_cmd), "ip -%d address add %s/%u dev %s", 4, ip, prefix, ifname); - ql_system(shell_cmd); - - //ping6 www.qq.com - snprintf(shell_cmd, sizeof(shell_cmd), "ip -%d route add default via %s dev %s", 4, gw, ifname); - ql_system(shell_cmd); - } else { - unsigned n = (0xFFFFFFFF >> (32 - prefix)) << (32 - prefix); - // n = (n>>24) | (n>>8&0xff00) | (n<<8&0xff0000) | (n<<24); - - snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s %s netmask %s", ifname, ip, ipv4Str(n)); - ql_system(shell_cmd); - - //Resetting default routes - snprintf(shell_cmd, sizeof(shell_cmd), "route del default dev %s", ifname); - while(!system(shell_cmd)); - - snprintf(shell_cmd, sizeof(shell_cmd), "route add default gw %s dev %s", gw, ifname); - ql_system(shell_cmd); - } -} - -void update_ipv6_address(const char *ifname, const char *ip, const char *gw, unsigned prefix) { - char shell_cmd[128]; - - (void)gw; - if (!access("/sbin/ip", X_OK)) { - snprintf(shell_cmd, sizeof(shell_cmd), "ip -%d address flush dev %s", 6, ifname); - ql_system(shell_cmd); - - snprintf(shell_cmd, sizeof(shell_cmd), "ip -%d address add %s/%u dev %s", 6, ip, prefix, ifname); - ql_system(shell_cmd); - - //ping6 www.qq.com - snprintf(shell_cmd, sizeof(shell_cmd), "ip -%d route add default dev %s", 6, ifname); - ql_system(shell_cmd); - } else { - snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s %s/%d", ifname, ip, prefix); - ql_system(shell_cmd); - - snprintf(shell_cmd, sizeof(shell_cmd), "route -A inet6 add default dev %s", ifname); - ql_system(shell_cmd); - } -} - -static void update_ip_address_by_qmi(const char *ifname, const IPV4_T *ipv4, const IPV6_T *ipv6) { - char *d1, *d2; - - if (ipv4 && ipv4->Address) { - d1 = strdup(ipv4Str(ipv4->Address)); - d2 = strdup(ipv4Str(ipv4->Gateway)); - unsigned prefix = 0; - unsigned n = 0; - - for (n = 0; n < 32; n++) { - if (ipv4->SubnetMask&((unsigned)1<DnsPrimary) { - d1 = strdup(ipv4Str(ipv4->DnsPrimary)); - d2 = strdup(ipv4Str(ipv4->DnsSecondary ? ipv4->DnsSecondary : ipv4->DnsPrimary)); - update_resolv_conf(4, ifname, d1, d2); - free(d1); free(d2); - } - } - - if (ipv6 && ipv6->Address[0] && ipv6->PrefixLengthIPAddr) { - d1 = strdup(ipv6Str(ipv6->Address)); - d2 = strdup(ipv6Str(ipv6->Gateway)); - - update_ipv6_address(ifname, d1, d2, ipv6->PrefixLengthIPAddr); - free(d1); free(d2); - - //Adding DNS - if (ipv6->DnsPrimary[0]) { - d1 = strdup(ipv6Str(ipv6->DnsPrimary)); - d2 = strdup(ipv6Str(ipv6->DnsSecondary[0] ? ipv6->DnsSecondary : ipv6->DnsPrimary)); - update_resolv_conf(6, ifname, d1, d2); - free(d1); free(d2); - } - } -} - -//#define QL_OPENWER_NETWORK_SETUP -#ifdef QL_OPENWER_NETWORK_SETUP -static const char *openwrt_lan = "br-lan"; -static const char *openwrt_wan = "wwan0"; - -static int ql_openwrt_system(const char *cmd) { - int i; - int ret = 1; - char shell_cmd[128]; - - snprintf(shell_cmd, sizeof(shell_cmd), "%s 2>1 > /dev/null", cmd); - - for (i = 0; i < 15; i++) { - dbg_time("%s", cmd); - ret = system(shell_cmd); - if (!ret) - break; - sleep(1); - } - - return ret; -} - -static int ql_openwrt_is_wan(const char *ifname) { - if (openwrt_lan == NULL) { - system("uci show network.wan.ifname"); - } - - if (strcmp(ifname, openwrt_wan)) - return 0; - - return 1; -} - -static void ql_openwrt_setup_wan(const char *ifname, const IPV4_T *ipv4) { - FILE *fp = NULL; - char config[64]; - - snprintf(config, sizeof(config), "/tmp/rmnet_%s_ipv4config", ifname); - - if (ipv4 == NULL) { - if (ql_openwrt_is_wan(ifname)) - ql_openwrt_system("ifdown wan"); - return; - } - - fp = fopen(config, "w"); - if (fp == NULL) - return; - - fprintf(fp, "IFNAME=\"%s\"\n", ifname); - fprintf(fp, "PUBLIC_IP=\"%s\"\n", ipv4Str(ipv4->Address)); - fprintf(fp, "NETMASK=\"%s\"\n", ipv4Str(ipv4->SubnetMask)); - fprintf(fp, "GATEWAY=\"%s\"\n", ipv4Str(ipv4->Gateway)); - fprintf(fp, "DNSSERVERS=\"%s", ipv4Str(ipv4->DnsPrimary)); - if (ipv4->DnsSecondary != 0) - fprintf(fp, " %s", ipv4Str(ipv4->DnsSecondary)); - fprintf(fp, "\"\n"); - - fclose(fp); - - if (!ql_openwrt_is_wan(ifname)) - return; - - ql_openwrt_system("ifup wan"); -} - -static void ql_openwrt_setup_wan6(const char *ifname, const IPV6_T *ipv6) { - FILE *fp = NULL; - char config[64]; - int first_ifup; - - snprintf(config, sizeof(config), "/tmp/rmnet_%s_ipv6config", ifname); - - if (ipv6 == NULL) { - if (ql_openwrt_is_wan(ifname)) - ql_openwrt_system("ifdown wan6"); - return; - } - - first_ifup = (access(config, F_OK) != 0); - - fp = fopen(config, "w"); - if (fp == NULL) - return; - - fprintf(fp, "IFNAME=\"%s\"\n", ifname); - fprintf(fp, "PUBLIC_IP=\"%s\"\n", ipv6Str(ipv6->Address)); - fprintf(fp, "NETMASK=\"%s\"\n", ipv6Str(ipv6->SubnetMask)); - fprintf(fp, "GATEWAY=\"%s\"\n", ipv6Str(ipv6->Gateway)); - fprintf(fp, "PrefixLength=\"%d\"\n", ipv6->PrefixLengthIPAddr); - fprintf(fp, "DNSSERVERS=\"%s", ipv6Str(ipv6->DnsPrimary)); - if (ipv6->DnsSecondary[0]) - fprintf(fp, " %s", ipv6Str(ipv6->DnsSecondary)); - fprintf(fp, "\"\n"); - - fclose(fp); - - if (!ql_openwrt_is_wan(ifname)) - return; - - if (first_ifup) - ql_openwrt_system("ifup wan6"); - else - ql_openwrt_system("/etc/init.d/network restart"); //make PC to release old IPV6 address, and RS new IPV6 address - -#if 1 //TODO? why need this? - if (openwrt_lan) { - int i; - char shell_cmd[128]; - UCHAR Address[16] = {0}; - - ql_openwrt_system(("ifstatus lan")); - - for (i = 0; i < (ipv6->PrefixLengthIPAddr/8); i++) - Address[i] = ipv6->Address[i]; - - snprintf(shell_cmd, sizeof(shell_cmd), "ip route del %s/%u dev %s", ipv6Str(Address), ipv6->PrefixLengthIPAddr, ifname); - ql_openwrt_system(shell_cmd); - - snprintf(shell_cmd, sizeof(shell_cmd), "ip route add %s/%u dev %s", ipv6Str(Address), ipv6->PrefixLengthIPAddr, openwrt_lan); - ql_system(shell_cmd); - } -#endif -} -#endif - -void udhcpc_start(PROFILE_T *profile) { - char *ifname = profile->usbnet_adapter; - - ql_set_driver_link_state(profile, 1); - - if (profile->qmapnet_adapter[0]) { - ifname = profile->qmapnet_adapter; - } - - if (profile->rawIP && profile->ipv4.Address && profile->ipv4.Mtu) { - ql_set_mtu(ifname, (profile->ipv4.Mtu)); - } - - if (strcmp(ifname, profile->usbnet_adapter)) { - ifc_set_state(profile->usbnet_adapter, 1); - if (ifc_get_flags(ifname)&IFF_UP) { - ifc_set_state(ifname, 0); - } - } - - ifc_set_state(ifname, 1); - if (profile->ipv4.Address) { - if (profile->PCSCFIpv4Addr1) - dbg_time("pcscf1: %s", ipv4Str(profile->PCSCFIpv4Addr1)); - if (profile->PCSCFIpv4Addr2) - dbg_time("pcscf2: %s", ipv4Str(profile->PCSCFIpv4Addr2)); - } - - if (profile->ipv6.Address[0] && profile->ipv6.PrefixLengthIPAddr) { - if (profile->PCSCFIpv6Addr1[0]) - dbg_time("pcscf1: %s", ipv6Str(profile->PCSCFIpv6Addr1)); - if (profile->PCSCFIpv6Addr2[0]) - dbg_time("pcscf2: %s", ipv6Str(profile->PCSCFIpv6Addr2)); - } - -#if 1 //for bridge mode, only one public IP, so do udhcpc manually - if (ql_bridge_mode_detect(profile)) { - return; - } -#endif - -//because must use udhcpc to obtain IP when working on ETH mode, -//so it is better also use udhcpc to obtain IP when working on IP mode. -//use the same policy for all modules -#if 0 - if (profile->rawIP != 0) //mdm9x07/ec25,ec20 R2.0 - { - update_ip_address_by_qmi(ifname, &profile->ipv4, &profile->ipv6); - return; - } -#endif - - 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 - update_ip_address_by_qmi(ifname, &profile->ipv4, NULL); - } - else -/* Do DHCP using busybox tools */ - { - char udhcpc_cmd[128]; - pthread_attr_t udhcpc_thread_attr; - pthread_t udhcpc_thread_id; - - pthread_attr_init(&udhcpc_thread_attr); - pthread_attr_setdetachstate(&udhcpc_thread_attr, PTHREAD_CREATE_DETACHED); - -#ifdef USE_DHCLIENT - snprintf(udhcpc_cmd, sizeof(udhcpc_cmd), "dhclient -4 -d --no-pid %s", ifname); - dhclient_alive++; -#else - if (access("/usr/share/udhcpc/default.script", X_OK) - && access("/etc//udhcpc/default.script", X_OK)) { - dbg_time("No default.script found, it should be in '/usr/share/udhcpc/' or '/etc//udhcpc' depend on your udhcpc version!"); - } - - //-f,--foreground Run in foreground - //-b,--background Background if lease is not obtained - //-n,--now Exit if lease is not obtained - //-q,--quit Exit after obtaining lease - //-t,--retries N Send up to N discover packets (default 3) - snprintf(udhcpc_cmd, sizeof(udhcpc_cmd), "busybox udhcpc -f -n -q -t 5 -i %s", ifname); -#endif - -#if 1 //for OpenWrt - if (!access("/lib/netifd/dhcp.script", X_OK) && !access("/sbin/ifup", X_OK) && !access("/sbin/ifstatus", X_OK)) { -#if 0 //20210415 do not promot these message - dbg_time("you are use OpenWrt?"); - dbg_time("should not calling udhcpc manually?"); - dbg_time("should modify /etc/config/network as below?"); - dbg_time("config interface wan"); - dbg_time("\toption ifname %s", ifname); - dbg_time("\toption proto dhcp"); - dbg_time("should use \"/sbin/ifstaus wan\" to check %s 's status?", ifname); -#endif - } -#endif - -#ifdef USE_DHCLIENT - pthread_create(&udhcpc_thread_id, &udhcpc_thread_attr, udhcpc_thread_function, (void*)strdup(udhcpc_cmd)); - sleep(1); -#else - 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 != &qmi_request_ops) { //only QMI modem support next fixup! - goto set_ipv6; - } - - if (ql_raw_ip_mode_check(ifname, profile->ipv4.Address)) { - pthread_create(&udhcpc_thread_id, NULL, udhcpc_thread_function, (void*)strdup(udhcpc_cmd)); - pthread_join(udhcpc_thread_id, NULL); - } - - if (!ql_netcard_ipv4_address_check(ifname, qmi2addr(profile->ipv4.Address))) { - //no udhcpc's default.script exist, directly set ip and dns - update_ip_address_by_qmi(ifname, &profile->ipv4, NULL); - } - //Add by Demon. check default route - FILE *rt_fp = NULL; - char rt_cmd[128] = {0}; - - //Check if there is a default route. - snprintf(rt_cmd, sizeof(rt_cmd), "route -n | grep %s | awk '{print $1}' | grep 0.0.0.0", ifname); - rt_fp = popen((const char *)rt_cmd, "r"); - if (rt_fp != NULL) { - char buf[20] = {0}; - int found_default_rt = 0; - - if (fgets(buf, sizeof(buf), rt_fp) != NULL) { - //Find the specified interface - found_default_rt = 1; - } - - if (1 == found_default_rt) { - //dbg_time("Route items found for %s", ifname); - } - else { - dbg_time("Warning: No route items found for %s", ifname); - } - - pclose(rt_fp); - } - //End by Demon. -#endif - } - -#ifdef QL_OPENWER_NETWORK_SETUP - ql_openwrt_setup_wan(ifname, &profile->ipv4); -#endif - -set_ipv6: - if (profile->ipv6.Address[0] && profile->ipv6.PrefixLengthIPAddr) { -#if 1 - //module do not support DHCPv6, only support 'Router Solicit' - //and it seem if enable /proc/sys/net/ipv6/conf/all/forwarding, Kernel do not send RS - const char *forward_file = "/proc/sys/net/ipv6/conf/all/forwarding"; - int forward_fd = open(forward_file, O_RDONLY); - if (forward_fd > 0) { - char forward_state[2]; - if (read(forward_fd, forward_state, 2) == -1) {}; - if (forward_state[0] == '1') { - //dbg_time("%s enabled, kernel maybe donot send 'Router Solicit'", forward_file); - } - close(forward_fd); - } - - update_ip_address_by_qmi(ifname, NULL, &profile->ipv6); - - if (profile->ipv6.DnsPrimary[0] || profile->ipv6.DnsSecondary[0]) { - char dns1str[64], dns2str[64]; - - if (profile->ipv6.DnsPrimary[0]) { - strcpy(dns1str, ipv6Str(profile->ipv6.DnsPrimary)); - } - - if (profile->ipv6.DnsSecondary[0]) { - strcpy(dns2str, ipv6Str(profile->ipv6.DnsSecondary)); - } - - update_resolv_conf(6, ifname, profile->ipv6.DnsPrimary[0] ? dns1str : NULL, - profile->ipv6.DnsSecondary[0] != '\0' ? dns2str : NULL); - } - -#ifdef QL_OPENWER_NETWORK_SETUP - ql_openwrt_setup_wan6(ifname, &profile->ipv6); -#endif -#else -#ifdef USE_DHCLIENT - snprintf(udhcpc_cmd, sizeof(udhcpc_cmd), "dhclient -6 -d --no-pid %s", ifname); - dhclient_alive++; -#else - /* - DHCPv6: Dibbler - a portable DHCPv6 - 1. download from http://klub.com.pl/dhcpv6/ - 2. cross-compile - 2.1 ./configure --host=arm-linux-gnueabihf - 2.2 copy dibbler-client to your board - 3. mkdir -p /var/log/dibbler/ /var/lib/ on your board - 4. create /etc/dibbler/client.conf on your board, the content is - log-mode short - log-level 7 - iface wwan0 { - ia - option dns-server - } - 5. run "dibbler-client start" to get ipV6 address - 6. run "route -A inet6 add default dev wwan0" to add default route - */ - snprintf(shell_cmd, sizeof(shell_cmd), "route -A inet6 add default %s", ifname); - ql_system(shell_cmd); - snprintf(udhcpc_cmd, sizeof(udhcpc_cmd), "dibbler-client run"); - dibbler_client_alive++; -#endif - - pthread_create(&udhcpc_thread_id, &udhcpc_thread_attr, udhcpc_thread_function, (void*)strdup(udhcpc_cmd)); -#endif - } -} - -void udhcpc_stop(PROFILE_T *profile) { - char *ifname = profile->usbnet_adapter; - char shell_cmd[128]; - - ql_set_driver_link_state(profile, 0); - - if (profile->qmapnet_adapter[0]) { - ifname = profile->qmapnet_adapter; - } - -#ifdef USE_DHCLIENT - if (dhclient_alive) { - system("killall dhclient"); - dhclient_alive = 0; - } -#endif - if (dibbler_client_alive) { - if (system("killall dibbler-client")) {}; - 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); - -#ifdef QL_OPENWER_NETWORK_SETUP - ql_openwrt_setup_wan(ifname, NULL); - ql_openwrt_setup_wan6(ifname, NULL); -#endif -} +/****************************************************************************** + @file udhcpc.c + @brief call DHCP tools to obtain IP address. + + 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 +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "QMIThread.h" +extern int ql_get_netcard_carrier_state(const char *devname); + +static __inline in_addr_t qmi2addr(uint32_t __x) { + return (__x>>24) | (__x>>8&0xff00) | (__x<<8&0xff0000) | (__x<<24); +} + +static int ql_system(const char *shell_cmd) { + dbg_time("%s", shell_cmd); + return system(shell_cmd); +} + +static void ifc_init_ifr(const char *name, struct ifreq *ifr) +{ + memset(ifr, 0, sizeof(struct ifreq)); + no_trunc_strncpy(ifr->ifr_name, name, IFNAMSIZ); + ifr->ifr_name[IFNAMSIZ - 1] = 0; +} + +static void ql_set_mtu(const char *ifname, int ifru_mtu) { + int inet_sock; + struct ifreq ifr; + + inet_sock = socket(AF_INET, SOCK_DGRAM, 0); + + if (inet_sock > 0) { + ifc_init_ifr(ifname, &ifr); + + if (!ioctl(inet_sock, SIOCGIFMTU, &ifr)) { + if (ifr.ifr_ifru.ifru_mtu != ifru_mtu) { + dbg_time("change mtu %d -> %d", ifr.ifr_ifru.ifru_mtu , ifru_mtu); + ifr.ifr_ifru.ifru_mtu = ifru_mtu; + ioctl(inet_sock, SIOCSIFMTU, &ifr); + } + } + + close(inet_sock); + } +} + +static int ifc_get_addr(const char *name, in_addr_t *addr) +{ + int inet_sock; + struct ifreq ifr; + int ret = 0; + + inet_sock = socket(AF_INET, SOCK_DGRAM, 0); + + ifc_init_ifr(name, &ifr); + if (addr != NULL) { + ret = ioctl(inet_sock, SIOCGIFADDR, &ifr); + if (ret < 0) { + *addr = 0; + } else { + *addr = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr; + } + } + close(inet_sock); + return ret; +} + +static short ifc_get_flags(const char *ifname) +{ + int inet_sock; + struct ifreq ifr; + int ret = 0; + + inet_sock = socket(AF_INET, SOCK_DGRAM, 0); + + if (inet_sock > 0) { + ifc_init_ifr(ifname, &ifr); + + if (!ioctl(inet_sock, SIOCGIFFLAGS, &ifr)) { + ret = ifr.ifr_ifru.ifru_flags; + } + + close(inet_sock); + } + + 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; + + ifc_get_addr(ifname, &addr); + return addr == ip; +} + +static int ql_raw_ip_mode_check(const char *ifname, uint32_t ip) { + int fd; + char raw_ip[128]; + char mode[2] = "X"; + int mode_change = 0; + + if (ql_netcard_ipv4_address_check(ifname, qmi2addr(ip))) + return 0; + + snprintf(raw_ip, sizeof(raw_ip), "/sys/class/net/%s/qmi/raw_ip", ifname); + if (access(raw_ip, F_OK)) + return 0; + + fd = open(raw_ip, O_RDWR | O_NONBLOCK | O_NOCTTY); + if (fd < 0) { + dbg_time("%s %d fail to open(%s), errno:%d (%s)", __FILE__, __LINE__, raw_ip, errno, strerror(errno)); + return 0; + } + + 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); + 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); + } + + close(fd); + return mode_change; +} + +static void* udhcpc_thread_function(void* arg) { + FILE * udhcpc_fp; + char *udhcpc_cmd = (char *)arg; + + if (udhcpc_cmd == NULL) + return NULL; + + dbg_time("%s", udhcpc_cmd); + udhcpc_fp = popen(udhcpc_cmd, "r"); + free(udhcpc_cmd); + if (udhcpc_fp) { + char buf[0xff]; + + buf[sizeof(buf)-1] = '\0'; + while((fgets(buf, sizeof(buf)-1, udhcpc_fp)) != NULL) { + if ((strlen(buf) > 1) && (buf[strlen(buf) - 1] == '\n')) + buf[strlen(buf) - 1] = '\0'; + dbg_time("%s", buf); + } + + pclose(udhcpc_fp); + } + + return NULL; +} + +//#define USE_DHCLIENT +#ifdef USE_DHCLIENT +static int dhclient_alive = 0; +#endif +static int dibbler_client_alive = 0; + +void ql_set_driver_link_state(PROFILE_T *profile, int link_state) { + char link_file[128]; + int fd; + int new_state = 0; + + snprintf(link_file, sizeof(link_file), "/sys/class/net/%s/link_state", profile->usbnet_adapter); + fd = open(link_file, O_RDWR | O_NONBLOCK | O_NOCTTY); + if (fd == -1) { + if (errno != ENOENT) + dbg_time("Fail to access %s, errno: %d (%s)", link_file, errno, strerror(errno)); + return; + } + + if (profile->qmap_mode <= 1) + new_state = !!link_state; + else { + //0x80 means link off this pdp + new_state = (link_state ? 0x00 : 0x80) + (profile->muxid & 0x7F); + } + + snprintf(link_file, sizeof(link_file), "%d\n", new_state); + if (write(fd, link_file, sizeof(link_file)) == -1) {}; + + if (link_state == 0 && profile->qmapnet_adapter[0] + && strcmp(profile->qmapnet_adapter, profile->usbnet_adapter)) { + size_t rc; + + 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); + } + } + + close(fd); +} + +static const char *ipv4Str(const uint32_t Address) { + static char str[] = {"255.225.255.255"}; + uint8_t *ip = (uint8_t *)&Address; + + snprintf(str, sizeof(str), "%d.%d.%d.%d", ip[3], ip[2], ip[1], ip[0]); + return str; +} + +static const char *ipv6Str(const UCHAR Address[16]) { + static char str[64]; + uint16_t ip[8]; + int i; + for (i = 0; i < 8; i++) { + ip[i] = (Address[i*2]<<8) + Address[i*2+1]; + } + + snprintf(str, sizeof(str), "%x:%x:%x:%x:%x:%x:%x:%x", + ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7]); + + return str; +} + +void update_ipv4_address(const char *ifname, const char *ip, const char *gw, unsigned prefix) +{ + char shell_cmd[128]; + + if (!ifname) + return; + + if (!access("/sbin/ip", X_OK)) { + snprintf(shell_cmd, sizeof(shell_cmd), "ip -%d address flush dev %s", 4, ifname); + ql_system(shell_cmd); + + snprintf(shell_cmd, sizeof(shell_cmd), "ip -%d address add %s/%u dev %s", 4, ip, prefix, ifname); + ql_system(shell_cmd); + + //ping6 www.qq.com + snprintf(shell_cmd, sizeof(shell_cmd), "ip -%d route add default via %s dev %s", 4, gw, ifname); + ql_system(shell_cmd); + } else { + unsigned n = (0xFFFFFFFF >> (32 - prefix)) << (32 - prefix); + // n = (n>>24) | (n>>8&0xff00) | (n<<8&0xff0000) | (n<<24); + + snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s %s netmask %s", ifname, ip, ipv4Str(n)); + ql_system(shell_cmd); + + //Resetting default routes + snprintf(shell_cmd, sizeof(shell_cmd), "route del default dev %s", ifname); + while(!system(shell_cmd)); + + snprintf(shell_cmd, sizeof(shell_cmd), "route add default gw %s dev %s", gw, ifname); + ql_system(shell_cmd); + } +} + +void update_ipv6_address(const char *ifname, const char *ip, const char *gw, unsigned prefix) { + char shell_cmd[128]; + + (void)gw; + if (!access("/sbin/ip", X_OK)) { + snprintf(shell_cmd, sizeof(shell_cmd), "ip -%d address flush dev %s", 6, ifname); + ql_system(shell_cmd); + + snprintf(shell_cmd, sizeof(shell_cmd), "ip -%d address add %s/%u dev %s", 6, ip, prefix, ifname); + ql_system(shell_cmd); + + //ping6 www.qq.com + snprintf(shell_cmd, sizeof(shell_cmd), "ip -%d route add default dev %s", 6, ifname); + ql_system(shell_cmd); + } else { + snprintf(shell_cmd, sizeof(shell_cmd), "ifconfig %s %s/%d", ifname, ip, prefix); + ql_system(shell_cmd); + + snprintf(shell_cmd, sizeof(shell_cmd), "route -A inet6 add default dev %s", ifname); + ql_system(shell_cmd); + } +} + +static void update_ip_address_by_qmi(const char *ifname, const IPV4_T *ipv4, const IPV6_T *ipv6) { + char *d1, *d2; + + if (ipv4 && ipv4->Address) { + d1 = strdup(ipv4Str(ipv4->Address)); + d2 = strdup(ipv4Str(ipv4->Gateway)); + unsigned prefix = 0; + unsigned n = 0; + + for (n = 0; n < 32; n++) { + if (ipv4->SubnetMask&((unsigned)1<DnsPrimary) { + d1 = strdup(ipv4Str(ipv4->DnsPrimary)); + d2 = strdup(ipv4Str(ipv4->DnsSecondary ? ipv4->DnsSecondary : ipv4->DnsPrimary)); + update_resolv_conf(4, ifname, d1, d2); + free(d1); free(d2); + } + } + + if (ipv6 && ipv6->Address[0] && ipv6->PrefixLengthIPAddr) { + d1 = strdup(ipv6Str(ipv6->Address)); + d2 = strdup(ipv6Str(ipv6->Gateway)); + + update_ipv6_address(ifname, d1, d2, ipv6->PrefixLengthIPAddr); + free(d1); free(d2); + + //Adding DNS + if (ipv6->DnsPrimary[0]) { + d1 = strdup(ipv6Str(ipv6->DnsPrimary)); + d2 = strdup(ipv6Str(ipv6->DnsSecondary[0] ? ipv6->DnsSecondary : ipv6->DnsPrimary)); + update_resolv_conf(6, ifname, d1, d2); + free(d1); free(d2); + } + } +} + +//#define QL_OPENWER_NETWORK_SETUP +#ifdef QL_OPENWER_NETWORK_SETUP +static const char *openwrt_lan = "br-lan"; +static const char *openwrt_wan = "wwan0"; + +static int ql_openwrt_system(const char *cmd) { + int i; + int ret = 1; + char shell_cmd[128]; + + snprintf(shell_cmd, sizeof(shell_cmd), "%s 2>1 > /dev/null", cmd); + + for (i = 0; i < 15; i++) { + dbg_time("%s", cmd); + ret = system(shell_cmd); + if (!ret) + break; + sleep(1); + } + + return ret; +} + +static int ql_openwrt_is_wan(const char *ifname) { + if (openwrt_lan == NULL) { + system("uci show network.wan.ifname"); + } + + if (strcmp(ifname, openwrt_wan)) + return 0; + + return 1; +} + +static void ql_openwrt_setup_wan(const char *ifname, const IPV4_T *ipv4) { + FILE *fp = NULL; + char config[64]; + + snprintf(config, sizeof(config), "/tmp/rmnet_%s_ipv4config", ifname); + + if (ipv4 == NULL) { + if (ql_openwrt_is_wan(ifname)) + ql_openwrt_system("ifdown wan"); + return; + } + + fp = fopen(config, "w"); + if (fp == NULL) + return; + + fprintf(fp, "IFNAME=\"%s\"\n", ifname); + fprintf(fp, "PUBLIC_IP=\"%s\"\n", ipv4Str(ipv4->Address)); + fprintf(fp, "NETMASK=\"%s\"\n", ipv4Str(ipv4->SubnetMask)); + fprintf(fp, "GATEWAY=\"%s\"\n", ipv4Str(ipv4->Gateway)); + fprintf(fp, "DNSSERVERS=\"%s", ipv4Str(ipv4->DnsPrimary)); + if (ipv4->DnsSecondary != 0) + fprintf(fp, " %s", ipv4Str(ipv4->DnsSecondary)); + fprintf(fp, "\"\n"); + + fclose(fp); + + if (!ql_openwrt_is_wan(ifname)) + return; + + ql_openwrt_system("ifup wan"); +} + +static void ql_openwrt_setup_wan6(const char *ifname, const IPV6_T *ipv6) { + FILE *fp = NULL; + char config[64]; + int first_ifup; + + snprintf(config, sizeof(config), "/tmp/rmnet_%s_ipv6config", ifname); + + if (ipv6 == NULL) { + if (ql_openwrt_is_wan(ifname)) + ql_openwrt_system("ifdown wan6"); + return; + } + + first_ifup = (access(config, F_OK) != 0); + + fp = fopen(config, "w"); + if (fp == NULL) + return; + + fprintf(fp, "IFNAME=\"%s\"\n", ifname); + fprintf(fp, "PUBLIC_IP=\"%s\"\n", ipv6Str(ipv6->Address)); + fprintf(fp, "NETMASK=\"%s\"\n", ipv6Str(ipv6->SubnetMask)); + fprintf(fp, "GATEWAY=\"%s\"\n", ipv6Str(ipv6->Gateway)); + fprintf(fp, "PrefixLength=\"%d\"\n", ipv6->PrefixLengthIPAddr); + fprintf(fp, "DNSSERVERS=\"%s", ipv6Str(ipv6->DnsPrimary)); + if (ipv6->DnsSecondary[0]) + fprintf(fp, " %s", ipv6Str(ipv6->DnsSecondary)); + fprintf(fp, "\"\n"); + + fclose(fp); + + if (!ql_openwrt_is_wan(ifname)) + return; + + if (first_ifup) + ql_openwrt_system("ifup wan6"); + else + ql_openwrt_system("/etc/init.d/network restart"); //make PC to release old IPV6 address, and RS new IPV6 address + +#if 1 //TODO? why need this? + if (openwrt_lan) { + int i; + char shell_cmd[128]; + UCHAR Address[16] = {0}; + + ql_openwrt_system(("ifstatus lan")); + + for (i = 0; i < (ipv6->PrefixLengthIPAddr/8); i++) + Address[i] = ipv6->Address[i]; + + snprintf(shell_cmd, sizeof(shell_cmd), "ip route del %s/%u dev %s", ipv6Str(Address), ipv6->PrefixLengthIPAddr, ifname); + ql_openwrt_system(shell_cmd); + + snprintf(shell_cmd, sizeof(shell_cmd), "ip route add %s/%u dev %s", ipv6Str(Address), ipv6->PrefixLengthIPAddr, openwrt_lan); + ql_system(shell_cmd); + } +#endif +} +#endif + +void udhcpc_start(PROFILE_T *profile) { + char *ifname = profile->usbnet_adapter; + + ql_set_driver_link_state(profile, 1); + + if (profile->qmapnet_adapter[0]) { + ifname = profile->qmapnet_adapter; + } + + if (profile->rawIP && profile->ipv4.Address && profile->ipv4.Mtu) { + ql_set_mtu(ifname, (profile->ipv4.Mtu)); + } + + if (strcmp(ifname, profile->usbnet_adapter)) { + ifc_set_state(profile->usbnet_adapter, 1); + if (ifc_get_flags(ifname)&IFF_UP) { + ifc_set_state(ifname, 0); + } + } + + ifc_set_state(ifname, 1); + if (profile->ipv4.Address) { + if (profile->PCSCFIpv4Addr1) + dbg_time("pcscf1: %s", ipv4Str(profile->PCSCFIpv4Addr1)); + if (profile->PCSCFIpv4Addr2) + dbg_time("pcscf2: %s", ipv4Str(profile->PCSCFIpv4Addr2)); + } + + if (profile->ipv6.Address[0] && profile->ipv6.PrefixLengthIPAddr) { + if (profile->PCSCFIpv6Addr1[0]) + dbg_time("pcscf1: %s", ipv6Str(profile->PCSCFIpv6Addr1)); + if (profile->PCSCFIpv6Addr2[0]) + dbg_time("pcscf2: %s", ipv6Str(profile->PCSCFIpv6Addr2)); + } + +#if 1 //for bridge mode, only one public IP, so do udhcpc manually + if (ql_bridge_mode_detect(profile)) { + return; + } +#endif + +//because must use udhcpc to obtain IP when working on ETH mode, +//so it is better also use udhcpc to obtain IP when working on IP mode. +//use the same policy for all modules +#if 0 + if (profile->rawIP != 0) //mdm9x07/ec25,ec20 R2.0 + { + update_ip_address_by_qmi(ifname, &profile->ipv4, &profile->ipv6); + return; + } +#endif + + 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 + update_ip_address_by_qmi(ifname, &profile->ipv4, NULL); + } + else +/* Do DHCP using busybox tools */ + { + char udhcpc_cmd[128]; + pthread_attr_t udhcpc_thread_attr; + pthread_t udhcpc_thread_id; + + pthread_attr_init(&udhcpc_thread_attr); + pthread_attr_setdetachstate(&udhcpc_thread_attr, PTHREAD_CREATE_DETACHED); + +#ifdef USE_DHCLIENT + snprintf(udhcpc_cmd, sizeof(udhcpc_cmd), "dhclient -4 -d --no-pid %s", ifname); + dhclient_alive++; +#else + if (access("/usr/share/udhcpc/default.script", X_OK) + && access("/etc//udhcpc/default.script", X_OK)) { + dbg_time("No default.script found, it should be in '/usr/share/udhcpc/' or '/etc//udhcpc' depend on your udhcpc version!"); + } + + //-f,--foreground Run in foreground + //-b,--background Background if lease is not obtained + //-n,--now Exit if lease is not obtained + //-q,--quit Exit after obtaining lease + //-t,--retries N Send up to N discover packets (default 3) + snprintf(udhcpc_cmd, sizeof(udhcpc_cmd), "busybox udhcpc -f -n -q -t 5 -i %s", ifname); +#endif + +#if 1 //for OpenWrt + if (!access("/lib/netifd/dhcp.script", X_OK) && !access("/sbin/ifup", X_OK) && !access("/sbin/ifstatus", X_OK)) { +#if 0 //20210415 do not promot these message + dbg_time("you are use OpenWrt?"); + dbg_time("should not calling udhcpc manually?"); + dbg_time("should modify /etc/config/network as below?"); + dbg_time("config interface wan"); + dbg_time("\toption ifname %s", ifname); + dbg_time("\toption proto dhcp"); + dbg_time("should use \"/sbin/ifstaus wan\" to check %s 's status?", ifname); +#endif + } +#endif + +#ifdef USE_DHCLIENT + pthread_create(&udhcpc_thread_id, &udhcpc_thread_attr, udhcpc_thread_function, (void*)strdup(udhcpc_cmd)); + sleep(1); +#else + 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 != &qmi_request_ops) { //only QMI modem support next fixup! + goto set_ipv6; + } + + if (ql_raw_ip_mode_check(ifname, profile->ipv4.Address)) { + pthread_create(&udhcpc_thread_id, NULL, udhcpc_thread_function, (void*)strdup(udhcpc_cmd)); + pthread_join(udhcpc_thread_id, NULL); + } + + if (!ql_netcard_ipv4_address_check(ifname, qmi2addr(profile->ipv4.Address))) { + //no udhcpc's default.script exist, directly set ip and dns + update_ip_address_by_qmi(ifname, &profile->ipv4, NULL); + } + //Add by Demon. check default route + FILE *rt_fp = NULL; + char rt_cmd[128] = {0}; + + //Check if there is a default route. + snprintf(rt_cmd, sizeof(rt_cmd), "route -n | grep %s | awk '{print $1}' | grep 0.0.0.0", ifname); + rt_fp = popen((const char *)rt_cmd, "r"); + if (rt_fp != NULL) { + char buf[20] = {0}; + int found_default_rt = 0; + + if (fgets(buf, sizeof(buf), rt_fp) != NULL) { + //Find the specified interface + found_default_rt = 1; + } + + if (1 == found_default_rt) { + //dbg_time("Route items found for %s", ifname); + } + else { + dbg_time("Warning: No route items found for %s", ifname); + } + + pclose(rt_fp); + } + //End by Demon. +#endif + } + +#ifdef QL_OPENWER_NETWORK_SETUP + ql_openwrt_setup_wan(ifname, &profile->ipv4); +#endif + +set_ipv6: + if (profile->ipv6.Address[0] && profile->ipv6.PrefixLengthIPAddr) { +#if 1 + //module do not support DHCPv6, only support 'Router Solicit' + //and it seem if enable /proc/sys/net/ipv6/conf/all/forwarding, Kernel do not send RS + const char *forward_file = "/proc/sys/net/ipv6/conf/all/forwarding"; + int forward_fd = open(forward_file, O_RDONLY); + if (forward_fd > 0) { + char forward_state[2]; + if (read(forward_fd, forward_state, 2) == -1) {}; + if (forward_state[0] == '1') { + //dbg_time("%s enabled, kernel maybe donot send 'Router Solicit'", forward_file); + } + close(forward_fd); + } + + update_ip_address_by_qmi(ifname, NULL, &profile->ipv6); + + if (profile->ipv6.DnsPrimary[0] || profile->ipv6.DnsSecondary[0]) { + char dns1str[64], dns2str[64]; + + if (profile->ipv6.DnsPrimary[0]) { + strcpy(dns1str, ipv6Str(profile->ipv6.DnsPrimary)); + } + + if (profile->ipv6.DnsSecondary[0]) { + strcpy(dns2str, ipv6Str(profile->ipv6.DnsSecondary)); + } + + update_resolv_conf(6, ifname, profile->ipv6.DnsPrimary[0] ? dns1str : NULL, + profile->ipv6.DnsSecondary[0] != '\0' ? dns2str : NULL); + } + +#ifdef QL_OPENWER_NETWORK_SETUP + ql_openwrt_setup_wan6(ifname, &profile->ipv6); +#endif +#else +#ifdef USE_DHCLIENT + snprintf(udhcpc_cmd, sizeof(udhcpc_cmd), "dhclient -6 -d --no-pid %s", ifname); + dhclient_alive++; +#else + /* + DHCPv6: Dibbler - a portable DHCPv6 + 1. download from http://klub.com.pl/dhcpv6/ + 2. cross-compile + 2.1 ./configure --host=arm-linux-gnueabihf + 2.2 copy dibbler-client to your board + 3. mkdir -p /var/log/dibbler/ /var/lib/ on your board + 4. create /etc/dibbler/client.conf on your board, the content is + log-mode short + log-level 7 + iface wwan0 { + ia + option dns-server + } + 5. run "dibbler-client start" to get ipV6 address + 6. run "route -A inet6 add default dev wwan0" to add default route + */ + snprintf(shell_cmd, sizeof(shell_cmd), "route -A inet6 add default %s", ifname); + ql_system(shell_cmd); + snprintf(udhcpc_cmd, sizeof(udhcpc_cmd), "dibbler-client run"); + dibbler_client_alive++; +#endif + + pthread_create(&udhcpc_thread_id, &udhcpc_thread_attr, udhcpc_thread_function, (void*)strdup(udhcpc_cmd)); +#endif + } +} + +void udhcpc_stop(PROFILE_T *profile) { + char *ifname = profile->usbnet_adapter; + char shell_cmd[128]; + + ql_set_driver_link_state(profile, 0); + + if (profile->qmapnet_adapter[0]) { + ifname = profile->qmapnet_adapter; + } + +#ifdef USE_DHCLIENT + if (dhclient_alive) { + system("killall dhclient"); + dhclient_alive = 0; + } +#endif + if (dibbler_client_alive) { + if (system("killall dibbler-client")) {}; + 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); + +#ifdef QL_OPENWER_NETWORK_SETUP + ql_openwrt_setup_wan(ifname, NULL); + ql_openwrt_setup_wan6(ifname, NULL); +#endif +} diff --git a/wwan/app/quectel_cm_5G/src/udhcpc_netlink.c b/wwan/app/quectel-cm/src/udhcpc_netlink.c similarity index 96% rename from wwan/app/quectel_cm_5G/src/udhcpc_netlink.c rename to wwan/app/quectel-cm/src/udhcpc_netlink.c index 5e05223..56209f8 100644 --- a/wwan/app/quectel_cm_5G/src/udhcpc_netlink.c +++ b/wwan/app/quectel-cm/src/udhcpc_netlink.c @@ -1,179 +1,179 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libmnl/ifutils.h" -#include "libmnl/dhcp/dhcp.h" -#include "util.h" -#include "QMIThread.h" - -static int ql_raw_ip_mode_check(const char *ifname) -{ - int fd; - char raw_ip[128]; - char mode[2] = "X"; - int mode_change = 0; - - snprintf(raw_ip, sizeof(raw_ip), "/sys/class/net/%s/qmi/raw_ip", ifname); - if (access(raw_ip, F_OK)) - return 0; - - fd = open(raw_ip, O_RDWR | O_NONBLOCK | O_NOCTTY); - if (fd < 0) - { - dbg_time("%s %d fail to open(%s), errno:%d (%s)", __FILE__, __LINE__, raw_ip, errno, strerror(errno)); - return 0; - } - - read(fd, mode, 2); - if (mode[0] == '0' || mode[0] == 'N') - { - if_link_down(ifname); - dbg_time("echo Y > /sys/class/net/%s/qmi/raw_ip", ifname); - mode[0] = 'Y'; - write(fd, mode, 2); - mode_change = 1; - if_link_up(ifname); - } - - close(fd); - return mode_change; -} - -void ql_set_driver_link_state(PROFILE_T *profile, int link_state) -{ - char link_file[128]; - int fd; - int new_state = 0; - - snprintf(link_file, sizeof(link_file), "/sys/class/net/%s/link_state", profile->usbnet_adapter); - fd = open(link_file, O_RDWR | O_NONBLOCK | O_NOCTTY); - if (fd == -1) - { - if (errno != ENOENT) - dbg_time("Fail to access %s, errno: %d (%s)", link_file, errno, strerror(errno)); - return; - } - - if (profile->qmap_mode <= 1) - new_state = !!link_state; - else - { - //0x80 means link off this pdp - new_state = (link_state ? 0x00 : 0x80) + profile->pdp; - } - - snprintf(link_file, sizeof(link_file), "%d\n", new_state); - write(fd, link_file, sizeof(link_file)); - - if (link_state == 0 && profile->qmap_mode > 1) - { - size_t rc; - - lseek(fd, 0, SEEK_SET); - rc = read(fd, link_file, sizeof(link_file)); - if (rc > 1 && (!strcasecmp(link_file, "0\n") || !strcasecmp(link_file, "0x0\n"))) - { - if_link_down(profile->usbnet_adapter); - } - } - - close(fd); -} - -void udhcpc_start(PROFILE_T *profile) -{ - char *ifname = profile->usbnet_adapter; - - ql_set_driver_link_state(profile, 1); - ql_raw_ip_mode_check(ifname); - - if (profile->qmapnet_adapter) - { - ifname = profile->qmapnet_adapter; - } - if (profile->rawIP && profile->ipv4.Address && profile->ipv4.Mtu) - { - if_set_mtu(ifname, (profile->ipv4.Mtu)); - } - - if (strcmp(ifname, profile->usbnet_adapter)) - { - if_link_up(profile->usbnet_adapter); - } - - if_link_up(ifname); - -#if 1 //for bridge mode, only one public IP, so do udhcpc manually - if (ql_bridge_mode_detect(profile)) - { - return; - } -#endif - // if use DHCP(should make with ${DHCP} src files) - // do_dhcp(ifname); - // return 0; - /* IPv4 Addr Info */ - if (profile->ipv4.Address) - { - dbg_time("IPv4 MTU: %d", profile->ipv4.Mtu); - dbg_time("IPv4 Address: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.Address))); - dbg_time("IPv4 Netmask: %d", mask_to_prefix_v4(ntohl(profile->ipv4.SubnetMask))); - dbg_time("IPv4 Gateway: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.Gateway))); - dbg_time("IPv4 DNS1: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.DnsPrimary))); - dbg_time("IPv4 DNS2: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.DnsSecondary))); - if_set_network_v4(ifname, ntohl(profile->ipv4.Address), - mask_to_prefix_v4(profile->ipv4.SubnetMask), - ntohl(profile->ipv4.Gateway), - ntohl(profile->ipv4.DnsPrimary), - ntohl(profile->ipv4.DnsSecondary)); - } - - if (profile->ipv6.Address[0] && profile->ipv6.PrefixLengthIPAddr) - { - //module do not support DHCPv6, only support 'Router Solicit' - //and it seem if enable /proc/sys/net/ipv6/conf/all/forwarding, Kernel do not send RS - const char *forward_file = "/proc/sys/net/ipv6/conf/all/forwarding"; - int forward_fd = open(forward_file, O_RDONLY); - if (forward_fd > 0) - { - char forward_state[2]; - read(forward_fd, forward_state, 2); - if (forward_state[0] == '1') - { - dbg_time("%s enabled, kernel maybe donot send 'Router Solicit'", forward_file); - } - close(forward_fd); - } - - dbg_time("IPv6 MTU: %d", profile->ipv6.Mtu); - dbg_time("IPv6 Address: %s", ipaddr_to_string_v6(profile->ipv6.Address)); - dbg_time("IPv6 Netmask: %d", profile->ipv6.PrefixLengthIPAddr); - dbg_time("IPv6 Gateway: %s", ipaddr_to_string_v6(profile->ipv6.Gateway)); - dbg_time("IPv6 DNS1: %s", ipaddr_to_string_v6(profile->ipv6.DnsPrimary)); - dbg_time("IPv6 DNS2: %s", ipaddr_to_string_v6(profile->ipv6.DnsSecondary)); - if_set_network_v6(ifname, profile->ipv6.Address, profile->ipv6.PrefixLengthIPAddr, - profile->ipv6.Gateway, profile->ipv6.DnsPrimary, profile->ipv6.DnsSecondary); - } -} - -void udhcpc_stop(PROFILE_T *profile) -{ - char *ifname = profile->usbnet_adapter; - - ql_set_driver_link_state(profile, 0); - - if (profile->qmapnet_adapter) - { - ifname = profile->qmapnet_adapter; - } - - if_link_down(ifname); - if_flush_v4_addr(ifname); - if_flush_v6_addr(ifname); -} +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libmnl/ifutils.h" +#include "libmnl/dhcp/dhcp.h" +#include "util.h" +#include "QMIThread.h" + +static int ql_raw_ip_mode_check(const char *ifname) +{ + int fd; + char raw_ip[128]; + char mode[2] = "X"; + int mode_change = 0; + + snprintf(raw_ip, sizeof(raw_ip), "/sys/class/net/%s/qmi/raw_ip", ifname); + if (access(raw_ip, F_OK)) + return 0; + + fd = open(raw_ip, O_RDWR | O_NONBLOCK | O_NOCTTY); + if (fd < 0) + { + dbg_time("%s %d fail to open(%s), errno:%d (%s)", __FILE__, __LINE__, raw_ip, errno, strerror(errno)); + return 0; + } + + read(fd, mode, 2); + if (mode[0] == '0' || mode[0] == 'N') + { + if_link_down(ifname); + dbg_time("echo Y > /sys/class/net/%s/qmi/raw_ip", ifname); + mode[0] = 'Y'; + write(fd, mode, 2); + mode_change = 1; + if_link_up(ifname); + } + + close(fd); + return mode_change; +} + +void ql_set_driver_link_state(PROFILE_T *profile, int link_state) +{ + char link_file[128]; + int fd; + int new_state = 0; + + snprintf(link_file, sizeof(link_file), "/sys/class/net/%s/link_state", profile->usbnet_adapter); + fd = open(link_file, O_RDWR | O_NONBLOCK | O_NOCTTY); + if (fd == -1) + { + if (errno != ENOENT) + dbg_time("Fail to access %s, errno: %d (%s)", link_file, errno, strerror(errno)); + return; + } + + if (profile->qmap_mode <= 1) + new_state = !!link_state; + else + { + //0x80 means link off this pdp + new_state = (link_state ? 0x00 : 0x80) + profile->pdp; + } + + snprintf(link_file, sizeof(link_file), "%d\n", new_state); + write(fd, link_file, sizeof(link_file)); + + if (link_state == 0 && profile->qmap_mode > 1) + { + size_t rc; + + lseek(fd, 0, SEEK_SET); + rc = read(fd, link_file, sizeof(link_file)); + if (rc > 1 && (!strcasecmp(link_file, "0\n") || !strcasecmp(link_file, "0x0\n"))) + { + if_link_down(profile->usbnet_adapter); + } + } + + close(fd); +} + +void udhcpc_start(PROFILE_T *profile) +{ + char *ifname = profile->usbnet_adapter; + + ql_set_driver_link_state(profile, 1); + ql_raw_ip_mode_check(ifname); + + if (profile->qmapnet_adapter) + { + ifname = profile->qmapnet_adapter; + } + if (profile->rawIP && profile->ipv4.Address && profile->ipv4.Mtu) + { + if_set_mtu(ifname, (profile->ipv4.Mtu)); + } + + if (strcmp(ifname, profile->usbnet_adapter)) + { + if_link_up(profile->usbnet_adapter); + } + + if_link_up(ifname); + +#if 1 //for bridge mode, only one public IP, so do udhcpc manually + if (ql_bridge_mode_detect(profile)) + { + return; + } +#endif + // if use DHCP(should make with ${DHCP} src files) + // do_dhcp(ifname); + // return 0; + /* IPv4 Addr Info */ + if (profile->ipv4.Address) + { + dbg_time("IPv4 MTU: %d", profile->ipv4.Mtu); + dbg_time("IPv4 Address: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.Address))); + dbg_time("IPv4 Netmask: %d", mask_to_prefix_v4(ntohl(profile->ipv4.SubnetMask))); + dbg_time("IPv4 Gateway: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.Gateway))); + dbg_time("IPv4 DNS1: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.DnsPrimary))); + dbg_time("IPv4 DNS2: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.DnsSecondary))); + if_set_network_v4(ifname, ntohl(profile->ipv4.Address), + mask_to_prefix_v4(profile->ipv4.SubnetMask), + ntohl(profile->ipv4.Gateway), + ntohl(profile->ipv4.DnsPrimary), + ntohl(profile->ipv4.DnsSecondary)); + } + + if (profile->ipv6.Address[0] && profile->ipv6.PrefixLengthIPAddr) + { + //module do not support DHCPv6, only support 'Router Solicit' + //and it seem if enable /proc/sys/net/ipv6/conf/all/forwarding, Kernel do not send RS + const char *forward_file = "/proc/sys/net/ipv6/conf/all/forwarding"; + int forward_fd = open(forward_file, O_RDONLY); + if (forward_fd > 0) + { + char forward_state[2]; + read(forward_fd, forward_state, 2); + if (forward_state[0] == '1') + { + dbg_time("%s enabled, kernel maybe donot send 'Router Solicit'", forward_file); + } + close(forward_fd); + } + + dbg_time("IPv6 MTU: %d", profile->ipv6.Mtu); + dbg_time("IPv6 Address: %s", ipaddr_to_string_v6(profile->ipv6.Address)); + dbg_time("IPv6 Netmask: %d", profile->ipv6.PrefixLengthIPAddr); + dbg_time("IPv6 Gateway: %s", ipaddr_to_string_v6(profile->ipv6.Gateway)); + dbg_time("IPv6 DNS1: %s", ipaddr_to_string_v6(profile->ipv6.DnsPrimary)); + dbg_time("IPv6 DNS2: %s", ipaddr_to_string_v6(profile->ipv6.DnsSecondary)); + if_set_network_v6(ifname, profile->ipv6.Address, profile->ipv6.PrefixLengthIPAddr, + profile->ipv6.Gateway, profile->ipv6.DnsPrimary, profile->ipv6.DnsSecondary); + } +} + +void udhcpc_stop(PROFILE_T *profile) +{ + char *ifname = profile->usbnet_adapter; + + ql_set_driver_link_state(profile, 0); + + if (profile->qmapnet_adapter) + { + ifname = profile->qmapnet_adapter; + } + + if_link_down(ifname); + if_flush_v4_addr(ifname); + if_flush_v6_addr(ifname); +} diff --git a/wwan/app/quectel_cm_5G/src/udhcpc_script.c b/wwan/app/quectel-cm/src/udhcpc_script.c similarity index 96% rename from wwan/app/quectel_cm_5G/src/udhcpc_script.c rename to wwan/app/quectel-cm/src/udhcpc_script.c index 3e164a4..3282316 100644 --- a/wwan/app/quectel_cm_5G/src/udhcpc_script.c +++ b/wwan/app/quectel-cm/src/udhcpc_script.c @@ -1,132 +1,132 @@ -/****************************************************************************** - @file udhcpc.c - @brief call DHCP tools to obtain IP address. - - 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 -#include -#include -#include -#include -#include -#include -#include - -#include "util.h" -#include "QMIThread.h" - -#define IFDOWN_SCRIPT "/etc/quectel/ifdown.sh" -#define IFUP_SCRIPT "/etc/quectel/ifup.sh" - -static int ql_system(const char *shell_cmd) -{ - dbg_time("%s", shell_cmd); - return system(shell_cmd); -} - -uint32_t mask_to_prefix_v4(uint32_t mask) -{ - uint32_t prefix = 0; - while (mask) - { - mask = mask & (mask - 1); - prefix++; - } - return prefix; -} - -uint32_t mask_from_prefix_v4(uint32_t prefix) -{ - return ~((1 << (32 - prefix)) - 1); -} - -/* mask in int */ -uint32_t broadcast_from_mask(uint32_t ip, uint32_t mask) -{ - return (ip & mask) | (~mask); -} - -const char *ipaddr_to_string_v4(in_addr_t ipaddr, char *buf, size_t size) -{ - // static char buf[INET6_ADDRSTRLEN] = {'\0'}; - buf[0] = '\0'; - uint32_t addr = ipaddr; - return inet_ntop(AF_INET, &addr, buf, size); -} - -const char *ipaddr_to_string_v6(uint8_t *ipaddr, char *buf, size_t size) -{ - buf[0] = '\0'; - return inet_ntop(AF_INET6, ipaddr, buf, size); -} - -/** - * For more details see default.script - * - * The main aim of this function is offload ip management to script, CM has not interest in manage IP address. - * just tell script all the info about ip, mask, router, dns... - */ -void udhcpc_start(PROFILE_T *profile) -{ - char shell_cmd[1024]; - char ip[128]; - char subnet[128]; - char broadcast[128]; - char router[128]; - char domain1[128]; - char domain2[128]; - - if (NULL == getenv(IFUP_SCRIPT)) - return; - - // manage IPv4??? - // check rawip ??? - snprintf(shell_cmd, sizeof(shell_cmd), - " netiface=%s interface=%s mtu=%u ip=%s subnet=%s broadcast=%s router=%s" - " domain=\"%s %s\" %s", - profile->usbnet_adapter, - profile->qmapnet_adapter ? profile->qmapnet_adapter : profile->usbnet_adapter, - profile->ipv4.Mtu, - ipaddr_to_string_v4(ntohl(profile->ipv4.Address), ip, sizeof(ip)), - ipaddr_to_string_v4(ntohl(profile->ipv4.SubnetMask), subnet, sizeof(subnet)), - ipaddr_to_string_v4(ntohl(broadcast_from_mask(profile->ipv4.Address, profile->ipv4.SubnetMask)), - broadcast, sizeof(broadcast)), - ipaddr_to_string_v4(ntohl(profile->ipv4.Gateway), router, sizeof(router)), - ipaddr_to_string_v4(ntohl(profile->ipv4.DnsPrimary), domain1, sizeof(domain1)), - ipaddr_to_string_v4(ntohl(profile->ipv4.DnsSecondary), domain2, sizeof(domain2)), - getenv(IFUP_SCRIPT)); - ql_system(shell_cmd); - - // manage IPv6??? -} - -/** - * For more details see default.script - * - * The main aim of this function is offload ip management to script, CM has not interest in manage IP address. - * just tell script all the info about ip, mask, router, dns... - */ -void udhcpc_stop(PROFILE_T *profile) -{ - char shell_cmd[1024]; - - if (NULL == getenv(IFDOWN_SCRIPT)) - return; - - snprintf(shell_cmd, sizeof(shell_cmd), - "netiface=%s interface=%s %s", - profile->usbnet_adapter, - profile->qmapnet_adapter ? profile->qmapnet_adapter : profile->usbnet_adapter, - getenv(IFDOWN_SCRIPT)); - ql_system(shell_cmd); -} +/****************************************************************************** + @file udhcpc.c + @brief call DHCP tools to obtain IP address. + + 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 +#include +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "QMIThread.h" + +#define IFDOWN_SCRIPT "/etc/quectel/ifdown.sh" +#define IFUP_SCRIPT "/etc/quectel/ifup.sh" + +static int ql_system(const char *shell_cmd) +{ + dbg_time("%s", shell_cmd); + return system(shell_cmd); +} + +uint32_t mask_to_prefix_v4(uint32_t mask) +{ + uint32_t prefix = 0; + while (mask) + { + mask = mask & (mask - 1); + prefix++; + } + return prefix; +} + +uint32_t mask_from_prefix_v4(uint32_t prefix) +{ + return ~((1 << (32 - prefix)) - 1); +} + +/* mask in int */ +uint32_t broadcast_from_mask(uint32_t ip, uint32_t mask) +{ + return (ip & mask) | (~mask); +} + +const char *ipaddr_to_string_v4(in_addr_t ipaddr, char *buf, size_t size) +{ + // static char buf[INET6_ADDRSTRLEN] = {'\0'}; + buf[0] = '\0'; + uint32_t addr = ipaddr; + return inet_ntop(AF_INET, &addr, buf, size); +} + +const char *ipaddr_to_string_v6(uint8_t *ipaddr, char *buf, size_t size) +{ + buf[0] = '\0'; + return inet_ntop(AF_INET6, ipaddr, buf, size); +} + +/** + * For more details see default.script + * + * The main aim of this function is offload ip management to script, CM has not interest in manage IP address. + * just tell script all the info about ip, mask, router, dns... + */ +void udhcpc_start(PROFILE_T *profile) +{ + char shell_cmd[1024]; + char ip[128]; + char subnet[128]; + char broadcast[128]; + char router[128]; + char domain1[128]; + char domain2[128]; + + if (NULL == getenv(IFUP_SCRIPT)) + return; + + // manage IPv4??? + // check rawip ??? + snprintf(shell_cmd, sizeof(shell_cmd), + " netiface=%s interface=%s mtu=%u ip=%s subnet=%s broadcast=%s router=%s" + " domain=\"%s %s\" %s", + profile->usbnet_adapter, + profile->qmapnet_adapter ? profile->qmapnet_adapter : profile->usbnet_adapter, + profile->ipv4.Mtu, + ipaddr_to_string_v4(ntohl(profile->ipv4.Address), ip, sizeof(ip)), + ipaddr_to_string_v4(ntohl(profile->ipv4.SubnetMask), subnet, sizeof(subnet)), + ipaddr_to_string_v4(ntohl(broadcast_from_mask(profile->ipv4.Address, profile->ipv4.SubnetMask)), + broadcast, sizeof(broadcast)), + ipaddr_to_string_v4(ntohl(profile->ipv4.Gateway), router, sizeof(router)), + ipaddr_to_string_v4(ntohl(profile->ipv4.DnsPrimary), domain1, sizeof(domain1)), + ipaddr_to_string_v4(ntohl(profile->ipv4.DnsSecondary), domain2, sizeof(domain2)), + getenv(IFUP_SCRIPT)); + ql_system(shell_cmd); + + // manage IPv6??? +} + +/** + * For more details see default.script + * + * The main aim of this function is offload ip management to script, CM has not interest in manage IP address. + * just tell script all the info about ip, mask, router, dns... + */ +void udhcpc_stop(PROFILE_T *profile) +{ + char shell_cmd[1024]; + + if (NULL == getenv(IFDOWN_SCRIPT)) + return; + + snprintf(shell_cmd, sizeof(shell_cmd), + "netiface=%s interface=%s %s", + profile->usbnet_adapter, + profile->qmapnet_adapter ? profile->qmapnet_adapter : profile->usbnet_adapter, + getenv(IFDOWN_SCRIPT)); + ql_system(shell_cmd); +} diff --git a/wwan/app/quectel_cm_5G/src/util.c b/wwan/app/quectel-cm/src/util.c similarity index 96% rename from wwan/app/quectel_cm_5G/src/util.c rename to wwan/app/quectel-cm/src/util.c index c84b076..ed99117 100644 --- a/wwan/app/quectel_cm_5G/src/util.c +++ b/wwan/app/quectel-cm/src/util.c @@ -1,361 +1,361 @@ -/****************************************************************************** - @file util.c - @brief some utils for this QCM tool. - - 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 -#include -typedef unsigned short sa_family_t; -#include - -#if defined(__STDC__) -#include -#define __V(x) x -#else -#include -#define __V(x) (va_alist) va_dcl -#define const -#define volatile -#endif - -#include - -#include "QMIThread.h" - -pthread_mutex_t cm_command_mutex = PTHREAD_MUTEX_INITIALIZER; -pthread_cond_t cm_command_cond = PTHREAD_COND_INITIALIZER; -unsigned int cm_recv_buf[1024]; - -int cm_open_dev(const char *dev) { - int fd; - - fd = open(dev, O_RDWR | O_NONBLOCK | O_NOCTTY); - if (fd != -1) { - fcntl(fd, F_SETFL, fcntl(fd,F_GETFL) | O_NONBLOCK); - fcntl(fd, F_SETFD, FD_CLOEXEC); - - if (!strncmp(dev, "/dev/tty", strlen("/dev/tty"))) - { - //disable echo on serial ports - struct termios ios; - - memset(&ios, 0, sizeof(ios)); - tcgetattr( fd, &ios ); - cfmakeraw(&ios); - cfsetispeed(&ios, B115200); - cfsetospeed(&ios, B115200); - tcsetattr( fd, TCSANOW, &ios ); - tcflush(fd, TCIOFLUSH); - } - } else { - dbg_time("Failed to open %s, errno: %d (%s)", dev, errno, strerror(errno)); - } - - return fd; -} - -int cm_open_proxy(const char *name) { - int sockfd = -1; - int reuse_addr = 1; - struct sockaddr_un sockaddr; - socklen_t alen; - - /*Create server socket*/ - sockfd = socket(AF_LOCAL, SOCK_STREAM, 0); - if (sockfd < 0) - return sockfd; - - memset(&sockaddr, 0, sizeof(sockaddr)); - sockaddr.sun_family = AF_LOCAL; - sockaddr.sun_path[0] = 0; - memcpy(sockaddr.sun_path + 1, name, strlen(name) ); - - alen = strlen(name) + offsetof(struct sockaddr_un, sun_path) + 1; - if(connect(sockfd, (struct sockaddr *)&sockaddr, alen) < 0) { - close(sockfd); - dbg_time("connect %s errno: %d (%s)", name, errno, strerror(errno)); - return -1; - } - setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse_addr,sizeof(reuse_addr)); - fcntl(sockfd, F_SETFL, fcntl(sockfd,F_GETFL) | O_NONBLOCK); - fcntl(sockfd, F_SETFD, FD_CLOEXEC); - - dbg_time("connect to %s sockfd = %d", name, sockfd); - - return sockfd; -} - -static void setTimespecRelative(struct timespec *p_ts, long long msec) -{ - struct timeval tv; - - gettimeofday(&tv, (struct timezone *) NULL); - - /* what's really funny about this is that I know - pthread_cond_timedwait just turns around and makes this - a relative time again */ - p_ts->tv_sec = tv.tv_sec + (msec / 1000); - p_ts->tv_nsec = (tv.tv_usec + (msec % 1000) * 1000L ) * 1000L; - if ((unsigned long)p_ts->tv_nsec >= 1000000000UL) { - p_ts->tv_sec += 1; - p_ts->tv_nsec -= 1000000000UL; - } -} - -int pthread_cond_timeout_np(pthread_cond_t *cond, pthread_mutex_t * mutex, unsigned msecs) { - if (msecs != 0) { - unsigned i; - unsigned t = msecs/4; - int ret = 0; - - if (t == 0) - t = 1; - - for (i = 0; i < msecs; i += t) { - struct timespec ts; - setTimespecRelative(&ts, t); -//very old uclibc do not support pthread_condattr_setclock(CLOCK_MONOTONIC) - ret = pthread_cond_timedwait(cond, mutex, &ts); //to advoid system time change - if (ret != ETIMEDOUT) { - if(ret) dbg_time("ret=%d, msecs=%u, t=%u", ret, msecs, t); - break; - } - } - - return ret; - } else { - return pthread_cond_wait(cond, mutex); - } -} - -const char * get_time(void) { - static char time_buf[128]; - struct timeval tv; - time_t time; - suseconds_t millitm; - struct tm *ti; - - gettimeofday (&tv, NULL); - - time= tv.tv_sec; - millitm = (tv.tv_usec + 500) / 1000; - - if (millitm == 1000) { - ++time; - millitm = 0; - } - - ti = localtime(&time); - sprintf(time_buf, "%02d-%02d_%02d:%02d:%02d:%03d", ti->tm_mon+1, ti->tm_mday, ti->tm_hour, ti->tm_min, ti->tm_sec, (int)millitm); - return time_buf; -} - -unsigned long clock_msec(void) -{ - struct timespec tm; - clock_gettime( CLOCK_MONOTONIC, &tm); - return (unsigned long)(tm.tv_sec*1000 + (tm.tv_nsec/1000000)); -} - -FILE *logfilefp = NULL; - -void update_resolv_conf(int iptype, const char *ifname, const char *dns1, const char *dns2) { - const char *dns_file = "/etc/resolv.conf"; - FILE *dns_fp; - char dns_line[256]; - #define MAX_DNS 16 - char *dns_info[MAX_DNS]; - char dns_tag[64]; - int dns_match = 0; - int i; - - snprintf(dns_tag, sizeof(dns_tag), "# IPV%d %s", iptype, ifname); - - for (i = 0; i < MAX_DNS; i++) - dns_info[i] = NULL; - - dns_fp = fopen(dns_file, "r"); - if (dns_fp) { - i = 0; - dns_line[sizeof(dns_line)-1] = '\0'; - - while((fgets(dns_line, sizeof(dns_line)-1, dns_fp)) != NULL) { - if ((strlen(dns_line) > 1) && (dns_line[strlen(dns_line) - 1] == '\n')) - dns_line[strlen(dns_line) - 1] = '\0'; - //dbg_time("%s", dns_line); - if (strstr(dns_line, dns_tag)) { - dns_match++; - continue; - } - dns_info[i++] = strdup(dns_line); - if (i == MAX_DNS) - break; - } - - fclose(dns_fp); - } - else if (errno != ENOENT) { - dbg_time("fopen %s fail, errno:%d (%s)", dns_file, errno, strerror(errno)); - return; - } - - if (dns1 == NULL && dns_match == 0) - return; - - dns_fp = fopen(dns_file, "w"); - if (dns_fp) { - if (dns1) - fprintf(dns_fp, "nameserver %s %s\n", dns1, dns_tag); - if (dns2) - fprintf(dns_fp, "nameserver %s %s\n", dns2, dns_tag); - - for (i = 0; i < MAX_DNS && dns_info[i]; i++) - fprintf(dns_fp, "%s\n", dns_info[i]); - fclose(dns_fp); - } - else { - dbg_time("fopen %s fail, errno:%d (%s)", dns_file, errno, strerror(errno)); - } - - for (i = 0; i < MAX_DNS && dns_info[i]; i++) - free(dns_info[i]); -} - -pid_t getpid_by_pdp(int pdp, const char* program_name) -{ - glob_t gt; - int ret; - char filter[16]; - pid_t pid; - - snprintf(filter, sizeof(filter), "-n %d", pdp); - ret = glob("/proc/*/cmdline", GLOB_NOSORT, NULL, >); - if (ret != 0) { - dbg_time("glob error, errno = %d(%s)", errno, strerror(errno)); - return -1; - } else { - int i = 0, fd = -1; - ssize_t nreads; - char cmdline[512] = {0}; - - for (i = 0; i < (int)gt.gl_pathc; i++) { - fd = open(gt.gl_pathv[i], O_RDONLY); - if (fd == -1) { - dbg_time("open %s failed, errno = %d(%s)", gt.gl_pathv[i], errno, strerror(errno)); - globfree(>); - return -1; - } - - nreads = read(fd, cmdline, sizeof(cmdline)); - if (nreads > 0) { - int pos = 0; - while (pos < nreads-1) { - if (cmdline[pos] == '\0') - cmdline[pos] = ' '; // space - pos++; - } - // printf("%s\n", cmdline); - } - - if (strstr(cmdline, program_name) && strstr(cmdline, filter)) { - char path[64] = {0}; - char pidstr[64] = {0}; - char *p; - - dbg_time("%s: %s", gt.gl_pathv[i], cmdline); - strcpy(path, gt.gl_pathv[i]); - p = strstr(gt.gl_pathv[i], "/cmdline"); - *p = '\0'; - while (*(--p) != '/') ; - - strcpy(pidstr, p+1); - pid = atoi(pidstr); - globfree(>); - - return pid; - } - } - } - - globfree(>); - return -1; -} - -void ql_get_driver_rmnet_info(PROFILE_T *profile, RMNET_INFO *rmnet_info) { - int ifc_ctl_sock; - struct ifreq ifr; - int rc; - int request = 0x89F3; - unsigned char data[512]; - - memset(rmnet_info, 0x00, sizeof(*rmnet_info)); - - ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM, 0); - if (ifc_ctl_sock <= 0) { - dbg_time("socket() failed: %s\n", strerror(errno)); - return; - } - - memset(&ifr, 0, sizeof(struct ifreq)); - strncpy(ifr.ifr_name, profile->usbnet_adapter, IFNAMSIZ); - ifr.ifr_name[IFNAMSIZ - 1] = 0; - ifr.ifr_ifru.ifru_data = (void *)data; - - rc = ioctl(ifc_ctl_sock, request, &ifr); - if (rc < 0) { - if (errno != ENOTSUP) - dbg_time("ioctl(0x%x, qmap_settings) errno:%d (%s), rc=%d", request, errno, strerror(errno), rc); - } - else { - memcpy(rmnet_info, data, sizeof(*rmnet_info)); - } - - close(ifc_ctl_sock); -} - -void ql_set_driver_qmap_setting(PROFILE_T *profile, QMAP_SETTING *qmap_settings) { - int ifc_ctl_sock; - struct ifreq ifr; - int rc; - int request = 0x89F2; - - ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM, 0); - if (ifc_ctl_sock <= 0) { - dbg_time("socket() failed: %s\n", strerror(errno)); - return; - } - - memset(&ifr, 0, sizeof(struct ifreq)); - strncpy(ifr.ifr_name, profile->usbnet_adapter, IFNAMSIZ); - ifr.ifr_name[IFNAMSIZ - 1] = 0; - ifr.ifr_ifru.ifru_data = (void *)qmap_settings; - - rc = ioctl(ifc_ctl_sock, request, &ifr); - if (rc < 0) { - dbg_time("ioctl(0x%x, qmap_settings) failed: %s, rc=%d", request, strerror(errno), rc); - } - - close(ifc_ctl_sock); -} - -void no_trunc_strncpy(char *dest, const char *src, size_t dest_size) -{ - size_t i = 0; - - for (i = 0; i < dest_size && *src; i++) { - *dest++ = *src++; - } - - *dest = 0; -} +/****************************************************************************** + @file util.c + @brief some utils for this QCM tool. + + 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 +#include +typedef unsigned short sa_family_t; +#include + +#if defined(__STDC__) +#include +#define __V(x) x +#else +#include +#define __V(x) (va_alist) va_dcl +#define const +#define volatile +#endif + +#include + +#include "QMIThread.h" + +pthread_mutex_t cm_command_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t cm_command_cond = PTHREAD_COND_INITIALIZER; +unsigned int cm_recv_buf[1024]; + +int cm_open_dev(const char *dev) { + int fd; + + fd = open(dev, O_RDWR | O_NONBLOCK | O_NOCTTY); + if (fd != -1) { + fcntl(fd, F_SETFL, fcntl(fd,F_GETFL) | O_NONBLOCK); + fcntl(fd, F_SETFD, FD_CLOEXEC); + + if (!strncmp(dev, "/dev/tty", strlen("/dev/tty"))) + { + //disable echo on serial ports + struct termios ios; + + memset(&ios, 0, sizeof(ios)); + tcgetattr( fd, &ios ); + cfmakeraw(&ios); + cfsetispeed(&ios, B115200); + cfsetospeed(&ios, B115200); + tcsetattr( fd, TCSANOW, &ios ); + tcflush(fd, TCIOFLUSH); + } + } else { + dbg_time("Failed to open %s, errno: %d (%s)", dev, errno, strerror(errno)); + } + + return fd; +} + +int cm_open_proxy(const char *name) { + int sockfd = -1; + int reuse_addr = 1; + struct sockaddr_un sockaddr; + socklen_t alen; + + /*Create server socket*/ + sockfd = socket(AF_LOCAL, SOCK_STREAM, 0); + if (sockfd < 0) + return sockfd; + + memset(&sockaddr, 0, sizeof(sockaddr)); + sockaddr.sun_family = AF_LOCAL; + sockaddr.sun_path[0] = 0; + memcpy(sockaddr.sun_path + 1, name, strlen(name) ); + + alen = strlen(name) + offsetof(struct sockaddr_un, sun_path) + 1; + if(connect(sockfd, (struct sockaddr *)&sockaddr, alen) < 0) { + close(sockfd); + dbg_time("connect %s errno: %d (%s)", name, errno, strerror(errno)); + return -1; + } + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse_addr,sizeof(reuse_addr)); + fcntl(sockfd, F_SETFL, fcntl(sockfd,F_GETFL) | O_NONBLOCK); + fcntl(sockfd, F_SETFD, FD_CLOEXEC); + + dbg_time("connect to %s sockfd = %d", name, sockfd); + + return sockfd; +} + +static void setTimespecRelative(struct timespec *p_ts, long long msec) +{ + struct timeval tv; + + gettimeofday(&tv, (struct timezone *) NULL); + + /* what's really funny about this is that I know + pthread_cond_timedwait just turns around and makes this + a relative time again */ + p_ts->tv_sec = tv.tv_sec + (msec / 1000); + p_ts->tv_nsec = (tv.tv_usec + (msec % 1000) * 1000L ) * 1000L; + if ((unsigned long)p_ts->tv_nsec >= 1000000000UL) { + p_ts->tv_sec += 1; + p_ts->tv_nsec -= 1000000000UL; + } +} + +int pthread_cond_timeout_np(pthread_cond_t *cond, pthread_mutex_t * mutex, unsigned msecs) { + if (msecs != 0) { + unsigned i; + unsigned t = msecs/4; + int ret = 0; + + if (t == 0) + t = 1; + + for (i = 0; i < msecs; i += t) { + struct timespec ts; + setTimespecRelative(&ts, t); +//very old uclibc do not support pthread_condattr_setclock(CLOCK_MONOTONIC) + ret = pthread_cond_timedwait(cond, mutex, &ts); //to advoid system time change + if (ret != ETIMEDOUT) { + if(ret) dbg_time("ret=%d, msecs=%u, t=%u", ret, msecs, t); + break; + } + } + + return ret; + } else { + return pthread_cond_wait(cond, mutex); + } +} + +const char * get_time(void) { + static char time_buf[128]; + struct timeval tv; + time_t time; + suseconds_t millitm; + struct tm *ti; + + gettimeofday (&tv, NULL); + + time= tv.tv_sec; + millitm = (tv.tv_usec + 500) / 1000; + + if (millitm == 1000) { + ++time; + millitm = 0; + } + + ti = localtime(&time); + sprintf(time_buf, "%02d-%02d_%02d:%02d:%02d:%03d", ti->tm_mon+1, ti->tm_mday, ti->tm_hour, ti->tm_min, ti->tm_sec, (int)millitm); + return time_buf; +} + +unsigned long clock_msec(void) +{ + struct timespec tm; + clock_gettime( CLOCK_MONOTONIC, &tm); + return (unsigned long)(tm.tv_sec*1000 + (tm.tv_nsec/1000000)); +} + +FILE *logfilefp = NULL; + +void update_resolv_conf(int iptype, const char *ifname, const char *dns1, const char *dns2) { + const char *dns_file = "/etc/resolv.conf"; + FILE *dns_fp; + char dns_line[256]; + #define MAX_DNS 16 + char *dns_info[MAX_DNS]; + char dns_tag[64]; + int dns_match = 0; + int i; + + snprintf(dns_tag, sizeof(dns_tag), "# IPV%d %s", iptype, ifname); + + for (i = 0; i < MAX_DNS; i++) + dns_info[i] = NULL; + + dns_fp = fopen(dns_file, "r"); + if (dns_fp) { + i = 0; + dns_line[sizeof(dns_line)-1] = '\0'; + + while((fgets(dns_line, sizeof(dns_line)-1, dns_fp)) != NULL) { + if ((strlen(dns_line) > 1) && (dns_line[strlen(dns_line) - 1] == '\n')) + dns_line[strlen(dns_line) - 1] = '\0'; + //dbg_time("%s", dns_line); + if (strstr(dns_line, dns_tag)) { + dns_match++; + continue; + } + dns_info[i++] = strdup(dns_line); + if (i == MAX_DNS) + break; + } + + fclose(dns_fp); + } + else if (errno != ENOENT) { + dbg_time("fopen %s fail, errno:%d (%s)", dns_file, errno, strerror(errno)); + return; + } + + if (dns1 == NULL && dns_match == 0) + return; + + dns_fp = fopen(dns_file, "w"); + if (dns_fp) { + if (dns1) + fprintf(dns_fp, "nameserver %s %s\n", dns1, dns_tag); + if (dns2) + fprintf(dns_fp, "nameserver %s %s\n", dns2, dns_tag); + + for (i = 0; i < MAX_DNS && dns_info[i]; i++) + fprintf(dns_fp, "%s\n", dns_info[i]); + fclose(dns_fp); + } + else { + dbg_time("fopen %s fail, errno:%d (%s)", dns_file, errno, strerror(errno)); + } + + for (i = 0; i < MAX_DNS && dns_info[i]; i++) + free(dns_info[i]); +} + +pid_t getpid_by_pdp(int pdp, const char* program_name) +{ + glob_t gt; + int ret; + char filter[16]; + pid_t pid; + + snprintf(filter, sizeof(filter), "-n %d", pdp); + ret = glob("/proc/*/cmdline", GLOB_NOSORT, NULL, >); + if (ret != 0) { + dbg_time("glob error, errno = %d(%s)", errno, strerror(errno)); + return -1; + } else { + int i = 0, fd = -1; + ssize_t nreads; + char cmdline[512] = {0}; + + for (i = 0; i < (int)gt.gl_pathc; i++) { + fd = open(gt.gl_pathv[i], O_RDONLY); + if (fd == -1) { + dbg_time("open %s failed, errno = %d(%s)", gt.gl_pathv[i], errno, strerror(errno)); + globfree(>); + return -1; + } + + nreads = read(fd, cmdline, sizeof(cmdline)); + if (nreads > 0) { + int pos = 0; + while (pos < nreads-1) { + if (cmdline[pos] == '\0') + cmdline[pos] = ' '; // space + pos++; + } + // printf("%s\n", cmdline); + } + + if (strstr(cmdline, program_name) && strstr(cmdline, filter)) { + char path[64] = {0}; + char pidstr[64] = {0}; + char *p; + + dbg_time("%s: %s", gt.gl_pathv[i], cmdline); + strcpy(path, gt.gl_pathv[i]); + p = strstr(gt.gl_pathv[i], "/cmdline"); + *p = '\0'; + while (*(--p) != '/') ; + + strcpy(pidstr, p+1); + pid = atoi(pidstr); + globfree(>); + + return pid; + } + } + } + + globfree(>); + return -1; +} + +void ql_get_driver_rmnet_info(PROFILE_T *profile, RMNET_INFO *rmnet_info) { + int ifc_ctl_sock; + struct ifreq ifr; + int rc; + int request = 0x89F3; + unsigned char data[512]; + + memset(rmnet_info, 0x00, sizeof(*rmnet_info)); + + ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM, 0); + if (ifc_ctl_sock <= 0) { + dbg_time("socket() failed: %s\n", strerror(errno)); + return; + } + + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_name, profile->usbnet_adapter, IFNAMSIZ); + ifr.ifr_name[IFNAMSIZ - 1] = 0; + ifr.ifr_ifru.ifru_data = (void *)data; + + rc = ioctl(ifc_ctl_sock, request, &ifr); + if (rc < 0) { + if (errno != ENOTSUP) + dbg_time("ioctl(0x%x, qmap_settings) errno:%d (%s), rc=%d", request, errno, strerror(errno), rc); + } + else { + memcpy(rmnet_info, data, sizeof(*rmnet_info)); + } + + close(ifc_ctl_sock); +} + +void ql_set_driver_qmap_setting(PROFILE_T *profile, QMAP_SETTING *qmap_settings) { + int ifc_ctl_sock; + struct ifreq ifr; + int rc; + int request = 0x89F2; + + ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM, 0); + if (ifc_ctl_sock <= 0) { + dbg_time("socket() failed: %s\n", strerror(errno)); + return; + } + + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_name, profile->usbnet_adapter, IFNAMSIZ); + ifr.ifr_name[IFNAMSIZ - 1] = 0; + ifr.ifr_ifru.ifru_data = (void *)qmap_settings; + + rc = ioctl(ifc_ctl_sock, request, &ifr); + if (rc < 0) { + dbg_time("ioctl(0x%x, qmap_settings) failed: %s, rc=%d", request, strerror(errno), rc); + } + + close(ifc_ctl_sock); +} + +void no_trunc_strncpy(char *dest, const char *src, size_t dest_size) +{ + size_t i = 0; + + for (i = 0; i < dest_size && *src; i++) { + *dest++ = *src++; + } + + *dest = 0; +} diff --git a/wwan/app/quectel_cm_5G/src/util.h b/wwan/app/quectel-cm/src/util.h similarity index 96% rename from wwan/app/quectel_cm_5G/src/util.h rename to wwan/app/quectel-cm/src/util.h index 392d401..4354bbc 100644 --- a/wwan/app/quectel_cm_5G/src/util.h +++ b/wwan/app/quectel-cm/src/util.h @@ -1,52 +1,52 @@ -/** - @file - util.h - - @brief - This file provides the definitions, and declares some common APIs for list-algorithm. - - */ - -#ifndef _UTILS_H_ -#define _UTILS_H_ - -#include -#include - -struct listnode -{ - struct listnode *next; - struct listnode *prev; -}; - -#define node_to_item(node, container, member) \ - (container *) (((char*) (node)) - offsetof(container, member)) - -#define list_declare(name) \ - struct listnode name = { \ - .next = &name, \ - .prev = &name, \ - } - -#define list_for_each(node, list) \ - for (node = (list)->next; node != (list); node = node->next) - -#define list_for_each_reverse(node, list) \ - for (node = (list)->prev; node != (list); node = node->prev) - -void list_init(struct listnode *list); -void list_add_tail(struct listnode *list, struct listnode *item); -void list_add_head(struct listnode *head, struct listnode *item); -void list_remove(struct listnode *item); - -#define list_empty(list) ((list) == (list)->next) -#define list_head(list) ((list)->next) -#define list_tail(list) ((list)->prev) - -int epoll_register(int epoll_fd, int fd, unsigned int events); -int epoll_deregister(int epoll_fd, int fd); -const char * get_time(void); -unsigned long clock_msec(void); -pid_t getpid_by_pdp(int, const char*); - -#endif +/** + @file + util.h + + @brief + This file provides the definitions, and declares some common APIs for list-algorithm. + + */ + +#ifndef _UTILS_H_ +#define _UTILS_H_ + +#include +#include + +struct listnode +{ + struct listnode *next; + struct listnode *prev; +}; + +#define node_to_item(node, container, member) \ + (container *) (((char*) (node)) - offsetof(container, member)) + +#define list_declare(name) \ + struct listnode name = { \ + .next = &name, \ + .prev = &name, \ + } + +#define list_for_each(node, list) \ + for (node = (list)->next; node != (list); node = node->next) + +#define list_for_each_reverse(node, list) \ + for (node = (list)->prev; node != (list); node = node->prev) + +void list_init(struct listnode *list); +void list_add_tail(struct listnode *list, struct listnode *item); +void list_add_head(struct listnode *head, struct listnode *item); +void list_remove(struct listnode *item); + +#define list_empty(list) ((list) == (list)->next) +#define list_head(list) ((list)->next) +#define list_tail(list) ((list)->prev) + +int epoll_register(int epoll_fd, int fd, unsigned int events); +int epoll_deregister(int epoll_fd, int fd); +const char * get_time(void); +unsigned long clock_msec(void); +pid_t getpid_by_pdp(int, const char*); + +#endif diff --git a/wwan/app/quectel_cm_5G/Makefile b/wwan/app/quectel_cm_5G/Makefile deleted file mode 100644 index 85507e6..0000000 --- a/wwan/app/quectel_cm_5G/Makefile +++ /dev/null @@ -1,39 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:= quectel-CM-5G -PKG_VERSION:=1.6.5 -PKG_RELEASE:=1 - -include $(INCLUDE_DIR)/package.mk - -define Package/quectel-CM-5G - SECTION:=utils - CATEGORY:=Utilities - TITLE:=quectel-CM-5G app -endef - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) - $(CP) ./src/* $(PKG_BUILD_DIR)/ -endef - -define Build/Compile - $(MAKE) -C "$(PKG_BUILD_DIR)" \ - EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ - CROSS_COMPILE="$(TARGET_CROSS)" \ - ARCH="$(LINUX_KARCH)" \ - M="$(PKG_BUILD_DIR)" \ - CC="$(TARGET_CC)" -endef - -define Package/quectel-CM-5G/install - $(INSTALL_DIR) $(1)/usr/bin $(1)/lib/netifd/proto - $(INSTALL_BIN) $(PKG_BUILD_DIR)/quectel-CM $(1)/usr/bin - $(INSTALL_BIN) ./files/rmnet_init.sh $(1)/lib/netifd - $(INSTALL_BIN) ./files/rmnet.script $(1)/lib/netifd - $(INSTALL_BIN) ./files/rmnet.sh $(1)/lib/netifd/proto - $(INSTALL_BIN) ./files/rmnet6.sh $(1)/lib/netifd/proto - $(INSTALL_BIN) ./files/rmnet6.script $(1)/lib/netifd -endef - -$(eval $(call BuildPackage,quectel-CM-5G)) diff --git a/wwan/app/quectel_cm_5G/files/dhcp b/wwan/app/quectel_cm_5G/files/dhcp deleted file mode 100644 index 7673927..0000000 --- a/wwan/app/quectel_cm_5G/files/dhcp +++ /dev/null @@ -1,48 +0,0 @@ - -config dnsmasq - option domainneeded '1' - option boguspriv '1' - option filterwin2k '0' - option localise_queries '1' - option rebind_protection '1' - option rebind_localhost '1' - option local '/lan/' - option domain 'lan' - option expandhosts '1' - option nonegcache '0' - option authoritative '1' - option readethers '1' - option leasefile '/tmp/dhcp.leases' - option resolvfile '/tmp/resolv.conf.auto' - option nonwildcard '1' - option localservice '1' - -config dhcp 'lan' - option interface 'lan' - option start '100' - option limit '150' - option leasetime '12h' - option ra 'relay' - option dhcpv6 'disabled' - option ndp 'relay' - -config dhcp 'wan' - option interface 'wan' - option ignore '1' - option ra 'relay' - option dhcpv6 'disabled' - option ndp 'relay' - option ndproxy_routing '0' - option master '1' - -config dhcp 'wan6' - option ra 'relay' - option dhcpv6 'disabled' - option ndp 'relay' - option ndproxy_routing '0' - option master '1' - option interface 'wan6' - -config odhcpd 'odhcpd' - option loglevel '7' - diff --git a/wwan/app/quectel_cm_5G/files/rmnet.script b/wwan/app/quectel_cm_5G/files/rmnet.script deleted file mode 100644 index 5bafb90..0000000 --- a/wwan/app/quectel_cm_5G/files/rmnet.script +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/sh -# Copyright (c) 2019 Qualcomm Technologies, Inc. -# All Rights Reserved. -# Confidential and Proprietary - Qualcomm Technologies, Inc. - - -[ -z "$1" ] && echo "Error: should be run by rmnet" && exit 1 -[ -z "$2" ] && echo "Error: should be run by rmnet" && exit 1 - -. /lib/functions.sh -. /lib/functions/network.sh -. /lib/netifd/netifd-proto.sh - -setup_interface() { - INTERFACE=$1 - CONFIG=/tmp/rmnet_$2_ipv4config - logger "rmnet setup_interface $1 $2 here" - #Fetch information from lower. - [ -f ${CONFIG} ] || { - proto_notify_error "$INTERFACE" "RMNET data call Not ready" - proto_block_restart "$INTERFACE" - return - } - . ${CONFIG} - ip=$PUBLIC_IP - DNS=$DNSSERVERS - router=$GATEWAY - subnet=$NETMASK - interface=$IFNAME - #Send the information to the netifd - proto_init_update "$interface" 1 1 - #ip and subnet - proto_add_ipv4_address "$ip" "${subnet:-255.255.255.0}" - - #Any router? if not, remove below scripts - #router format should be separated by space - for i in $router; do - proto_add_ipv4_route "$i" 32 "" "$ip" - proto_add_ipv4_route 0.0.0.0 0 "$i" "$ip" - done - - #dns information tell the netifd. - for dns in $DNS; do - proto_add_dns_server "$dns" - done - - #Domain information tell the netifd - for domain in $domain; do - proto_add_dns_search "$domain" - done - - #proto_add_data - [ -n "$ZONE" ] && json_add_string zone "$ZONE" - proto_close_data - - proto_send_update "$INTERFACE" - -} - -case "$1" in - renew) - setup_interface $2 $3 - ;; -esac - -exit 0 diff --git a/wwan/app/quectel_cm_5G/files/rmnet.sh b/wwan/app/quectel_cm_5G/files/rmnet.sh deleted file mode 100644 index 101ee60..0000000 --- a/wwan/app/quectel_cm_5G/files/rmnet.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh -# Copyright (c) 2019 Qualcomm Technologies, Inc. -# All Rights Reserved. -# Confidential and Proprietary - Qualcomm Technologies, Inc. - -. /lib/functions.sh -. /lib/functions/network.sh -. ../netifd-proto.sh - -init_proto "$@" - -proto_rmnet_setup() { - local cfg="$1" - local iface="$2" - - logger "rmnet started" - #Call rmnet management script below!! - logger "rmnet updated ${cfg} ${iface}" - /lib/netifd/rmnet.script renew $cfg $iface -} - -proto_rmnet_teardown() { - local cfg="$1" - #Tear down rmnet manager script here.*/ -} - -proto_rmnet_init_config() { - #ddno_device=1 - available=1 -} - -add_protocol rmnet diff --git a/wwan/app/quectel_cm_5G/files/rmnet6.script b/wwan/app/quectel_cm_5G/files/rmnet6.script deleted file mode 100644 index bbe05b2..0000000 --- a/wwan/app/quectel_cm_5G/files/rmnet6.script +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/sh -# Copyright (c) 2019 Qualcomm Technologies, Inc. -# All Rights Reserved. -# Confidential and Proprietary - Qualcomm Technologies, Inc. - - -[ -z "$1" ] && echo "Error: should be run by rmnet" && exit 1 -[ -z "$2" ] && echo "Error: should be run by rmnet" && exit 1 - -. /lib/functions.sh -. /lib/functions/network.sh -. /lib/netifd/netifd-proto.sh - -setup_interface() { - INTERFACE=$1 - CONFIG=/tmp/rmnet_$2_ipv6config - logger "rmnet setup_interface $1 $2 here" - #Fetch information from lower. - [ -f ${CONFIG} ] || { - proto_notify_error "$INTERFACE" "RMNET data call NOT ready" - proto_block_restart "$INTERFACE" - return - } - . ${CONFIG} - ADDRESSES=$PUBLIC_IP - interface=$IFNAME - #Send the information to the netifd - proto_init_update "$interface" 1 1 - - #ip and subnet - proto_add_ipv6_address "${PUBLIC_IP}" "128" - proto_add_ipv6_prefix "${PUBLIC_IP}/${PrefixLength}" - - #router format should be separated by space - proto_add_ipv6_route "$GATEWAY" 128 - proto_add_ipv6_route "::0" 0 "$GATEWAY" "" "" "${PUBLIC_IP}/${PrefixLength}" - - #dns information tell the netifd. - for dns in $DNSSERVERS; do - proto_add_dns_server "$dns" - done - - #Domain information tell the netifd - for domain in $domain; do - proto_add_dns_search "$domain" - done - - #proto_add_data - [ -n "$ZONE" ] && json_add_string zone "$ZONE" - proto_close_data - - proto_send_update "$INTERFACE" -} - -case "$1" in - renew|bound) - setup_interface $2 $3 - ;; -esac - -exit 0 diff --git a/wwan/app/quectel_cm_5G/files/rmnet6.sh b/wwan/app/quectel_cm_5G/files/rmnet6.sh deleted file mode 100644 index 57a5495..0000000 --- a/wwan/app/quectel_cm_5G/files/rmnet6.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh -# Copyright (c) 2019 Qualcomm Technologies, Inc. -# All Rights Reserved. -# Confidential and Proprietary - Qualcomm Technologies, Inc. - -. /lib/functions.sh -. /lib/functions/network.sh -. ../netifd-proto.sh - -init_proto "$@" - -proto_rmnet6_setup() { - local cfg="$1" - local iface="$2" - - logger "rmnet6 started" - #Call rmnet management script below!! - /lib/netifd/rmnet6.script renew $cfg $iface - logger "rmnet6 updated" -} - -proto_rmnet6_teardown() { - local cfg="$1" - #Tear down rmnet manager script here.*/ -} - -proto_rmnet6_init_config() { - #ddno_device=1 - available=1 -} - -add_protocol rmnet6 diff --git a/wwan/app/quectel_cm_5G/files/rmnet_init.sh b/wwan/app/quectel_cm_5G/files/rmnet_init.sh deleted file mode 100644 index 3d55438..0000000 --- a/wwan/app/quectel_cm_5G/files/rmnet_init.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh - -uci set network.wan='interface' -uci set network.wan.ifname='wwan0' -uci set network.wan.proto='rmnet' - -uci set network.wan6='interface' -uci set network.wan6.ifname='wwan0' -uci set network.wan6.proto='rmnet6' - -uci set dhcp.lan.ra='relay' -uci set dhcp.lan.dhcpv6='disabled' -uci set dhcp.lan.ndp='relay' - -uci set dhcp.wan.ra='relay' -uci set dhcp.wan.dhcpv6='disabled' -uci set dhcp.wan.ndp='relay' -uci set dhcp.wan.ndproxy_routing='0' - -uci set dhcp.wan6=dhcp -uci set dhcp.wan6.interface='wan6' -uci set dhcp.wan6.ra='relay' -uci set dhcp.wan6.dhcpv6='disabled' -uci set dhcp.wan6.ndp='relay' -uci set dhcp.wan6.ndproxy_routing='0' -uci set dhcp.wan6.master='1' - -uci set dhcp.odhcpd=odhcpd -uci set dhcp.odhcpd.loglevel='7' - -uci commit diff --git a/wwan/driver/quectel_QMI_WWAN/patches/100-kernel-6.6.patch b/wwan/driver/quectel_QMI_WWAN/patches/100-kernel-6.6.patch index 6cbc30c..5b5453e 100644 --- a/wwan/driver/quectel_QMI_WWAN/patches/100-kernel-6.6.patch +++ b/wwan/driver/quectel_QMI_WWAN/patches/100-kernel-6.6.patch @@ -25,7 +25,7 @@ /* This driver supports wwan (3G/LTE/?) devices using a vendor * specific management protocol called Qualcomm MSM Interface (QMI) - -@@ -828,26 +826,25 @@ static struct rtnl_link_stats64 *_rmnet_ +@@ -846,12 +846,20 @@ static struct rtnl_link_stats64 *_rmnet_ stats64 = per_cpu_ptr(dev->stats64, cpu); do { diff --git a/wwan/driver/quectel_QMI_WWAN/src/qmi_wwan_q.c b/wwan/driver/quectel_QMI_WWAN/src/qmi_wwan_q.c index 4f1a468..13258c9 100644 --- a/wwan/driver/quectel_QMI_WWAN/src/qmi_wwan_q.c +++ b/wwan/driver/quectel_QMI_WWAN/src/qmi_wwan_q.c @@ -59,13 +59,15 @@ 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) -#ifdef CONFIG_RMNET_DATA +#if defined(CONFIG_PINCTRL_IPQ807x) || defined(CONFIG_PINCTRL_IPQ5018) || defined(CONFIG_PINCTRL_IPQ8074) +//#ifdef CONFIG_RMNET_DATA //spf12.x none, not effect for spf11.x #define CONFIG_QCA_NSS_DRV -/* define at qsdk/qca/src/linux-4.4/net/rmnet_data/rmnet_data_main.c */ +/* 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 /* 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 /* This driver supports wwan (3G/LTE/?) devices using a vendor @@ -91,7 +93,7 @@ extern struct rmnet_nss_cb *rmnet_nss_callbacks __rcu __read_mostly; * These devices may alternatively/additionally be configured using AT * commands on a serial interface */ -#define VERSION_NUMBER "V1.2.2" +#define VERSION_NUMBER "V1.2.6" #define QUECTEL_WWAN_VERSION "Quectel_Linux&Android_QMI_WWAN_Driver_"VERSION_NUMBER static const char driver_name[] = "qmi_wwan_q"; @@ -115,6 +117,7 @@ static const u8 default_modem_addr[ETH_ALEN] = {0x02, 0x50, 0xf3}; 1 - QMAP (Aggregation protocol) X - QMAP (Multiplexing and Aggregation protocol) */ +//#define CONFIG_CLEAR_HALT #define QUECTEL_WWAN_QMAP 4 //MAX is 7 #if defined(QUECTEL_WWAN_QMAP) @@ -216,7 +219,7 @@ struct qmap_priv { struct timespec64 agg_time; struct hrtimer agg_hrtimer; struct work_struct agg_wq; - + #ifdef QUECTEL_BRIDGE_MODE uint bridge_mode; uint bridge_ipv4; @@ -225,7 +228,7 @@ struct qmap_priv { unsigned char bridge_self_mac[ETH_ALEN]; #endif #endif - uint use_qca_nss; + uint use_qca_nss; }; struct qmap_hdr { @@ -319,10 +322,10 @@ static int bridge_arp_reply(struct net_device *net, struct sk_buff *skb, uint br reply->ip_summed = CHECKSUM_UNNECESSARY; reply->pkt_type = PACKET_HOST; -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0) - netif_rx_ni(reply); -#else +#if (LINUX_VERSION_CODE >= KERNEL_VERSION( 5,18,0 )) netif_rx(reply); +#else + netif_rx_ni(reply); #endif } return 1; @@ -357,14 +360,14 @@ static struct sk_buff *bridge_mode_tx_fixup(struct net_device *net, struct sk_bu bridge_mac[0], bridge_mac[1], bridge_mac[2], bridge_mac[3], bridge_mac[4], bridge_mac[5]); } } - + #ifdef CONFIG_BRIDGE_LAN //bridge Lan IP 192.168.0.0 if (ehdr->h_proto == htons(ETH_P_IP) && (iph->daddr & 0xFFFF) == 0xA8C0) { struct sk_buff *reply = skb_copy(skb, GFP_ATOMIC); ehdr = eth_hdr(reply); - + memcpy(ehdr->h_source, default_modem_addr, ETH_ALEN); if(is_qmap_netdev(net)) { @@ -378,20 +381,16 @@ static struct sk_buff *bridge_mode_tx_fixup(struct net_device *net, struct sk_bu sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused; memcpy(ehdr->h_dest, pQmapDev->bridge_self_mac, ETH_ALEN); } - + //pr_info("%s br rx pkt addr: %02x:%02x:%02x:%02x:%02x:%02x -> %02x:%02x:%02x:%02x:%02x:%02x\n", netdev_name(net), // ehdr->h_source[0], ehdr->h_source[1], ehdr->h_source[2], ehdr->h_source[3], ehdr->h_source[4], ehdr->h_source[5], // ehdr->h_dest[0], ehdr->h_dest[1], ehdr->h_dest[2], ehdr->h_dest[3], ehdr->h_dest[4], ehdr->h_dest[5]); - + 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_ni(reply); -#else - netif_rx(reply); -#endif return NULL; } #endif @@ -510,7 +509,7 @@ static ssize_t link_state_store(struct device *dev, struct device_attribute *att } } - if (usbnetdev->net->flags & IFF_UP) { + if (usbnetdev->net->flags & IFF_UP) { if (!pQmapDev->link_state) { netif_carrier_off(usbnetdev->net); } @@ -683,7 +682,7 @@ static void qmap_wake_queue(sQmiWwanQmap *pQmapDev) if (!pQmapDev || !pQmapDev->use_rmnet_usb) return; - + for (i = 0; i < pQmapDev->qmap_mode; i++) { struct net_device *qmap_net = pQmapDev->mpQmapNetDev[i]; @@ -693,7 +692,7 @@ static void qmap_wake_queue(sQmiWwanQmap *pQmapDev) } } -static struct sk_buff * add_qhdr(struct sk_buff *skb, u8 mux_id) { +static struct sk_buff * add_qhdr(struct sk_buff *skb, u8 mux_id, int *hdr_data, int ip_offset) { struct qmap_hdr *qhdr; int pad = 0; @@ -701,44 +700,55 @@ static struct sk_buff * add_qhdr(struct sk_buff *skb, u8 mux_id) { if (pad) { pad = 4 - pad; if (skb_tailroom(skb) < pad) { - printk("skb_tailroom small!\n"); + //printk("skb_tailroom small!\n"); pad = 0; } if (pad) __skb_put(skb, pad); } - - qhdr = (struct qmap_hdr *)skb_push(skb, sizeof(struct qmap_hdr)); + + if (hdr_data) { + qhdr = (struct qmap_hdr *)hdr_data; + qhdr->pkt_len = cpu_to_be16(skb->len - ip_offset); + } + else { + qhdr = (struct qmap_hdr *)skb_push(skb, sizeof(struct qmap_hdr)); + qhdr->pkt_len = cpu_to_be16(skb->len - sizeof(struct qmap_hdr)); + } qhdr->cd_rsvd_pad = pad; qhdr->mux_id = mux_id; - qhdr->pkt_len = cpu_to_be16(skb->len - sizeof(struct qmap_hdr)); return skb; } -static struct sk_buff * add_qhdr_v5(struct sk_buff *skb, u8 mux_id) { +static struct sk_buff * add_qhdr_v5(struct sk_buff *skb, u8 mux_id, int *hdr_data, int ip_offset) { struct rmnet_map_header *map_header; struct rmnet_map_v5_csum_header *ul_header; - u32 padding, map_datalen; + int pad = 0; - map_datalen = skb->len; - padding = map_datalen%4; - if (padding) { - padding = 4 - padding; - if (skb_tailroom(skb) < padding) { - printk("skb_tailroom small!\n"); - padding = 0; + pad = (skb->len - ip_offset) %4; + if (pad) { + pad = 4 - pad; + if (skb_tailroom(skb) < pad) { + //printk("skb_tailroom small!\n"); + pad = 0; } - if (padding) - __skb_put(skb, padding); + if (pad) + __skb_put(skb, pad); + } + + if (hdr_data) { + map_header = (struct rmnet_map_header *)hdr_data; + map_header->pkt_len = htons(skb->len - ip_offset); + } + else { + map_header = (struct rmnet_map_header *)skb_push(skb, (sizeof(struct rmnet_map_header) + sizeof(struct rmnet_map_v5_csum_header))); + map_header->pkt_len = htons(skb->len - (sizeof(struct rmnet_map_header) + sizeof(struct rmnet_map_v5_csum_header))); } - - map_header = (struct rmnet_map_header *)skb_push(skb, (sizeof(struct rmnet_map_header) + sizeof(struct rmnet_map_v5_csum_header))); map_header->cd_bit = 0; map_header->next_hdr = 1; - map_header->pad_len = padding; + map_header->pad_len = pad; map_header->mux_id = mux_id; - map_header->pkt_len = htons(map_datalen + padding); ul_header = (struct rmnet_map_v5_csum_header *)(map_header + 1); memset(ul_header, 0, sizeof(*ul_header)); @@ -761,48 +771,38 @@ static void rmnet_vnd_update_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(5,18,0) +#if (LINUX_VERSION_CODE < KERNEL_VERSION( 6,0,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_packets, rx_packets); + u64_stats_add(&stats64->rx_bytes, rx_bytes); #endif u64_stats_update_end(&stats64->syncp); #else -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0) net->stats.rx_packets += rx_packets; net->stats.rx_bytes += rx_bytes; -#else - u64_stats_add(&net->stats.rx_packets, rx_packets); - u64_stats_add(&net->stats.rx_bytes, rx_bytes); -#endif #endif } static void rmnet_vnd_update_tx_stats(struct net_device *net, - unsigned tx_packets, unsigned tx_bytes) { + unsigned tx_packets, unsigned tx_bytes) { #if defined(MHI_NETDEV_STATUS64) struct qmap_priv *dev = netdev_priv(net); struct pcpu_sw_netstats *stats64 = this_cpu_ptr(dev->stats64); u64_stats_update_begin(&stats64->syncp); -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0) +#if (LINUX_VERSION_CODE < KERNEL_VERSION( 6,0,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_packets, tx_packets); + u64_stats_add(&stats64->tx_bytes, tx_bytes); #endif u64_stats_update_end(&stats64->syncp); #else -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0) net->stats.tx_packets += tx_packets; net->stats.tx_bytes += tx_bytes; -#else - u64_stats_add(&net->stats.tx_packets, tx_packets); - u64_stats_add(&net->tx_bytes, tx_bytes); -#endif #endif } @@ -822,26 +822,37 @@ 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; stats64 = per_cpu_ptr(dev->stats64, cpu); do { -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 6,6,0 )) start = u64_stats_fetch_begin_irq(&stats64->syncp); -#else - start = u64_stats_fetch_begin(&stats64->syncp); -#endif rx_packets = stats64->rx_packets; rx_bytes = stats64->rx_bytes; tx_packets = stats64->tx_packets; tx_bytes = stats64->tx_bytes; -#if (LINUX_VERSION_CODE < KERNEL_VERSION( 6,6,0 )) } 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 - } while (u64_stats_fetch_retry(&stats64->syncp, start)); -#endif + 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_irq(&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_irq(&stats64->syncp, start)); stats->rx_packets += u64_stats_read(&rx_packets); stats->rx_bytes += u64_stats_read(&rx_bytes); @@ -897,7 +908,7 @@ static void rmnet_usb_tx_skb_destructor(struct sk_buff *skb) { if (pQmapDev && pQmapDev->use_rmnet_usb) { int i; - + for (i = 0; i < pQmapDev->qmap_mode; i++) { struct net_device *qmap_net = pQmapDev->mpQmapNetDev[i]; @@ -967,7 +978,7 @@ static void rmnet_usb_tx_agg_work(struct work_struct *work) ktime_get_ts64(&priv->agg_time); } spin_unlock_irqrestore(&priv->agg_lock, flags); - + if (skb) { int err; #if 0 @@ -998,7 +1009,7 @@ static long agg_bypass_time __read_mostly = 10000000L; module_param(agg_bypass_time, long, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(agg_bypass_time, "Skip agg when apart spaced more than this"); -static int rmnet_usb_tx_agg(struct sk_buff *skb, struct qmap_priv *priv) { +static int rmnet_usb_tx_agg(struct sk_buff *skb, struct qmap_priv *priv, int *hdr_data, int hdr_len, int ip_offset) { struct qmi_wwan_state *info = (void *)&priv->dev->data; sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused; struct tx_agg_ctx *ctx = &pQmapDev->tx_ctx; @@ -1021,15 +1032,22 @@ static int rmnet_usb_tx_agg(struct sk_buff *skb, struct qmap_priv *priv) { rmnet_vnd_update_tx_stats(pNet, 1, skb->len); if (ctx->ul_data_aggregation_max_datagrams == 1) { - skb->protocol = htons(ETH_P_MAP); - skb->dev = priv->real_dev; + agg_skb = alloc_skb(skb->len + hdr_len, GFP_ATOMIC); + if (agg_skb) { + memcpy(skb_put(agg_skb, hdr_len), hdr_data, hdr_len); + memcpy(skb_put(agg_skb, skb->len - ip_offset), skb->data + ip_offset, skb->len - ip_offset); + agg_skb->protocol = htons(ETH_P_MAP); + agg_skb->dev = priv->real_dev; #if 0 - if (!skb->destructor) - skb->destructor = rmnet_usb_tx_skb_destructor; + if (!agg_skb->destructor) + agg_skb->destructor = rmnet_usb_tx_skb_destructor; #endif - err = dev_queue_xmit(skb); - if (err != NET_XMIT_SUCCESS) + err = dev_queue_xmit(agg_skb); + if (err != NET_XMIT_SUCCESS) pNet->stats.tx_errors++; + } + dev_kfree_skb_any(skb); + skb = NULL; return NET_XMIT_SUCCESS; } @@ -1041,8 +1059,9 @@ new_packet: diff = timespec64_sub(now, priv->agg_time); if (priv->agg_skb) { - if ((priv->agg_skb->len + skb->len) < ctx->ul_data_aggregation_max_size) { - memcpy(skb_put(priv->agg_skb, skb->len), skb->data, skb->len); + if ((priv->agg_skb->len + skb->len + hdr_len) < ctx->ul_data_aggregation_max_size) { + memcpy(skb_put(priv->agg_skb, hdr_len), hdr_data, hdr_len); + memcpy(skb_put(priv->agg_skb, skb->len - ip_offset), skb->data + ip_offset, skb->len - ip_offset); priv->agg_count++; if (diff.tv_sec > 0 || diff.tv_nsec > agg_time_limit) { @@ -1052,14 +1071,14 @@ new_packet: ready2send = 1; } else if (xmit_more == 0) { - struct rmnet_map_header *map_header = (struct rmnet_map_header *)skb->data; + struct rmnet_map_header *map_header = (struct rmnet_map_header *)hdr_data; size_t offset = sizeof(struct rmnet_map_header); if (map_header->next_hdr) offset += sizeof(struct rmnet_map_v5_csum_header); ready2send = rmnet_usb_tx_agg_skip(skb, offset); } - + dev_kfree_skb_any(skb); skb = NULL; } @@ -1078,7 +1097,7 @@ new_packet: ready2send = 1; } else if (xmit_more == 0) { - struct rmnet_map_header *map_header = (struct rmnet_map_header *)skb->data; + struct rmnet_map_header *map_header = (struct rmnet_map_header *)hdr_data; size_t offset = sizeof(struct rmnet_map_header); if (map_header->next_hdr) offset += sizeof(struct rmnet_map_v5_csum_header); @@ -1090,7 +1109,8 @@ new_packet: priv->agg_skb = alloc_skb(ctx->ul_data_aggregation_max_size, GFP_ATOMIC); if (priv->agg_skb) { skb_reset_network_header(priv->agg_skb); //protocol da1a is buggy, dev wwan0 - memcpy(skb_put(priv->agg_skb, skb->len), skb->data, skb->len); + memcpy(skb_put(priv->agg_skb, hdr_len), hdr_data, hdr_len); + memcpy(skb_put(priv->agg_skb, skb->len - ip_offset), skb->data + ip_offset, skb->len - ip_offset); priv->agg_count++; dev_kfree_skb_any(skb); skb = NULL; @@ -1101,7 +1121,12 @@ new_packet: } if (ready2send) { - agg_skb = skb; + agg_skb = alloc_skb(skb->len + hdr_len, GFP_ATOMIC); + if (agg_skb) { + memcpy(skb_put(agg_skb, hdr_len), hdr_data, hdr_len); + memcpy(skb_put(agg_skb, skb->len - ip_offset), skb->data + ip_offset, skb->len - ip_offset); + } + dev_kfree_skb_any(skb); skb = NULL; } } @@ -1142,6 +1167,9 @@ static netdev_tx_t rmnet_vnd_start_xmit(struct sk_buff *skb, { int err; struct qmap_priv *priv = netdev_priv(pNet); + int qmap_hdr[2]; + int hdr_len = 0; + int ip_offset = 0; if (netif_queue_stopped(priv->real_dev)) { netif_stop_queue(pNet); @@ -1159,18 +1187,24 @@ static netdev_tx_t rmnet_vnd_start_xmit(struct sk_buff *skb, } #endif +#if 1 + ip_offset = ETH_HLEN; +#else if (skb_pull(skb, ETH_HLEN) == NULL) { dev_kfree_skb_any (skb); return NETDEV_TX_OK; } +#endif } //printk("%s 2 skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len); if (priv->qmap_version == 5) { - add_qhdr(skb, priv->mux_id); + add_qhdr(skb, priv->mux_id, qmap_hdr, ip_offset); + hdr_len = 4; } else if (priv->qmap_version == 9) { - add_qhdr_v5(skb, priv->mux_id); + add_qhdr_v5(skb, priv->mux_id, qmap_hdr, ip_offset); + hdr_len = 8; } else { dev_kfree_skb_any (skb); @@ -1178,7 +1212,7 @@ static netdev_tx_t rmnet_vnd_start_xmit(struct sk_buff *skb, } //printk("%s skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len); - err = rmnet_usb_tx_agg(skb, priv); + err = rmnet_usb_tx_agg(skb, priv, qmap_hdr, hdr_len, ip_offset); return err; } @@ -1246,7 +1280,7 @@ static rx_handler_result_t qca_nss_rx_handler(struct sk_buff **pskb) if (!skb) return RX_HANDLER_CONSUMED; - + //printk("%s skb=%p, len=%d, protocol=%x, hdr_len=%d\n", __func__, skb, skb->len, skb->protocol, skb->hdr_len); if (skb->pkt_type == PACKET_LOOPBACK) @@ -1295,10 +1329,10 @@ static int qmap_register_device(sQmiWwanQmap * pDev, u8 offset_id) priv->dev = pDev->mpNetDev; priv->qmap_version = pDev->qmap_version; priv->mux_id = QUECTEL_QMAP_MUX_ID + offset_id; -#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 17, 0) - memcpy (qmap_net->dev_addr, real_dev->dev_addr, ETH_ALEN); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,17,0) + __dev_addr_set(qmap_net, real_dev->dev_addr, ETH_ALEN); #else - eth_hw_addr_set (real_dev, qmap_net->dev_addr); + memcpy (qmap_net->dev_addr, real_dev->dev_addr, ETH_ALEN); #endif #ifdef QUECTEL_BRIDGE_MODE @@ -1314,7 +1348,9 @@ static int qmap_register_device(sQmiWwanQmap * pDev, u8 offset_id) if (nss_cb && use_qca_nss) { rmnet_usb_rawip_setup(qmap_net); } - +#ifdef CONFIG_PINCTRL_IPQ9574 + rmnet_usb_rawip_setup(qmap_net); +#endif priv->agg_skb = NULL; priv->agg_count = 0; hrtimer_init(&priv->agg_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); @@ -1350,7 +1386,7 @@ static int qmap_register_device(sQmiWwanQmap * pDev, u8 offset_id) netdev_info(qmap_net, "NSS context created\n"); rtnl_lock(); netdev_rx_handler_register(qmap_net, qca_nss_rx_handler, NULL); - rtnl_unlock(); + rtnl_unlock(); } } @@ -1379,7 +1415,7 @@ static void qmap_unregister_device(sQmiWwanQmap * pDev, u8 offset_id) { pDev->mpQmapNetDev[offset_id] = NULL; netif_carrier_off( qmap_net ); netif_stop_queue( qmap_net ); - + hrtimer_cancel(&priv->agg_hrtimer); cancel_work_sync(&priv->agg_wq); spin_lock_irqsave(&priv->agg_lock, flags); @@ -1460,7 +1496,11 @@ static int qmap_ndo_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) #ifdef CONFIG_BRIDGE_LAN BRMAC_SETTING brmac_settings = {0}; #endif - +#ifdef CONFIG_CLEAR_HALT + uint clear_halt = 0; +#endif + + switch (cmd) { case 0x89F1: //SIOCDEVPRIVATE rc = copy_from_user(&link_state, ifr->ifr_ifru.ifru_data, sizeof(link_state)); @@ -1493,7 +1533,7 @@ static int qmap_ndo_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) rc = copy_to_user(ifr->ifr_ifru.ifru_data, &pQmapDev->rmnet_info, sizeof(pQmapDev->rmnet_info)); } break; - + #ifdef CONFIG_BRIDGE_LAN case 0x89F4: //SIOCDEVPRIVATE rc = copy_from_user(&brmac_settings, ifr->ifr_ifru.ifru_data, sizeof(brmac_settings)); @@ -1515,6 +1555,16 @@ static int qmap_ndo_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) } break; #endif +#ifdef CONFIG_CLEAR_HALT + case 0x89F5: //SIOCDEVPRIVATE + rc = copy_from_user(&clear_halt, ifr->ifr_ifru.ifru_data, sizeof(clear_halt)); + if (rc == 0 && clear_halt == 1) { + usb_clear_halt(usbnetdev->udev,usbnetdev->in); + usb_clear_halt(usbnetdev->udev,usbnetdev->out); + pr_info("usb_clear_halt EPIN EPOUT\n"); + } + break; +#endif default: break; @@ -1657,9 +1707,9 @@ static struct sk_buff *qmap_qmi_wwan_tx_fixup(struct usbnet *dev, struct sk_buff if (skb) { if(pQmapDev->qmap_version == 5) - add_qhdr(skb, QUECTEL_QMAP_MUX_ID); + add_qhdr(skb, QUECTEL_QMAP_MUX_ID, NULL, 0); else - add_qhdr_v5(skb, QUECTEL_QMAP_MUX_ID); + add_qhdr_v5(skb, QUECTEL_QMAP_MUX_ID, NULL, 0); } else { return NULL; @@ -1690,7 +1740,7 @@ static void qmap_packet_decode(sQmiWwanQmap *pQmapDev, while (skb_in->len > sizeof(struct qmap_hdr)) { struct rmnet_map_header *map_header = (struct rmnet_map_header *)skb_in->data; struct rmnet_map_v5_csum_header *ul_header = NULL; - size_t hdr_size = sizeof(struct rmnet_map_header); + size_t hdr_size = sizeof(struct rmnet_map_header); struct net_device *qmap_net; int pkt_len = ntohs(map_header->pkt_len); int skb_len; @@ -1702,7 +1752,7 @@ static void qmap_packet_decode(sQmiWwanQmap *pQmapDev, ul_header = (struct rmnet_map_v5_csum_header *)(map_header + 1); hdr_size += sizeof(struct rmnet_map_v5_csum_header); } - + skb_len = pkt_len - (map_header->pad_len&0x3F); skb_len -= dl_minimum_padding; @@ -1717,7 +1767,7 @@ static void qmap_packet_decode(sQmiWwanQmap *pQmapDev, dev_info(dev, "drop qmap unknow mux_id %x\n", map_header->mux_id); goto skip_pkt; } - + if (skb_len > qmap_net->mtu) { dev_info(dev, "drop skb_len=%x larger than mtu=%d\n", skb_len, qmap_net->mtu); goto error_pkt; @@ -1760,7 +1810,7 @@ static void qmap_packet_decode(sQmiWwanQmap *pQmapDev, dev_info(dev, "unknow skb->protocol %02x\n", skb_in->data[hdr_size]); goto error_pkt; } - + qmap_skb = netdev_alloc_skb(qmap_net, skb_len); if (qmap_skb) { skb_put(qmap_skb, skb_len); @@ -1815,7 +1865,7 @@ static int qmap_qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in) sQmiWwanQmap *pQmapDev = (sQmiWwanQmap *)info->unused; struct sk_buff *qmap_skb; struct sk_buff_head skb_chain; - + if (pQmapDev->qmap_mode == 0) return qmi_wwan_rx_fixup(dev, skb_in); @@ -1862,7 +1912,7 @@ static void (*_usbnet_get_stats64)(struct net_device *net, struct rtnl_link_stat static void qmi_wwan_get_stats64(struct net_device *net, struct rtnl_link_stats64 *stats) { if (_usbnet_get_stats64) ////c8b5d129ee293bcf972e7279ac996bb8a138505c return _usbnet_get_stats64(net, stats); - + netdev_stats_to_stats64(stats, &net->stats); } #else @@ -1871,7 +1921,7 @@ static struct rtnl_link_stats64 * (*_usbnet_get_stats64)(struct net_device *net, static struct rtnl_link_stats64 * qmi_wwan_get_stats64(struct net_device *net, struct rtnl_link_stats64 *stats) { if (_usbnet_get_stats64) return _usbnet_get_stats64(net, stats); - + netdev_stats_to_stats64(stats, &net->stats); return stats; } @@ -1896,7 +1946,7 @@ static int qmi_wwan_open (struct net_device *net) { } static netdev_tx_t qmi_wwan_start_xmit (struct sk_buff *skb, - struct net_device *net) + struct net_device *net) { struct usbnet * usbnetdev = netdev_priv( net ); struct qmi_wwan_state *info = (void *)&usbnetdev->data; @@ -1907,7 +1957,7 @@ static netdev_tx_t qmi_wwan_start_xmit (struct sk_buff *skb, if (netif_queue_stopped(net) && pQmapDev && pQmapDev->use_rmnet_usb) { int i; - + for (i = 0; i < pQmapDev->qmap_mode; i++) { struct net_device *qmap_net = pQmapDev->mpQmapNetDev[i]; if (qmap_net) { @@ -2066,17 +2116,17 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf) /* make MAC addr easily distinguishable from an IP header */ if (possibly_iphdr(dev->net->dev_addr)) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,18,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,17,0) + u8 temp_addr[ETH_ALEN]; + memcpy(temp_addr, dev->net->dev_addr, ETH_ALEN); + temp_addr[0] |= 0x02; /* set local assignment bit */ + temp_addr[0] &= 0xbf; /* clear "IP" bit */ + __dev_addr_set(dev->net, temp_addr, ETH_ALEN); +#else dev->net->dev_addr[0] |= 0x02; /* set local assignment bit */ dev->net->dev_addr[0] &= 0xbf; /* clear "IP" bit */ -#else - u8 addr = dev->net->dev_addr[0]; - - addr |= 0x02; /* set local assignment bit */ - addr &= 0xbf; /* clear "IP" bit */ - dev_addr_mod(dev->net, 0, &addr, 1); #endif - } + } if (!_usbnet_get_stats64) _usbnet_get_stats64 = dev->net->netdev_ops->ndo_get_stats64; dev->net->netdev_ops = &qmi_wwan_netdev_ops; @@ -2109,6 +2159,9 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf) NULL, 0, 100); } + usb_clear_halt(dev->udev,dev->in); + usb_clear_halt(dev->udev,dev->out); + //to advoid module report mtu 1460, but rx 1500 bytes IP packets, and cause the customer's system crash //next setting can make usbnet.c:usbnet_change_mtu() do not modify rx_urb_size according to hard mtu dev->rx_urb_size = ETH_DATA_LEN + ETH_HLEN + 6; @@ -2140,12 +2193,13 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf) int qmap_version = (dev->driver_info->data>>8)&0xFF; int qmap_size = (dev->driver_info->data)&0xFF; int idProduct = le16_to_cpu(dev->udev->descriptor.idProduct); - int lte_a = (idProduct == 0x0306 || idProduct == 0x030B || idProduct == 0x0512 || idProduct == 0x0620 || idProduct == 0x0800 || idProduct == 0x0801); + int lte_a = (idProduct == 0x0306 || idProduct == 0x030B || idProduct == 0x0512 || idProduct == 0x0620 || + idProduct == 0x0800 || idProduct == 0x0801 || idProduct == 0x0122); if (qmap_size > 4096 || dev->udev->speed >= USB_SPEED_SUPER) { //if meet this requirements, must be LTE-A or 5G lte_a = 1; } - + pQmapDev->qmap_mode = qmap_mode; if (lte_a && pQmapDev->qmap_mode == 0) { pQmapDev->qmap_mode = 1; //force use QMAP @@ -2162,13 +2216,13 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf) if (pQmapDev->qmap_mode > 1) pQmapDev->use_rmnet_usb = 1; - else if (idProduct == 0x0800 || idProduct == 0x0801) + else if (idProduct == 0x0800 || idProduct == 0x0801 || idProduct == 0x0122) pQmapDev->use_rmnet_usb = 1; //benefit for ul data agg #ifdef QMI_NETDEV_ONE_CARD_MODE if(pQmapDev->use_rmnet_usb == 1 && pQmapDev->qmap_mode == 1) one_card_mode = 1; pQmapDev->rmnet_info.mux_id[0] = QUECTEL_QMAP_MUX_ID; -#endif +#endif pQmapDev->rmnet_info.size = sizeof(RMNET_INFO); pQmapDev->rmnet_info.rx_urb_size = pQmapDev->qmap_size; pQmapDev->rmnet_info.ep_type = 2; //DATA_EP_TYPE_HSUSB @@ -2182,7 +2236,7 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf) pQmapDev->tx_ctx.ul_data_aggregation_max_size = 1500; #endif - if (pQmapDev->use_rmnet_usb && !one_card_mode) { + if (pQmapDev->use_rmnet_usb && !one_card_mode) { pQmapDev->driver_info = rmnet_usb_info; pQmapDev->driver_info.data = dev->driver_info->data; dev->driver_info = &pQmapDev->driver_info; @@ -2350,7 +2404,7 @@ static int rmnet_usb_rx_fixup(struct usbnet *dev, struct sk_buff *skb) return 1; } - + return 0; } @@ -2411,7 +2465,7 @@ static const struct driver_info qmi_wwan_info = { }; #define qmi_wwan_raw_ip_info \ - .description = "WWAN/QMI device", \ + .description = "WWAN/QMI Raw IP device", \ .flags = FLAG_WWAN | FLAG_RX_ASSEMBLE | FLAG_NOARP | FLAG_SEND_ZLP, \ .bind = qmi_wwan_bind, \ .unbind = qmi_wwan_unbind, \ @@ -2459,6 +2513,7 @@ static const struct usb_device_id products[] = { { QMI_FIXED_INTF(0x05C6, 0x9215, 4) }, /* Quectel EC20 (MDM9215) */ { QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0125, 4, mdm9x07) }, /* Quectel EC20 (MDM9X07)/EC25/EG25 */ { QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0121, 4, mdm9x07) }, /* Quectel EC21 */ + { QMI_FIXED_RAWIP_INTF(0x2C7C, 0x030E, 4, mdm9x07) }, /* Quectel EM05G */ { QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0191, 4, mdm9x07) }, /* Quectel EG91 */ { QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0195, 4, mdm9x07) }, /* Quectel EG95 */ { QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0700, 3, mdm9x07) }, /* Quectel BG95 (at+qcfgext="usbnet","rmnet") */ @@ -2470,6 +2525,7 @@ static const struct usb_device_id products[] = { { QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0620, 4, mdm9x40) }, /* Quectel EG20 */ { QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0800, 4, sdx55) }, /* Quectel RG500 */ { QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0801, 4, sdx55) }, /* Quectel RG520 */ + { QMI_FIXED_RAWIP_INTF(0x2C7C, 0x0122, 4, sdx55) }, /* Quectel RG650 */ { } /* END */ }; MODULE_DEVICE_TABLE(usb, products); @@ -2576,11 +2632,11 @@ static void qmap_qmi_wwan_disconnect(struct usb_interface *intf) } tasklet_kill(&pQmapDev->txq); - + usbnet_disconnect(intf); /* struct usbnet *dev had free by usbnet_disconnect()->free_netdev(). so we should access info. */ - //info->unused = 0; + //info->unused = 0; kfree(pQmapDev); } #endif