Adding support for MikroTik hAP ac3 LTE6 kit (D53GR_5HacD2HnD)

I have no first hand experience with that modem, but see that I've been involved in discussion. See MikroTik RBM33G installing 4G and WIFI module - #9 by Ryking

Yep, the setup is clear, I am getting an IP via DHCP from the RNDIS interface (DHCP client on the eth2 port which is the RNDIS interface), it is jut not the IP the mobile operator gives out, but an internal one. And there is no forwarding towards the internet.... :slight_smile:

I assume Mikrotik are managing the modem by (possibly vendor specific) AT commands on one of the ACM functions. You might have to connect the modem by som magic AT command sequence to get it to provide a public IP and routing on the RNDIS interface.

If you're lucky then they're using standard commands like AT+CGATT and AT+CGACT to connect the modem. Otherwise you'll probably have to figure out what ROS does and replicate that. Or ask Mikrotik. Or replace the modem

Well, on the serial line the modem can be used after AT+CFUN=1, of course with limited speed. On RNDIS I think they call this feature "IP passthrough". Under ROS you can select the modem as "auto", "mbim" and "serial", but even if you select "mbim" it works as RNDIS (like in auto mode). As this modem is also sold separately I am not accepting the fact they intentionally boot the modem into a mode where it does not work, so I opened a support request for these questions. Nobody else does that, so they need to provide the correct AT commands, and that still does not change the fact no other modem vendor does this crap that you need extra AT commands to make the base functionality work...

Further findings with modem:

  1. it is now definitive that the modem by default goes into CFUN=4 ("fligh mode"). And mikrotik ROS moves the modem out from this state during bringup.

  2. By default the modem is in RNDIS state. In order to get proper IP the RNDIS interface needs to be set up as a DHCP client interface and extra AT commands needeD:

AT+ZGDCONT=5,"IP","internet",0
AT+ZGPCOAUTH=5,"","",0
AT+CFUN=1
AT+ZGACT=1,5

After this a restart of the RNDIS DHCP client will pass the IP issued by the mobile operator directly to the RNDIS interface:

image

Issuing a reset (AT+RESET) to the modem will move the RNDIS interface back to its internal IP state:

image

This is a pile of shite of course, as normally we don't want to deal with this, the modem should just boot to a default working state. But at least we know this is the situation presented by MikroTik.

MOD: searching for this issue I found that someone already find and fixed this issue for a different modem device with a similar Marvell chipset:

https://git.openwrt.org/?p=openwrt/openwrt.git;a=commitdiff;h=0a5f3b012669208f5454ebe4a1def16e5ab093dd

1 Like

@bmork

Sorry to annoy you with this, but maybe you can take a look at this.

I tried to add Mikrotik based on the commit I linked above:

package/network/utils/comgt/files/ncm.json:

        "\"mikrotik\"": {
                "initialize": [
                        "AT+CFUN=1"
                ],
                "configure": [
                        "AT+ZGDCONT=${profile},\\\"${pdptype}\\\",\\\"${apn}\\\",\\\"\\\",0,0",
                        "AT+ZGPCOAUTH=${profile},\\\"${username}\\\",\\\"${password}\\\",0"
                ],
                "connect": "AT+ZGACT=1,${profile}",
                "disconnect": "AT+ZGACT=0,${profile}"
        }

Yet when I add the modem as NCM (with modem device /dev/ttyACM0), the log say:

Thu Sep 22 22:09:04 2022 daemon.notice netifd: lte (3461): Failed to parse message data
Thu Sep 22 22:09:04 2022 daemon.notice netifd: lte (3461): WARNING: Variable '"mikrotik"' does not exist or is not an array/object
Thu Sep 22 22:09:04 2022 daemon.notice netifd: lte (3461): Unsupported modem
Thu Sep 22 22:09:04 2022 daemon.notice netifd: lte (3657): Stopping network lte
Thu Sep 22 22:09:06 2022 daemon.notice netifd: lte (3657): Failed to parse message data
Thu Sep 22 22:09:06 2022 daemon.notice netifd: lte (3657): WARNING: Variable '"mikrotik"' does not exist or is not an array/object
Thu Sep 22 22:09:06 2022 daemon.notice netifd: lte (3657): Unsupported modem
Thu Sep 22 22:09:06 2022 daemon.notice netifd: Interface 'lte' is now down

Is there something I am missing?

Looks sensible to me. I guess it's something minor relating to quoting, commas or other stuff I'm unable to parse manually. Test the modified json file with jq, and maybe play with quoting or not.

Don't know what else to suggest. Your solution looks fine

I have a bit of hard time understanding the concept, so lets try to clear that first.

This modem as it stands has the following interafces:

root@OpenWrt:~# lsusb -v|grep iInterface
      iInterface              0
      iInterface              0
      iInterface              5 RNDIS Communications Control
      iInterface              6 RNDIS Ethernet Data
      iInterface              8 CDC Abstract Control Model (ACM)
      iInterface              9 CDC ACM Data
      iInterface              8 CDC Abstract Control Model (ACM)
      iInterface              9 CDC ACM Data
      iInterface             11 Marvell DIAG
      iInterface             12 Marvell DEBUG
      iInterface              0
      iInterface              0

If I understand the NCM methhod correctly, we need two things:

  1. Set up an NCM interface with modem device = /dev/ttyACM0
  2. Set up a normal ethernet interface for RNDIS (eth2 in our case) with DHCP client.

The NCM interface acts as "control plane" and the ethernet interafce acts as "user plane". Is that correct?

And the NCM interface based on the addition to ncm.json will send the necessary commands at interface bringup?

Yes, if we replace NCM with ACM.

NCM is just another ethernet transport for USB, similar to RNDIS or ECM. None of these have any modem control plane (ignoring the Huawei variant, which transports AT command inside NCM control messages). Using these ethernet emulation protocols for a modems means that the control plane must be implemented on some other channel. Most of the time that's a USB serial function speaking AT commands.

MBIM is different by having a standardized modem control protocol as part of the spec, using the same control messages as the Huawei NCM variant I mentioned for transport. It's otherwise closely related to NCM, using the same framing where multiple packets are stuffed together.

QMI (or RMNET) in it's basic form is mostly identical to ECM, but using the same control messages as MBIM and Huawei NCM to transport Qualcomms QMI protocol. Which is actually a multiplex of modem subsystem protocols. We're only using a small subset for basic modem control. There is also a more complex RMNET framing variant called QMAP.

More info than you or anyone wanted, I guess :slight_smile:

No, no. Not at all.

So my setup should look like this?

and the RNDIS interface:

image

??

MOD: no matter how I change the syntax, the NCM interface always reports:
Error: Network device is not present

I tried with:


       "\"mikrotik\"": {
       "mikrotik": {
       "\"mikrotik": {

none of these work...

You don't need separate "RNDIS" interface, the NCM protocol handler will create a dynamic DHCP interface.
Could you add "set -x" and "set +x" around this part:

        manufacturer=$(gcom -d "$device" -s /etc/gcom/getcardinfo.gcom | awk 'NF && $0 !~ /AT\+CGMI/ { sub(/\+CGMI: /,""); print tolower($1); exit; }')
        [ $? -ne 0 -o -z "$manufacturer" ] && {
                echo "Failed to get modem information"
                proto_notify_error "$interface" GETINFO_FAILED
                return 1
        }

and then post syslog output?

Can you be a little more specific?

This is the reposnse for AT+CGMI if you need this:

+CGMI: "MikroTik"

OK

The Response for ATI is:

MikroTik

OK

MOD: ok, so I guess I need to use "MikroTik" instead of "mikrotik" in the ncm.json file. I modified it and now the output changes:

Tue Sep 27 17:25:38 2022 daemon.notice netifd: Interface 'lte' is setting up now
Tue Sep 27 17:25:40 2022 daemon.notice netifd: lte (2366): Failed to parse message data
Tue Sep 27 17:25:40 2022 daemon.notice netifd: lte (2366): WARNING: Variable 'ok' does not exist or is not an array/object
Tue Sep 27 17:25:40 2022 daemon.notice netifd: lte (2366): Unsupported modem
Tue Sep 27 17:25:40 2022 daemon.notice netifd: lte (2426): Stopping network lte
Tue Sep 27 17:25:42 2022 daemon.notice netifd: lte (2426): Failed to parse message data
Tue Sep 27 17:25:42 2022 daemon.notice netifd: lte (2426): WARNING: Variable '*simdetec:1,sim' does not exist or is not an array/object
Tue Sep 27 17:25:42 2022 daemon.notice netifd: lte (2426): Unsupported modem
Tue Sep 27 17:25:42 2022 daemon.notice netifd: Interface 'lte' is now down

Note that the /dev/ttyACM0 interface is quite verbose by default. Not sure if that is a problem or not.

My point was to extract the manufacturer string that lands in the variable inside the script, so a proper match could be found. With MF286R it took some time to figure out the proper string, and there was more than one entry, because of multitude of revisions of this modem.
See https://github.com/openwrt/openwrt/commit/e02fb42c53bad5dd36726c6ef5a46bfe31d2e400
Maybe you need the variant only with escaped forward quote, i.e. "\"mikrotik": {?

So small and capital letters does not count as different?

I tried:

"\"MikroTik\"": {
"\"MikroTik": {
"MikroTik": {

So far, none of the above worked.

FYI, this is how verbose this interface is after startup:

+CGMI: "MikroTik"

OK

*ICCID: 8988211000000073653

*EUICC: 1

+CREG: 0

$CREG: 0

+CESQ: 99,99,255,255,255,255

*CESQ: 99,99,255,255,255,255,0

+CGREG: 0

+CEREG: 0

+CESQ: 99,99,255,255,255,255

*CESQ: 99,99,255,255,255,255,0

*RADIOPOWER: 0

*ADMINDATA: 0, 2, 0

+CPIN: READY

*EUICC: 1

*ECCLIST: 5, 0, 112, 0, 000, 0, 08, 0, 118, 0, 911

+MMSG: 0, 0

+MMSG: 0, 0

+MMSG: 1, 0

+MPBK: 1

Susceptibility to URCs (Unsolicited Result Codes) is known problem of NCM handler :frowning:
You may try the other ACM port, usually there is one for control and one for data - maybe this one won't be so verbose.
What does AT+CLAC return? Maybe there is a way to disable those pesky URCs...

The other port (ttyACM1) does not respond to any command, minicom connects to it and that is it.

AT+CLAC:

ATE
ATI
ATL
ATM
ATO
ATP
ATQ
ATT
ATV
ATX
ATZ
AT&C
AT&D
AT&F
AT&S
AT&Z
ATS0
AT+CGMI
AT+CGMM
AT+CGMR
AT+CGSN
AT+CSCS
AT+CIMI
AT+ASTO
AT+GMI
AT+GMM
AT+GMR
AT+GSN
AT+GOI
AT+GCAP
AT+GCI
AT+IPR
AT+ICF
AT+IFC
AT+IDSR
AT+EXAMPLE
AT^HVER
AT
ATA
ATD
ATH
AT+MVSYNAUD
AT+CDU
AT+CMOD
AT+CBST
AT+CVHU
AT+CRLP
AT+CMUT
AT+ECHUPVT
AT+CTTY
AT+CREG
AT+CIND
AT+COPS
AT+CPOL
AT+COPN
AT+CLCK
AT+CPWD
AT+CLIP
AT+CLIR
AT+COLP
AT+COLR
AT+CNAP
AT+CCFC
AT+CCWA
AT+CHLD
AT+CUSD
AT+CAOC
AT+VTS
AT+VTD
AT+CSSN
AT+CLCC
AT+CEER
AT+PEER
AT+CSQ
AT*REJCAUSE
AT+CPAS
AT+CFUN
AT*CFUN
AT+CPIN
AT+ZSEC
AT+CPIN2
AT+EPIN
AT*SIMDETEC
AT+CTZR
AT+CTZU
AT*CTZR
AT+CCLK
AT*PINCNT
AT+CPBS
AT+CPBR
AT+CPBW
AT*CPBR
AT*CPBS
AT+CPBF
AT+CSVM
AT+CSIM
AT+CRSM
AT+CGLA
AT+CRLA
AT+CCHO
AT+CCHC
AT+MSTK
AT*EUICC
AT+CACM
AT+CAMM
AT+CCWE
AT+CGREG
AT+CGATT
AT*CGATTC
AT+ZGACT
AT+CGACT
AT+CGDATA
AT+ZGDCONT
AT*ZGDCONT
AT+CGDCONT
AT+CGDSCONT
AT+CGQMIN
AT+CGQREQ
AT+CGEQREQ
AT+CGEQMIN
AT*REPORTIP
AT+GETIP
AT*TGSINK
AT*TGSINK
AT+CGSEND
AT*ICSSINK
AT+ZGPCOAUTH
AT*AUTHReq
AT+FCLASS
AT+CMGF
AT+CMSS
AT+CMGS
AT+CMGC
AT+CMGR
AT+CMGW
AT+CSCA
AT+CSCB
AT+CNMI
AT+CGSMS
AT+CMMS
AT+CMGD
AT+CMGL
AT+CSMS
AT+CPMS
AT+CSDH
AT+CNMA
AT+CSMP
AT+CGCI
AT+CGOI
AT+VDUMP
AT+LOG
AT+VPDUS
AT+VHDL
AT+VECHO
AT+ATDB
AT*CCIREG
AT+CPUC
AT+CHUP
AT+CSTA
AT+CRC
AT+CMEE
AT+CMER
AT+CMEC
AT+CLAC
AT+CBC
AT+CDIP
AT+CPLS
AT+CGCMOD
AT+CNUM
AT+DS
AT+CGTFT
AT*BAND
AT*BANDIND
AT+WS46
AT*CLCK
AT+LOCKLEVEL
AT+ZNCK
AT*MEPCG
AT*ENVSIM
AT*CNMA
AT*POWERIND
AT*APPOWERIND
AT*FASTDORM
AT+EEMOPT
AT+EEMGINFO
AT*ZAIRINFO
AT*ZCQI
AT+ERGA
AT+ERTCA
AT+LPNWUL
AT+LPLOCVR
AT+LPECID
AT+LPOTDOAABORT
AT+LPOTDOAREQ
AT*CELL
AT*SYSSLEEP
AT*CP_MIPS
AT*MRD_CDF
AT*MRD_SN
AT*MRD_SECOND_SN
AT*MRD_HWINFO
AT+RESET
AT+POWEROFF
AT+RSTSET
AT*MRD_WIFISSID
AT*MRD_WIFISSID_5G
AT*MRD_IMEI
AT*CALINFO
AT*MRD_MEP
AT*MRD_WIFIID
AT*MRD_BTID
AT*MRD_VEND
AT*MRD_BAND
AT*PROD
AT+LOCKNETLIST
AT+LOCKLIST
AT+UNLOCKKEY
AT+GPSSTEST
AT*GPSTEST
AT*GPSRST
AT*TDTR
AT*GSMTR
AT*TGCTRL
AT*WBTR
AT*RFC
AT*MRD_DUMP
AT*CPMRD_DUMP
AT*MRD_AUTH
AT+FUELGAIC
AT*MRD_LIST
AT*MAXPOWER
AT+CKPD
AT+OFF
AT*CGSN
AT*MODEMTYPE
AT$VTS
AT*MODEMRESET
AT*SWITCHMODEM
AT*HTCCTO
AT+CMEMFULL
AT*EHSDPA
AT^DCTS
AT^DEELS
AT^DEVEI
AT^DNPR
AT^DUSR
AT+CIREG
AT+CGEQOS
AT+CEREG
AT+CGCONTRDP
AT+CGSCONTRDP
AT+CGTFTRDP
AT+CGEQOSRDP
AT+CGEREP
AT+CVMOD
AT+CEMODE
AT+CGPADDR
AT+CGPIAF
AT^CACAP
AT+CGCLASS
AT+CESQ
AT*CESQ
AT+BGLTEPLMN
AT*FDY
AT^SYSINFO
AT*DIALE
AT*CPBC
AT*FDNBYPASS
AT*RSTMEMFULL
AT*CSCB
AT*CBMCS
AT*NASCHK
AT*USBT
AT*MOBILEDATA
AT*GATR
AT*CGATT
AT*GRIP
AT*PSPG
AT*CGMR
AT*READVER
AT*COMCFG
AT+VZWRSRP
AT+VZWRSRQ
AT*CGDFLT
AT*CGDFAUTH
AT*VZWTESTAPP
AT+VZWAPNE
AT*LTEBAND
AT*RFTEMP
AT*CSQ
AT+LTEPOWER
AT*LTECOEX
AT%MBMSCMD
AT%MBMSEV
AT+CEN
AT+CNEM
AT*SINR
AT*RSSI
AT*RSRP
AT*RSRPP
AT*RSRPS
AT*RSRQ
AT*RSRQP
AT*RSRQS
AT*CQI
AT*URSLCT
AT+CISRVCC
AT+CEVDP
AT+CVDP
AT+CEUS
AT+CAVIMS
AT+CASIMS
AT+CMMIVT
AT+CIREP
AT+CSSAC
AT*DONOF
AT*PWRPLMN
AT*CISCC
AT*RANDFILL
AT$CSQ
AT$CREG
AT$CCLK
AT*CSG
AT*APCFG
AT*ISIMAID
AT+MPBK
AT*CIIND
AT*PRXYSET
AT*PRXYRSP
AT*CHDSTST
AT+CNMPSD
AT+CSAS
AT+CRES
AT*TELMODE
AT*PSDC
AT*CBRAT
AT*IMLCONFIG
AT*IGN
AT*FRATLIST
AT*PCO
AT+CSDF
AT+RSRP
AT+RSRQ
AT+RSCP
AT+ECNO
AT+CLAN
AT*CELLINFO
AT+CCUG
AT+CPNER
AT*CATPROF
AT*CATEN
AT*RCATR
AT*CATTR
AT*CATENV
AT*RCATE
AT*AUDIOMODE
AT*AUDIODEVICE
AT*AUDIOVOL
AT*AUDIOMUTE
AT*ECALLDATA
AT*ECALLVOICE
AT*ECALLCFG
AT*ECALLONLY
AT*ECALLREG
AT*SIMPLUG
AT*CGDCONTL
AT*SPIND
AT*ECCLIST
AT*IMSSRV
AT+CPLMNS
AT+CACL
AT*DCONF
AT*CGCLASS
AT*CIWLANCID
AT*BTSCNCT
AT*BTSDISSCNCT
AT*BTSTAPDU
AT*BTSTATR
AT*BTSCTRL
AT*BTSCRSTAT
AT*BTSTP
AT+OPERCFG
AT*ICCID
AT*PARK
AT*CHECKEMER
AT+CECALL
AT*RPM
AT*TEMPTEST
AT*ZFACTORY
AT+ZDON
AT+ZSNT
AT+ZCAINFO
AT+ZCACFG
AT+ZRSSI
AT+ZNLOCKBAND
AT+ZPAS
AT+ZCELLINFO
AT+ACONFIG
AT+IMSFUNC
AT+ZVN
AT+ZSTM
AT+ZSELM
AT+ZSELI
AT+ZBK
AT+ZINKR
AT+ZINPR
AT+ZDISTR
AT+ZNITZ
AT+ZSYNCNITZ
AT+ZDOGREF
AT+ZATNUM
AT+STRESS
AT+SULOG
AT+MEDCR
AT+MIPLVER
AT+MIPLCREATE
AT+MIPLDELETE
AT+MIPLADDOBJ
AT+MIPLDELOBJ
AT+MIPLOPEN
AT+MIPLUPDATE
AT+MIPLCLOSE
AT+MIPLDISCOVERRSP
AT+MIPLREADRSP
AT+MIPLWRITERSP
AT+MIPLEXECUTERSP
AT+MIPLPARAMETERRSP
AT+MIPLOBSERVERSP
AT+MIPLNOTIFY
AT+ZDHCPLEASE
AT+GEFLAG
AT+ZCFG
AT+ZROAM
AT+ZVMAIL
AT+ZGDFLT
AT*ZCGMR
AT+WIFISSID
AT+WIFICHANNEL
AT+WIFIFUN
AT+SDCARD
AT+FUNC
AT%EXE
AT%SRVCHANGE
AT+OTADOWNLOAD
AT*CPMRD_LIST
AT+SWITCHNETWORK
AT+MIFIVER
AT*MRD_BANDSUPPORT
AT*BANDSUPPORT
AT+FDEL
AT+MKK_GPIO

Duh, those Marvell modems are so weird :confused:
I don't see anything meaningful in those commands.

ttyACM1 doesn't respond even to ATE1 (blindly)?

Also, if I recall correctly, you can use AT commands to disable URCs for each of those output respectively - not sure if it'll survive the reset, though. For example, like here: https://m2msupport.net/m2msupport/atcreg-network-registration/
This might come in handy, an AT command reference for different Marvell-based modem: https://2keep.net/wp-content/uploads/2019/06/Luat-LTE-Module-AT-Command-User-Manual-V1.0.pdf

On eko.one.pl found I found a stash of commands for it: https://eko.one.pl/?p=modem-r11elte - maybe it'll help you out somehow.

Ok, so the idea is that the unsolicited messages are the cause for not detecting the modem in NCM mode?

Correct, they buffer up and cause further parts of the script read garbage.

Ok. I am not sure if we can make the modem completely quiet, but I will try.