EM9291 How to on PCI and QMI

Board: miniPC ERVPES E3C 16GB, 512G NVME, QCNCM865

Modem: EM9291 through NVME M2. M+B key adapter (with of course dedicated power supply line from USB)

OpenWrt SNAPSHOT, r35027-8db23dc91a , kernel 6.18.35

Why like this? As I have already EM9291 and waiting for mini BananaPi BPI-R4 :slight_smile: Also I f** up buying RM520N-GL GLAP version (my initial intention was with that modem on make it running on PCI) but it is totally customised and no chance to move forward... :frowning:

Initially I was thinking to use ModemManger as out of box the modem was visible but for some reasons I gave up and I went to pure MBIM/QMI.

root@e3c:~# mmcli -L
    /org/freedesktop/ModemManager1/Modem/0 [Sierra Wireless, Incorporated] EM9291
root@e3c:~# mmcli -m 0
  ----------------------------------
  General  |                   path: /org/freedesktop/ModemManager1/Modem/0
           |              device id: 56e9789aaf45aa89e59e497daa47d7f9c4ec1c7f
  ----------------------------------
  Hardware |           manufacturer: Sierra Wireless, Incorporated
           |                  model: EM9291
           |      firmware revision: SWIX65C_02.17.08.00 944ad5 jenkins 2024/08/01 20:22:05
           |           h/w revision: 1
           |              supported: gsm-umts, lte, 5gnr
           |                current: gsm-umts, lte, 5gnr
           |           equipment id: xxxxxxx
  ----------------------------------
  System   |                 device: /sys/devices/pci0000:00/0000:00:02.4/0000:04:00.0
           |                physdev: /sys/devices/pci0000:00/0000:00:02.4/0000:04:00.0
           |                drivers: mhi_net, mhi-pci-generic
           |                 plugin: generic
           |           primary port: wwan0qmi0
           |                  ports: mhi_hwip0 (net), wwan0at0 (at), wwan0mbim0 (mbim),
           |                         wwan0qmi0 (qmi)
           |          ignored ports: wwan0qcdm0 (qcdm)
root@e3c:~# mmcli -m 0 --set-allowed-modes='5g'
successfully set current modes in the modem
root@e3c:~# mmcli -m 0 --simple-connect="apn='internet'"
error: couldn't connect the modem: 'GDBus.Error:org.freedesktop.ModemManager1.Error.MobileEquipment.NetworkTimeout: Network timeout'


root@e3c:~# mmcli -m 0 |grep -i state
           |                  state: enabled
           |            power state: on
           |   packet service state: detached
root@e3c:~# mmcli -m 0 --simple-connect="apn='internet'"
error: couldn't connect the modem: 'GDBus.Error:org.freedesktop.ModemManager1.Error.MobileEquipment.NetworkTimeout: Network timeout'

Preparartion (what we need)

root@E3C:~# lspci |grep -i qua
03:00.0 Network controller: Qualcomm Technologies, Inc WCN785x Wi-Fi 7(802.11be)                                                                                         320MHz 2x2 [FastConnect 7800] (rev 01)
04:00.0 Unassigned class [ff00]: Qualcomm Technologies, Inc SDX61/SDX62/SDX65 [S                                                                                        napdragon 5G X6X-series]
root@E3C:~# lsmod |grep -iE "qmi|mhi|rmnet|mbi"
cdc_mbim               12288  0
cdc_ncm                24576  1 cdc_mbim
cdc_wdm                24576  2 cdc_mbim,qmi_wwan
mhi                    73728  6 ath12k,mhi_wwan_mbim,mhi_wwan_ctrl,qrtr_mhi,mhi_                                                                                        pci_generic,mhi_net
mhi_net                12288  0
mhi_pci_generic        28672  0
mhi_wwan_ctrl          12288  0
mhi_wwan_mbim          12288  0
qmi_helpers            20480  1 ath12k
qmi_wwan               32768  0
qrtr                   28672  4 qrtr_tun,qrtr_mhi
qrtr_mhi               12288  0
rmnet                  24576  0
usbnet                 32768  6 cdc_mbim,sierra_net,rndis_host,qmi_wwan,cdc_ncm,                                                                                        cdc_ether
wwan                   20480  2 mhi_wwan_mbim,mhi_wwan_ctrl

Openwrt packages:



grep -E "CONFIG_PACKAGE_(qmi-utils|mbim-utils|picocom|kmod-rmnet|kmod-usb-serial-option)" .config
CONFIG_PACKAGE_kmod-rmnet=y
CONFIG_PACKAGE_kmod-usb-serial-option=y
CONFIG_PACKAGE_picocom=y
CONFIG_PACKAGE_mbim-utils=y
CONFIG_PACKAGE_qmi-utils=y
cat .config |grep -iE "mhi|qmi|mbib|modem"
CONFIG_PACKAGE_kmod-mhi-net=y
CONFIG_PACKAGE_kmod-mhi-wwan-ctrl=y
CONFIG_PACKAGE_kmod-mhi-wwan-mbim=y
CONFIG_PACKAGE_kmod-qrtr-mhi=m
CONFIG_PACKAGE_kmod-mhi-bus=y
CONFIG_PACKAGE_kmod-mhi-pci-generic=m
CONFIG_PACKAGE_kmod-usb-net-qmi-wwan=y
CONFIG_PACKAGE_kmod-qcom-qmi-helpers=m
CONFIG_PACKAGE_libqmi=y
CONFIG_LIBQMI_WITH_MBIM_QMUX=y
CONFIG_LIBQMI_WITH_QRTR_GLIB=y
CONFIG_LIBQMI_COLLECTION_FULL=y
CONFIG_PACKAGE_luci-proto-modemmanager=y
CONFIG_PACKAGE_luci-proto-qmi=y
CONFIG_PACKAGE_uqmi=y
CONFIG_PACKAGE_modemmanager=y
CONFIG_MODEMMANAGER_WITH_NETIFD=y
CONFIG_MODEMMANAGER_WITH_MBIM=y
CONFIG_MODEMMANAGER_WITH_QMI=y
CONFIG_MODEMMANAGER_WITH_QRTR=y
CONFIG_FWUPD_PLUGIN_MODEMMANAGER=y
CONFIG_LPAC_WITH_UQMI=y
CONFIG_PACKAGE_qmi-utils=y

After that we should see our modem and ports:

root@E3C:~# ls -ltr /dev/ww*
crw-------    1 root     root      242,   2 Jun 24 12:12 /dev/wwan0qmi0
crw-------    1 root     root      242,   0 Jun 24 12:12 /dev/wwan0qcdm0
crw-------    1 root     root      242,   1 Jun 24 12:12 /dev/wwan0mbim0
crw-------    1 root     root      242,   3 Jun 24 12:12 /dev/wwan0at0

Configuration

Start script, my network interface created by mhi driver is mhi_hwip0

3: mhi_hwip0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 16384 qdisc fq_codel state UNKNOWN group default qlen 1000

/etc/init.d/modemmanager stop
/etc/init.d/modemmanager disable
uqmi -s -d /dev/wwan0qmi0 --get-client-id wds
qmicli -d /dev/wwan0qmi0 --wds-noop
cid=$(uqmi -s -d /dev/wwan0qmi0 --get-client-id wds)
uqmi -s -d /dev/wwan0qmi0 --network-register
uqmi -s -d /dev/wwan0qmi0 --set-client-id wds,"$cid" --start-network internet --apn internet
sleep 30

SETTINGS=$(uqmi -d /dev/wwan0qmi0 --get-current-settings)

IP=$(echo "$SETTINGS" | grep '"ip":' | cut -d '"' -f 4)
GATEWAY=$(echo "$SETTINGS" | grep '"gateway":' | cut -d '"' -f 4)
DNS1=$(echo "$SETTINGS" | grep '"dns1":' | cut -d '"' -f 4)
DNS2=$(echo "$SETTINGS" | grep '"dns2":' | cut -d '"' -f 4)

[ -z "$IP" ] || [ -z "$GATEWAY" ] && exit 1

/sbin/ip link set dev mhi_hwip0 up
/sbin/ip addr flush dev mhi_hwip0
/sbin/ip addr add "$IP/30" dev mhi_hwip0
/sbin/ip route replace "$GATEWAY" dev mhi_hwip0
/sbin/ip route replace default via "$GATEWAY" dev mhi_hwip0

echo "nameserver $DNS1" > /tmp/resolv.conf.d/resolv.conf.auto
echo "nameserver $DNS2" >> /tmp/resolv.conf.d/resolv.conf.auto
[ -n "$DNS1" ] && /sbin/ip route replace "$DNS1" dev mhi_hwip0
[ -n "$DNS2" ] && /sbin/ip route replace "$DNS2" dev mhi_hwip0

and openwrt interface called EM9291:

uci set network.EM9291=interface
uci set network.EM9291.proto='none'
uci set network.EM9291.device='mhi_hwip0'
uci add_list firewall.@zone[1].device='mhi_hwip0'
uci commit network
uci commit firewall
/etc/init.d/firewall restart

Sometimes we should check in LUCI if EM9291 has a good zone :wink:

That's all :slight_smile: Some usefull commands:

root@E3C:~# uqmi -d /dev/wwan0qmi0 --get-data-status
"connected"
root@E3C:~# uqmi -d /dev/wwan0qmi0 --get-current-settings
{
        "pdp-type": "ipv4",
        "ip-family": "ipv4",
        "mtu": 1500,
        "ipv4": {
                "ip": "x.x.x.x",
                "dns1": "x.x.x.x",
                "dns2": "x.x.x.x",
                "gateway": "x.x.x.x",
                "subnet": "255.255.255.248"
        },
        "ipv6": {

        },
        "domain-names": {

        }
}

and

qmicli -d /dev/wwan0qmi0 --nas-get-serving-system
qmicli -d /dev/wwan0qmi0 --nas-get-signal-info
qmicli -d /dev/wwan0qmi0 --device-open-proxy --dms-get-model
[/dev/wwan0qmi0] Device model retrieved:
        Model: 'EM9291'
qmicli -d /dev/wwan0qmi0 --device-open-proxy --wda-get-data-format
[/dev/wwan0qmi0] Successfully got data format
                   QoS flow header: no
               Link layer protocol: 'raw-ip'
  Uplink data aggregation protocol: 'disabled'
Downlink data aggregation protocol: 'disabled'
                     NDP signature: '0'
Downlink data aggregation max datagrams: '0'
Downlink data aggregation max size: '0'

I didnt mark any fixes for some initial steps like SIM card slot change or activation....

Update. The modem inserted in bananpi bpi-r4 is in permament state:

Status | state: failed

| failed reason: sim-missing

| power state: on

I guess this is a known hardware bug....

I have this modem on BPI-R4 as well. To properly detect sim card, you need to change the sim hot swap polarity like this:

Usage:
• Execution: AT!SIMDETPOL=<m>,<n>
Response: OK
Purpose: Configure the SIM detection polarity levels for both SIM interfaces.
• Query: AT!SIMDETPOL?
Response: !SIMDETPOL:<CR>
UIM1: <m><CR>
UIM2: <n><CR>
OK
Purpose: Display the current configuration.
• Query List: AT!SIMDETPOL=?
Purpose: Display the execution command format and parameter values.
Parameters:
<m> (SIM detection polarity level for the UIM1 interface):
• 0—LOW polarity indicates a SIM is inserted
• 1—HIGH polarity indicates a SIM is inserted
<n> (SIM detection polarity level for the UIM2 interface):
• 0—LOW polarity indicates a SIM is inserted
• 1—HIGH polarity indicates a SIM is inserted

The AT commands interface should be wwan0at0. One more thing about this modem and BPI-R4, is that it will work ONLY in PCIe mode. For USB mode, you need to use a special adapter, or external adapter, you can't change it to USB mode with AT commands.

I know that is polarity sim detection issue but not sure what you propose... Of course the modem will be working on PCIE mode / QMI.

Now it is fixed and working also on BPI-R4 (thanks to LS3434)