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
On mainline this works:
qmicli -d /dev/rpmsg0 --get-service-version-info.
Instead of using
/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).
[/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 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(?)
- libqmi: List of QMI services
- libqmi: Service messages of the DMS service
- libqmi: Enums used by the DMS service
smd, smdpkt, rmtfs, rpmsg, rpmsgexport, qrtr, msmipc?
- 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
- msmipc = AF_MSM_IPC
- qrtr = AF_QIPCRTR
A fifo based communication channel for sending data between the various subsystems in Qualcomm platforms. The low-level form of mostly everything else here???
Communication channels over smd, the names are strings and these are hardcoded in e.g. modem firmware? e.g. DATA5_CNTL
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
Kernel driver on downstream kernels which creates /dev nodes for different SMD Channels and handles the communication.
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/rpmsg.txt
User space tool for telling the kernel to create a /dev node for the specified SMD Channel via the RPMSG_CREATE_EPT_IOCTL call.
User space daemon for giving to modem (and other remote processors?) access to persistent storage
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).
Wrapper to work around a kernel bug on smdpkt devices which makes operations hang. Used in applications that access smd devices.
Protocol used to communicate with service providing remote processors.
Consists of kernel components and user space component. Kernel components: ? User space components: ?
The equivalent of qrtr but on downstream kernels, but it includes a service discovery mechanism that's done by qrtr in user space.
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.