The firmware limits mf1_read_emu_block_data to at most 32 blocks per
request, but eview's chunk_count only honored data_max_length (256).
Added the same 32-block cap already used by esave.
When autopwn detects a HardNested vulnerable card (nt_level=2) with some known keys,
it now automatically attempts to recover remaining keys using the hardnested attack,
instead of only printing an advisory message. The implementation:
- Iterates over each missing key slot, picking a known key before each attempt
(allows newly recovered keys to be reused for subsequent targets)
- Invokes hardnested.recover_key() with standard parameters (200 max runs, 3 max attempts)
- After each found key, checks if it is reusable for other sectors
- Falls back to senested attack if hardnested does not recover all keys
This matches the existing behavior for nested and static-encrypted-nested attacks.
Split the single --id argument into --cn (8 ASCII chars) and --raw
(32 hex char T55XX bitstream, directly compatible with PM3 raw output).
Add Python-side PAC bitstream encoder/decoder for raw format support.
Output now shows CN and Raw labels matching PM3's format.
Add NRF_LOG module registration to pac.c for debug logging,
consistent with other protocol implementations.
Reassign PAC command IDs (3014/3015) to avoid collision with ioProx
(3010/3011) after rebase onto upstream/main.
- Remove lf pac debug command (development-only)
- Accept both 16-hex and 8-ASCII card ID formats with 7-bit validation
- Add T55xx write command under lf pac write
- Handle unknown TagSpecificType values in slot list without crashing
- Auto-initialize slot data when setting tag type
- Simplify pac_write_to_t55xx by removing unused key parameters
Three fixes that together bring rapid-fire read reliability from ~20%
to 100%:
- Add MIN_SPIKE_CAP floor (8000) to prevent spike_cap from clipping
NRZ high when prescan correctly captures NRZ low. Without this,
spike_cap = raw_min*3 ≈ 2820 collapses the signal range.
- Reorder carrier-before-SAADC in pac_read(): start the 125kHz field
and wait 10ms before enabling ADC sampling, so prescan calibration
sees real NRZ signal levels rather than T55XX power-on-reset noise.
- Add auto-recalibration: if no valid frame is found after 20480
Phase 3 samples (~164ms, ~5 frame periods), reset the decoder to
Phase 1 and re-calibrate from fresh samples. This gives ~3
calibration attempts per 500ms scan window instead of just one.
Tested with Proxmark3 sim (15 consecutive rapid-fire reads, 100%) and
T55XX tag (write-read roundtrip + 15x rapid-fire, 100%).
Add pac_t55xx_writer() for encoding PAC card data into T55XX blocks,
along with the T5577_PAC_CONFIG (NRZ/Direct, RF/32, password-protected,
4 data blocks). Wire DATA_CMD_PAC_WRITE_TO_T55XX (3011) through the
command processor, dispatch table, and Python client.
Replace the 32-sample moving average + hysteresis demodulation with
Proxmark3-inspired per-sample thresholding and dead zone. This
eliminates ~16 samples of group delay per edge, reducing timing
jitter from ~11 samples to ~2-3 samples.
The new approach:
- Prescan: track raw_min, compute spike_cap (unchanged)
- Warmup: track min/max of clipped samples directly (not averaged)
- Detection: per-sample dead zone classification — sample >= high
threshold → 1, sample <= low threshold → 0, between → keep
previous state. Thresholds set at 75% fuzz of signal range.
Removes the avg_buf[32] circular buffer, avg_sum, avg_idx, and
sum-unit threshold/hysteresis state. Struct is 72 bytes smaller.
Widen integer types to prevent overflow UB:
- sample_count: uint16_t -> uint32_t (overflows at 524ms)
- interval, nbits: uint16_t -> uint32_t (matching sample_count width)
Implements NRZ/Direct modulation decoder for PAC/Stanley 125kHz cards
using SAADC ADC sampling with spike-aware threshold calibration.
The LC antenna produces brief high-amplitude transients at NRZ transitions
which are clipped before the moving-average filter to isolate the actual
data levels.
Real NTAG 215 chips never reveal the stored password over NFC, so
Flipper .nfc dumps always have zeros for pages 133-134 (PWD/PACK).
This causes readers to reject the emulated tag when they attempt
PWD_AUTH as part of their amiibo validation flow.
The --amiibo flag derives the correct PWD from the UID using the
well-known XOR algorithm and sets PACK to the standard 0x8080,
enabling proper authentication with Nintendo devices.
Usage: hf mfu nfcimport -f Kirby.nfc -s 6 --amiibo
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add `hf mfu nfcimport` command to import Flipper Zero .nfc files
directly into ChameleonUltra emulator slots. Supports NTAG 210/212/
213/215/216, Mifare Ultralight, Ultralight C, and Ultralight EV1.
The importer parses the Flipper .nfc format and configures the slot
with the correct tag type, anti-collision data (UID/ATQA/SAK),
GET_VERSION response, READ_SIG signature, counter values, and full
page data.
Handles NTAG counter index mapping (Flipper's NFC counter index 2
maps to firmware internal index 0) and gracefully skips unsupported
counters with a warning.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The pthreads4w dependency uses MSVC-specific architecture detection
(_M_X64, _M_IX86 macros) which fails under MinGW/MSYS2/ProxSpace
with "unknown not supported in version.rc".
MinGW-w64 ships with winpthreads, so only MSVC builds need pthreads4w.
Fixes#378
When runnin static nested recovery, we run into a sector auth faild
error that stops the recovery process. Add a try/execpt handler so we
can continue to try all possibitlities
- refines comments
- use unified code for `lf tag not found` error
- merge lf_em410x_data.h & lf_hidprox_data.h, remove unused macros
- split btn_fn_copy_ic_uid as btn_fn_copy_lf & btn_fn_copy_hf
- fixes offline em410x tag copy not working
- fixes conflict SAADC usage between battery level service & lf fsk demodulator
- Replace Python 3.10+ type hint syntax (`int | None`) with `Union[int, None]`.
- Add explicit `byteorder='big'` argument to all `int.from_bytes()` calls.
* feat: add lf HIDProx read, t55xx write, emulate function
code quaility:
- consistance: simulation -> emulation, label -> tag
- machine translated unreadable comments are made native
logic:
- newly added cli command includes: `lf hid prox read`, `lf hid prox write`, `lf hid prox econfig`
- machester demodulator is simplified
- various wiegand formats of HIDProx are supported
- goertzel algorithm is used in HIDProx FSK demod
- lf read is refactored using stream/feed pattern to boost scan speed
- t55xx write is refactored to share same logic between em410x & HIDProx
- lf emulating is refactored to use PWM peripheral, allowing more card type to be added
closes: #212, #210
* chore: remove not implemented wiegand format comments
* fix: build ci
* fix: build ci
* fix: build ci
* fix: build ci
* Implement MF1_ENC_NESTED_ACQUIRE in firmware
* Implement MF1_ENC_NESTED_ACQUIRE in software + fix code formatter
* Remove xz and pthreads from sources, use CMake FetchContent
* Update changelog
* lzma.h
* Update CMakeLists.txt
* Update CMakeLists.txt
* Probably fix workflow taking wrong commit for building
* Fix CMake building tools into bin/Debug on Windows
* Added cmd for fetching all slots nicks (without 16 commands)
* Fix type and use temp directory instead cwd (https://github.com/RfidResearchGroup/ChameleonUltra/pull/261)
* Fix endian for mfu_read_emu_counter_data and mfu_write_emu_counter_data
* Fix --key interpreted as list
* hardnested test fixed, increased timeout on mf1_hard_nested_acquire to fix cmd exec timeout on clone
* hardnested recovery(cli command not yet ready), based in noproto/HardnestedRecovery
* removed compiled binary
* Hardnested cli ready
* removed some unnecesary files
* removed unnecesary cached files
* cmake now builds hardnested too
* removed license.md
* added liblzma source(should fix checks not passing)
* i missed a line
* trimmed xz sources
* cmake now links local liblzma.a
* third try(warning solved)
* cmake now builds and links correcctly liblzma.a
* xz-5.8.1 vfolder renamed to xz
* fixed paths
* runner test
* removed wrong placed check
* disable landlock under windows
* missing files
* missing files
* windows strtok fix
* corrected lzma path under windows
* fix
* set release config for liblzma
* corrected path
* trailing_zeros
* msclock
* msclock integer issue
* msclock missing header
* fallback if not using msvc
* deleted include by accident
* revert clock change
* change custom target for custom command
* windows fmemopen implementation
* wrong path
* wrong name
* use fmemopen only when not using msvc
* use fmemopen.h when building on windows, non msvc
* re-add static link
* wrong filename
* pthread handling for mingw(proxspace)
* cleanup
Defined a working function load_key_file(import_key, keys) for command hf mf fchk --key
function load_dic_file(import_dic, keys) is empty for now, to prevent an error when executing hf mf fchk --dic
1. Added 'cmd_processor_mf0_ntag_get_emu_page_count' interface to get available page count of mf0.
2. We can reuse the 'STATUS_PAR_ERR', and we can delete repeated cmd 'STATUS_INVALID_PARAMS'.
Added `wrbl` and `rcnt` commands for writing blocks and reading counters. Added `-P` parameter to all commands that may need it to allow prior auth with a 4-byte password. `dump` command now dumps all pages until it fails rather than just the first 16 pages when no `-q` parameter is provided. Added `version` command to allow requesting version bytes.
This (often largely) improves the speed of the decrypt process. On my
laptop, with the same logs (37 records for one block and 37 records
for another block), here are the performances, as measuerd using a
simple command:
```bash
time echo -e "hw connect\nhf mf elog --decrypt\nhw disconnect" | ./chameleon_cli_main.py
```
- Before parallelisation (#187): 14m59,277s
- With parallelisation (current main): 6m13,513s
- With item skipping (this PR): 2m42,491s
pcd_14a_reader_ats_request didn't check for NAK so in case the tag NAKd
the RATS it would return a zero length ATS which would cause an
underflow in pcd_14a_reader_scan_once, that in turn resulted in
HF_ERR_ATS being returned due to an invalid ATS length.
fds_util event handler was ignoring all the events related to
peer_manager files and that was causing a deadlock while waiting for
record deletion that in turn caused a wdt reset, usually this resulted in
a partially done factory reset.
The fix adds a `ignore_pm` flag to op_info struct that gets cleared by
fds_wipe allowing for a true reset to happen.
- visually closer to pm3 (differenciate groups and commands)
- "dumphelp" allows to quickly dump all cmds and their options
- now all commands support '-h', so e.g. `hw settings store -h` will print help instead of storing
- no more command description in decorator, it is now taken from argparse description
@@ -3,8 +3,68 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
- Fix firmware application USB serial number (@taichunmin)
- Added ioProx LF protocol support (read, emulate and T55xx clone)
- Added `hf mfu nfcimport` to import Flipper Zero `.nfc` files into MFU/NTAG emulator slots, with `--amiibo` flag for automatic PWD/PACK derivation (@fmuk)
- Added commands to dump and clone Mifare tags
- Fix bad missing tools warning (@suut)
- Fix for FAST_READ command for nfc - mf0 tags
- Rewrite of the dynamic and static locks logic for NTAG213, NTAG215 and NTAG216; we shouldn't take into account the block lock bits
- Fixed an issue where we wouldn't be able to change CFG0 and CFG1 for NTAG213, NTAG215 and NTG216 once a password was added even if the cfg bit was reset.
- Fix for static nested key recovery (@jekkos)
- Fix LEDs being stuck on after battery check (@suut)
- Add TCP support for the CLI (@suut)
- Fix build on Android in Termux (@suut)
- Fix the issue where some reader cause CU to enter a strange state (@xianglin1998)
- The transmission performance of USB has been improved (@xianglin1998)
- Added cmd for set mf1 config 'field_off_do_reset' (@xianglin1998)
- Fix Windows build (@suut)
- Added `hf 14a config` to deal with badly configured cards (@azuwis)
- New Symmetrical LED Animation Mode and Improved Minimal Mode (@WillyJL)
## [v2.1.0][2025-09-02]
- Added UV, formatter and linter. Contribution guidelines. (@GameTec-live)
- Extend max packet data size from 512 to 4096 bytes (@Foxushka)
- HID Prox support (@TeCHiScy)
-`hf mf elog --decrypt` skip records with found keys (@taichunmin)
- Added cmd for fetching all slots nicks (@Foxushka)
- Added `hf mf senested` for recovering keys from static encrypted cards via backdoor (https://eprint.iacr.org/2024/1275) (@Foxushka)
- Added cmd for faster bulk key checking on one block (~33 keys per second) (@Foxushka, @taichunmin)
- Added cmd to acquire nonces for static encrypted cards via backdoor (@Foxushka)
- Added `firmware/docker-compose.yml` to build firmware in local docker (@taichunmin)
- Added cmd to acquire nonces for hardnested(Protocol doc need update) (@xianglin1998)
- Added command to check keys of multiple sectors at once (@taichunmin)
- Fixed unused target key type parameter for nested (@petepriority)
- Skip already used items `hf mf elog --decrypt` (@p-l-)
- Parallelize mfkey32v2 processes called from CLI (@p-l-)
- Added support for mifare classic value block operations (@taichunmin)
- Added regression tests (@doegox)
- Changed git version to version tag instead of dev tag (@taichunmin)
- Fixed 14A emulate bug and MF1 emulate bug (@spp2000 and @xianglin1998)
Heres a bit of info and a few guidelines to get you started:
- General
- Avoid force pushes. Force pushes and "one commit" PRs not only make reviewing more annoying but also erase a significant part of the git history. This, among other things, makes future debugging and bisection a lot harder.
- Conventional commits. It is recommended to follow the [conventional commit](https://www.conventionalcommits.org/en/v1.0.0/) pattern when it comes to commit messages. While this is not strictly enforced, its highly recommended and a good habbit.
- Atomic PRs. To help keep an overview and avoid conflicts, it is highly encouraged to file Atomic PRs. Atomic PRs are:
- Focused Scope: It targets a single, well-defined change, making it easier to understand and review.
- Minimal Size: It contains only the necessary code modifications to achieve its goal, avoiding unrelated changes.
- Independent: It should be able to stand on its own without depending on other unmerged PRs, reviewed, and merged independently.
- Self-Tested: each PR should include an appropriate set of unit tests that tests the changes. (optional but highly appreciated)
- Atomic Commits. Similar thing as atomic PRs. When you are done with a feature, commit. Made a working change? commit. Git commits are basically free. Doing frequent commits at sensible points throughout development not only helps you keep track of progress but also saves progress and changes so you can revert when something goes wrong. It also helps when debugging and bisecting as more granular commits allow for easier issue location.
- CLI
- The recommended packagemanager is [UV](https://docs.astral.sh/uv/) (from astralsh). You may use the manager of your choice, but when adding new dependencies they must be added to the UV lock file and pyproject toml as well.
- Type safety is important. The CLI should be typesafe. Python 3.9+ offer a wide variety of type declarations. Metas [pyrefly](https://pyrefly.org/) is used to do type validation. It is recommended to install the appropriate vscode extension and check your types before opening a PR.
- Formatting matters. Mostly. While pixelpeeping and exact rules are annoying and unnescesary, format your code in a readable and logical way. [Ruff](https://docs.astral.sh/ruff/) is used to enforce various formatting rules. You may install the Ruff vscode extension or use the CLI to format before opening a PR.
- Avoid extra packages. Almost everyone knows the "meme" of the javascript ["is-even"](https://www.npmjs.com/package/is-even) package. While it is encouraged and makes sense to use packages where appropriate, just installing packages for the hell of it even if its a 2 liner is not sensible.
This guide goal is to guide you through setting up and using your ChameleonUltra and Lite.
The docs have moved! [Wiki](https://github.com/RfidResearchGroup/ChameleonUltra/wiki)
This Guide is split up into multiple "subguides":
### About the device
- [Whitepaper](./technical_whitepaper.md): Discover what the Chameleon Ultra is capable of.
- [Hardware](./hardware.md): Learn to know the hardware of your Chameleon.
- [Firmware](./firmware.md): Your Chameleon runs a firmware, learn what it can do and how to use it.
### Interacting with the device
- [Quickstart](./quickstart.md): For the impatient people to just get you up and running with anything.
- [CLI](./cli.md): The official way to control your Chameleon is via the **C**ommand **L**ine **I**nterface (CLI). Learn how to install and master the CLI.
- [GUIs](./gui.md): Some people also develop **G**raphical **U**ser **I**nterfaces (GUIs), these may be a good start for people that do not want to deal with a CLI.
- [Troubleshooting](./troubleshooting.md): For when things go wrong, here are some common tips to maybe fix whatever issue you might have.
### For developers
- [Development](./development.md): For all developers. This covers how to build firmware from source and set up a development environment.
- [SDKs](./sdk.md): SDKs for Chameleon, useful if you want to develop your own application to control Chameleon.
- [Protocol](./protocol.md): The gory details of the communication protocol, useful if you want to develop your own client.
### Miscellaneous
- [Modding](./modding.md): Third party moddings worth mentioning.
- [FAQ](./faq.md): **F**requently **A**sked **Q**uestions, if you have a question, it might already be answered here.
The CLI (**C**ommand **L**ine **I**nterface) is the official way to control your Chameleon.
It requires at least **Python 3.9** version.
## Installing
There are multiple ways to install the CLI, depending on your OS.
### Windows
Windows users have the choice of 4 options:
#### ProxSpace
Using ProxSpace to build the CLI is the easiest and most comfortable way to get started.
1. Download ProxSpace from the [official GitHub](https://github.com/Gator96100/ProxSpace/releases/latest)
2. [Download 7zip](https://www.7-zip.org/) to extract the archive
3. Install 7zip by double clicking the Installer and clicking `Install`
4. Right-click on the downloaded archive and select `7zip -> Unpack to "ProxSpace"`
5. Open a terminal in the proxspace folder. If you are on a new Windows install, you should be able to just right-click and select `Open in Terminal`. If that option is not visible and the ProxSpace folder is still in your downloads folder, press `win+r` and type `powershell` followed by enter. In Powershell now type `cd ~/Downloads/ProxSpace`
6. Run the command `.\runme64.bat`. After successful completion, you should be dropped to the `pm3 ~ $` shell.
7. Clone the Repository by typing `git clone https://github.com/RfidResearchGroup/ChameleonUltra.git`
8. Now go into the newly created folder with `cd ChameleonUltra/software/src`
9. Prepare for package installation with `pacman-key --init; pacman-key --populate; pacman -S msys2-keyring --noconfirm; pacman-key --refresh`
10. Proceed by installing Ninja with `pacman -S ninja --noconfirm`
11. Build the required config by running `cmake .`
12. And the binaries with `cmake --build .`
13. Copy the binaries by running `cp -r ~/ChameleonUltra/software/bin/* ~/ChameleonUltra/software/script/`
14. Go into the script folder with `cd ~/ChameleonUltra/software/script/`
15. Install python requirements with `pip install -r requirements.txt`
16. Finally run the CLI with `python chameleon_cli_main.py`
To use after installing, just do the following:
1. Run `runme64.bat`
2. Go into the script folder with `cd ~/ChameleonUltra/software/script/`
3. Run the CLI with `python chameleon_cli_main.py`
#### WSL2
Coming Soon
#### WSL1
Coming Soon
#### Build Natively
Building natively is a bit more advanced and not recommended for beginners
1. Download and install [Visual Studio Community](https://visualstudio.microsoft.com/de/downloads/)
2. On the workload selection screen, choose the `Desktop development with C++` workload. Click `Download and Install`
3. Download and install [git](https://git-scm.com/download). When asked, add to your path
4. Download and install [cmake](https://cmake.org/download/). Again, when asked, add to your path
5. Download and install [python](https://www.python.org/downloads/). When asked, add to your path (small checkbox in the bottom left)
6. Choose a suitable location and open a terminal. Clone the repository with `git clone https://github.com/RfidResearchGroup/ChameleonUltra.git`
7. Change into the binaries folder with `cd ChameleonUltra/software/src`
8. Build the required config by running `cmake .`
9. And the binaries with `cmake --build .`
10. Copy the binaries by running `cp -r ../bin/Debug/* ../script/`
11. Go into the script folder with `cd ../script/`
12. Create a python virtual environment with `python -m venv venv`
13. Activate it by running `.\venv\Scripts\Activate.ps1`
14. Install python requirements with `pip install -r requirements.txt`
15. Finally run the CLI with `python chameleon_cli_main.py`
To run again after installing, just do the following:
1. Activate venv by running `.\venv\Scripts\Activate.ps1`
2. Run the CLI with `python chameleon_cli_main.py`
### Linux
*Coming Soon*
### MacOS
*Coming Soon*
## Usage
When in the CLI, plug in your Chameleon and connect with `hw connect`. If autodetection fails, get the Serial Port used by your Chameleon and run `hw connect -p COM11` (Replace `COM11` with your serial port, on Linux it may be `/dev/ttyACM0`)
### Common activities
- Connect to the CLI: `hw connect`
- Change slot: `hw slot change -s [1-8]`
*More examples coming soon*
### MFKEY32v2 walk-through
Make sure to be in the `software/` directory and run the Python CLI from there.
- Connect to the CLI: `hw connect`
- Check which slot can be used: `hw slot list`
- Change the slot type, here using slot 8 for a MFC 1k emulation: `hw slot type -s8 -t3`
- Init the slot content: `hw slot init -s8 -t3`
- or load an existing dump and set UID and anticollision data, cf `hf mf eload -h` and `hf mf sim -h`
- Enable the slot: `hw slot enable -s8 -e1`
- Change to the new slot: `hw slot change -s8`
- Activate the detection: `hf detection enable -e1`
Now disconnect, go to a reader and swipe it a few times
- Come back and connect to the CLI: `hw connect`
- See if nonces were collected: `hf detection count`
- We need 2 nonces per key to recover
- Recover the key(s) based on the collected nonces: `hf detection decrypt`. Output example:
```
- MF1 detection log count = 6, start download.
- Download done (144bytes), start parse and decrypt
- Detection log for uid [DEADBEEF]
> Block 0 detect log decrypting...
> Block 1 detect log decrypting...
> Result ---------------------------
> Block 0, A key result: ['a0a1a2a3a4a5', 'aabbccddeeff']
> Block 1, A key result: ['010203040506']
```
- To clean the logged detection nonces: `hf detection enable -e0` then `hf detection enable -e1`
In this file you can look up how to [install requirements](#Prerequisites-for-compiling), [edit](#Editing-the-code), [compile](#Compiling-the-code) and [debug](#Debugging-the-code) the firmware!
## Prerequisites for compiling
### install a cross-compiler
So far, the following compilers have been reported to work fine.
- [arm-gnu-toolchain-12.2.rel1-XXX-arm-none-eabi](https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads), e.g. [arm-gnu-toolchain-12.2.rel1-x86_64-arm-none-eabi.tar.xz](https://developer.arm.com/-/media/Files/downloads/gnu/12.2.rel1/binrel/arm-gnu-toolchain-12.2.rel1-x86_64-arm-none-eabi.tar.xz) for a x86_64 Linux host
Always use the official versions from ARM, *DO NOT* install `gcc-arm-none-eabi` from Debian/Ubuntu.
For some unknown reasons, same gcc version from Debian creates a bootloader too large to fit in the allocated flash space.
Moreover it does not contain the `gdb` debugger.
### install make
* **Debian/Ubuntu alike**
* Open a terminal.
* Run the following command to install Make: `sudo apt-get install build-essential`
* **Windows using Chocolatey:**
* Open a PowerShell terminal with administrator privileges.
* If not yet installed, run the following command to install Chocolatey:
* In the same PowerShell terminal, run the following command to install Make using Chocolatey: `choco install make`
* **macOS:**
* Open a terminal.
* If not yet installed, install Homebrew package manager by running the following command: `/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"`
* Once Homebrew is installed, run the following command to install Make: `brew install make`
- Install [nRF Command Line Tools](https://www.nordicsemi.com/Products/Development-tools/nrf-command-line-tools/download) to get `nrfjprog`, `mergehex` etc.
### install programmer tools
Depending on the hardware programmer you want to use, additional tools are needed.
- If under Windows, install [ST-Link drivers](https://www.st.com/en/development-tools/stsw-link009.html), extract the zip and run `dpinst_amd64.exe`
### configure the project
- Edit `Makefile.defs`:
- Change `GNU_INSTALL_ROOT` (path of previously installed Compiler `bin` folder)
- Change `GNU_VERSION` (Version of the installed Compiler) (FIXME: is it really used?)
- Change the other paths to match your system if needed
- Don't forget to remove the `#` in front of the changed lines
- Alternatively, if you are committing often code, it may be easier to leave `Makefile.defs` intact and to invoke `make` with the desired variables from a script, e.g. `make GNU_INSTALL_ROOT=../../../arm-gnu-toolchain-12.2.rel1-x86_64-arm-none-eabi/bin/`
## Editing the code
You can use [Visual Studio Code](https://code.visualstudio.com/download) to edit this project! Simply download and
install it!
- Install the [C++ Extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) in VS-Code.
- Install
the [C++ Extension Pack](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools-extension-pack) in
VS-Code.
- Create a new IntelliSense Configuration:
- press F1 in VS-Code and enter `C/C++: Edit Configurations (UI)`
- Add a new Configuration and name it
- Specify your Compiler path (path of previously installed Compiler `bin` folder)
- Change IntelliSense mode to `gcc-arm (legacy)`
- Add include path `${workspaceFolder}/**`
## Compiling the code
- Install prerequisites (for instructions have a look at [Prerequisites for compiling](#Prerequisites-for-compiling))
- Run `build.sh` or try to execute its steps manually if your platform is not yet properly supported. Feedback is always welcome.
The script produces several images in `objects`.
*`fullimage.hex` to be used with a programmer over the SWD pins
*`dfu-app.zip` and `dfu-full.zip` to be used with DFU mode
## Uploading the code in DFU mode
If the bootloader and the SoftDevice are already properly installed on the Chameleon, you can reflash it directly over DFU.
To set the device in DFU mode:
* you can use the Python client and issue the command `hw dfu`
* you can use the script `resource/tools/enter_dfu.py` that does exactly the same but may be easier to call from your scripts
* you can unplug the device, wait for it to sleep, then press the button B and plug it. If the application is bogus, this is the only way.
The LEDs 4 & 5 should blink green when in DFU mode.
To flash only the application (safer):
`nrfutil device program --firmware objects/dfu-app.zip --traits nordicDfu`
To flash everything (be sure to also have a JLink or ST-Link V2 programmer if something goes wrong):
`nrfutil device program --firmware objects/dfu-full.zip --traits nordicDfu`
Under Linux you can use the scripts `flash-dfu-app.sh` and `flash-dfu-full.sh`, they will put the device in DFU mode and flash it.
## Uploading the code with a programmer
Connect pins GND, SWC (swclk) and SWD (swdio) to your programmer.
If you are adventurous it is possible to flash the device over BLE (DFU mode).
To put the device in DFU mode
* you can use the Python client and issue the command `hw dfu`**TODO:** this will be possible only when the client will be able to work over BLE...
* you can use the script `resource/tools/enter_dfu_over_ble.py`
Once in DFU mode, the device will announce itself over BLE as `CU-xxxx` where xxxx are the last 2 bytes of the Device Serial Number.
Then use the official [nRF Device Firmware Update](https://www.nordicsemi.com/Products/Development-tools/nRF-Device-Firmware-Update) mobile application to flash one of the DFU images.
Get [BMP full sources](https://github.com/blackmagic-debug/blackmagic/releases)
Comment out all probes except Nordic nrf51 in `src/target/cortexm.c` big switch for probes. It should remain
```c
switch(t->designer_code){
caseJEP106_MANUFACTURER_NORDIC:
PROBE(nrf51_probe);
break;
}
```
```
make -j PROBE_HOST=stlink ST_BOOTLOADER=1 ENABLE_RTT=1
```
Then flash the ST_Link V2
```
stlink-tool src/blackmagic.bin
```
See [src/platforms/stlink/README.md](https://github.com/blackmagic-debug/blackmagic/blob/main/src/platforms/stlink/README.md) for more details.
Unplug/plug.
Every time you plug the ST-Link, you have to run `stlink-tool` to enable BMP.
Under linux, it is convenient to install [udev rules](https://github.com/blackmagic-debug/blackmagic/blob/main/driver/README.md#99-blackmagic-plugdevrules) to get aliases `/dev/ttyBmpGdb` and `/dev/ttyBmpTarg`.
Note that using a native ST-Link V2 with BlackMagicProbe "hosted" will not allow to see NRF_LOG messages.
## Debugging the code with gdb and BMP with RTT to monitor NRF_LOG
Assuming you have a BlackMagicProbe with RTT support made out of a ST-Link V2.
RTT usage: https://black-magic.org/usage/rtt.html
```
stlink-tool
sleep 1
screen /dev/ttyBmpTarg
```
In another terminal
```
$ arm-none-eabi-gdb
(gdb) target extended-remote /dev/ttyBmpGdb
(gdb) monitor swdp_scan
1 Nordic nRF52 M4
2 Nordic nRF52 Access Port.
(gdb) attach 1
(gdb) monitor rtt
```
We are now able to use gdb and see the NRF_LOG messages on the other terminal.
One can set `NRF_LOG_UART_ON_SWO_ENABLED := 1` in `Makefile.defs` to activate this functionality.
When activated, NRF_LOG will be available if one connects a UART bridge to the SWO pin which will work as a UART TX pin.
UART works at 115200 bauds. E.g. one can use a FTDI dongle and `screen /dev/ttyUSB0 115200`.
Contrary to RTT that needs to be activated by a JTAG probe, UART logs are immediately available.
Limitations:
* SWO pin is shared with... SWO so when e.g. reflashing the device, garbage may appear on the monitoring terminal.
* SWO pin is also shared with the blue channel of the RGB slot LEDs, so faint blue may appear briefly when logs are sent and LED might not work properly when supposed to be blue.
The Chameleon flash contains several parts: the bootloader and its settings, the application, the user data and the SoftDevice.
NOTE: If you are a developer searching for the building instructions, look into [development](./development.md)
## The Bootloader
The bootloader is the lowest-level program running on your Chameleon. It is read-only and provides the DFU (**D**evice **F**irmware **U**pgrade) mode. The bootloader being read-only, it makes it really hard to brick your Chameleon. The flash also contains a special section to store bootloader settings required by the nRF to deal with upgrades. This is only a concern for developers.
You enter DFU mode by of the following methods:
1. Physical button
- Disconnect the Chameleon and wait for it to enter sleep mode
- Hold down the 🅑 button. If you are using Windows you have to wait about ~5s before next step.
- Plug USB into a PC while still holding the button. If you are using Windows you have to wait about ~10s before next step.
- Then release the 🅑 button
2. From CLI
- Execute the command `hw dfu`
3. From GUI
- Click on `Enter DFU mode`
4. From Shell
- Execute the script `resource/tools/enter_dfu.py`
The device stays in DFU mode for ~30s.
While in DFU mode waiting for the update, the LEDs 4 and 5 blink alternatively green 🟢🟢.
You can then perform firmware upgrades either via a GUI or the command line:
1. Download nRF Util from the [nRF website](https://www.nordicsemi.com/Products/Development-tools/nrf-util)
2. Open a Command Line / Terminal on your PC
3. Install the "device" toolkit by running `nrfutil install device`
4. Download the Chameleon firmware from [GitHub](https://github.com/RfidResearchGroup/ChameleonUltra/releases). At the moment it is better to take the *Development release* but beware bugs can occur. Choose `ultra-dfu-app.zip` for the Ultra or the Devkit, and `lite-dfu-app.zip` for the Lite.
5. Put your Chameleon into DFU mode and install the firmware with the following command: `nrfutil device program --firmware ultra-dfu-app.zip --traits nordicDfu` (keep in mind to change the filename if you are using a Lite).
Step 5: Alternatively you can connect the Chameleon over USB and use the script `firmware/flash-dfu-app.sh` which will take care of flipping it into DFU mode and flashing it with the adequate firmware.
While flashing firmware is in progress, the LEDs 4 and 5 should blink fast blue 🔵🔵 and the firmware update should be finished in a matter of seconds. Using DFU and performing a firmware update also helps recovering from most device-related issues.
If LEDs 4 and 5 are flashing slow red 🔴🔴, it indicates an issue with DFU. Try to unplug and plug again or unplug and wait for it to timeout and try again the whole procedure.
## The Application
The application is the piece of software being loaded by the bootloader. It communicates with the client, emulates, reads and writes cards, drives the LEDs, handles buttons and much more. The application is also writable, it is the piece of software being updated via DFU.
The communication with the application is either done via the CLI or a GUI. Communication can be done over USB or BLE (**B**luetooth **L**ow **E**nergy), although, at time of writing, only GUIs support BLE.
On boot, the application starts in emulation mode, so it can emulate up to 8 HF tags and up to 8 LF tags (one slot can handle both a HF and a LF).
The Chameleon can be awaken:
- by pressing a button
- when it comes close to a HF or LF field, *only if* a card corresponding to that field (HF/LF) is loaded into the active slot.
The white LED labeled RF lights up when it detects a field, again only if the active slot supports it.
In some situations, it can be cumbersome to wait for the boot-up animation. This is configurable, cf e.g. the CLI command `hw settings animation set -h`.
On a new Chameleon (or after a factory reset), 3 slots are defined, slot 1 holding both a HF and a LF:
- slot 1 LF: a EM4100 with UID `DEADBEEF88`
- slot 1 HF: a MIFARE Classic 1k with UID `DEADBEEF`
- slot 2 HF: a MIFARE Classic 1k with UID `DEADBEEF`
- slot 3 LF: a EM4100 with UID `DEADBEEF88`
When a slot is selected, the LED shows what type of card is loaded with the following color code:
- 🟢 HF card loaded
- 🔵 LF card loaded
- 🔴 Both HF and LF loaded
When a dual HF/LF slot is activated by an external field, it will turn green or blue according to the frequency.
The application controls the buttons. The behavior of the buttons is customizable via the CLI or a GUI. The default behavior is the following:
- 🅐 short press: Select previous slot
- 🅑 short press: Select next slot
- 🅐 long press: Copy LF or HF tag UID (only Ultra, not Lite)
- 🅑 long press: Copy LF or HF tag UID (only Ultra, not Lite)
*About UID copy*: the action depends on the current slot support. So to be able to copy an EM4100 LF tag, the slot must be configured firstly to emulate an EM4100 tag. And to be able to copy a HF 14a tag, the slot must be configured for the right type of HF tag. Only the UID will be copied, not the data.
The Chameleon also shows the following LED effects:
- Charging: 4 pulsing green lights
- CLI / GUI connected over USB: Chasing LEDs in the color of the selected slot (left to right for slots 1-4 and right to left for slots 5-8).
The device enters sleep mode after about 5s unless it is plugged in USB or if a client is connected over BLE. You can use the buttons to wake it up again. You can also press quickly a button during the sleep animation to keep the device awake.
## Write Modes
- **Normal**: Behaves like any normal card
- **Denied**: Read-only card, send NACK to write attempts
- **Deceive**: Accepts write commands but don't change any data (reader thinks write was successful but when reading back, nothing changed)
- **Shadow**: Accepts writes but reverts changes when device goes to sleep (reader can read and write like a normal card but changes are kept in RAM and are lost when the chameleon goes to sleep)
## The SoftDevice
A [SoftDevice](https://infocenter.nordicsemi.com/index.jsp?topic=%2Fstruct_nrf52%2Fstruct%2Fnrf52_softdevices.html) is a precompiled and linked binary software implementing a wireless protocol developed by Nordic Semiconductor.
We are using the [SoftDevice S140](https://infocenter.nordicsemi.com/index.jsp?topic=%2Fstruct_nrf52%2Fstruct%2Fnrf52_softdevices.html) which implements a BLE Central and Peripheral protocol stack solution.
## The User Data
The Chameleon has a reserved space of memory and flash where it stores application settings, active slot and slots configurations and data. This will not be overwritten by DFU updates and the data will only be reset by either issuing `hw factory_reset --i-know-what-im-doing` in the CLI or clicking `Factory reset` in a GUI.
*Warning:* Settings and/or data might be reset to defaults if you downgrade the firmware version up to a version not supporting the newer format.
The Chameleon comes in 3 Hardware variants, the Ultra, the Lite and the Devkit.
## The Ultra
The Chameleon Ultra comes in a black box with gold printing. This box has the following dimensions: 9.5 cm x 5.5 cm x 3.5 cm

The Box contains a foam pad, a USB cable that has a removable end to convert it to USB-C, a Proxgrind 3.5 hex screwdriver, 2 replacement screws and a keychain and the device itself.
The device itself features 4 screws holding it together, 2 buttons labeled `A` and `B`. The device consists of 2 PCBs (**P**rinted **C**ircuit **B**oards) and a plastic spacer, one contains the Electronic and the HF (**H**igh **F**requency), 13.56 MHz, antenna as well as the 8 LEDs indicating which slot is currently active and the other board features the Chameleon Ultra text, the screws and the LF (**L**ow **F**requency), 125KHz, antenna. The plastic spacer houses the battery as well as the ferrite pad which enables HF and LF emulation at the same time. It also has has the USB-C charging and data port and a hole for inserting the keychain loop. The Chameleon Ultra dimensions are: 2.4cm x 4cm x 8mm

## The Lite
The Chameleon Lite comes in a white box with blue printing. This box has the following dimensions: 9.5 cm x 6 cm x 3.5 cm

The Box contains a foam pad, a USB cable that has a removable end to convert it to USB-C and the device itself.
The device itself features 2 buttons labeled with arrows. The device consists of one PCB in a blue plastic housing. This one PCB contains the electronics and the HF antenna as well as the 8 LEDs indicating which slot is currently active, and the USB-C port. The LF antenna is glued onto the back of the PCB and is visible through the housing. The battery is soldered in place and the housing is held together by thin fragile pins which are easy to snap. It is not designed to be disassembled. The keychain loop is also relatively fragile, so be careful. The Chameleon Lites dimensions are: 3.6 cm x 6.1 cm x 0.8 cm

## The Devkit
Just like the Chameleon Ultra, the Devkit comes in a black box with gold printing. This box has the following dimensions: 12 cm x 8 cm x 3.5 cm

Again, just like the lite, the box contains a foam pad, a USB cable that has a removable end to convert it to USB-C and the device itself.
The device itself features 2 buttons labeled `A` and `B`. The device is made of only one PCB without a case. At the bottom of this PCB both the HF and LF coils are found. Because it is a Devkit, this Chameleon has its SWD (**S**ingle **W**ire **D**ebug) port and some testpoints exposed. (In the photos below, a pinheader is already soldered into the SWD port, this is not the case from factory) The Chameleon Devkit dimensions are: 5.3 cm x 8.5 cm x 1.1 cm (including rubber feet, battery and buttons. PCB thickness: 0,16 cm)

## What is the difference between the Lite and the Ultra/DevKit?
The Chameleon Ultra as well as the Devkit contain a second chip called [MFRC522 ](https://www.nxp.com/docs/en/data-sheet/MFRC522.pdf). This chip allows the Chameleon to read and write to HF 14a tags. The Chameleon Lite does not contain this chip and therefore cannot read and write HF tags, it can only simulate some. The Chameleon Lite also swaps the big LIPO (**LI**thium **PO**lymer) battery with a smaller buttoncell. The Devkit is a Chameleon Ultra on a bigger PCB and with a bigger battery and some component differences such as a mechanical relay but which should not make any practical difference.
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.