# EG25-G reverse engineering

## quectel_daemon

- makes `/sys/class/gpio/gpio1018/direction` an output
- monitors `/sys/devices/virtual/android_usb/android0/state` and `/sys/devices/virtual/android_usb/android0/usb_sleep` and passes the state to modem via qmi
- monitors `/run/gpio_data` and updates `/sys/class/gpio/gpio1018/direction` with `high`/`low`
- opens various pcm devices (voice_pcm_service)
- handles call ringing and voice audio configuration
- touches `/tmp/quec_daemon_rdy`
- talks via `/run/voc_svr` in the main loop

## quectel_monitor_daemon

- if `/data/ModemRestartSystem` exists it writes `SYSTEM` to `/sys/devices/4080000.qcom,mss/subsys1/restart_level` or `/sys/devices/4080000.qcom,mss/subsys0/restart_level`
- if `/data/ModemRestartRelated` exists it writes `RELATED` to `/sys/devices/4080000.qcom,mss/subsys1/restart_level` or `/sys/devices/4080000.qcom,mss/subsys0/restart_level`
- then it monitors `/sys/devices/4080000.qcom,mss/subsys1/quec_state` and if it is changed to non-0 it restarts various daemons:
  - system(„killall atfwd_daemon“);
  - system(„killall quectel_daemon“);
  - system(„killall alsaucm_test“);

## quectel_pcm_daemon

- waits for pcm codec to probe
- reads `/data/quec/conf/auxpcm.conf` (written by `atfwd_daemon` via AT+QDAI command)
- based on values therein it:
  - loads various kernel modules for supported external codecs
    - eg.:

      system(„echo \"nau8814-codec.2–001a\“ > /sys/devices/soc:sound/codec_name");

      system(„echo \"nau8814-aif1\“ > /sys/devices/soc:sound/rx_dai_name");

      system(„echo \"nau8814-aif1\“ > /sys/devices/soc:sound/tx_dai_name");

      system(„insmod /usr/lib/modules/3.18.44/kernel/sound/soc/codecs/snd-soc-nau8814.ko“);

  - configures PCM interface, like:

    „echo %d > /sys/devices/soc:qcom,msm-sec-auxpcm/mode“

    „echo %d > /sys/devices/soc:qcom,msm-sec-auxpcm/sync“

    „echo %d > /sys/devices/soc:sound/pcm_mode_select“

    „echo %d > /sys/devices/soc:qcom,msm-sec-auxpcm/frame“

    „echo %d > /sys/devices/soc:qcom,msm-sec-auxpcm/quant“

    „echo %d > /sys/devices/soc:qcom,msm-sec-auxpcm/data“

    „echo %d > /sys/devices/soc:qcom,msm-sec-auxpcm/rate“

    „echo %d > /sys/devices/soc:qcom,msm-sec-auxpcm/num_slots“

    „echo %d > /sys/devices/soc:qcom,msm-sec-auxpcm/slot_mapping“

    „echo %d > /sys/devices/soc:sound/quec_auxpcm_rate“

## quectel_psm_aware

- creates fifo `/run/psm_aware_cmd`
- reads this fifo and issues various `psm_*` calls to a library
- some power saving stuff
- fifo is written from `atfwd_daemon` via `AT+QPSM="fifo string"` command

## quectel_tts_service

- binds to 127.0.0.1:17824
- accepts connections and plays TTS audio from the issued command

## sendcal

- creates `/run/sendcal` device
- does some basic processing

## subsystem_ramdump

- allow to dump ram to a file in /data

## time_daemon

- reads RTC time from modem over qmi and updates the ARM CPU time

## uim_test_client

- sim testing console client

## quectel-uart-ddp

- reads `/data/quec/conf/dynamic_console`
- passes data between debug uart port and `/dev/smd9`

## quectel-thermal

- monitors `/sys/devices/virtual/thermal/thermal_zone%d/temp`
- updates SAR and RF signal strength based on temperature via QMI

## quectel-smd-atcmd

- probably supposed to forward commands from `/dev/ttyGS0` to `/dev/smd7`
- does nothing, just prints some crap in a weird way to console/kmsg
- Sundy still didn't learn stdio so is using system(„echo %s > /dev/kmsg“); instead of fprintf

## quectel-remotefs-service

- opens `/dev/smd8`
- waits for commands from the modem over `/dev/smd8` and performs basic VFS operations, like open/close/read/write/seek, etc.
- implements reaction to OMA DM push message by executing `/data/ipth_dme` binary, which implements vendor (Verizon, AT&T) specific remote FOTA/system config updates
  - only if `fota_ip_a` or `fota_ip_v` exist in `/data/fota` directory

## quectel-gps-handle

- Sundy strikes again, this time using stdio in addition to system() calls for debug output!
- writes 0 to `/data/quec/conf/gps_outport_flag`
- opens `/dev/smd7` (modem's GPS data shmem device)
- reads a number from `/data/quec/conf/gps_outport_flag`
  - uses `/dev/ttyHSL0` or `/dev/ttyGS0` for NMEA output based on the number
- forwards data from `/dev/sdm7` to one of the serial ports
- monitors `/sys/class/android_usb/android0/state` and `/sys/class/android_usb/f_serial/is_connected_flag` and presumably turns off GPS output if USB is not ‚CONNECTED‘

## quec_wifi_bridge

- opens `/data/wifi_bridge_in_pipe` and `/data/wifi_bridge_out_pipe`
- listens on ‚0.0.0.0:5555‘
- forwards data from connections to `/data/wifi_bridge_in_pipe` as is
- forwards data from `/data/wifi_bridge_out_pipe` to the last accepted connection

## ql_usbcfg

- loads USB configuration for recovery mode

## ql_manager_server / ql_manager_cli

- some WWAN/WIFI management server + cli client
- quectel code

…

# Files

## /tmp/.urc_sock

- Unix socket that can be used to send URCs from linux userspace

# Un(der)-documented AT commands

## AT+QPRINT=1

- (does literally `cat /proc/kmsg >/dev/ttyGS0 &`), you can get dmesg output from `cat /dev/ttyUSB1` on the A64 side

## AT+QPRINT=0

- does literally `killall cat`

## AT+QFASTBOOT

- reboots the modem in fastboot mode

## AT+QCFG=„modemrstlevel“,`<val>`

- /sys/bus/msm_subsys/devices/subsys1/restart_level

val == 0:

- echo SYSTEM > /sys/bus/msm_subsys/devices/subsys0/restart_level
- echo 00 > /data/ModemRestartSystem
- rm -rf /data/ModemRestartRelated

val == 1:

- echo RELATED > /sys/bus/msm_subsys/devices/subsys0/restart_level
- echo 11 > /data/ModemRestartRelated
- rm -rf /data/ModemRestartSystem

## AT+QCFG=„aprstlevel“,`<val>`

- echo `val` > /sys/bus/msm_subsys/devices/subsys0/system_reset_mode

## AT+QCFG=„usbid“

- handled by quectel-manager (see ql_mgmt_client_open C api)

## AT+QCFG=„usbee“

- handled by quectel-manager (see ql_mgmt_client_open C api)

## AT+QCFG=„usbcfg“

- handled by quectel-manager (see ql_mgmt_client_open C api)

## AT+QCFG=„usbnet“

- handled by quectel-manager (see ql_mgmt_client_open C api)

## AT+QCFG=„pcmclk“

- reads/writes /sys/devices/soc:qcom,msm-sec-auxpcm/enable_clk
- sets some params on alsa hw:0,0 device

## AT+QCFG=„tone/incoming“,`<val>`

- reads/writes DWORD `val` to /data/quec/conf/ringtype.conf

## AT+QCFG=„sleepind/level“,`<val>`

- echo `val` > /sys/devices/soc:quec,quectel-power-manager/sleep_polarity
- echo `val` > /data/quec/conf/sleepind.txt

## AT+QCFG=„wakeupin/level“,`<val>`

- echo `val` > /data/quec/conf/wakeupin.txt

## AT+QCFG=„thermal/modem“, „thermal/limit_rates“, „thermal/txpwrlmt“

- modifies /data/quec_thermal_threshold (37B binary file)
- modifies /data/quec_therm_cfg
  - format enable=%d,sensor=%d,tempthreshold=%d,duration=%d,trig_cnt=%d,clr_cnt=%d

## AT+QCFG=„codec/powsave“

- echo `val` > /sys/devices/78b6000.i2c/i2c-2/2–001b/alc5616_pow_save_cfg

## AT+QCFG=„qcautoconnect“,`<val>`

- sed -i ‚/<AutoConnect>[01]</<AutoConnect>‘$val'</g' /data/mobileap_cfg.xml

## AT+QCFG=„ftm/mbim“

- opens /data/quec/usb/ftm_mbim and drops the fd, doesn't close it?
- kinda weird

## AT+QCFG=„multi_ip_package“

- configures /sys/devices/virtual/android_usb/android0/multi_package_enabled
- and some other related sysfs files

## AT+QCFG=„dbgctl“

- `echo 1 > /etc/dbgctl`
- or `rm /etc/dbgctl`
- of course it fails, since /etc is read-only fs

## AT+QCFG=„bootup“,`<op>`

- 1 = start, 0 = stop, 2 = check if service (/etc/init.d) is running

## AT+QCFG=„usbmode“

- echo %d > /data/usb/quec_usbmode_check
- cat /sys/devices/virtual/android_usb/android0/state (CONFIGURED / other)
- cat /sys/devices/virtual/android_usb/android0/usb_sleep (0/1)