Open-source project
wlzh/dji-4g-vohive-mac avatar
wlzh/dji-4g-vohive-mac

wlzh/dji-4g-vohive-mac: turning a DJI 4G module into a Quectel EC25 inside a UTM Linux VM

在 Mac(Apple Silicon / Intel)上用 UTM 跑 Linux 虚拟机,把大疆 4G 模块(EG25-G)伪装成移远 Quectel EC25 并部署 vohive 平台的完整步骤

1,046 stars421 forksShellLicense varies

At a glance

What is it?
The repository is a Mac-only runbook, not software: it walks through UTM, Ubuntu Server, USB passthrough and an AT command that permanently rewrites the DJI module's USB identity so vohive can manage it. The hard part is not the command, it is keeping the passthrough alive while the device re-enumerates.
Who is it for?
Adopt this if you have a DJI 4G module, an Apple Silicon or Intel Mac, and no spare Linux box, and you accept that the USB identity change is permanent. Skip it if you already own a Raspberry Pi or NAS with a USB port, since vohive installs there directly and you avoid the passthrough problem entirely.
Can I use it commercially?
Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
Is it still maintained?
Yes. The repository last received commits 7 days ago.
What is it written in?
Mainly Shell, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 17, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

What the DJI module actually is, and why generic drivers ignore it

The first-generation DJI 4G module costs roughly 30 to 40 yuan and is, per the README, a Quectel EG25-G underneath. The problem is identity. It enumerates with DJI's private USB VID/PID `2ca3:4006`, so the Linux `option` driver and anything built on top of it do not recognize the device as a modem. vohive, the management platform this repository targets, expects Qualcomm-based Quectel hardware such as EC20CE, EM500Q or EC25. A module that announces itself as a DJI accessory is invisible to it.

The repository's answer is to change what the module claims to be, not to patch drivers. It sends an AT command that rewrites the USB configuration stored in the module's non-volatile memory to Quectel's `2C7C:0125`. The README states this is a one-time operation that survives reboots and follows the module to any other host. That is the whole value proposition: one command converts unsupported hardware into hardware the platform already supports.

Who this is for: people who already own the module, want vohive's SMS, eSIM and proxy features, and have a Mac rather than a Linux machine. The README is explicit that every operational command is Linux-only (`modprobe option`, `/sys/bus/usb-serial/drivers/option1/new_id`, `/dev/ttyUSB2`, `apt-get`, `lsusb`, systemd), so macOS cannot run this natively. The virtual machine is not a convenience, it is the only path.

Why a UTM VM with USB passthrough is the only viable Mac route

The README explains the constraint clearly: vohive's `install.sh` exits immediately when `os != linux`, so a Linux environment is mandatory. It also notes the script supports arm64 and downloads `vohive_<ver>_linux_arm64`, which means an Apple Silicon Mac can run an arm64 guest at native virtualization speed instead of emulating x86.

The binding constraint is USB passthrough. The DJI module must be handed directly to the guest, and the README states this rules out OrbStack, Multipass and Docker Desktop because none of them support arbitrary USB device passthrough. UTM, a QEMU-based front end, does. That single requirement determines the entire architecture: UTM on the host, Ubuntu Server 24.04 in the guest, the module passed through, and all AT commands issued from inside the guest over `/dev/ttyUSB2`.

The data flow is short. The module appears on the guest's USB bus, the `option` driver is told to claim `2ca3:4006` and creates serial nodes, an AT command is written to one of those nodes with socat, the module reboots itself, and it comes back as `2c7c:0125`. From that point vohive sees a Quectel EC25 and behaves accordingly. There is no agent, no daemon on the Mac side, and no network component in the identity change.

Installing UTM and standing up the Ubuntu guest

Start by confirming which Mac you have. The README's branch point is the CPU architecture, and it changes the ISO you download and the VM architecture you select.

bash
uname -m
# arm64  -> Apple Silicon, use the arm64 ISO
# x86_64 -> Intel, use the amd64 ISO

Install UTM through Homebrew, then launch it once so macOS can prompt for the privacy approval it needs.

bash
brew install --cask utm

Download the matching Ubuntu Server 24.04 ISO. On Apple Silicon the README points at the arm64 image; on Intel, the amd64 image. Both are roughly 2 GB or larger, which the README suggests verifying with `ls -lh`.

bash
curl -L -o ~/Downloads/ubuntu-24.04-live-server-arm64.iso \
  https://cdimage.ubuntu.com/releases/24.04/release/ubuntu-24.04-live-server-arm64.iso

In UTM, create a new VM and choose Virtualize rather than Emulate. Select `aarch64` on Apple Silicon or `x86_64` on Intel, pick Debian/Ubuntu as the system type, and size it at 2 GB RAM, 2 CPU cores and 20 GB disk. Mount the ISO as the CD/DVD, leave networking on the default NAT, and install Ubuntu Server. Two details matter: the README says to install OpenSSH server during setup, and to note the username and password you choose. After the first reboot, eject the ISO.

From the VM console, run `ip a` to find the DHCP address, then SSH in from the Mac terminal with `ssh <user>@192.168.x.x`. Every remaining command runs in that session.

Changing the device ID, and the re-enumeration trap

With the module plugged into the Mac and enabled in UTM's USB tab (it shows as `2ca3:4006`), confirm it reached the guest with `lsusb`. If the command is missing, the README gives `sudo apt-get install usbutils -y`. Then run the sequence below, which is reproduced from the README.

bash
sudo apt-get update && sudo apt-get install socat -y

sudo modprobe option

echo 2ca3 4006 | sudo tee /sys/bus/usb-serial/drivers/option1/new_id

echo 'AT+QCFG="usbcfg",0x2C7C,0x0125,1,1,1,1,1,0,0' | socat - /dev/ttyUSB2,crnl

echo 'AT+CFUN=1,1' | socat - /dev/ttyUSB2,crnl

The first two lines load the `option` driver and force it to claim DJI's identifiers so serial device nodes appear. The third writes the new USB configuration into the module. The fourth soft-restarts it. After a few seconds, `lsusb` should report `2c7c:0125 Quectel Wireless Solutions Co., Ltd. EC25 LTE modem`.

The trap the README flags is that `AT+CFUN=1,1` causes the VID/PID to change mid-flight. If UTM bound the passthrough by VID/PID, that binding breaks the moment the module re-enumerates, and `lsusb` inside the guest may briefly show nothing. This is the single most likely place for a first attempt to fail, and it is a property of how the passthrough is attached, not of the AT command. The README does not document a rollback for the identity change, and it presents the change as permanent, so treat the module as converted once this step succeeds.

Installing vohive: online zip versus the Intel-only offline bundle

The repository holds no application code. It ships two assets: `vohive-release-1.5.5.zip`, an online installer that fetches the architecture-appropriate binary from the upstream `iniwex5/vohive-release` releases at runtime, and `vohive-backup.tar.gz`, an offline recovery bundle containing the vohive binary (sha1 `ee16a5c0cd04505df43805fc81838f3e20b16aee`), `install.sh`, `vohive.service` and `mcc-mnc-table.json`.

The asymmetry matters. The offline bundle is x86_64 only, so it serves Intel Macs. Apple Silicon users have no bundled arm64 binary and must either use the online zip or obtain `vohive_<ver>_linux_arm64` themselves and follow the `install.sh` inside the backup archive. The online path looks like this:

bash
curl -L -o vohive-release-1.5.5.zip \
  https://raw.githubusercontent.com/wlzh/dji-4g-vohive-mac/main/vohive-release-1.5.5.zip
unzip -o vohive-release-1.5.5.zip
cd vohive-release-1.5.5
bash install.sh

After installation the README lists the binary at `/opt/vohive/bin/vohive`, configuration at `/opt/vohive/config/config.yaml`, a systemd unit named `vohive`, and a web console on port 7575 with default credentials `admin/admin`. The bot commands documented upstream include `/list`, `/sms`, `/send`, `/rotate`, `/esim`, `/switch` and `/vocall`. One caveat is stated plainly: VoHive blocks VoWiFi initiation from domestic Chinese carrier SIMs, and the supported operator list is maintained in the upstream README, not here.

Where this approach breaks down

The identity rewrite is irreversible in practice. The README describes it as writing the module's internal NV and as effective permanently, and it offers no procedure for restoring `2ca3:4006`. Anyone who wants to keep using the module with DJI hardware should not run the AT command at all.

The passthrough dependency is the second failure mode. Every time the module re-enumerates, whether from the `AT+CFUN=1,1` restart or from an unplug, the VM-side attachment can drop. A setup that works today can require re-attaching the device in UTM after a reboot, and the README's troubleshooting content centers on exactly this class of problem.

There is also a platform mismatch worth naming. If you already have a Raspberry Pi, an x86 NAS, or any Linux machine with a free USB port, this repository is the wrong tool. vohive's own documentation targets Linux directly, and the README lists Debian, Ubuntu, Raspberry Pi and NAS as supported environments. The Mac VM exists solely to manufacture a Linux host. Choosing it when a real one is available adds a hypervisor, a passthrough layer and an SSH hop for no benefit.

Finally, the offline story is incomplete for Apple Silicon. Intel users get a fully offline path; arm64 users depend on reaching GitHub releases or sourcing the binary themselves. The README says as much rather than papering over it.

How it compares to running vohive on dedicated Linux hardware

The natural alternative is a small always-on Linux box: a Raspberry Pi, a mini PC, or the NAS many people already run. The difference is not the software, since both routes end at the same `install.sh` and the same port 7575 console. It is the USB path.

On dedicated hardware the module plugs into a physical port and the kernel sees it directly. There is no passthrough binding to break, no hypervisor to keep running, and no dependency on the Mac being awake. The module also stays attached across reboots without intervention, which is the opposite of the re-enumeration problem described above.

The Mac route wins on one axis only: it requires no additional purchase. If the module and the Mac are what you have, UTM costs nothing and the README's steps are reproducible. The trade is that the Mac must be running whenever you want vohive reachable, and the VM becomes a second system to maintain alongside macOS. For a module used to hold a number or receive occasional SMS, an always-on Pi is the lower-friction choice. For someone who wants to try vohive this weekend without buying hardware, the UTM path is the shorter one.

Maintenance, licensing and what the repository does not tell you

The repository is a README plus a `scripts/` directory, two archive assets and a `.gitignore`. Its last push was on 2026-09-12, days before this writing, and it is not archived. That recency applies to the runbook, not to vohive itself: the platform lives at `iniwex5/vohive-release`, and the pinned reference here is `v1.5.5`. Upgrades therefore happen upstream, and the practical maintenance task is re-checking that release page rather than watching this repository.

The repository states no licence. Neither the README nor the repository metadata given here identifies one, and the upstream vohive project's licensing is likewise not described in this material. That is a real gap for anyone planning to redistribute the bundled `vohive-release-1.5.5.zip` or `vohive-backup.tar.gz`, since those archives contain a compiled binary of unknown provenance terms. Verify the upstream licence before shipping either archive to anyone else. Nothing here should be read as legal advice.

Upgrade cost is low but manual. There is no documented update command. The README's maintenance commands and verification checklist are the closest thing to operational guidance, and the offline bundle's fixed sha1 means it will not track upstream releases on its own.

Editorial conclusion

Adopt this if you have a DJI 4G module, an Apple Silicon or Intel Mac, and no spare Linux box, and you accept that the USB identity change is permanent. Skip it if you already own a Raspberry Pi or NAS with a USB port, since vohive installs there directly and you avoid the passthrough problem entirely. Before starting, confirm `uname -m` on your Mac, decide whether you need the offline `vohive-backup.tar.gz` path (Intel only) or the online `vohive-release-1.5.5.zip` path, and check in UTM's USB tab that the module appears as `2ca3:4006` before you run any AT command.

Frequently asked questions

Can I change the DJI 4G module's device ID without a Mac?

The AT command itself is not Mac-specific, but every supporting step in this repository is Linux-only, including `modprobe option`, the `/sys/bus/usb-serial/drivers/option1/new_id` write and the `/dev/ttyUSB2` access. On Windows the README offers no equivalent path, so the practical options are a Linux machine or a Linux VM with USB passthrough.

Why does the DJI 4G module disappear from lsusb after I run the AT command?

The README attributes this to `AT+CFUN=1,1` changing the VID/PID from `2ca3:4006` to `2c7c:0125` while the module restarts. If UTM attached the passthrough by VID/PID, that binding breaks during re-enumeration and the device can briefly vanish inside the guest.

Which Macs does wlzh/dji-4g-vohive-mac support?

Both Apple Silicon and Intel, with different ISO files and VM architectures: `ubuntu-24.04-live-server-arm64.iso` with an `aarch64` guest, or `ubuntu-24.04-live-server-amd64.iso` with an `x86_64` guest. The README states that from the USB passthrough step onward the two paths are identical.

Official sources

  1. Issues
  2. README
  3. wlzh/dji-4g-vohive-mac on GitHub
Community notes

Community notes