Talk:QMI

From postmarketOS

libqmi

libqmi can be used on downstream kernels with qcom_rmtfs running with env LD_PRELOAD=/usr/lib/preload/libsmdpkt_wrapper.so qmicli -d /dev/smdcntl0 --get-service-version-info . You can replace the last argument with another different one (for available commands consult --help).

On mainline this works: qmicli -d /dev/rpmsg0 --get-service-version-info.

Instead of using /dev/smdcntl0 or /dev/rpmsg0 you can use the /dev/modem symlink which should exist in both cases.

Without libsmdpkt_wrapper, qmicli hangs on downstream on writing/reading to the smdpkt device, read the comment in libsmdpkt_wrapper/wrapper.c for more information.

Make sure to use libqmi from git master until the next version is released (as of 2019-10-21).

Example output:

[/dev/smdcntl0] Supported versions:
        ctl (1.5)
        wds (1.36)
        dms (1.14)
        nas (1.25)
        qos (1.3)
        wms (1.10)
        auth (1.3)
        at (1.2)
        voice (2.1)
        cat2 (2.24)
        uim (1.36)
        pbm (1.4)
        test (1.0)
        loc (2.0)
        sar (1.0)
        ts (1.0)
        tmd (1.0)
        wda (1.11)
        csvt (1.1)
        coex (1.0)
        pdc (1.0)
        rfrpe (1.0)
        dsd (1.0)
        ssctl (1.0)
        unknown [0x30] (1.0)

QMI

QMI is a protocol using fixed structured data.

There are services (e.g. DMS = Device Management Service with ID 0x02). Each service has multiple messages and/or indications which have IDs that identify them (e.g. "Get Manufacturer" with ID "0x21" in "DMS" service).

Messages are requested by the client (e.g. qmicli) and will have a response. Indications are 'unsolicited' messages from the other side, e.g. to notify the client that something has happened.

Each message has a defined input structure and an output structure where some parts can be optional. These are called TLV (Type-length-value). The structures can contain integers, arrays, structs, sequences etc (TODO Difference between sequence and struct?). Each top level parameter has their own ID as well, it seems that 0x00-0x0F are required attributes and optional starting with ID 0x10.

In libqmi, enums (integers with fixed meanings) have a so-called "public-format" attached which is basically a reference to the enum.

There are also other implementations of qmi other than libqmi, such as uqmi from OpenWrt, ofono has its own implementation, qrtr user space also has an implementation(?)

Links

smd, smdpkt, rmtfs, rpmsg, rpmsgexport, qrtr, msmipc?

Acronyms:

  • smd: Shared Memory Device
  • smdpkt: Qualcomm Shared Memory Packet Driver
  • qrtr: Qualcomm IPC router
  • remoteproc: Remote Processor
  • rpmsg: Remote Processor Messaging
  • rmtfs: Remote File System

Socket types:

  • msmipc = AF_MSM_IPC
  • qrtr = AF_QIPCRTR

smd

A fifo based communication channel for sending data between the various subsystems in Qualcomm platforms. The low-level form of mostly everything else here???

smd channels

Communication channels over smd, the names are strings and these are hardcoded in e.g. modem firmware? e.g. DATA5_CNTL

smd edges

Represents a remote subsystem or a remote processor of some sort - see https://github.com/torvalds/linux/blob/master/Documentation/devicetree/bindings/soc/qcom/qcom%2Csmd.txt

smdpkt

Kernel driver on downstream kernels which creates /dev nodes for different SMD Channels and handles the communication.

rpmsg

Framework in the Linux kernel that provides a messaging bus that allows kernel drivers to communicate with remote processors available on the system - see https://github.com/torvalds/linux/blob/master/Documentation/staging/rpmsg.rst

rpmsgexport

User space tool for telling the kernel to create a /dev node for the specified SMD Channel via the RPMSG_CREATE_EPT_IOCTL call.

https://github.com/andersson/rpmsgexport

rmtfs

User space daemon for giving to modem (and other remote processors?) access to persistent storage

https://github.com/andersson/rmtfs

libqipcrtr4msmipc

Library for translating QIPCRTR (QRTR) sockets to MSM_IPC sockets, so software using AF_QIPCRTR sockets can run on downstream kernels (which only support AF_MSM_IPC).

https://github.com/scintill/libqipcrtr4msmipc

libsmdpkt_wrapper

Wrapper to work around a kernel bug on smdpkt devices which makes operations hang. Used in applications that access smd devices.

https://github.com/scintill/libsmdpkt_wrapper

qrtr

Protocol used to communicate with service providing remote processors.

Consists of kernel components and user space component. Kernel components: ? User space components: ?

https://github.com/andersson/qrtr

msmipc

The equivalent of qrtr but on downstream kernels, but it includes a service discovery mechanism that's done by qrtr in user space.

sysmon

sysmon is a mechanism in Qualcomm devices to notify remote processors when other remote processors goes away. This is required for such things as letting the modem firmware know that the audio path is gone in the case that the adsp abruptly disappears - i.e. when the adsp hits a watchdog bite and doesn't have a chance to close the modem<->audio communication channels.

Example on mainline kernel

  • rmtfs gets started by openrc
  • rpmsgexport gets called by the modem-qcom-msm-mainline-common udev rule and tells /dev/rpmsg_ctrl0 (or whichever rpmsg control-node is for the modem) to create /dev/modem with the DATA5_CNTL channel
  • ofono uses that dev node to communicate with the modem over QMI.

Note: the SMD Edge IDs are defined in the device tree with the qcom,smd-edge attribute.

Note: some device tree nodes also have qcom,smd-channels defined, when they use channels directly, e.g. wcnss (wifi/bt/fm)

Example on downstream kernel

  • Kernel creates /dev/smdcntl0 on boot (which is hardcoded in the kernel to be: SMD Edge "SMD_APPS_MODEM" (0); SMD Channel "DATA5_CNTL", see arch/arm/mach-msm/smd_pkt.c for a list (smd_pkt_dev_name, smd_ch_name, smd_ch_edge is matched index-based))
  • /dev/smdcntl0 gets symlinked to /dev/modem by the modem-qcom-msm-downstream-common udev rule
  • rmtfs gets started (with libqipcrtr4msmipc LD_PRELOADed) by openrc
  • ofono (with libsmdpkt_wrapper LD_PRELOADed) gets started and uses that dev node to communicate with the modem over QMI.

Links