OpenWrt Forum Archive

Topic: DWM-157 3G Dongle in MBIM mode

The content of this topic has been archived on 11 Apr 2018. There are no obvious gaps in this topic, but there may still be some posts missing at the end.

Hello folks.

I have a WR842ND v1 running CC 15.05.1 and a DWM-157 USB 3G dongle connected using '3g' (serial) protocol.

I got bored and looking for some fun tried to switch to a faster and stable protocol. After researching I found something about QMI/NCM/MBIM protocol and found that my dongle works in MBIM mode (also Windows 10 use that mode natively).

Installed all necessary packages into my router but unfortunately I can't get any valid answer from any commands sent to modem like I do in Ubuntu (mbimcli -d /dev/cdc-wdm0 --query-packet-service-state).

Almost every command returns same data:

root@OpenWrt:~# umbim -n -v -d /dev/cdc-wdm0 caps
sending (16): 01 00 00 00 10 00 00 00 01 00 00 00 00 04 00 00
  header_type: 0001
  header_length: 0010
  header_transaction: 0001
reading (16): 04 00 00 80 10 00 00 00 01 00 00 00 08 00 00 00
  header_type: 80000004
  header_length: 0010
  header_transaction: 0001
sending (16): 02 00 00 00 10 00 00 00 02 00 00 00 08 00 00 00
  header_type: 0002
  header_length: 0010
  header_transaction: 0002
reading (16): 02 00 00 80 10 00 00 00 02 00 00 00 02 00 00 00
  header_type: 80000002
  header_length: 0010
  header_transaction: 0002

Looks like I have a lot to lean about it, where do I start? smile

(Last edited by rmacielalves on 6 May 2016, 19:03)

rmacielalves wrote:

Hello folks.

I have a WR842ND v1 running CC 15.05.1 and a DWM-157 USB 3G dongle connected using '3g' (serial) protocol.

I got bored and looking for some fun tried to switch to a faster and stable protocol. After researching I found something about QMI/NCM/MBIM protocol and found that my dongle works in MBIM mode (also Windows 10 use that mode natively).

Installed all necessary packages into my router but unfortunately I can't get any valid answer from any commands sent to modem like I do in Ubuntu (mbimcli -d /dev/cdc-wdm0 --query-packet-service-state).

Almost every command returns same data:

root@OpenWrt:~# umbim -n -v -d /dev/cdc-wdm0 caps
sending (16): 01 00 00 00 10 00 00 00 01 00 00 00 00 04 00 00
  header_type: 0001
  header_length: 0010
  header_transaction: 0001
reading (16): 04 00 00 80 10 00 00 00 01 00 00 00 08 00 00 00
  header_type: 80000004
  header_length: 0010
  header_transaction: 0001
sending (16): 02 00 00 00 10 00 00 00 02 00 00 00 08 00 00 00
  header_type: 0002
  header_length: 0010
  header_transaction: 0002
reading (16): 02 00 00 80 10 00 00 00 02 00 00 00 02 00 00 00
  header_type: 80000002
  header_length: 0010
  header_transaction: 0002

Looks like I have a lot to lean about it, where do I start? smile

Downloading the current MBIM spec from http://www.usb.org/developers/docs/devc … 073013.zip and use it to a a bit more verbose error messages to umbim would be a great start smile

The "header_type: 80000004" is MBIM_FUNCTION_ERROR_MSG, and the last 4 bytes of that message is the error code in le32 (which is the only integer type in MBIM messages). Error code 8 is MBIM_ERROR_MAX_TRANSFER, which "Shall be sent if the function does not support the maximum control transfer the host supports."

So the problem is that the modem doesn't support the requested message size.  That's the last 4 bytes of the open message: 0x00000400, or 1024 in decimal, which is hardcoded in umbim (MBIM_BUFFER_SIZE).  This is not the right way to do that. We should pick the message size from the MBIM descriptor.  For convenience, the driver also provides it through an ioctl. A nice fix would be to add support for that in umbim.

For a quickfix, I suggest checking the value of your modem: run "lsusb -v" and look for the MBIM descriptor:

      CDC MBIM:
        bcdMBIMVersion       1.00
        wMaxControlMessage   4096
        bNumberFilters       16
        bMaxFilterSize       128
        wMaxSegmentSize      1430
        bmNetworkCapabilities 0x20
          8-byte ntb input size

The value you are after is the wMaxControlMessage.  Yours is probably significantly smaller.  I'm guessing 512. Then change

#define MBIM_BUFFER_SIZE 1024

to

#define MBIM_BUFFER_SIZE 512

in mbim.h and rebuild umbim.  This should make it work.  But the real fix is to make it automatically match the value set by the modem.  In theory a smaller value can always be used, but I'm not sure all MBIM firmwares expect anything else than their preferred value.

bmork wrote:

Downloading the current MBIM spec from http://www.usb.org/developers/docs/devc … 073013.zip and use it to a a bit more verbose error messages to umbim would be a great start smile

Thanks for the docs smile

bmork wrote:

The "header_type: 80000004" is MBIM_FUNCTION_ERROR_MSG, and the last 4 bytes of that message is the error code in le32 (which is the only integer type in MBIM messages). Error code 8 is MBIM_ERROR_MAX_TRANSFER, which "Shall be sent if the function does not support the maximum control transfer the host supports."

So the problem is that the modem doesn't support the requested message size.  That's the last 4 bytes of the open message: 0x00000400, or 1024 in decimal, which is hardcoded in umbim (MBIM_BUFFER_SIZE).  This is not the right way to do that. We should pick the message size from the MBIM descriptor.  For convenience, the driver also provides it through an ioctl. A nice fix would be to add support for that in umbim.

Hardcoded? It should have at least a parameter to set buffer manually... hmm

bmork wrote:

For a quickfix, I suggest checking the value of your modem: run "lsusb -v" and look for the MBIM descriptor:

The value you are after is the wMaxControlMessage.  Yours is probably significantly smaller.  I'm guessing 512.

You guessed it! 512.

      CDC MBIM:
        bcdMBIMVersion       1.00
        wMaxControlMessage   512
        bNumberFilters       16
        bMaxFilterSize       64
        wMaxSegmentSize      1500
        bmNetworkCapabilities 0x20
          8-byte ntb input size
bmork wrote:

Then change

#define MBIM_BUFFER_SIZE 1024

to

#define MBIM_BUFFER_SIZE 512

in mbim.h and rebuild umbim.

Rebuild package? Uh oh more homework to do smile

bmork wrote:

This should make it work.  But the real fix is to make it automatically match the value set by the modem.  In theory a smaller value can always be used, but I'm not sure all MBIM firmwares expect anything else than their preferred value.

Looks like mbim-cli from Ubuntu auto-detect buffer size.

May opening a bug report/feature request to fix/add auto-detection? Hardcoded isn't good for supporting multiple dongles who have different buffer sizes. I can help providing data from my DWM-157 and testing if they need it.

From now going to rebuild with 512. Thank you so much for all the info you gave me so far.

(Last edited by rmacielalves on 7 May 2016, 00:44)

rmacielalves wrote:

Looks like mbim-cli from Ubuntu auto-detect buffer size.

Yup, it does. 

rmacielalves wrote:

May opening a bug report/feature request to fix/add auto-detection? Hardcoded isn't good for supporting multiple dongles who have different buffer sizes. I can help providing data from my DWM-157 and testing if they need it.

A bug report is fine, but a patch is probably better. Here's proof-of-concept code for Linux v3.10 or newer (I I think we can assume that now smile

#include <fcntl.h>
#include <linux/types.h>
#include <linux/usb/cdc-wdm.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <unistd.h>

int main(int argc, char **argv)
{
     __u16 max;
    int rc, fd;

    fd = open("/dev/cdc-wdm0", O_RDWR);
    if (fd < 0)
        return fd;
    rc = ioctl(fd, IOCTL_WDM_MAX_COMMAND, &max);
    close(fd);
    if (rc < 0)
        return rc;
    
    printf("IOCTL_WDM_MAX_COMMAND returned %u\n", max);
    return 0;
}

it's of course also possible to parse the descriptor, but I believe the above is a bit simpler.

Progress! Rebuilt umbim, overwritten binary and voilá:

root@OpenWrt:~# umbim -d /dev/cdc-wdm0 caps
  devicetype: 0002 - removable
  cellularclass: 0001
  voiceclass: 0003 - simultaneous-voice-data
  simclass: 0002
  dataclass: 001F
  smscaps: 0003
  controlcaps: 0001
  maxsessions: 0002
  deviceid: 35xxxxxxxxxxxxxxxxxx
  firmwareinfo: MOLY.WR8.W1231.DC.WG.MP.V3
  hardwareinfo: MTK2
root@OpenWrt:~# umbim -d /dev/cdc-wdm0 pinstate
Pin Unlocked
root@OpenWrt:~# umbim -d /dev/cdc-wdm0 subscriber
  readystate: 0001 - initialized
  simiccid: 895xxxxxxxxxxxxxxxxxxxxxx
  subscriberid: 72xxxxxxxxxxxxxxxxxx
  number: 5513xxxxxxxxxxx
root@OpenWrt:~# umbim -d /dev/cdc-wdm0 registration
  nwerror: 0000 - unknown
  registerstate: 0001 - deregistered
  registermode: 0001 - automatic
  availabledataclasses: 0000 - (null)
  currentcellularclass: 0001 - gsm
  provider_id: (null)
  provider_name: (null)
  roamingtext: (null)

EDIT: I don't know how to register to the network using mbim, so gcom did the trick for now:

root@OpenWrt:~# gcom -d /dev/ttyUSB1
SIM ready
Waiting for Registration..(120 sec max).
Registered on Home network: "72403"
Signal Quality: 16, 99
root@OpenWrt:~# umbim -d /dev/cdc-wdm0 attach
  nwerror: 0000 - unknown
  packetservicestate: 0002 - attached
  uplinkspeed: 11500000
  downlinkspeed: 42000000
root@OpenWrt:~# umbim -d /dev/cdc-wdm0 connect
  sessionid: 0
  activationstate: 0001 - activated
  voicecallstate: 0000 - none
  nwerror: 0000 - unknown
  iptype: 0003 - ipv4v6

EDIT2: Requesting config return timed out and forces modem disconnect from PS

root@OpenWrt:~# umbim -v -d /dev/cdc-wdm0 config
sending (16): 01 00 00 00 10 00 00 00 01 00 00 00 00 02 00 00
  header_type: 0001
  header_length: 0010
  header_transaction: 0001
reading (72): 07 00 00 80 48 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 a2 89 cc 33 bc bb 8b 4f b6 b0 13 3e c2 aa e6 df 0a 00 00 00 1c 00 00 00 00 00 00 00 02 00 00 00 08 00 00 00 e0 79 af 00 00 00 00 00 80 de 80 02 00 00 00 00
  header_type: 80000007
  header_length: 0048
  header_transaction: 0000
reading (72): 00 00 00 00 00 00 00 00 e4 a0 bc f0 e4 a0 bc f0 e4 a1 bc f0 00 00 00 00 00 00 00 00 00 00 00 00 64 a6 bc f0 00 00 00 00 f1 a0 bc f0 e4 a1 bc f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ee 0c
  header_type: 0000
  header_length: 0000
  header_transaction: F0BCA0E4
reading (16): 01 00 00 80 10 00 00 00 01 00 00 00 00 00 00 00
  header_type: 80000001
  header_length: 0010
  header_transaction: 0001
sending (108): 03 00 00 00 6c 00 00 00 02 00 00 00 01 00 00 00 00 00 00 00 a2 89 cc 33 bc bb 8b 4f b6 b0 13 3e c2 aa e6 df 0f 00 00 00 00 00 00 00 3c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  header_type: 0003
  header_length: 006C
  header_transaction: 0002
ERROR: mbim message timeout

EDIT3: A little more of researching and got it! IPv4 and IPv6 connectivity over MBIM protocol setup big_smile

I'll post details later, it's bed time wink

(Last edited by rmacielalves on 9 May 2016, 03:44)

Alright, IPv6 is a lot hell unstable!!! High CPU time from dhclient6 process, it was slowing down internet speed...

Also, I edited mbim.sh to fit MBIM standard, because my dongle don´t act as a DHCP server, instead I query IP from 'AT+CGPADDR' and set it on wwan0 interface plus routing. DNS is another thing, had to change to 8.8.8.8 (Google).

Here is what I have done so far (thanks bmork for the help).

  • Compiled umbim with 512 buffer size.
    Customized mbim.sh to set IP address manually instead of getting from DHCP (my dongle dont support, also it's non-standard).
    Created a dummy luci-proto-mbim as a placeholder and to make shell-less dependent (for something later smile)

Currently porting jake1981's NCM Protocol support scripts to MBIM standard (mediatek chipset) as now I have the full AT commands documentation from Mediatek big_smile.

In meantime, I need to figure it out how to handle PPP lease time, my dongle is forced to disconnect after uptime of 8 hours and instead of report to the router, it crashes kernel driver!

Mon May  9 22:04:05 2016 kern.warn kernel: [29011.010000] ------------[ cut here ]------------
Mon May  9 22:04:05 2016 kern.warn kernel: [29011.010000] WARNING: CPU: 0 PID: 0 at net/sched/sch_generic.c:303 dev_watchdog+0x1d8/0x25c()
Mon May  9 22:04:05 2016 kern.info kernel: [29011.020000] NETDEV WATCHDOG: wwan0 (cdc_mbim): transmit queue 0 timed out
Mon May  9 22:04:05 2016 kern.warn kernel: [29011.030000] Modules linked in: ath9k ath9k_common pppoe ppp_async option iptable_nat cdc_mbim ath9k_hw ath usb_wwan qmi_wwan pppox ppp_generic nf_nat_ipv4 nf_conntrack_ipv6 nf_conntrack_ipv4 mac80211 ipt_REJECT ipt_MASQUERADE cfg80211 cdc_ncm xt_time xt_tcpudp xt_state xt_nat xt_multiport xt_mark xt_mac xt_limit xt_id xt_conntrack xt_comment xt_TCPMSS xt_REDIRECT xt_LOG xt_CT usbserial usbnet slhc nf_reject_ipv4 nf_nat_masquerade_ipv4 nf_nat_ftp nf_nat nf_log_iMon May  9 22:04:05 2016 kern.warn kernel: [29011.100000] CPU: 0 PID: 0 Comm: swapper Not tainted 3.18.23 #1
Mon May  9 22:04:05 2016 kern.warn kernel: [29011.110000] Stack : 00000000 00000000 00000000 00000000 803d4292 00000032 00000000 80255800
Mon May  9 22:04:05 2016 kern.warn kernel: [29011.110000]         00000001 0000003d 8031f208 80376ba3 00000000 803d34d0 80376ed8 0000003d
Mon May  9 22:04:05 2016 kern.warn kernel: [29011.110000]         803d3918 00000001 00000004 800a364c 00000003 8008043c 0000012f 0000003d
Mon May  9 22:04:05 2016 kern.warn kernel: [29011.110000]         80322800 80371c6c 00000000 00000000 00000000 00000000 00000000 00000000
Mon May  9 22:04:05 2016 kern.warn kernel: [29011.110000]         00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
Mon May  9 22:04:05 2016 kern.warn kernel: [29011.110000]         ...
Mon May  9 22:04:05 2016 kern.warn kernel: [29011.140000] Call Trace:
Mon May  9 22:04:05 2016 kern.warn kernel: [29011.150000] [<80071060>] show_stack+0x50/0x84
Mon May  9 22:04:05 2016 kern.warn kernel: [29011.150000] [<80080544>] warn_slowpath_common+0x84/0xb4
Mon May  9 22:04:05 2016 kern.warn kernel: [29011.160000] [<800805a0>] warn_slowpath_fmt+0x2c/0x38
Mon May  9 22:04:05 2016 kern.warn kernel: [29011.160000] [<80255800>] dev_watchdog+0x1d8/0x25c
Mon May  9 22:04:05 2016 kern.warn kernel: [29011.170000] [<800ab0e8>] call_timer_fn.isra.38+0x24/0x84
Mon May  9 22:04:05 2016 kern.warn kernel: [29011.170000] [<800ab900>] run_timer_softirq+0x1bc/0x1f8
Mon May  9 22:04:05 2016 kern.warn kernel: [29011.180000] [<80082a44>] __do_softirq+0xf8/0x230
Mon May  9 22:04:05 2016 kern.warn kernel: [29011.180000] [<80082db0>] irq_exit+0x54/0x70
Mon May  9 22:04:05 2016 kern.warn kernel: [29011.180000] [<80060830>] ret_from_irq+0x0/0x4
Mon May  9 22:04:05 2016 kern.warn kernel: [29011.190000] [<80060a80>] __r4k_wait+0x20/0x40
Mon May  9 22:04:05 2016 kern.warn kernel: [29011.190000] [<8009f5e4>] cpu_startup_entry+0xf0/0x13c
Mon May  9 22:04:05 2016 kern.warn kernel: [29011.200000] [<80390b5c>] start_kernel+0x42c/0x444
Mon May  9 22:04:05 2016 kern.warn kernel: [29011.200000]
Mon May  9 22:04:05 2016 kern.warn kernel: [29011.200000] ---[ end trace a7f4a01030fd7dab ]---

Thanks,
rmaciel.


- sorry for my broken english wink

(Last edited by rmacielalves on 17 May 2016, 00:07)

rmacielalves wrote:

In meantime, I need to figure it out how to handle PPP lease time, my dongle is forced to disconnect after uptime of 8 hours and instead of report to the router, it crashes kernel driver!

Mon May  9 22:04:05 2016 kern.warn kernel: [29011.010000] ------------[ cut here ]------------
Mon May  9 22:04:05 2016 kern.warn kernel: [29011.010000] WARNING: CPU: 0 PID: 0 at net/sched/sch_generic.c:303 dev_watchdog+0x1d8/0x25c()
Mon May  9 22:04:05 2016 kern.info kernel: [29011.020000] NETDEV WATCHDOG: wwan0 (cdc_mbim): transmit queue 0 timed out

Don't know what to do about the disconnect, but what you see is not a crash.  It is simply a noisy way to warn about "transmit queue 0 timed out", which is to be expected if the modem is disconnected without the driver knowing.   Just ignore the warning and carry on with a reconnect.

The discussion might have continued from here.