Skip to content

Latest commit

Β 

History

47 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ“‘ Free FCC Unlock for iOS

FCC unlock for DJI controllers, native on iPhone; 500m altitude research in progress

DJI FCC mode, unlocked from an iPhone. Free for noncommercial use.

License: PolyForm Noncommercial 1.0.0 Platform Confirmed Website Version Build

The first FCC unlock built natively for iPhone. No server, no account, no tracking. Everything runs on device.

An app by Andrea Piani. Project page and FAQ: andreapiani.com/dji-fcc-unlock-ios.


⚠️ Disclaimer

For educational and research purposes. Modifying radio transmission power or altitude limits may violate the law where you are. In most places, transmitting above the power permitted for your region, or flying above the permitted altitude, requires authorisation from the regulator. You are solely responsible for compliance. If you are not sure whether this is legal where you live, do not use it.

Not affiliated with, endorsed by, or sponsored by DJI. Using this may void your warranty and DJI Care Refresh coverage.


✨ What it does

Feature
πŸ“Ά FCC unlock. Switches the radio from CE to FCC: 33 dBm (about 2 W) instead of 20 dBm (about 100 mW) on 2.4 GHz, DJI's own limits for the RC-N3, for more channels and more range.
πŸ›°οΈ Altitude research. Requests 500m; the tested DJI Neo stores 120m. A working altitude unlock is still under investigation (#1).
πŸ”Œ Native MFi. Talks to the controller over the same certified channel DJI Fly uses, no jailbreak, no desktop, no second device.
πŸ” Readable. Every byte sent is a plain JSON profile you can inspect on the Profile tab.
πŸ”’ Offline. No server contact, no account, no tracking, ever.
πŸ” Auto-hold. Re-applies while the app is backgrounded, so FCC survives DJI Fly reconnecting.

πŸ“± Screens

FCC active Activity log Command profile About
FCC active Activity log Command profile About

The FCC and Log captures predate the fifth tab and show four tabs; Profile and About show five. The green connection states require real hardware to recapture.

There is a fifth tab, Experimental, with the reverse-engineering probes the issues below refer to: green buttons only read, the amber one writes altitude limits, the red one writes flight-control parameters and is flight-test territory.

DJI Fly transmission spectrum, clean 2.4GHz floor with FCC power active
DJI Fly Transmission, 2.4GHz spectrum with FCC power active on an RC-N3 + DJI Neo

βœ… Confirmed on hardware

Tested on real hardware, a DJI RC-N3 controller cabled to an iPhone with a DJI Neo aircraft: FCC power reached, verified on the DJI Fly Transmission graph with the signal extending well past the 1km reference. Not a simulator or a protocol mock, an actual controller and an actual drone in the air. Three things had to be right, and finding them was the work:

  • πŸ”‘ The channel is com.dji.logiclink, one of the two MFi protocol strings DJI does not publish. A build declaring only the three documented strings never sees the controller at all, because iOS hides an accessory whose protocols you did not declare. The string was read off the hardware.
  • πŸ‡ΊπŸ‡Έ The region is set by country code US. The command is the WiFi Set Country Code the controller already accepts; the country it carries is what decides CE or FCC.
  • πŸ”— The aircraft must be linked when you apply, not just powered on. The frames reach the controller and stop there until it is relaying to a drone. The app shows a green link line with the aircraft serial once the drone is there.

One honest limit: this firmware answers no region-read command, so the app cannot read the mode back. The DJI Fly Transmission graph is the confirmation.

🧩 Hardware compatibility

Every pair anyone has reported, working or not. A failure is as useful as a success here, so both get a row.

Controller Aircraft FCC Reported by What happened
DJI RC-N3 DJI Neo βœ… confirmed @andreapianidev FW v00.05.00.12. Verified on the DJI Fly Transmission graph, signal well past the 1km reference.
DJI RC-N3 DJI Mini 5 Pro ❌ no response @theboyroberts Link healthy, RCLink framing correct, aircraft linked, and zero acks on all six paths. Under investigation in #5.
DJI RC-N1 any ❓ untested Wanted. The protocol should be identical, but nobody has run it.
DJI RC-N2 any ❓ untested Wanted.

Add a row by filing a hardware report. It takes a cable, five minutes and no coding, and it is the single most useful thing anyone can contribute to this project right now.

πŸ› οΈ Build and install

Requirements: Xcode 26+, iOS 17+ target, an Apple ID in Xcode.

brew install xcodegen        # once
xcodegen generate
open FreeFCC.xcodeproj

Pick your iPhone as the destination and Run. The project signs with the team wildcard profile, so no App Store Connect setup is needed. This is a sideload for your own hardware, not an App Store build: it opens DJI's MFi protocol strings and changes a regulatory radio setting.

Install without a Mac

Every push builds an unsigned .ipa in CI, so reporting a hardware log does not require owning a Mac. Open the Build workflow, pick the latest green run and download the FreeFCC-<version>-build<n>-unsigned artifact.

Be clear about what that file is: it carries no signature and no provisioning profile, so an iPhone will refuse it as it comes out of CI. It has to be re-signed with your own Apple ID first, with Sideloadly or AltStore on Windows, Linux or macOS. A free Apple ID signs it for 7 days; a paid developer account, for a year.

The MFi protocol strings the app needs (com.dji.logiclink and the rest) live in Info.plist and survive re-signing, so a re-signed build talks to the controller exactly like one built in Xcode.

If a run fails on your fork, open an issue with the job log rather than patching around it; the workflow is meant to work for everyone.

πŸš€ Using it

The order matters. The controller only relays commands to the aircraft once DJI Fly has woken that link, and the link stays warm for a while after DJI Fly closes. That warm window is what the app needs.

  1. Power on the drone and the controller, wait for them to pair.
  2. Open DJI Fly first and wait until it shows the drone connected with a live camera feed. This is the step that wakes the controller-to-aircraft link. Skipping it is why an apply gets 0 responses even with the drone detected.
  3. Close DJI Fly (swipe it away).
  4. Cable the iPhone to the TOP USB port of the controller, the phone-cradle port.
  5. Open FCC Unlock, tap Connect, wait for the green line with the aircraft serial, then tap Enable FCC Mode and let the sweep finish. A line like profile@02/RCLink: 38 responses means the aircraft answered.
  6. Do not reopen DJI Fly straight away. Reopening it right after the unlock drops the radio back to CE every time (see the sequence below).

Making FCC stick (confirmed on hardware, RC-N3 + DJI Neo)

Reopening DJI Fly immediately after the unlock loses FCC: DJI Fly renegotiates the region on connect and the radio falls back to CE. The sequence that holds, observed on hardware:

  1. Start DJI Fly, let the drone link, then run the unlock in FCC Unlock (Connect, then Enable FCC Mode).
  2. Close DJI Fly.
  3. Power the controller off, then the drone off.
  4. Power the controller back on, with the iPhone still cabled and FCC Unlock still holding the link.
  5. Power the drone back on and let it relink.
  6. Open DJI Fly, Transmission tab. FCC power is there and holds, matching the signal-graph screenshot in this repo.

FCC is RAM-based and the app re-applies on an interval while it holds the link, which is what survives the power cycle here. If it ever reverts, repeat from step 1.

Altitude, what the hardware actually reports. The app writes the aircraft's flying_limit.max_height to 500 and the flight controller acknowledges it with status OK, but reading the value back the drone reports 120, not 500: the 0xF9 reply carries 00 8A 23 71 03 78 00, where 78 00 is 120. So the 120m ceiling is enforced drone-side too, not only inside DJI Fly, and max_height alone does not lift it. The parameter that actually governs a real 500m unlock is still being reverse engineered (issue #1). FCC power is a separate matter and works.

🧭 How it works

The app opens an EASession on the controller's MFi protocol and speaks the DUML command protocol over the stream: it builds each frame with its CRC-8 and CRC-16, wraps it in the link envelope, keeps the session alive with a keepalive, and parses the aircraft's replies out of a stream that also carries the video feed.

Each apply sweeps several sender and framing combinations and counts the responses, so the Log tab names the path your hardware answered on. The region is set with the country code and the altitude ceiling with the flight controller's max_height parameter, both inside one service-mode window.

Everything beyond FCC power lives on the Experimental tab: the 0xF7/0xF8 and 0xFB reads, the 500m-gate probe, the OSD telemetry decode, the 30-second flight recorder and the staged Sport-speed boost. Section 17 of the technical documentation describes each one and what the hardware said.

Deep dive. The full walkthrough, protocol and frames, transport, the service-mode window, the sweep, and every hardware finding is in docs/TECHNICAL-DOCUMENTATION.md (English) or docs/DOCUMENTAZIONE-TECNICA.md (Italian).

πŸ“‚ Project layout

FreeFCC/
  Core/    frame builder + CRC, link envelope + stream parser, profile loader,
           MFi transport, controller (sweep, hold, region, altitude, diagnostics,
           experimental probes)
  App/     SwiftUI screens (FCC, Log, Profile, Experimental, About) and design system
  Resources/profiles/   fcc.json (FCC + 500m), ce_restore.json
FreeFCCTests/            frames, parser, profiles and OSD speed regression checks
docs/TECHNICAL-DOCUMENTATION.md  full protocol + architecture writeup (English)
docs/DOCUMENTAZIONE-TECNICA.md   the same writeup in Italian
docs/screenshots/        hardware captures; Profile/About can use -initialTab N

🀝 Contributing, help wanted

This is the free, source-available answer to the paid FCC/altitude tools. FCC power is done and confirmed; the rest is open reverse engineering, and it moves faster with more hands and more hardware. Everything still to do is written up as detailed issues:

  • πŸ›°οΈ #1 Unlock 500m altitude and #3 unlock ~60 km/h speed, the headline features, both drone-side RE. The gate probe is on the Experimental tab. The Sport boost was rewritten in v1.8, after the log showed the old one wrote parameters the Neo does not have: it now targets the Sport config block and needs a ground run, a recorded flight and the log.
  • πŸ”‘ #2 Get the config-table read answering, the tool that unblocks both of the above. 0xF7/0xF8 are dead on this firmware, the 0xF9 echo reads limits only, and the 0xFB read is shipped and waiting for a result.
  • ⚑ #4 Drop the "open DJI Fly first" step by initialising the link ourselves. The warmth gate already tells a cold link from a wrong write; the DJI Fly init sequence is what is left to capture.
  • πŸ§ͺ #5 Testers wanted on RC-N1 / RC-N2 and other aircraft, no coding needed, just a device and a log.
  • πŸ“‘ #6 Read the region back for a real in-app CE/FCC indicator.

Each issue lists what is known, the exact parameter hashes and commands, and the next concrete step. Pick one, open a PR, or just run the app on your hardware and post your log. Findings from real devices are as valuable as code.

A write-up and a call for testers will go up on Reddit (r/dji and friends) so owners of other DJI gear can help map the parameters across models.

πŸ“œ License

Free for noncommercial use under the PolyForm Noncommercial License 1.0.0. See LICENSE and NOTICE.md. You may use, study, modify and share it for any noncommercial purpose, with attribution. Commercial use is not permitted without a separate license from the author. The DUML protocol the app implements is publicly documented by the dji-firmware-tools project; the iOS app and its logic are original work.


Β© 2026 Andrea Piani Β· NIE Z2331796-S Β· Tijarafe, Santa Cruz de Tenerife Β· Islas Canarias

andreapiani.com

About

FCC unlock and 500m altitude for DJI RC-N1/N2/N3, native on iPhone. First FCC unlock built for iOS. Confirmed on RC-N3 + DJI Neo.

Topics

Resources

Contributing

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages