mirror of
https://github.com/RfidResearchGroup/ChameleonUltra.git
synced 2026-05-12 11:22:59 -07:00
Merge remote-tracking branch 'origin/main' into cli-overhaul
This commit is contained in:
@@ -76,7 +76,8 @@ jobs:
|
||||
name: ${{ matrix.device_type }}-dfu-full
|
||||
path: firmware/objects/dfu-full/*
|
||||
create_release:
|
||||
permissions: write-all
|
||||
permissions:
|
||||
contents: write
|
||||
name: Create Pre-Release with dfu app images
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/main'
|
||||
@@ -85,52 +86,34 @@ jobs:
|
||||
steps:
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v3
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.run_number }}
|
||||
release_name: Compiled commit ${{ github.sha }}
|
||||
body: |
|
||||
Auto-Generated DFU images
|
||||
draft: false
|
||||
prerelease: true
|
||||
- name: Download Ultra DFU
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: ultra-dfu-app
|
||||
path: dfu-app-artifacts
|
||||
- name: Compress
|
||||
path: ultra-dfu-app
|
||||
- name: Compress Ultra DFU package
|
||||
run: |
|
||||
zip --junk-paths -0 -r ./dfu-app-artifacts/dfu-app.zip ./dfu-app-artifacts/*
|
||||
- name: Upload Ultra DFU
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./dfu-app-artifacts/dfu-app.zip
|
||||
asset_name: ultra-dfu-app.zip
|
||||
asset_content_type: application/zip
|
||||
- name: Clear
|
||||
run: |
|
||||
rm -rf ./dfu-app-artifacts/
|
||||
zip --junk-paths -0 -r ./ultra-dfu-app.zip ./ultra-dfu-app/*
|
||||
- name: Download Lite DFU
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: lite-dfu-app
|
||||
path: dfu-app-artifacts
|
||||
- name: Compress
|
||||
path: lite-dfu-app
|
||||
- name: Compress Lite DFU package
|
||||
run: |
|
||||
zip --junk-paths -0 -r ./dfu-app-artifacts/dfu-app.zip ./dfu-app-artifacts/*
|
||||
- name: Upload Lite DFU
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
zip --junk-paths -0 -r ./lite-dfu-app.zip ./lite-dfu-app/*
|
||||
- name: Upload to dev release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./dfu-app-artifacts/dfu-app.zip
|
||||
asset_name: lite-dfu-app.zip
|
||||
asset_content_type: application/zip
|
||||
body: |
|
||||
Auto-Generated DFU packages from latest `main` commit.
|
||||
For development purposes only.
|
||||
These are not tested, here be dragons.
|
||||
Built from commit ${{ github.sha }}
|
||||
tag_name: dev
|
||||
name: Development release
|
||||
draft: false
|
||||
prerelease: true
|
||||
target_commitish: main
|
||||
generate_release_notes: true
|
||||
files: ./*-dfu-app.zip
|
||||
|
||||
+3
-1
@@ -1,3 +1,5 @@
|
||||
.idea/
|
||||
.vscode/
|
||||
.vs/
|
||||
.vs/
|
||||
|
||||
.DS_Store
|
||||
@@ -309,3 +309,14 @@ in a second terminal:
|
||||
```
|
||||
JLinkRTTClient
|
||||
```
|
||||
|
||||
## Using SWO pin as UART to monitor NRF_LOG
|
||||
|
||||
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.
|
||||
|
||||
@@ -1,20 +1,32 @@
|
||||
[nrf52_nfc_module_doc]: https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52832.ps.v1.1%2Fnfc.html
|
||||
[tech_white_paper]: https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/Technical_White_Paper.md
|
||||
|
||||
[how_use_firmware]: https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/How_to_use_Firmware.md
|
||||
|
||||
[go_to_buy_lab401]: https://lab401.com/
|
||||
|
||||
[go_to_buy_hackerwarehouse]: https://hackerwarehouse.com/
|
||||
|
||||
[go_to_buy_sneaktechnology]: https://sneaktechnology.com
|
||||
|
||||
[go_to_buy_proxgrind_aliexpress]: https://proxgrind.aliexpress.com/store/1101312023
|
||||
|
||||
[nxp_rc522_datasheet]: https://www.nxp.com/docs/en/data-sheet/MFRC522.pdf
|
||||
|
||||

|
||||
|
||||
# ChameleonUltra Authorised Distributors
|
||||
|
||||
Europe: [Lab401](https://lab401.com/)
|
||||
Europe: [Lab401][go_to_buy_lab401]
|
||||
|
||||
United States: [Hackerwarehouse](https://hackerwarehouse.com/)
|
||||
United States: [Hackerwarehouse][go_to_buy_hackerwarehouse]
|
||||
|
||||
Anywhere else: [Sneaktechnology](https://sneaktechnology.com) / [Aliexpress by RRG](https://proxgrind.aliexpress.com/store/1101312023)
|
||||
Anywhere else: [Sneaktechnology][go_to_buy_sneaktechnology] / [Aliexpress by RRG][go_to_buy_proxgrind_aliexpress]
|
||||
|
||||
# How to use ?
|
||||
|
||||
Coming Soon.
|
||||
- ChameleonUltra: [Technical White Paper][tech_white_paper] (Old content of this readme in here)
|
||||
- ChameleonUltra: [Firmware][how_use_firmware]
|
||||
|
||||
More Coming Soon.
|
||||
|
||||
# Videos to reference
|
||||
|
||||
@@ -27,221 +39,9 @@ Downloading a GUI
|
||||
https://www.youtube.com/watch?v=rHH7iqbX3nY
|
||||
|
||||
Link to the GUI
|
||||
|
||||
https://github.com/GameTec-live/ChameleonUltraGUI
|
||||
|
||||
|
||||
# ChameleonUltra
|
||||
|
||||
Why not keep using ATxmega128?
|
||||
First of all, it is difficult to buy chips because the lead time for the main chip is too long, and because the price
|
||||
has skyrocketed. Secondly, because the interaction speed of the ATxmega simulation is slow, the decryption performance
|
||||
of the READER mode cannot meet the needs, and the low-frequency function cannot be added, so we have been trying to
|
||||
upgrade it, such as using the latest ARM to replace the AVR framework, and the performance will definitely be greatly
|
||||
improved.
|
||||
|
||||
# Why NRF52840?
|
||||
|
||||
NRF52840 has a built-in NFC Tag-A module, but no one seems to care about it. After playing with HydraNFC's TRF7970A and
|
||||
FlipperZero's ST25R3916, ~~the developers found that they can only simulate MIFARE UID~~. I accidentally tested the NFC of
|
||||
52840, and found that it is not only surprisingly easy to simulate a complete MIFARE card, but also has very good
|
||||
simulation performance, friendly data flow interaction, and very fast response, unlike the former which is limited by
|
||||
the SPI bus clock rate. We also found that it has ultra-low power consumption, ultra-small size, 256kb/1M large RAM and
|
||||
FLASH, also has BLE5.0 and USB2.0 FS, super CotexM4F, most importantly, he is very cheap! This is undoubtedly a treasure
|
||||
discovery for us!
|
||||
|
||||
Below we will explain in detail how we exploited the performance of the NRF52840, and what seemingly impossible
|
||||
functions have been realized with it!
|
||||
|
||||
**Update**:
|
||||
* FlipperZero can simulate mifare sector now, but FDT so high.
|
||||
|
||||
# Supported functions
|
||||
|
||||
## High Frequency Attack
|
||||
|
||||
| Attack Type | Tag Type | Whether the hardware supports | Does the software support | Whether the application layer supports | Note |
|
||||
|--------------|:-------------:|------------------------------:|---------------------------|:--------------------------------------:|------------------------:|
|
||||
| Sniffing | No | No | No | No | |
|
||||
| MFKEY32 V2 | MifareClassic | Support | Support | Support | MifareClassic Detection |
|
||||
| Darkside | MifareClassic | Support | Support | Support | Encrypted 4 bit NAck |
|
||||
| Nested | MifareClassic | Support | Support | Support | PRNG(Distance guess) |
|
||||
| StaticNested | MifareClassic | Support | Support | Not yet implemented | PRNG(2NT Fast Decrypt) |
|
||||
| HardNested | MifareClassic | Support | Support | Not yet implemented | No |
|
||||
| Relay attack | ISO14443A | Support | Support | Not yet implemented | No |
|
||||
|
||||
## High Frequency Simulation
|
||||
|
||||
| Card Type | Encoding Type | Whether the hardware supports | Does the software support | Whether the application layer supports | Note |
|
||||
|-------------------------------|:--------------------:|------------------------------:|---------------------------|:--------------------------------------:|-----------------------------------------:|
|
||||
| Non <13.56MHz or ISO14443A> | No | No | No | No | [NRF52 NFC Module][nrf52_nfc_module_doc] |
|
||||
| NTAG 21x (210-218) | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
|
||||
| Mifare Ultralight | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
|
||||
| Mifare Ultralight Ev1 | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
|
||||
| Mifare Ultralight C | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
|
||||
| MifareClassic1K/2K/4K (4B/7B) | ISO14443A/106 kbit/s | Support | Support | Support | |
|
||||
| Mifare DESFire | ISO14443A High Rate | Only supported Low rate | Only supported Low rate | Not yet implemented | |
|
||||
| Mifare DESFire EV1 | ISO14443A High rate | Only supported Low rate | Only supported Low rate | Not yet implemented | Backward compatible |
|
||||
| Mifare DESFire EV2 | ISO14443A High rate | Only supported Low rate | Only supported Low rate | Not yet implemented | |
|
||||
| Mifare PLUS | ISO14443A High rate | Only supported Low rate | Only supported Low rate | Not yet implemented | |
|
||||
|
||||
## High Frequency Reader
|
||||
|
||||
| Card Type | Encoding Type | Whether the hardware supports | Does the software support | Whether the application layer supports | Note |
|
||||
|-------------------------------|:--------------------:|---------------------------------------------:|----------------------------------------------|:--------------------------------------:|-------------------------------------------:|
|
||||
| Non <13.56MHz or ISO14443A> | No | No | No | No | [NXP RC522 Datasheet][nxp_rc522_datasheet] |
|
||||
| NTAG 21x (210-218) | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
|
||||
| Mifare Ultralight | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
|
||||
| Mifare Ultralight Ev1 | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
|
||||
| Mifare Ultralight C | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
|
||||
| MifareClassic1K/2K/4K (4B/7B) | ISO14443A/106 kbit/s | Support | Support | Support | |
|
||||
| Mifare DESFire | ISO14443A High Rate | Supports low rates, or possibly higher rates | Supports low rates, or possibly higher rates | Not yet implemented | |
|
||||
| Mifare DESFire EV1 | ISO14443A High rate | Supports low rates, or possibly higher rates | Supports low rates, or possibly higher rates | Not yet implemented | Backward compatible |
|
||||
| Mifare DESFire EV2 | ISO14443A High rate | Supports low rates, or possibly higher rates | Supports low rates, or possibly higher rates | Not yet implemented | |
|
||||
| Mifare PLUS | ISO14443A High rate | Supports low rates, or possibly higher rates | Supports low rates, or possibly higher rates | Not yet implemented | |
|
||||
|
||||
## Low Frequency Attack
|
||||
|
||||
| Vulnerability Type | Tag Type | Whether the hardware supports | Does the software support | Whether the application layer supports | Note |
|
||||
|--------------------|:---------:|------------------------------:|---------------------------|:--------------------------------------:|-----:|
|
||||
| Sniffing | 125KHz | Support | Support | Not yet implemented | |
|
||||
| Brute Force | EM410x ID | Support | Support | Not yet implemented | |
|
||||
|
||||
## Low Frequency Simulation
|
||||
|
||||
| Card Type | Encoding Type | Whether the hardware supports | Does the software support | Whether the application layer supports | Note |
|
||||
|--------------------------|:-------------:|------------------------------:|---------------------------|:--------------------------------------:|----------------------------------------------:|
|
||||
| Non <125KHz/ASK/PSK/FSK> | No | No | No | No | Only 125 khz RF, Modulation ASK, FSK and PSK. |
|
||||
| EM410x | ASK | Support | Support | Support | EM4100 is support(AD 64bit) |
|
||||
| T5577 | ASK | Support | Support | Not yet implemented | |
|
||||
| HID Prox | FSK | Support | Support | Not yet implemented | |
|
||||
| Indala | PSK | Support | Support | Not yet implemented | |
|
||||
| FDX-B | ASK | Support | Support | Not yet implemented | |
|
||||
| Paradox | FSK | Support | Support | Not yet implemented | |
|
||||
| Keri | PSK | Support | Support | Not yet implemented | |
|
||||
| AWD | FSK | Support | Support | Not yet implemented | |
|
||||
| ioProx | FSK | Support | Support | Not yet implemented | |
|
||||
| securakey | ASK | Support | Support | Not yet implemented | |
|
||||
| gallagher | ASK | Support | Support | Not yet implemented | |
|
||||
| PAC/Stanley | ASK | Support | Support | Not yet implemented | |
|
||||
| Presco | ASK | Support | Support | Not yet implemented | |
|
||||
| Visa2000 | ASK | Support | Support | Not yet implemented | |
|
||||
| Viking | ASK | Support | Support | Not yet implemented | |
|
||||
| Noralsy | ASK | Support | Support | Not yet implemented | |
|
||||
| NexWatch | PSK | Support | Support | Not yet implemented | |
|
||||
| Jablotron | ASK | Support | Support | Not yet implemented | |
|
||||
|
||||
## Low Frequency Reader
|
||||
|
||||
| Card Type | Encoding Type | Whether the hardware supports | Does the software support | Whether the application layer supports | Note |
|
||||
|--------------------------|:-------------:|------------------------------:|---------------------------|:--------------------------------------:|----------------------------------------------:|
|
||||
| Non <125KHz/ASK/PSK/FSK> | No | No | No | No | Only 125 khz RF, Modulation ASK, FSK and PSK. |
|
||||
| EM410x | ASK | Support | Support | Support | |
|
||||
| T5577 | ASK | Support | Support | Support(Write) | |
|
||||
| HID Prox | FSK | Support | Support | Not yet implemented | |
|
||||
| Indala | PSK | Support | Support | Not yet implemented | |
|
||||
| FDX-B | ASK | Support | Support | Not yet implemented | |
|
||||
| Paradox | FSK | Support | Support | Not yet implemented | |
|
||||
| Keri | PSK | Support | Support | Not yet implemented | |
|
||||
| AWD | FSK | Support | Support | Not yet implemented | |
|
||||
| ioProx | FSK | Support | Support | Not yet implemented | |
|
||||
| securakey | ASK | Support | Support | Not yet implemented | |
|
||||
| gallagher | ASK | Support | Support | Not yet implemented | |
|
||||
| PAC/Stanley | ASK | Support | Support | Not yet implemented | |
|
||||
| Presco | ASK | Support | Support | Not yet implemented | |
|
||||
| Visa2000 | ASK | Support | Support | Not yet implemented | |
|
||||
| Viking | ASK | Support | Support | Not yet implemented | |
|
||||
| Noralsy | ASK | Support | Support | Not yet implemented | |
|
||||
| NexWatch | PSK | Support | Support | Not yet implemented | |
|
||||
| Jablotron | ASK | Support | Support | Not yet implemented | |
|
||||
|
||||
## Low Frequency Modulation
|
||||
|
||||
[modulation_psk]: https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/resource/picture/PSK.png
|
||||
|
||||
[modulation_fsk]: https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/resource/picture/FSK.png
|
||||
|
||||
[modulation_ask]: https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/resource/picture/ASK.png
|
||||
|
||||
| Modulation Type | wav |
|
||||
|-----------------|----------------------------:|
|
||||
| PSK | ![alt text][modulation_psk] |
|
||||
| FSK | ![alt text][modulation_fsk] |
|
||||
| ASK | ![alt text][modulation_ask] |
|
||||
|
||||
# 1. Ultra-low power consumption
|
||||
|
||||
It integrates a high-performance and low-power NFC module inside. When the NFC unit is turned on, the total current of
|
||||
the chip is only 5mA@3.3V.
|
||||
The underlying interaction is done independently by the NFC unit and does not occupy the CPU.
|
||||
In addition, the 52840 itself is a high-performance low-power Bluetooth chip, and the encryption and calculation process
|
||||
is only 7mA@3.3V. It can greatly reduce the battery volume and prolong the working time. That is to say, the 35mAh 10mm*
|
||||
40mm button lithium battery can guarantee to be charged once every half a year under the working condition of swiping
|
||||
the card 8 times a day for 3 seconds each time. Full potential for everyday use.
|
||||
|
||||
# 2. Not just UID, but a real and complete MIFARE encrypted data simulation
|
||||
|
||||
We can easily and completely simulate all data and password verification of all sectors, and can customize SAK, ATQA,
|
||||
ATS, etc. Similar to an open CPU card development platform, 14A interaction of various architectures can be easily
|
||||
realized.
|
||||
|
||||
# 3. Super compatibility with low-power locks using batteries
|
||||
|
||||
The structure of the old Chameleon AVR is slow to start during simulation. Faced with a battery-powered low-power lock
|
||||
and an integrated lock on the door, it will be frequently interrupted, and the verification interaction cannot be
|
||||
completed completely, resulting in no response when swiping the card.
|
||||
|
||||
In order to reduce power consumption, the battery lock will send out a field signal as short as possible when searching
|
||||
for a card, which is no problem for the original card, but it is fatal for the MCU simulated card. Cards or mobile smart
|
||||
bracelets simulated by the MCU cannot wake up and respond in such a short time, so many battery locks cannot open the
|
||||
door, which greatly reduces the user experience.
|
||||
|
||||
This project specially optimizes the start-up and interaction logic and antenna for low-power reading heads. After
|
||||
testing a variety of common low-power reading heads, they can open the door perfectly by swiping the card.
|
||||
|
||||
# 4. Ultra-fast response speed and low interaction delay(MifareClassic)
|
||||
|
||||
[fdt_standard_s50]: https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/resource/picture/Standard_m1_s50.png
|
||||
|
||||
[fdt_redmi_k30]: https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/resource/picture/Xiaomi_k30u_smartkey.png
|
||||
|
||||
[fdt_pm3_rdv401]: https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/resource/picture/Proxmark3_Rdv4_RRG_(Firmware%20build%20at%2020201026).png
|
||||
|
||||
[fdt_chameleon_ultra]: https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/resource/picture/ChameleonUltra.png
|
||||
|
||||
[fdt_chameleon_tiny]: https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/resource/picture/ChameleonTiny.png
|
||||
|
||||
[fdt_flipper_zero]: https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/resource/picture/FlipperZero%20Simulation.png
|
||||
|
||||
| Simulation | FDT | "**_FDT_**" Rating |
|
||||
|----------------------|:---------------------------:|:--------------------------------------------------------------------------------:|
|
||||
| Standard MIFARE Card | ![alt][fdt_standard_s50] | ⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐ |
|
||||
| ChameleonUltra | ![alt][fdt_chameleon_ultra] | ⭐⭐⭐⭐⭐⭐⭐⭐ |
|
||||
| Proxmark3 Rdv4.01 | ![alt][fdt_pm3_rdv401] | ⭐⭐⭐⭐ |
|
||||
| RedMi K30 | ![alt][fdt_redmi_k30] | ⭐⭐⭐⭐⭐⭐ |
|
||||
| ChameleonTiny | ![alt][fdt_chameleon_tiny] | ⭐⭐⭐⭐⭐ |
|
||||
| FlipperZero | ![alt][fdt_flipper_zero] | ⭐⭐ |
|
||||
|
||||
# 5. 256kB super large RAM cooperates with RC522 to replace Proxmark3 magically to complete the decoding
|
||||
|
||||
[attack_mifare_darkside]: https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/resource/picture/Darkside.png
|
||||
|
||||
[attack_mifare_nested]: https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/resource/picture/Nested.png
|
||||
|
||||
[attack_mifare_mfkey32]: https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/resource/picture/MFKEY32V2.png
|
||||
|
||||
| Attack Type | CLI |
|
||||
|--------------|:------------------------------:|
|
||||
| MFKEY32 V2 | ![alt][attack_mifare_mfkey32] |
|
||||
| Darkside | ![alt][attack_mifare_darkside] |
|
||||
| Nested | ![alt][attack_mifare_nested] |
|
||||
| StaticNested | Coming Soon |
|
||||
| HardNested | Coming Soon |
|
||||
| Relay attack | Coming Soon |
|
||||
|
||||
# Hardware frame diagram:
|
||||
|
||||

|
||||
|
||||
# Hardware Pictures
|
||||
|
||||

|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
[nrf52_nfc_module_doc]: https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52832.ps.v1.1%2Fnfc.html
|
||||
|
||||
[nxp_rc522_datasheet]: https://www.nxp.com/docs/en/data-sheet/MFRC522.pdf
|
||||
|
||||
# ChameleonUltra
|
||||
|
||||
Why not keep using ATxmega128?
|
||||
First of all, it is difficult to buy chips because the lead time for the main chip is too long, and because the price
|
||||
has skyrocketed. Secondly, because the interaction speed of the ATxmega simulation is slow, the decryption performance
|
||||
of the READER mode cannot meet the needs, and the low-frequency function cannot be added, so we have been trying to
|
||||
upgrade it, such as using the latest ARM to replace the AVR framework, and the performance will definitely be greatly
|
||||
improved.
|
||||
|
||||
# Why NRF52840?
|
||||
|
||||
NRF52840 has a built-in NFC Tag-A module, but no one seems to care about it. After playing with HydraNFC's TRF7970A and
|
||||
FlipperZero's ST25R3916, ~~the developers found that they can only simulate MIFARE UID~~. I accidentally tested the NFC of
|
||||
52840, and found that it is not only surprisingly easy to simulate a complete MIFARE card, but also has very good
|
||||
simulation performance, friendly data flow interaction, and very fast response, unlike the former which is limited by
|
||||
the SPI bus clock rate. We also found that it has ultra-low power consumption, ultra-small size, 256kb/1M large RAM and
|
||||
FLASH, also has BLE5.0 and USB2.0 FS, super CotexM4F, most importantly, he is very cheap! This is undoubtedly a treasure
|
||||
discovery for us!
|
||||
|
||||
Below we will explain in detail how we exploited the performance of the NRF52840, and what seemingly impossible
|
||||
functions have been realized with it!
|
||||
|
||||
**Update**:
|
||||
* FlipperZero can simulate mifare sector now, but FDT so high.
|
||||
|
||||
# Supported functions
|
||||
|
||||
## High Frequency Attack
|
||||
|
||||
| Attack Type | Tag Type | Whether the hardware supports | Does the software support | Whether the application layer supports | Note |
|
||||
|--------------|:-------------:|------------------------------:|---------------------------|:--------------------------------------:|------------------------:|
|
||||
| Sniffing | No | No | No | No | |
|
||||
| MFKEY32 V2 | MifareClassic | Support | Support | Support | MifareClassic Detection |
|
||||
| Darkside | MifareClassic | Support | Support | Support | Encrypted 4 bit NAck |
|
||||
| Nested | MifareClassic | Support | Support | Support | PRNG(Distance guess) |
|
||||
| StaticNested | MifareClassic | Support | Support | Not yet implemented | PRNG(2NT Fast Decrypt) |
|
||||
| HardNested | MifareClassic | Support | Support | Not yet implemented | No |
|
||||
| Relay attack | ISO14443A | Support | Support | Not yet implemented | No |
|
||||
|
||||
## High Frequency Simulation
|
||||
|
||||
| Card Type | Encoding Type | Whether the hardware supports | Does the software support | Whether the application layer supports | Note |
|
||||
|-------------------------------|:--------------------:|------------------------------:|---------------------------|:--------------------------------------:|-----------------------------------------:|
|
||||
| Non <13.56MHz or ISO14443A> | No | No | No | No | [NRF52 NFC Module][nrf52_nfc_module_doc] |
|
||||
| NTAG 21x (210-218) | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
|
||||
| Mifare Ultralight | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
|
||||
| Mifare Ultralight Ev1 | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
|
||||
| Mifare Ultralight C | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
|
||||
| MifareClassic1K/2K/4K (4B/7B) | ISO14443A/106 kbit/s | Support | Support | Support | |
|
||||
| Mifare DESFire | ISO14443A High Rate | Only supported Low rate | Only supported Low rate | Not yet implemented | |
|
||||
| Mifare DESFire EV1 | ISO14443A High rate | Only supported Low rate | Only supported Low rate | Not yet implemented | Backward compatible |
|
||||
| Mifare DESFire EV2 | ISO14443A High rate | Only supported Low rate | Only supported Low rate | Not yet implemented | |
|
||||
| Mifare PLUS | ISO14443A High rate | Only supported Low rate | Only supported Low rate | Not yet implemented | |
|
||||
|
||||
## High Frequency Reader
|
||||
|
||||
| Card Type | Encoding Type | Whether the hardware supports | Does the software support | Whether the application layer supports | Note |
|
||||
|-------------------------------|:--------------------:|---------------------------------------------:|----------------------------------------------|:--------------------------------------:|-------------------------------------------:|
|
||||
| Non <13.56MHz or ISO14443A> | No | No | No | No | [NXP RC522 Datasheet][nxp_rc522_datasheet] |
|
||||
| NTAG 21x (210-218) | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
|
||||
| Mifare Ultralight | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
|
||||
| Mifare Ultralight Ev1 | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
|
||||
| Mifare Ultralight C | ISO14443A/106 kbit/s | Support | Support | Not yet implemented | |
|
||||
| MifareClassic1K/2K/4K (4B/7B) | ISO14443A/106 kbit/s | Support | Support | Support | |
|
||||
| Mifare DESFire | ISO14443A High Rate | Supports low rates, or possibly higher rates | Supports low rates, or possibly higher rates | Not yet implemented | |
|
||||
| Mifare DESFire EV1 | ISO14443A High rate | Supports low rates, or possibly higher rates | Supports low rates, or possibly higher rates | Not yet implemented | Backward compatible |
|
||||
| Mifare DESFire EV2 | ISO14443A High rate | Supports low rates, or possibly higher rates | Supports low rates, or possibly higher rates | Not yet implemented | |
|
||||
| Mifare PLUS | ISO14443A High rate | Supports low rates, or possibly higher rates | Supports low rates, or possibly higher rates | Not yet implemented | |
|
||||
|
||||
## Low Frequency Attack
|
||||
|
||||
| Vulnerability Type | Tag Type | Whether the hardware supports | Does the software support | Whether the application layer supports | Note |
|
||||
|--------------------|:---------:|------------------------------:|---------------------------|:--------------------------------------:|-----:|
|
||||
| Sniffing | 125KHz | Support | Support | Not yet implemented | |
|
||||
| Brute Force | EM410x ID | Support | Support | Not yet implemented | |
|
||||
|
||||
## Low Frequency Simulation
|
||||
|
||||
| Card Type | Encoding Type | Whether the hardware supports | Does the software support | Whether the application layer supports | Note |
|
||||
|--------------------------|:-------------:|------------------------------:|---------------------------|:--------------------------------------:|----------------------------------------------:|
|
||||
| Non <125KHz/ASK/PSK/FSK> | No | No | No | No | Only 125 khz RF, Modulation ASK, FSK and PSK. |
|
||||
| EM410x | ASK | Support | Support | Support | EM4100 is support(AD 64bit) |
|
||||
| T5577 | ASK | Support | Support | Not yet implemented | |
|
||||
| HID Prox | FSK | Support | Support | Not yet implemented | |
|
||||
| Indala | PSK | Support | Support | Not yet implemented | |
|
||||
| FDX-B | ASK | Support | Support | Not yet implemented | |
|
||||
| Paradox | FSK | Support | Support | Not yet implemented | |
|
||||
| Keri | PSK | Support | Support | Not yet implemented | |
|
||||
| AWD | FSK | Support | Support | Not yet implemented | |
|
||||
| ioProx | FSK | Support | Support | Not yet implemented | |
|
||||
| securakey | ASK | Support | Support | Not yet implemented | |
|
||||
| gallagher | ASK | Support | Support | Not yet implemented | |
|
||||
| PAC/Stanley | ASK | Support | Support | Not yet implemented | |
|
||||
| Presco | ASK | Support | Support | Not yet implemented | |
|
||||
| Visa2000 | ASK | Support | Support | Not yet implemented | |
|
||||
| Viking | ASK | Support | Support | Not yet implemented | |
|
||||
| Noralsy | ASK | Support | Support | Not yet implemented | |
|
||||
| NexWatch | PSK | Support | Support | Not yet implemented | |
|
||||
| Jablotron | ASK | Support | Support | Not yet implemented | |
|
||||
|
||||
## Low Frequency Reader
|
||||
|
||||
| Card Type | Encoding Type | Whether the hardware supports | Does the software support | Whether the application layer supports | Note |
|
||||
|--------------------------|:-------------:|------------------------------:|---------------------------|:--------------------------------------:|----------------------------------------------:|
|
||||
| Non <125KHz/ASK/PSK/FSK> | No | No | No | No | Only 125 khz RF, Modulation ASK, FSK and PSK. |
|
||||
| EM410x | ASK | Support | Support | Support | |
|
||||
| T5577 | ASK | Support | Support | Support(Write) | |
|
||||
| HID Prox | FSK | Support | Support | Not yet implemented | |
|
||||
| Indala | PSK | Support | Support | Not yet implemented | |
|
||||
| FDX-B | ASK | Support | Support | Not yet implemented | |
|
||||
| Paradox | FSK | Support | Support | Not yet implemented | |
|
||||
| Keri | PSK | Support | Support | Not yet implemented | |
|
||||
| AWD | FSK | Support | Support | Not yet implemented | |
|
||||
| ioProx | FSK | Support | Support | Not yet implemented | |
|
||||
| securakey | ASK | Support | Support | Not yet implemented | |
|
||||
| gallagher | ASK | Support | Support | Not yet implemented | |
|
||||
| PAC/Stanley | ASK | Support | Support | Not yet implemented | |
|
||||
| Presco | ASK | Support | Support | Not yet implemented | |
|
||||
| Visa2000 | ASK | Support | Support | Not yet implemented | |
|
||||
| Viking | ASK | Support | Support | Not yet implemented | |
|
||||
| Noralsy | ASK | Support | Support | Not yet implemented | |
|
||||
| NexWatch | PSK | Support | Support | Not yet implemented | |
|
||||
| Jablotron | ASK | Support | Support | Not yet implemented | |
|
||||
|
||||
## Low Frequency Modulation
|
||||
|
||||
[modulation_psk]: https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/resource/picture/PSK.png
|
||||
|
||||
[modulation_fsk]: https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/resource/picture/FSK.png
|
||||
|
||||
[modulation_ask]: https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/resource/picture/ASK.png
|
||||
|
||||
| Modulation Type | wav |
|
||||
|-----------------|----------------------------:|
|
||||
| PSK | ![alt text][modulation_psk] |
|
||||
| FSK | ![alt text][modulation_fsk] |
|
||||
| ASK | ![alt text][modulation_ask] |
|
||||
|
||||
# 1. Ultra-low power consumption
|
||||
|
||||
It integrates a high-performance and low-power NFC module inside. When the NFC unit is turned on, the total current of
|
||||
the chip is only 5mA@3.3V.
|
||||
The underlying interaction is done independently by the NFC unit and does not occupy the CPU.
|
||||
In addition, the 52840 itself is a high-performance low-power Bluetooth chip, and the encryption and calculation process
|
||||
is only 7mA@3.3V. It can greatly reduce the battery volume and prolong the working time. That is to say, the 35mAh 10mm*
|
||||
40mm button lithium battery can guarantee to be charged once every half a year under the working condition of swiping
|
||||
the card 8 times a day for 3 seconds each time. Full potential for everyday use.
|
||||
|
||||
# 2. Not just UID, but a real and complete MIFARE encrypted data simulation
|
||||
|
||||
We can easily and completely simulate all data and password verification of all sectors, and can customize SAK, ATQA,
|
||||
ATS, etc. Similar to an open CPU card development platform, 14A interaction of various architectures can be easily
|
||||
realized.
|
||||
|
||||
# 3. Super compatibility with low-power locks using batteries
|
||||
|
||||
The structure of the old Chameleon AVR is slow to start during simulation. Faced with a battery-powered low-power lock
|
||||
and an integrated lock on the door, it will be frequently interrupted, and the verification interaction cannot be
|
||||
completed completely, resulting in no response when swiping the card.
|
||||
|
||||
In order to reduce power consumption, the battery lock will send out a field signal as short as possible when searching
|
||||
for a card, which is no problem for the original card, but it is fatal for the MCU simulated card. Cards or mobile smart
|
||||
bracelets simulated by the MCU cannot wake up and respond in such a short time, so many battery locks cannot open the
|
||||
door, which greatly reduces the user experience.
|
||||
|
||||
This project specially optimizes the start-up and interaction logic and antenna for low-power reading heads. After
|
||||
testing a variety of common low-power reading heads, they can open the door perfectly by swiping the card.
|
||||
|
||||
# 4. Ultra-fast response speed and low interaction delay(MifareClassic)
|
||||
|
||||
[fdt_standard_s50]: https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/resource/picture/Standard_m1_s50.png
|
||||
|
||||
[fdt_redmi_k30]: https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/resource/picture/Xiaomi_k30u_smartkey.png
|
||||
|
||||
[fdt_pm3_rdv401]: https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/resource/picture/Proxmark3_Rdv4_RRG_(Firmware%20build%20at%2020201026).png
|
||||
|
||||
[fdt_chameleon_ultra]: https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/resource/picture/ChameleonUltra.png
|
||||
|
||||
[fdt_chameleon_tiny]: https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/resource/picture/ChameleonTiny.png
|
||||
|
||||
[fdt_flipper_zero]: https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/resource/picture/FlipperZero%20Simulation.png
|
||||
|
||||
| Simulation | FDT | "**_FDT_**" Rating |
|
||||
|----------------------|:---------------------------:|:--------------------------------------------------------------------------------:|
|
||||
| Standard MIFARE Card | ![alt][fdt_standard_s50] | ⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐ |
|
||||
| ChameleonUltra | ![alt][fdt_chameleon_ultra] | ⭐⭐⭐⭐⭐⭐⭐⭐ |
|
||||
| Proxmark3 Rdv4.01 | ![alt][fdt_pm3_rdv401] | ⭐⭐⭐⭐ |
|
||||
| RedMi K30 | ![alt][fdt_redmi_k30] | ⭐⭐⭐⭐⭐⭐ |
|
||||
| ChameleonTiny | ![alt][fdt_chameleon_tiny] | ⭐⭐⭐⭐⭐ |
|
||||
| FlipperZero | ![alt][fdt_flipper_zero] | ⭐⭐ |
|
||||
|
||||
# 5. 256kB super large RAM cooperates with RC522 to replace Proxmark3 magically to complete the decoding
|
||||
|
||||
[attack_mifare_darkside]: https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/resource/picture/Darkside.png
|
||||
|
||||
[attack_mifare_nested]: https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/resource/picture/Nested.png
|
||||
|
||||
[attack_mifare_mfkey32]: https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/resource/picture/MFKEY32V2.png
|
||||
|
||||
| Attack Type | CLI |
|
||||
|--------------|:------------------------------:|
|
||||
| MFKEY32 V2 | ![alt][attack_mifare_mfkey32] |
|
||||
| Darkside | ![alt][attack_mifare_darkside] |
|
||||
| Nested | ![alt][attack_mifare_nested] |
|
||||
| StaticNested | Coming Soon |
|
||||
| HardNested | Coming Soon |
|
||||
| Relay attack | Coming Soon |
|
||||
|
||||
# Hardware frame diagram:
|
||||
|
||||

|
||||
+2
-1
@@ -6,7 +6,8 @@ ARG NRF_CLT_URL=https://nsscprodmedia.blob.core.windows.net/prod/software-and-ot
|
||||
RUN set -xe; \
|
||||
DEBIAN_FRONTEND=noninteractive; \
|
||||
apt update -q; \
|
||||
apt install -qy --no-install-recommends ca-certificates curl xz-utils make; \
|
||||
apt install -qy --no-install-recommends ca-certificates curl xz-utils make git; \
|
||||
git config --global --add safe.directory /workdir; \
|
||||
curl -sLo /usr/bin/nrfutil https://developer.nordicsemi.com/.pc-tools/nrfutil/x64-linux/nrfutil; \
|
||||
curl -sLo /tmp/nrf-clt.deb $NRF_CLT_URL; \
|
||||
apt install -qfy /tmp/nrf-clt.deb; \
|
||||
|
||||
@@ -22,4 +22,11 @@ LD_DIR := $(SRC_COMMON)
|
||||
CHAMELEON_ULTRA := ultra
|
||||
CHAMELEON_LITE := lite
|
||||
# What device is it?
|
||||
|
||||
CURRENT_DEVICE_TYPE ?= ${CHAMELEON_ULTRA}
|
||||
|
||||
# Versioning information
|
||||
GIT_VERSION := "$(shell git describe --abbrev=7 --dirty --always --tags)"
|
||||
|
||||
# Enable NRF_LOG on SWO pin as UART TX
|
||||
NRF_LOG_UART_ON_SWO_ENABLED := 0
|
||||
|
||||
@@ -7,14 +7,17 @@ $(OUTPUT_DIRECTORY)/application.out: \
|
||||
# Source files common to all targets
|
||||
SRC_FILES += \
|
||||
$(SRC_COMMON)/hw_connect.c \
|
||||
$(SRC_COMMON)/libc_nano_stubs.c \
|
||||
$(PROJ_DIR)/app_main.c \
|
||||
$(PROJ_DIR)/app_cmd.c \
|
||||
$(PROJ_DIR)/ble_main.c \
|
||||
$(PROJ_DIR)/rfid_main.c \
|
||||
$(PROJ_DIR)/settings.c \
|
||||
$(PROJ_DIR)/usb_main.c \
|
||||
$(PROJ_DIR)/rgb_marquee.c \
|
||||
$(PROJ_DIR)/bsp/bsp_delay.c \
|
||||
$(PROJ_DIR)/bsp/bsp_time.c \
|
||||
$(PROJ_DIR)/bsp/bsp_wdt.c \
|
||||
$(PROJ_DIR)/rfid/crc_utils.c \
|
||||
$(PROJ_DIR)/rfid/hex_utils.c \
|
||||
$(PROJ_DIR)/rfid/mf1_crapto1.c \
|
||||
@@ -28,6 +31,7 @@ SRC_FILES += \
|
||||
$(PROJ_DIR)/rfid/nfctag/hf/nfc_ntag.c \
|
||||
$(PROJ_DIR)/rfid/nfctag/lf/lf_tag_em.c \
|
||||
$(PROJ_DIR)/utils/dataframe.c \
|
||||
$(PROJ_DIR)/utils/delayed_reset.c \
|
||||
$(PROJ_DIR)/utils/fds_util.c \
|
||||
$(PROJ_DIR)/utils/syssleep.c \
|
||||
$(PROJ_DIR)/utils/timeslot.c \
|
||||
@@ -91,6 +95,7 @@ SRC_FILES += \
|
||||
$(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_spi.c \
|
||||
$(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_rng.c \
|
||||
$(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_ppi.c \
|
||||
$(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_wdt.c \
|
||||
$(SDK_ROOT)/external/segger_rtt/SEGGER_RTT.c \
|
||||
$(SDK_ROOT)/external/segger_rtt/SEGGER_RTT_Syscalls_GCC.c \
|
||||
$(SDK_ROOT)/external/segger_rtt/SEGGER_RTT_printf.c \
|
||||
@@ -286,6 +291,23 @@ else
|
||||
$(error Chameleon <Application>: No device type define.)
|
||||
endif
|
||||
|
||||
ifeq (${NRF_LOG_UART_ON_SWO_ENABLED}, 1)
|
||||
SRC_FILES += \
|
||||
$(SDK_ROOT)/components/libraries/log/src/nrf_log_backend_uart.c \
|
||||
$(SDK_ROOT)/integration/nrfx/legacy/nrf_drv_uart.c \
|
||||
$(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_uarte.c
|
||||
|
||||
CFLAGS += -DNRFX_UARTE_ENABLED=1 -DNRFX_UARTE0_ENABLED=1
|
||||
CFLAGS += -DNRF_LOG_BACKEND_UART_ENABLED=1
|
||||
#define NRF_GPIO_PIN_MAP(port, pin) (((port) << 5) | ((pin) & 0x1F))
|
||||
#define NRF_LOG_BACKEND_UART_TX_PIN NRF_GPIO_PIN_MAP(1, 0)
|
||||
CFLAGS += -DNRF_LOG_BACKEND_UART_TX_PIN=32
|
||||
# 30801920 = 115200 baud
|
||||
CFLAGS += -DNRF_LOG_BACKEND_UART_BAUDRATE=30801920
|
||||
CFLAGS += -DNRF_LOG_BACKEND_UART_TEMP_BUFFER_SIZE=64
|
||||
|
||||
$(info Chameleon <Application>: enable NRF_LOG on UART via SWO pin.)
|
||||
endif
|
||||
|
||||
# Optimization flags
|
||||
OPT = -O3 -g3
|
||||
@@ -311,6 +333,9 @@ CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
|
||||
CFLAGS += -ffunction-sections -fdata-sections -fno-strict-aliasing
|
||||
CFLAGS += -fno-builtin -fshort-enums
|
||||
|
||||
# Versioning flags
|
||||
CFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\"
|
||||
|
||||
# C++ flags common to all targets
|
||||
CXXFLAGS += $(OPT)
|
||||
# Assembler flags common to all targets
|
||||
@@ -366,14 +391,13 @@ TEMPLATE_PATH := $(SDK_ROOT)/components/toolchain/gcc
|
||||
include ../Makefile.defs
|
||||
include $(TEMPLATE_PATH)/Makefile.common
|
||||
|
||||
# tolerate warnings in newer gcc versions
|
||||
# need to be called after $(TEMPLATE_PATH)/Makefile.common
|
||||
CC_VERSION = $(shell $(CC) -dumpversion 2>/dev/null|sed 's/\..*//')
|
||||
CC_VERSION := $(or $(strip $(CC_VERSION)),0)
|
||||
CFLAGS += -Wno-error=array-bounds
|
||||
ifeq ($(shell expr $(CC_VERSION) \>= 12), 1)
|
||||
CFLAGS += -Wno-error=sizeof-array-div
|
||||
endif
|
||||
# usage example:
|
||||
#ifeq ($(shell expr $(CC_VERSION) \>= 12), 1)
|
||||
# CFLAGS += -Wno-error=sizeof-array-div
|
||||
#endif
|
||||
|
||||
$(foreach target, $(TARGETS), $(call define_target, $(target)))
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include "app_status.h"
|
||||
#include "tag_persistence.h"
|
||||
#include "nrf_pwr_mgmt.h"
|
||||
#include "settings.h"
|
||||
#include "delayed_reset.h"
|
||||
|
||||
|
||||
#define NRF_LOG_MODULE_NAME app_cmd
|
||||
@@ -27,6 +29,12 @@ data_frame_tx_t* cmd_processor_get_version(uint16_t cmd, uint16_t status, uint16
|
||||
return data_frame_make(cmd, status, 2, (uint8_t*)&version);
|
||||
}
|
||||
|
||||
|
||||
data_frame_tx_t* cmd_processor_get_git_version(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
|
||||
return data_frame_make(cmd, status, strlen(GIT_VERSION), (uint8_t*)GIT_VERSION);
|
||||
}
|
||||
|
||||
|
||||
data_frame_tx_t* cmd_processor_change_device_mode(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
|
||||
#if defined(PROJECT_CHAMELEON_ULTRA)
|
||||
if (length == 1) {
|
||||
@@ -80,6 +88,32 @@ data_frame_tx_t* cmd_processor_get_device_address(uint16_t cmd, uint16_t status,
|
||||
return data_frame_make(cmd, STATUS_DEVICE_SUCCESS, 6, (uint8_t*)(&device_address[0]));
|
||||
}
|
||||
|
||||
data_frame_tx_t* cmd_processor_save_settings(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
|
||||
status = settings_save_config();
|
||||
return data_frame_make(cmd, status, 0, NULL);
|
||||
}
|
||||
|
||||
data_frame_tx_t* cmd_processor_reset_settings(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
|
||||
settings_init_config();
|
||||
status = settings_save_config();
|
||||
return data_frame_make(cmd, status, 0, NULL);
|
||||
}
|
||||
|
||||
data_frame_tx_t* cmd_processor_set_animation_mode(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
|
||||
if (length == 1) {
|
||||
settings_set_animation_config(data[0]);
|
||||
}
|
||||
else {
|
||||
status = STATUS_PAR_ERR;
|
||||
}
|
||||
return data_frame_make(cmd, status, 0, NULL);
|
||||
}
|
||||
|
||||
data_frame_tx_t* cmd_processor_get_animation_mode(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
|
||||
uint8_t animation_mode = settings_get_animation_config();
|
||||
return data_frame_make(cmd, STATUS_DEVICE_SUCCESS, 1, (uint8_t *)(&animation_mode));
|
||||
}
|
||||
|
||||
#if defined(PROJECT_CHAMELEON_ULTRA)
|
||||
|
||||
data_frame_tx_t* cmd_processor_14a_scan(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
|
||||
@@ -307,6 +341,30 @@ data_frame_tx_t* cmd_processor_slot_data_config_save(uint16_t cmd, uint16_t stat
|
||||
return data_frame_make(cmd, STATUS_DEVICE_SUCCESS, 0, NULL);
|
||||
}
|
||||
|
||||
data_frame_tx_t* cmd_processor_get_activated_slot(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
|
||||
uint8_t slot = tag_emulation_get_slot();
|
||||
return data_frame_make(cmd, STATUS_DEVICE_SUCCESS, 1, &slot);
|
||||
}
|
||||
|
||||
data_frame_tx_t* cmd_processor_get_slot_info(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
|
||||
uint8_t slot_info[16] = {};
|
||||
tag_specific_type_t tag_type[2];
|
||||
for (uint8_t slot = 0; slot < 8; slot++) {
|
||||
tag_emulation_get_specific_type_by_slot(slot, tag_type);
|
||||
slot_info[slot * 2] = tag_type[0];
|
||||
slot_info[slot * 2 + 1] = tag_type[1];
|
||||
}
|
||||
|
||||
return data_frame_make(cmd, STATUS_DEVICE_SUCCESS, 16, slot_info);
|
||||
}
|
||||
|
||||
data_frame_tx_t* cmd_processor_wipe_fds(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
|
||||
bool success = fds_wipe();
|
||||
status = success ? STATUS_DEVICE_SUCCESS : STATUS_FLASH_WRITE_FAIL;
|
||||
delayed_reset(50);
|
||||
return data_frame_make(cmd, status, 0, NULL);
|
||||
}
|
||||
|
||||
data_frame_tx_t* cmd_processor_set_em410x_emu_id(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
|
||||
if (length == LF_EM410X_TAG_ID_SIZE) {
|
||||
tag_data_buffer_t* buffer = get_buffer_by_tag_type(TAG_TYPE_EM410X);
|
||||
@@ -380,13 +438,13 @@ data_frame_tx_t* cmd_processor_get_mf1_detection_log(uint16_t cmd, uint16_t stat
|
||||
data_frame_tx_t* cmd_processor_set_mf1_emulator_block(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
|
||||
if (length > 0 && (((length - 1) % NFC_TAG_MF1_DATA_SIZE) == 0)) {
|
||||
uint8_t block_index = data[0];
|
||||
uint8_t block_count = (length - 1) % NFC_TAG_MF1_DATA_SIZE;
|
||||
uint8_t block_count = (length - 1) / NFC_TAG_MF1_DATA_SIZE;
|
||||
if (block_index + block_count > NFC_TAG_MF1_BLOCK_MAX) {
|
||||
status = STATUS_PAR_ERR;
|
||||
} else {
|
||||
tag_data_buffer_t* buffer = get_buffer_by_tag_type(TAG_TYPE_MIFARE_4096);
|
||||
nfc_tag_mf1_information_t *info = (nfc_tag_mf1_information_t *)buffer->buffer;
|
||||
for (int i = 1, j = block_index; i < length - 1; i += NFC_TAG_MF1_DATA_SIZE, j++) {
|
||||
for (int i = 1, j = block_index; i < length; i += NFC_TAG_MF1_DATA_SIZE, j++) {
|
||||
uint8_t *p_block = &data[i];
|
||||
memcpy(info->memory[j], p_block, NFC_TAG_MF1_DATA_SIZE);
|
||||
}
|
||||
@@ -423,7 +481,6 @@ data_frame_tx_t* cmd_processor_set_mf1_anti_collision_res(uint16_t cmd, uint16_t
|
||||
}
|
||||
|
||||
data_frame_tx_t* cmd_processor_set_slot_tag_nick_name(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
|
||||
// one chinese have 2byte(gbk).
|
||||
if (length > 34 || length < 3) {
|
||||
status = STATUS_PAR_ERR;
|
||||
} else {
|
||||
@@ -448,7 +505,6 @@ data_frame_tx_t* cmd_processor_set_slot_tag_nick_name(uint16_t cmd, uint16_t sta
|
||||
}
|
||||
|
||||
data_frame_tx_t* cmd_processor_get_slot_tag_nick_name(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) {
|
||||
// one chinese have 2byte(gbk).
|
||||
if (length != 2) {
|
||||
status = STATUS_PAR_ERR;
|
||||
} else {
|
||||
@@ -524,6 +580,11 @@ static cmd_data_map_t m_data_cmd_map[] = {
|
||||
{ DATA_CMD_ENTER_BOOTLOADER, NULL, cmd_processor_enter_bootloader, NULL },
|
||||
{ DATA_CMD_GET_DEVICE_CHIP_ID, NULL, cmd_processor_get_device_chip_id, NULL },
|
||||
{ DATA_CMD_GET_DEVICE_ADDRESS, NULL, cmd_processor_get_device_address, NULL },
|
||||
{ DATA_CMD_SAVE_SETTINGS, NULL, cmd_processor_save_settings, NULL },
|
||||
{ DATA_CMD_RESET_SETTINGS, NULL, cmd_processor_reset_settings, NULL },
|
||||
{ DATA_CMD_SET_ANIMATION_MODE, NULL, cmd_processor_set_animation_mode, NULL },
|
||||
{ DATA_CMD_GET_ANIMATION_MODE, NULL, cmd_processor_get_animation_mode, NULL },
|
||||
{ DATA_CMD_GET_GIT_VERSION, NULL, cmd_processor_get_git_version, NULL },
|
||||
|
||||
#if defined(PROJECT_CHAMELEON_ULTRA)
|
||||
|
||||
@@ -550,6 +611,9 @@ static cmd_data_map_t m_data_cmd_map[] = {
|
||||
{ DATA_CMD_SET_SLOT_DATA_DEFAULT, NULL, cmd_processor_set_slot_data_default, NULL },
|
||||
{ DATA_CMD_SET_SLOT_ENABLE, NULL, cmd_processor_set_slot_enable, NULL },
|
||||
{ DATA_CMD_SLOT_DATA_CONFIG_SAVE, NULL, cmd_processor_slot_data_config_save, NULL },
|
||||
{ DATA_CMD_GET_ACTIVE_SLOT, NULL, cmd_processor_get_activated_slot, NULL },
|
||||
{ DATA_CMD_GET_SLOT_INFO, NULL, cmd_processor_get_slot_info, NULL },
|
||||
{ DATA_CMD_WIPE_FDS, NULL, cmd_processor_wipe_fds, NULL },
|
||||
|
||||
|
||||
{ DATA_CMD_SET_EM410X_EMU_ID, NULL, cmd_processor_set_em410x_emu_id, NULL },
|
||||
|
||||
@@ -27,6 +27,7 @@ NRF_LOG_MODULE_REGISTER();
|
||||
#include "ble_main.h"
|
||||
#include "bsp_delay.h"
|
||||
#include "bsp_time.h"
|
||||
#include "bsp_wdt.h"
|
||||
#include "dataframe.h"
|
||||
#include "fds_util.h"
|
||||
#include "hex_utils.h"
|
||||
@@ -36,6 +37,7 @@ NRF_LOG_MODULE_REGISTER();
|
||||
#include "usb_main.h"
|
||||
#include "rgb_marquee.h"
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
// Defining soft timers
|
||||
APP_TIMER_DEF(m_button_check_timer); // Timer for button debounce
|
||||
@@ -219,22 +221,25 @@ static void system_off_enter(void) {
|
||||
for (uint8_t i = 0; i < RGB_LIST_NUM; i++) {
|
||||
nrf_gpio_pin_clear(p_led_array[i]);
|
||||
}
|
||||
uint8_t slot = tag_emulation_get_slot();
|
||||
// Power off animation
|
||||
uint8_t dir = slot > 3 ? 1 : 0;
|
||||
uint8_t color = get_color_by_slot(slot);
|
||||
if (m_reset_source & (NRF_POWER_RESETREAS_NFC_MASK | NRF_POWER_RESETREAS_LPCOMP_MASK)) {
|
||||
if (m_reset_source & NRF_POWER_RESETREAS_NFC_MASK) {
|
||||
color = 1;
|
||||
} else {
|
||||
color = 2;
|
||||
uint8_t animation_config = settings_get_animation_config();
|
||||
if (animation_config == SettingsAnimationModeFull) {
|
||||
uint8_t slot = tag_emulation_get_slot();
|
||||
// Power off animation
|
||||
uint8_t dir = slot > 3 ? 1 : 0;
|
||||
uint8_t color = get_color_by_slot(slot);
|
||||
if (m_reset_source & (NRF_POWER_RESETREAS_NFC_MASK | NRF_POWER_RESETREAS_LPCOMP_MASK)) {
|
||||
if (m_reset_source & NRF_POWER_RESETREAS_NFC_MASK) {
|
||||
color = 1;
|
||||
} else {
|
||||
color = 2;
|
||||
}
|
||||
}
|
||||
ledblink5(color, slot, dir ? 7 : 0);
|
||||
ledblink4(color, dir, 7, 99, 75);
|
||||
ledblink4(color, !dir, 7, 75, 50);
|
||||
ledblink4(color, dir, 7, 50, 25);
|
||||
ledblink4(color, !dir, 7, 25, 0);
|
||||
}
|
||||
ledblink5(color, slot, dir ? 7 : 0);
|
||||
ledblink4(color, dir, 7, 99, 75);
|
||||
ledblink4(color, !dir, 7, 75, 50);
|
||||
ledblink4(color, dir, 7, 50, 25);
|
||||
ledblink4(color, !dir, 7, 25, 0);
|
||||
rgb_marquee_stop();
|
||||
}
|
||||
|
||||
@@ -346,9 +351,18 @@ static void check_wakeup_src(void) {
|
||||
advertising_start(); // Turn on Bluetooth radio
|
||||
|
||||
// Button wake-up boot animation
|
||||
ledblink2(color, !dir, 11);
|
||||
ledblink2(color, dir, 11);
|
||||
ledblink2(color, !dir, dir ? slot : 7 - slot);
|
||||
uint8_t animation_config = settings_get_animation_config();
|
||||
if (animation_config == SettingsAnimationModeFull)
|
||||
{
|
||||
ledblink2(color, !dir, 11);
|
||||
ledblink2(color, dir, 11);
|
||||
ledblink2(color, !dir, dir ? slot : 7 - slot);
|
||||
} else if (animation_config == SettingsAnimationModeMinimal) {
|
||||
ledblink2(color, !dir, dir ? slot : 7 - slot);
|
||||
} else {
|
||||
set_slot_light_color(color);
|
||||
}
|
||||
|
||||
// The indicator of the current card slot lights up at the end of the animation
|
||||
light_up_by_slot();
|
||||
|
||||
@@ -374,8 +388,11 @@ static void check_wakeup_src(void) {
|
||||
// 当前是模拟卡事件唤醒系统,我们可以让场强灯先亮起来
|
||||
TAG_FIELD_LED_ON();
|
||||
|
||||
// In the case of field wake-up, only one round of RGB is swept as the power-on animation
|
||||
ledblink2(color, !dir, dir ? slot : 7 - slot);
|
||||
uint8_t animation_config = settings_get_animation_config();
|
||||
if (animation_config == SettingsAnimationModeFull) {
|
||||
// In the case of field wake-up, only one round of RGB is swept as the power-on animation
|
||||
ledblink2(color, !dir, dir ? slot : 7 - slot);
|
||||
}
|
||||
set_slot_light_color(color);
|
||||
light_up_by_slot();
|
||||
|
||||
@@ -517,6 +534,8 @@ int main(void) {
|
||||
tag_emulation_init(); // Analog card initialization
|
||||
rgb_marquee_init(); // Light effect initialization
|
||||
|
||||
settings_load_config(); // Load settings from flash
|
||||
|
||||
// cmd callback register
|
||||
on_data_frame_complete(on_data_frame_received);
|
||||
|
||||
@@ -526,6 +545,7 @@ int main(void) {
|
||||
// usbd event listener
|
||||
APP_ERROR_CHECK(app_usbd_power_events_enable());
|
||||
|
||||
bsp_wdt_init();
|
||||
// Enter main loop.
|
||||
NRF_LOG_INFO("Chameleon working");
|
||||
while (1) {
|
||||
@@ -539,6 +559,8 @@ int main(void) {
|
||||
while (NRF_LOG_PROCESS());
|
||||
// USB event process
|
||||
while (app_usbd_event_queue_process());
|
||||
// WDT refresh
|
||||
bsp_wdt_feed();
|
||||
// No task to process, system sleep enter.
|
||||
// If system idle sometime, we can enter deep sleep state.
|
||||
// Some task process done, we can enter cpu sleep state.
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "nrf_drv_wdt.h"
|
||||
#include "hw_connect.h"
|
||||
#include "nrf_gpio.h"
|
||||
|
||||
static nrf_drv_wdt_channel_id m_channel_id;
|
||||
|
||||
static void wdt_event_handler(void)
|
||||
{
|
||||
//NOTE: The max amount of time we can spend in WDT interrupt is two cycles of 32768[Hz] clock - after that, reset occurs
|
||||
uint32_t* p_led_array = hw_get_led_array();
|
||||
for (uint8_t i = 0; i < RGB_LIST_NUM; i++) {
|
||||
nrf_gpio_pin_clear(p_led_array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void bsp_wdt_init(void) {
|
||||
ret_code_t err_code;
|
||||
// err_code = nrf_drv_clock_init(); // already done by usb_cdc_init() -> app_usbd_init()
|
||||
// APP_ERROR_CHECK(err_code);
|
||||
nrf_drv_wdt_config_t config = NRF_DRV_WDT_DEAFULT_CONFIG; // typo is in the SDK...
|
||||
err_code = nrf_drv_wdt_init(&config, wdt_event_handler);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
err_code = nrf_drv_wdt_channel_alloc(&m_channel_id);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
nrf_drv_wdt_enable();
|
||||
}
|
||||
|
||||
void bsp_wdt_feed(void) {
|
||||
nrf_drv_wdt_channel_feed(m_channel_id);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#ifndef __BSP_WDT_H__
|
||||
#define __BSP_WDT_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void bsp_wdt_init(void);
|
||||
void bsp_wdt_feed(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __BSP_WDT_H__
|
||||
@@ -20,6 +20,14 @@
|
||||
#define DATA_CMD_ENTER_BOOTLOADER (1010)
|
||||
#define DATA_CMD_GET_DEVICE_CHIP_ID (1011)
|
||||
#define DATA_CMD_GET_DEVICE_ADDRESS (1012)
|
||||
#define DATA_CMD_SAVE_SETTINGS (1013)
|
||||
#define DATA_CMD_RESET_SETTINGS (1014)
|
||||
#define DATA_CMD_SET_ANIMATION_MODE (1015)
|
||||
#define DATA_CMD_GET_ANIMATION_MODE (1016)
|
||||
#define DATA_CMD_GET_GIT_VERSION (1017)
|
||||
#define DATA_CMD_GET_ACTIVE_SLOT (1018)
|
||||
#define DATA_CMD_GET_SLOT_INFO (1019)
|
||||
#define DATA_CMD_WIPE_FDS (1020)
|
||||
//
|
||||
// ******************************************************************
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "lf_tag_em.h"
|
||||
#include "nfc_mf1.h"
|
||||
#include "nfc_ntag.h"
|
||||
#include "fds_ids.h"
|
||||
#include "fds_util.h"
|
||||
#include "tag_emulation.h"
|
||||
#include "tag_persistence.h"
|
||||
@@ -383,7 +384,7 @@ void tag_emulation_sense_switch(tag_sense_type_t type, bool enable) {
|
||||
*/
|
||||
void tag_emulation_load_config(void) {
|
||||
// 读取卡槽配置数据
|
||||
bool ret = fds_read_sync(FDS_CONFIG_RECORD_FILE_ID, FDS_CONFIG_RECORD_FILE_KEY, sizeof(slotConfig), (uint8_t *)&slotConfig);
|
||||
bool ret = fds_read_sync(FDS_EMULATION_CONFIG_FILE_ID, FDS_EMULATION_CONFIG_RECORD_KEY, sizeof(slotConfig), (uint8_t *)&slotConfig);
|
||||
if (ret) {
|
||||
// 读取完成后,我们先保存一份当前配置的BCC,后面保存的时候可以作为变动对比的参考
|
||||
calc_14a_crc_lut((uint8_t *)&slotConfig, sizeof(slotConfig), (uint8_t *)&m_slot_config_crc);
|
||||
@@ -402,7 +403,7 @@ void tag_emulation_save_config(void) {
|
||||
calc_14a_crc_lut((uint8_t *)&slotConfig, sizeof(slotConfig), (uint8_t *)&new_calc_crc);
|
||||
if (new_calc_crc != m_slot_config_crc) { // 在保存之前,先确保卡槽配置有变动了
|
||||
NRF_LOG_INFO("Save tag slot config start.");
|
||||
bool ret = fds_write_sync(FDS_CONFIG_RECORD_FILE_ID, FDS_CONFIG_RECORD_FILE_KEY, sizeof(slotConfig) / 4, (uint8_t *)&slotConfig);
|
||||
bool ret = fds_write_sync(FDS_EMULATION_CONFIG_FILE_ID, FDS_EMULATION_CONFIG_RECORD_KEY, sizeof(slotConfig) / 4, (uint8_t *)&slotConfig);
|
||||
if (ret) {
|
||||
NRF_LOG_INFO("Save tag slot config success.");
|
||||
} else {
|
||||
|
||||
@@ -5,12 +5,11 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "tag_base_type.h"
|
||||
|
||||
// 最多八张卡槽
|
||||
#define TAG_MAX_SLOT_NUM 8
|
||||
// u32 size align.
|
||||
#define ALIGN_U32 __attribute__((aligned(4)))
|
||||
|
||||
extern bool g_is_tag_emulating;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "tag_persistence.h"
|
||||
|
||||
#include "fds_ids.h"
|
||||
|
||||
#define NRF_LOG_MODULE_NAME tag_persistence
|
||||
#include "nrf_log.h"
|
||||
@@ -9,35 +9,24 @@ NRF_LOG_MODULE_REGISTER();
|
||||
|
||||
|
||||
|
||||
void get_fds_map_by_slot_auto_inc_id(uint16_t key, uint16_t id, uint8_t slot, tag_sense_type_t sense_type, fds_slot_record_map_t* map) {
|
||||
map->key = key + slot;
|
||||
uint8_t base_id = 0;
|
||||
switch(sense_type) {
|
||||
case TAG_SENSE_HF:
|
||||
base_id = 0;
|
||||
break;
|
||||
case TAG_SENSE_LF:
|
||||
base_id = 1;
|
||||
break;
|
||||
case TAG_SENSE_NO:
|
||||
// never to here...(if dev wrong, must fix)
|
||||
APP_ERROR_CHECK(NRF_ERROR_INVALID_PARAM);
|
||||
static void get_fds_map_by_slot_auto_inc_id(uint16_t id, uint8_t slot, tag_sense_type_t sense_type, fds_slot_record_map_t* map) {
|
||||
if ((sense_type == TAG_SENSE_NO) || (slot > 7)) {
|
||||
APP_ERROR_CHECK(NRF_ERROR_INVALID_PARAM);
|
||||
}
|
||||
map->id = id + base_id;
|
||||
map->id = id + slot;
|
||||
map->key = sense_type;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据卡槽和卡槽中指定的场类型获得其在FDS中对应的数据的KEY和ID
|
||||
* Obtain the KEY and ID of the corresponding data in FDS according to the card slot and the field type specified in the card slot
|
||||
*/
|
||||
void get_fds_map_by_slot_sense_type_for_dump(uint8_t slot, tag_sense_type_t sense_type, fds_slot_record_map_t* map) {
|
||||
// 根据 @see FDS_SLOT_TAG_DUMP_FILE_KEY 的约定,每个slot以其为起点,每个slot都有其单独的key的record,并且每个slot中独特的场类型也有一个数据的id
|
||||
get_fds_map_by_slot_auto_inc_id(FDS_SLOT_TAG_DUMP_FILE_KEY, FDS_SLOT_TAG_DUMP_FILE_ID, slot, sense_type, map);
|
||||
get_fds_map_by_slot_auto_inc_id(FDS_SLOT_TAG_DUMP_FILE_ID_BASE, slot, sense_type, map);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据卡槽和卡槽中指定的场类型获得其在FDS中对应的数据的KEY和ID
|
||||
* Obtain the KEY and ID of the corresponding data in FDS according to the card slot and the field type specified in the card slot
|
||||
*/
|
||||
void get_fds_map_by_slot_sense_type_for_nick(uint8_t slot, tag_sense_type_t sense_type, fds_slot_record_map_t* map) {
|
||||
get_fds_map_by_slot_auto_inc_id(FDS_SLOT_TAG_NICK_NAME_KEY, FDS_SLOT_TAG_NICK_NAME_ID, slot, sense_type, map);
|
||||
get_fds_map_by_slot_auto_inc_id(FDS_SLOT_TAG_NICK_NAME_FILE_ID_BASE, slot, sense_type, map);
|
||||
}
|
||||
|
||||
@@ -5,27 +5,6 @@
|
||||
#include "tag_base_type.h"
|
||||
|
||||
|
||||
/*
|
||||
* 卡槽配置,只有一份,一致即可
|
||||
*/
|
||||
#define FDS_CONFIG_RECORD_FILE_KEY 0x1066
|
||||
#define FDS_CONFIG_RECORD_FILE_ID 0x1066
|
||||
|
||||
/*
|
||||
* 每个卡槽有高低频两种数据,其中key是跟卡槽走的,而id+n就等于数据索引,固定某个索引为指定类型即可
|
||||
* 每个slot的file_key都不一样
|
||||
* 每个slot有两种类型的卡片,因此有两个数据ID(当前)
|
||||
*/
|
||||
#define FDS_SLOT_TAG_DUMP_FILE_KEY 0x1067
|
||||
#define FDS_SLOT_TAG_DUMP_FILE_ID 0x1067
|
||||
|
||||
/*
|
||||
* 每个卡槽有高低频两种数据,因此卡槽的昵称也要有两种,其中key是跟卡槽走的,而id+n就等于数据索引,固定某个索引为指定类型即可
|
||||
*/
|
||||
#define FDS_SLOT_TAG_NICK_NAME_KEY 0x1068
|
||||
#define FDS_SLOT_TAG_NICK_NAME_ID 0x1068
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint16_t key;
|
||||
uint16_t id;
|
||||
|
||||
@@ -4630,7 +4630,7 @@
|
||||
// <e> NRFX_WDT_ENABLED - nrfx_wdt - WDT peripheral driver
|
||||
//==========================================================
|
||||
#ifndef NRFX_WDT_ENABLED
|
||||
#define NRFX_WDT_ENABLED 0
|
||||
#define NRFX_WDT_ENABLED 1
|
||||
#endif
|
||||
// <o> NRFX_WDT_CONFIG_BEHAVIOUR - WDT behavior in CPU SLEEP or HALT mode
|
||||
|
||||
@@ -4647,7 +4647,7 @@
|
||||
|
||||
|
||||
#ifndef NRFX_WDT_CONFIG_RELOAD_VALUE
|
||||
#define NRFX_WDT_CONFIG_RELOAD_VALUE 2000
|
||||
#define NRFX_WDT_CONFIG_RELOAD_VALUE 5000
|
||||
#endif
|
||||
|
||||
// <o> NRFX_WDT_CONFIG_NO_IRQ - Remove WDT IRQ handling from WDT driver
|
||||
@@ -4677,7 +4677,7 @@
|
||||
// <e> NRFX_WDT_CONFIG_LOG_ENABLED - Enables logging in the module.
|
||||
//==========================================================
|
||||
#ifndef NRFX_WDT_CONFIG_LOG_ENABLED
|
||||
#define NRFX_WDT_CONFIG_LOG_ENABLED 0
|
||||
#define NRFX_WDT_CONFIG_LOG_ENABLED 1
|
||||
#endif
|
||||
// <o> NRFX_WDT_CONFIG_LOG_LEVEL - Default Severity level
|
||||
|
||||
@@ -5868,9 +5868,10 @@
|
||||
|
||||
// <e> UART_ENABLED - nrf_drv_uart - UART/UARTE peripheral driver - legacy layer
|
||||
//==========================================================
|
||||
#ifndef UART_ENABLED
|
||||
#define UART_ENABLED 0
|
||||
#endif
|
||||
//Don't define it at all else it conflicts with NRFX
|
||||
//#ifndef UART_ENABLED
|
||||
//#define UART_ENABLED 0
|
||||
//#endif
|
||||
// <o> UART_DEFAULT_CONFIG_HWFC - Hardware Flow Control
|
||||
|
||||
// <0=> Disabled
|
||||
@@ -6018,9 +6019,10 @@
|
||||
|
||||
// <e> WDT_ENABLED - nrf_drv_wdt - WDT peripheral driver - legacy layer
|
||||
//==========================================================
|
||||
#ifndef WDT_ENABLED
|
||||
#define WDT_ENABLED 0
|
||||
#endif
|
||||
//Don't define it at all else it conflicts with NRFX
|
||||
//#ifndef WDT_ENABLED
|
||||
//#define WDT_ENABLED 0
|
||||
//#endif
|
||||
// <o> WDT_CONFIG_BEHAVIOUR - WDT behavior in CPU SLEEP or HALT mode
|
||||
|
||||
// <1=> Run in SLEEP, Pause in HALT
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
#include <stdbool.h>
|
||||
#include "crc_utils.h"
|
||||
#include "app_status.h"
|
||||
#include "settings.h"
|
||||
#include "fds_ids.h"
|
||||
#include "fds_util.h"
|
||||
|
||||
#define NRF_LOG_MODULE_NAME settings
|
||||
#include "nrf_log.h"
|
||||
#include "nrf_log_ctrl.h"
|
||||
#include "nrf_log_default_backends.h"
|
||||
NRF_LOG_MODULE_REGISTER();
|
||||
|
||||
static settings_data_t config;
|
||||
|
||||
static uint16_t m_config_crc;
|
||||
|
||||
static void update_config_crc(void)
|
||||
{
|
||||
calc_14a_crc_lut((uint8_t *)&config, sizeof(config), (uint8_t *)&m_config_crc);
|
||||
}
|
||||
|
||||
static bool config_did_change(void)
|
||||
{
|
||||
uint16_t new_calc_crc;
|
||||
calc_14a_crc_lut((uint8_t *)&config, sizeof(config), (uint8_t *)&new_calc_crc);
|
||||
return new_calc_crc != m_config_crc;
|
||||
}
|
||||
|
||||
void settings_init_config(void)
|
||||
{
|
||||
config.version = SETTINGS_CURRENT_VERSION;
|
||||
config.animation_config = SettingsAnimationModeFull;
|
||||
}
|
||||
|
||||
void settings_migrate(void)
|
||||
{
|
||||
switch (config.version) {
|
||||
case 0:
|
||||
NRF_LOG_ERROR("Unexpected configuration version detected!");
|
||||
settings_init_config();
|
||||
break;
|
||||
/*
|
||||
* When needed migrations can be implemented like this:
|
||||
*
|
||||
* case 1:
|
||||
* config->new_field = some_default_value;
|
||||
* case 2:
|
||||
* config->another_new_field = some_default_value;
|
||||
* case 3:
|
||||
* config->another_new_field = some_default_value;
|
||||
* break;
|
||||
*
|
||||
* Note that the `break` statement should only be used on the last migration step, all the previous steps must fall
|
||||
* through to the next case.
|
||||
*/
|
||||
default:
|
||||
NRF_LOG_ERROR("Unsupported configuration migration attempted! (%d -> %d)", config.version, SETTINGS_CURRENT_VERSION);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void settings_load_config(void)
|
||||
{
|
||||
bool ret = fds_read_sync(FDS_SETTINGS_FILE_ID, FDS_SETTINGS_RECORD_KEY, sizeof(config), (uint8_t *)&config);
|
||||
if (ret) {
|
||||
NRF_LOG_INFO("Load config done.");
|
||||
// After the reading is complete, we first save a copy of the current CRC, which can be used as a reference for comparison of changes when saving later
|
||||
update_config_crc();
|
||||
} else {
|
||||
NRF_LOG_WARNING("Config does not exist, loading default values...");
|
||||
settings_init_config();
|
||||
}
|
||||
if (config.version > SETTINGS_CURRENT_VERSION) {
|
||||
NRF_LOG_WARNING("Config version %d is greater than current firmware supports (%d). Default config will be loaded.", config.version, SETTINGS_CURRENT_VERSION);
|
||||
settings_init_config();
|
||||
}
|
||||
if (config.version < SETTINGS_CURRENT_VERSION) {
|
||||
NRF_LOG_INFO("Config version (%d) is not latest, performing migration to %d", config.version, SETTINGS_CURRENT_VERSION);
|
||||
settings_migrate();
|
||||
}
|
||||
if (config_did_change()) {
|
||||
settings_save_config();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t settings_save_config(void)
|
||||
{
|
||||
// We are saving the configuration, we need to calculate the crc code of the current configuration to judge whether the following data is updated
|
||||
if (config_did_change()) { // Before saving, make sure that the configuration has changed
|
||||
NRF_LOG_INFO("Save config start.");
|
||||
bool ret = fds_write_sync(FDS_SETTINGS_FILE_ID, FDS_SETTINGS_RECORD_KEY, sizeof(config) / 4, (uint8_t *)&config);
|
||||
if (ret) {
|
||||
NRF_LOG_INFO("Save config success.");
|
||||
update_config_crc();
|
||||
}
|
||||
else
|
||||
{
|
||||
NRF_LOG_ERROR("Save config error.");
|
||||
return STATUS_FLASH_WRITE_FAIL;
|
||||
}
|
||||
} else {
|
||||
NRF_LOG_INFO("Config did not change.");
|
||||
}
|
||||
|
||||
return STATUS_DEVICE_SUCCESS;
|
||||
}
|
||||
|
||||
uint8_t settings_get_animation_config()
|
||||
{
|
||||
return config.animation_config;
|
||||
}
|
||||
|
||||
void settings_set_animation_config(uint8_t value)
|
||||
{
|
||||
config.animation_config = value;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef SETTINGS_H
|
||||
#define SETTINGS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#define SETTINGS_CURRENT_VERSION 1
|
||||
|
||||
typedef enum {
|
||||
SettingsAnimationModeFull = 0,
|
||||
SettingsAnimationModeMinimal = 1,
|
||||
SettingsAnimationModeNone = 2,
|
||||
} settings_animation_mode_t;
|
||||
|
||||
typedef struct ALIGN_U32 {
|
||||
uint16_t version;
|
||||
uint8_t animation_config : 2;
|
||||
uint16_t reserved0 : 14;
|
||||
uint32_t reserved1;
|
||||
uint32_t reserved2;
|
||||
} settings_data_t;
|
||||
|
||||
void settings_init_config(void);
|
||||
void settings_migrate(void);
|
||||
void settings_load_config(void);
|
||||
uint8_t settings_save_config(void);
|
||||
uint8_t settings_get_animation_config(void);
|
||||
void settings_set_animation_config(uint8_t value);
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user