From 93c4965e2c520d2ae7bf5e948c397d96058a0551 Mon Sep 17 00:00:00 2001 From: dxl <64101226@qq.com> Date: Thu, 10 Aug 2023 12:28:18 +0800 Subject: [PATCH 01/28] Reformatting readme files --- README.md | 237 +++----------------------------------- Technical _White_Paper.md | 215 ++++++++++++++++++++++++++++++++++ 2 files changed, 233 insertions(+), 219 deletions(-) create mode 100644 Technical _White_Paper.md diff --git a/README.md b/README.md index feb8c1f..124db27 100644 --- a/README.md +++ b/README.md @@ -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 ![alt text](https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/resource/picture/Header.png) # 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 @@ -29,219 +41,6 @@ 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: - -![alt text](https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/resource/picture/Hardware%20%20Frame%20Diagram.png) - # Hardware Pictures ![alt text](https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/resource/picture/Hardware%20Photos.png) diff --git a/Technical _White_Paper.md b/Technical _White_Paper.md new file mode 100644 index 0000000..36048e7 --- /dev/null +++ b/Technical _White_Paper.md @@ -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: + +![alt text](https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/resource/picture/Hardware%20%20Frame%20Diagram.png) From c197a0ff0555ee3d5ed0e9f73cda6f07ddd5a481 Mon Sep 17 00:00:00 2001 From: dxl <64101226@qq.com> Date: Thu, 10 Aug 2023 12:53:20 +0800 Subject: [PATCH 02/28] Fixed issue with multiple spaces in readme file names --- Technical _White_Paper.md => Technical_White_Paper.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Technical _White_Paper.md => Technical_White_Paper.md (100%) diff --git a/Technical _White_Paper.md b/Technical_White_Paper.md similarity index 100% rename from Technical _White_Paper.md rename to Technical_White_Paper.md From f30ff7054c503b853a17bc9a88f8d5216d5539c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Szyma=C5=84ski?= Date: Thu, 10 Aug 2023 22:26:22 +0200 Subject: [PATCH 03/28] Add animation modes support --- .gitignore | 4 +- firmware/application/Makefile | 1 + firmware/application/src/app_cmd.c | 24 +++++++ firmware/application/src/app_main.c | 56 +++++++++++------ firmware/application/src/data_cmd.h | 3 + .../src/rfid/nfctag/tag_emulation.c | 1 + .../src/rfid/nfctag/tag_persistence.c | 2 +- .../src/rfid/nfctag/tag_persistence.h | 21 ------- firmware/application/src/settings.c | 63 +++++++++++++++++++ firmware/application/src/settings.h | 21 +++++++ firmware/application/src/utils/fds_ids.h | 30 +++++++++ software/script/chameleon_cli_main.py | 9 +++ software/script/chameleon_cli_unit.py | 38 +++++++++++ software/script/chameleon_cmd.py | 22 +++++++ software/script/chameleon_status.py | 4 ++ 15 files changed, 257 insertions(+), 42 deletions(-) create mode 100644 firmware/application/src/settings.c create mode 100644 firmware/application/src/settings.h create mode 100644 firmware/application/src/utils/fds_ids.h diff --git a/.gitignore b/.gitignore index 79e7608..9b759bb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ .idea/ .vscode/ -.vs/ \ No newline at end of file +.vs/ + +.DS_Store \ No newline at end of file diff --git a/firmware/application/Makefile b/firmware/application/Makefile index f248a1a..c0e0122 100644 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -11,6 +11,7 @@ SRC_FILES += \ $(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 \ diff --git a/firmware/application/src/app_cmd.c b/firmware/application/src/app_cmd.c index 2eb7559..27e2e52 100644 --- a/firmware/application/src/app_cmd.c +++ b/firmware/application/src/app_cmd.c @@ -12,6 +12,7 @@ #include "app_status.h" #include "tag_persistence.h" #include "nrf_pwr_mgmt.h" +#include "settings.h" #define NRF_LOG_MODULE_NAME app_cmd @@ -80,6 +81,26 @@ 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_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) { @@ -524,6 +545,9 @@ 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_SET_ANIMATION_MODE, NULL, cmd_processor_set_animation_mode, NULL }, + { DATA_CMD_GET_ANIMATION_MODE, NULL, cmd_processor_get_animation_mode, NULL }, #if defined(PROJECT_CHAMELEON_ULTRA) diff --git a/firmware/application/src/app_main.c b/firmware/application/src/app_main.c index 2c4a529..387bd5e 100644 --- a/firmware/application/src/app_main.c +++ b/firmware/application/src/app_main.c @@ -36,6 +36,8 @@ 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 == SETTINGS_ANIMATION_FULL) { + 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,17 @@ 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 == SETTINGS_ANIMATION_FULL) + { + ledblink2(color, !dir, 11); + ledblink2(color, dir, 11); + ledblink2(color, !dir, dir ? slot : 7 - slot); + } + else if (animation_config == SETTINGS_ANIMATION_MINIMAL) { + ledblink2(color, !dir, dir ? slot : 7 - slot); + } + // The indicator of the current card slot lights up at the end of the animation light_up_by_slot(); @@ -374,8 +387,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 == SETTINGS_ANIMATION_FULL) { + // 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 +533,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); diff --git a/firmware/application/src/data_cmd.h b/firmware/application/src/data_cmd.h index e5437ae..89284f2 100644 --- a/firmware/application/src/data_cmd.h +++ b/firmware/application/src/data_cmd.h @@ -20,6 +20,9 @@ #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_SET_ANIMATION_MODE (1014) +#define DATA_CMD_GET_ANIMATION_MODE (1015) // // ****************************************************************** diff --git a/firmware/application/src/rfid/nfctag/tag_emulation.c b/firmware/application/src/rfid/nfctag/tag_emulation.c index dfa1ff1..849cd03 100644 --- a/firmware/application/src/rfid/nfctag/tag_emulation.c +++ b/firmware/application/src/rfid/nfctag/tag_emulation.c @@ -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" diff --git a/firmware/application/src/rfid/nfctag/tag_persistence.c b/firmware/application/src/rfid/nfctag/tag_persistence.c index 2bf7a38..4997be2 100644 --- a/firmware/application/src/rfid/nfctag/tag_persistence.c +++ b/firmware/application/src/rfid/nfctag/tag_persistence.c @@ -1,5 +1,5 @@ #include "tag_persistence.h" - +#include "fds_ids.h" #define NRF_LOG_MODULE_NAME tag_persistence #include "nrf_log.h" diff --git a/firmware/application/src/rfid/nfctag/tag_persistence.h b/firmware/application/src/rfid/nfctag/tag_persistence.h index d25982e..21b51d0 100644 --- a/firmware/application/src/rfid/nfctag/tag_persistence.h +++ b/firmware/application/src/rfid/nfctag/tag_persistence.h @@ -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; diff --git a/firmware/application/src/settings.c b/firmware/application/src/settings.c new file mode 100644 index 0000000..1dc03f5 --- /dev/null +++ b/firmware/application/src/settings.c @@ -0,0 +1,63 @@ +#include +#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; + +void settings_load_config(void) +{ + bool ret = fds_read_sync(FDS_SETTINGS_ID, FDS_SETTINGS_KEY, sizeof(config), (uint8_t *)&config); + if (ret) { + // 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 + calc_14a_crc_lut((uint8_t *)&config, sizeof(config), (uint8_t *)&m_config_crc); + NRF_LOG_INFO("Load config done."); + } else { + NRF_LOG_INFO("config no exists."); + } +} + +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 + uint16_t new_calc_crc; + calc_14a_crc_lut((uint8_t *)&config, sizeof(config), (uint8_t *)&new_calc_crc); + if (new_calc_crc != m_config_crc) { // Before saving, make sure that the configuration has changed + NRF_LOG_INFO("Save tag slot config start."); + bool ret = fds_write_sync(FDS_CONFIG_RECORD_FILE_ID, FDS_CONFIG_RECORD_FILE_KEY, sizeof(config) / 4, (uint8_t *)&config); + if (ret) { + NRF_LOG_INFO("Save tag slot config success."); + m_config_crc = new_calc_crc; // store new CRC so we know that we've updated the configuration + } + else + { + NRF_LOG_ERROR("Save tag slot config error."); + return STATUS_FLASH_WRITE_FAIL; + } + } else { + NRF_LOG_INFO("Tag slot config no change."); + } + + return STATUS_DEVICE_SUCCESS; +} + +uint8_t settings_get_animation_config() +{ + return config & 0x3; +} + +void settings_set_animation_config(uint8_t value) +{ + config &= ~(0x3); + config |= value; +} diff --git a/firmware/application/src/settings.h b/firmware/application/src/settings.h new file mode 100644 index 0000000..a42baa3 --- /dev/null +++ b/firmware/application/src/settings.h @@ -0,0 +1,21 @@ +#ifndef SETTINGS_H +#define SETTINGS_H + +#include + +#define SETTINGS_ANIMATION_FULL 0 +#define SETTINGS_ANIMATION_MINIMAL 1 +#define SETTINGS_ANIMATION_NONE 2 + +/* + * bits [0-1]: animation config + * bits [2-31]: reserved + */ +typedef uint32_t settings_data_t; + +void settings_load_config(void); +uint8_t settings_save_config(void); +uint8_t settings_get_animation_config(); +void settings_set_animation_config(uint8_t value); + +#endif \ No newline at end of file diff --git a/firmware/application/src/utils/fds_ids.h b/firmware/application/src/utils/fds_ids.h new file mode 100644 index 0000000..ca11e2e --- /dev/null +++ b/firmware/application/src/utils/fds_ids.h @@ -0,0 +1,30 @@ +#ifndef FDS_IDS_H +#define FDS_IDS_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 + +/* + * Slot for settings like LED animation mode and future options + */ +#define FDS_SETTINGS_KEY 0x1069 +#define FDS_SETTINGS_ID 0x1069 + +#endif \ No newline at end of file diff --git a/software/script/chameleon_cli_main.py b/software/script/chameleon_cli_main.py index 83fba87..fe23a4e 100755 --- a/software/script/chameleon_cli_main.py +++ b/software/script/chameleon_cli_main.py @@ -87,6 +87,15 @@ class ChameleonCLI: 'help': "Emulation tag slot.", }, 'dfu': new_uint(chameleon_cli_unit.HWDFU, "Restart application to bootloader mode(Not yet implement dfu)."), + 'settings': { + 'animation': { + 'get': new_uint(chameleon_cli_unit.HWSettingsAnimationGet, "Get current animation mode value"), + 'set': new_uint(chameleon_cli_unit.HWSettingsAnimationSet, "Change chameleon animation mode"), + 'help': 'Manage wake-up and sleep animation mode' + }, + 'store': new_uint(chameleon_cli_unit.HWSettingsStore, "Store current settings to flash"), + 'help': "Chameleon settings management" + }, 'help': "hardware controller", }, 'hf': { diff --git a/software/script/chameleon_cli_unit.py b/software/script/chameleon_cli_unit.py index 4cb0ded..0654743 100644 --- a/software/script/chameleon_cli_unit.py +++ b/software/script/chameleon_cli_unit.py @@ -994,3 +994,41 @@ class HWDFU(DeviceRequiredUnit): print(" - Enter success @.@~") # let time for comm thread to send dfu cmd and close port time.sleep(0.1) + +class HWSettingsAnimationGet(DeviceRequiredUnit): + def args_parser(self) -> ArgumentParserNoExit or None: + return None + def on_exec(self, args: argparse.Namespace): + resp: chameleon_com.Response = self.cmd_standard.get_settings_animation() + if resp.data[0] == 0: + print("Full animation") + elif resp.data[0] == 1: + print("Minimal animation") + elif resp.data[0] == 2: + print("No animation") + else: + print("Unknown setting value, something failed.") + +class HWSettingsAnimationSet(DeviceRequiredUnit): + def args_parser(self) -> ArgumentParserNoExit or None: + parser = ArgumentParserNoExit() + parser.add_argument('-m', '--mode', type=int, required=True, help="0 is full (default), 1 is minimal (only single pass on button wakeup), 2 is none", choices=[0, 1, 2]) + return None + + def on_exec(self, args: argparse.Namespace): + mode = args.mode + self.cmd_standard.set_settings_animation(mode) + print("Animation mode change success. Do not forget to store your settings in flash!") + + +class HWSettingsStore(DeviceRequiredUnit): + def args_parser(self) -> ArgumentParserNoExit or None: + return None + + def on_exec(self, args: argparse.Namespace): + print("Storing settings...") + resp: chameleon_com.Response = self.cmd_standard.store_settings() + if resp.status == chameleon_status.Device.STATUS_DEVICE_SUCCESS: + print(" - Store success @.@~") + else: + print(" - Store failed") diff --git a/software/script/chameleon_cmd.py b/software/script/chameleon_cmd.py index 0f793d5..924ff33 100644 --- a/software/script/chameleon_cmd.py +++ b/software/script/chameleon_cmd.py @@ -20,6 +20,10 @@ DATA_CMD_ENTER_BOOTLOADER = 1010 DATA_CMD_GET_DEVICE_CHIP_ID = 1011 DATA_CMD_GET_DEVICE_ADDRESS = 1012 +DATA_CMD_SAVE_SETTINGS = 1013 +DATA_CMD_SET_ANIMATION_MODE = 1014 +DATA_CMD_GET_ANIMATION_MODE = 1015 + DATA_CMD_SCAN_14A_TAG = 2000 DATA_CMD_MF1_SUPPORT_DETECT = 2001 DATA_CMD_MF1_NT_LEVEL_DETECT = 2002 @@ -424,6 +428,24 @@ class BaseChameleonCMD: :return: """ return self.device.send_cmd_auto(DATA_CMD_ENTER_BOOTLOADER, 0x00, close=True) + + def get_settings_animation(self): + """ + Get animation mode value + """ + return self.device.send_cmd_sync(DATA_CMD_GET_ANIMATION_MODE, 0x00, None) + + def set_settings_animation(self, value: int): + """ + Set animation mode value + """ + return self.device.send_cmd_sync(DATA_CMD_SET_ANIMATION_MODE, 0x00, bytearray([value])) + + def store_settings(self): + """ + Store settings to flash memory + """ + return self.device.send_cmd_sync(DATA_CMD_SAVE_SETTINGS, 0x00) class NegativeResponseError(Exception): diff --git a/software/script/chameleon_status.py b/software/script/chameleon_status.py index bab7cde..675aaea 100644 --- a/software/script/chameleon_status.py +++ b/software/script/chameleon_status.py @@ -41,6 +41,8 @@ class Device(metaclass=MetaDevice): STATUS_INVALID_CMD = 0x67 # 无效的指令 STATUS_DEVICE_SUCCESS = 0x68 # 设备相关操作成功执行 STATUS_NOT_IMPLEMENTED = 0x69 # 调用了某些未实现的操作,属于开发者遗漏的错误 + STATUS_FLASH_WRITE_FAIL = 0x70 # flash写入失败 + STATUS_FLASH_READ_FAIL = 0x71 # flash读取失败 message = { @@ -68,4 +70,6 @@ message = { Device.STATUS_INVALID_CMD : "API request fail, cmd invalid", Device.STATUS_DEVICE_SUCCESS : "Device operation succeeded", Device.STATUS_NOT_IMPLEMENTED : "Some api not implemented", + Device.STATUS_FLASH_WRITE_FAIL : "Flash write failed", + Device.STATUS_FLASH_READ_FAIL : "Flash read failed" } From 85b2fb3d8ace6f828548693de304e39de07157b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Szyma=C5=84ski?= Date: Thu, 10 Aug 2023 22:59:00 +0200 Subject: [PATCH 04/28] Upgrade command parser --- software/script/chameleon_cli_main.py | 5 +++-- software/script/chameleon_cli_unit.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/software/script/chameleon_cli_main.py b/software/script/chameleon_cli_main.py index fe23a4e..212fa34 100755 --- a/software/script/chameleon_cli_main.py +++ b/software/script/chameleon_cli_main.py @@ -152,14 +152,15 @@ class ChameleonCLI: cmds = cmd_str.split(" ") cmd_maps: dict or types.FunctionType = self.cmd_maps cmd_end = "" + cmd_end_position = 0 for cmd in cmds: if cmd in cmd_maps: # CMD found in map, we can continue find next cmd_maps = cmd_maps[cmd] cmd_end = cmd + cmd_end_position += len(cmd) + 1 else: # CMD not found break - cmd_end_position = cmd_str.index(cmd_end) + len(cmd_end) + 1 - return cmd_maps, (cmd_str[:cmd_end_position], cmd_str[cmd_end_position:]) + return cmd_maps, (cmd_str[:cmd_end_position - 1], cmd_str[cmd_end_position:]) def startCLI(self): """ diff --git a/software/script/chameleon_cli_unit.py b/software/script/chameleon_cli_unit.py index 0654743..aec53f8 100644 --- a/software/script/chameleon_cli_unit.py +++ b/software/script/chameleon_cli_unit.py @@ -1013,7 +1013,7 @@ class HWSettingsAnimationSet(DeviceRequiredUnit): def args_parser(self) -> ArgumentParserNoExit or None: parser = ArgumentParserNoExit() parser.add_argument('-m', '--mode', type=int, required=True, help="0 is full (default), 1 is minimal (only single pass on button wakeup), 2 is none", choices=[0, 1, 2]) - return None + return parser def on_exec(self, args: argparse.Namespace): mode = args.mode From 166faaeee7cf574596b44f259fe351e69b73d2d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Szyma=C5=84ski?= Date: Thu, 10 Aug 2023 23:04:39 +0200 Subject: [PATCH 05/28] Fix wrong storage space --- firmware/application/src/settings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firmware/application/src/settings.c b/firmware/application/src/settings.c index 1dc03f5..52db9bf 100644 --- a/firmware/application/src/settings.c +++ b/firmware/application/src/settings.c @@ -34,7 +34,7 @@ uint8_t settings_save_config(void) calc_14a_crc_lut((uint8_t *)&config, sizeof(config), (uint8_t *)&new_calc_crc); if (new_calc_crc != m_config_crc) { // Before saving, make sure that the configuration has changed NRF_LOG_INFO("Save tag slot config start."); - bool ret = fds_write_sync(FDS_CONFIG_RECORD_FILE_ID, FDS_CONFIG_RECORD_FILE_KEY, sizeof(config) / 4, (uint8_t *)&config); + bool ret = fds_write_sync(FDS_SETTINGS_ID, FDS_SETTINGS_KEY, sizeof(config) / 4, (uint8_t *)&config); if (ret) { NRF_LOG_INFO("Save tag slot config success."); m_config_crc = new_calc_crc; // store new CRC so we know that we've updated the configuration From d77ca3cd7d9141573e34ac57bcbc5b3a4ff1c956 Mon Sep 17 00:00:00 2001 From: Alexander Featherston Date: Fri, 11 Aug 2023 01:16:25 -0400 Subject: [PATCH 06/28] Attempted fix of Offset issues and utilizing enums in place of hardcoded numbers. Changes to be committed: modified: software/script/chameleon_cli_unit.py modified: software/script/chameleon_cmd.py --- software/script/chameleon_cli_unit.py | 16 ++++-- software/script/chameleon_cmd.py | 75 ++++++++++++++++++++++----- 2 files changed, 74 insertions(+), 17 deletions(-) diff --git a/software/script/chameleon_cli_unit.py b/software/script/chameleon_cli_unit.py index 4cb0ded..cbd7fff 100644 --- a/software/script/chameleon_cli_unit.py +++ b/software/script/chameleon_cli_unit.py @@ -788,9 +788,11 @@ class SlotIndexRequireUint(DeviceRequiredUnit): @staticmethod def add_slot_args(parser: ArgumentParserNoExit): - slot_choices = [1, 2, 3, 4, 5, 6, 7, 8] + slot_choices = chameleon_cmd.SlotNumber.list() + help_str = f"Slot Indexes: {slot_choices}" + parser.add_argument('-s', "--slot", type=int, required=True, - help="Slot index", metavar="number", choices=slot_choices) + help=help_str, metavar="number", choices=slot_choices) return parser class SenseTypeRequireUint(DeviceRequiredUnit): @@ -803,9 +805,12 @@ class SenseTypeRequireUint(DeviceRequiredUnit): @staticmethod def add_sense_type_args(parser: ArgumentParserNoExit): - slot_choices = [1, 2] + slot_list = chameleon_cmd.TagSenseType.list() + slot_choices = chameleon_cmd.TagSenseType.choices() + help_str = f"Sense Types: {slot_list}" + parser.add_argument('-st', "--sense_type", type=int, required=True, - help="Sense type", metavar="number", choices=slot_choices) + help=help_str, metavar="number", choices=slot_choices) return parser @@ -910,7 +915,7 @@ class HWSlotNickSet(SlotIndexRequireUint, SenseTypeRequireUint): parser = ArgumentParserNoExit() self.add_slot_args(parser) self.add_sense_type_args(parser) - parser.add_argument('-n', '--name', type=str, required=True, help="Yout tag nick name for slot") + parser.add_argument('-n', '--name', type=str, required=True, help="Your tag nick name for slot") return parser # hw slot nick set -s 1 -st 1 -n 测试名称保存 @@ -921,6 +926,7 @@ class HWSlotNickSet(SlotIndexRequireUint, SenseTypeRequireUint): if len(name.encode(encoding="gbk")) > 32: raise ValueError("Your tag nick name too long.") self.cmd_positive.set_slot_tag_nick_name(slot_num, sense_type, name) + #print(f'{slot_num} selected for nickname {name}.') print(f' - Set tag nick name for slot {slot_num} success.') diff --git a/software/script/chameleon_cmd.py b/software/script/chameleon_cmd.py index 0f793d5..d0b8ccd 100644 --- a/software/script/chameleon_cmd.py +++ b/software/script/chameleon_cmd.py @@ -42,6 +42,37 @@ DATA_CMD_SET_MF1_DETECTION_ENABLE = 5003 DATA_CMD_GET_MF1_DETECTION_COUNT = 5004 DATA_CMD_GET_MF1_DETECTION_RESULT = 5005 +@enum.unique +class SlotNumber(enum.IntEnum): + SLOT_1 = 0, + SLOT_2 = 1, + SLOT_3 = 2, + SLOT_4 = 3, + SLOT_5 = 4, + SLOT_6 = 5, + SLOT_7 = 6, + SLOT_8 = 7, + SLOT_NO = 8, + + @staticmethod + def list(exclude_unknown=True): + enum_list = [] + for name, value in SlotNumber.__members__.items(): + if value == SlotNumber.SLOT_NO: + continue + enum_list.append(int(name.replace('SLOT_',''))) + + return enum_list + + @staticmethod + def fix(index: int): + for name, value in SlotNumber.__members__.items(): + if value == SlotNumber.SLOT_NO: + continue + if index == int(name.replace('SLOT_','')): + return value + + @enum.unique class TagSenseType(enum.IntEnum): @@ -52,6 +83,26 @@ class TagSenseType(enum.IntEnum): # 高频13.56mhz场感应 TAG_SENSE_HF = 2, + @staticmethod + def list(exclude_unknown=True): + enum_list = [] + for name, value in TagSenseType.__members__.items(): + if value == TagSenseType.TAG_SENSE_NO: + continue + enum_list.append(f"{name.replace('TAG_SENSE_','')} = {value}") + + return enum_list + + @staticmethod + def choices(exclude_unknown=True): + choice_list = [] + for name, value in TagSenseType.__members__.items(): + if value == TagSenseType.TAG_SENSE_NO: + continue + choice_list.append(value) + + return choice_list + @enum.unique class TagSpecificType(enum.IntEnum): @@ -267,7 +318,7 @@ class BaseChameleonCMD: data.extend(key) return self.device.send_cmd_sync(DATA_CMD_WRITE_EM410X_TO_T5577, 0x00, data) - def set_slot_activated(self, slot_index): + def set_slot_activated(self, slot_index: SlotNumber): """ 设置当前激活使用的卡槽 :param slot_index: 卡槽索引,从 1 - 8(不是从0下标开始) @@ -276,10 +327,10 @@ class BaseChameleonCMD: if slot_index < 1 or slot_index > 8: raise ValueError("The slot index range error(1-8)") data = bytearray() - data.append(slot_index - 1) + data.append(SlotNumber.fix(slot_index)) return self.device.send_cmd_sync(DATA_CMD_SET_SLOT_ACTIVATED, 0x00, data) - def set_slot_tag_type(self, slot_index: int, tag_type: TagSpecificType): + def set_slot_tag_type(self, slot_index: SlotNumber, tag_type: TagSpecificType): """ 设置当前卡槽的模拟卡的标签类型 注意:此操作并不会更改flash中的数据,flash中的数据的变动仅在下次保存时更新 @@ -290,11 +341,11 @@ class BaseChameleonCMD: if slot_index < 1 or slot_index > 8: raise ValueError("The slot index range error(1-8)") data = bytearray() - data.append(slot_index - 1) + data.append(SlotNumber.fix(slot_index)) data.append(tag_type) return self.device.send_cmd_sync(DATA_CMD_SET_SLOT_TAG_TYPE, 0x00, data) - def set_slot_data_default(self, slot_index: int, tag_type: TagSpecificType): + def set_slot_data_default(self, slot_index: SlotNumber, tag_type: TagSpecificType): """ 设置指定卡槽的模拟卡的数据为缺省数据 注意:此API会将flash中的数据一并进行设置 @@ -305,11 +356,11 @@ class BaseChameleonCMD: if slot_index < 1 or slot_index > 8: raise ValueError("The slot index range error(1-8)") data = bytearray() - data.append(slot_index - 1) + data.append(SlotNumber.fix(slot_index)) data.append(tag_type) return self.device.send_cmd_sync(DATA_CMD_SET_SLOT_DATA_DEFAULT, 0x00, data) - def set_slot_enable(self, slot_index: int, enable: bool): + def set_slot_enable(self, slot_index: SlotNumber, enable: bool): """ 设置指定的卡槽是否使能 :param slot_index: 卡槽号码 @@ -319,7 +370,7 @@ class BaseChameleonCMD: if slot_index < 1 or slot_index > 8: raise ValueError("The slot index range error(1-8)") data = bytearray() - data.append(slot_index - 1) + data.append(SlotNumber.fix(slot_index)) data.append(0x01 if enable else 0x00) return self.device.send_cmd_sync(DATA_CMD_SET_SLOT_ENABLE, 0X00, data) @@ -386,7 +437,7 @@ class BaseChameleonCMD: data.extend(uid) return self.device.send_cmd_sync(DATA_CMD_SET_MF1_ANTI_COLLISION_RES, 0X00, data) - def set_slot_tag_nick_name(self, slot: int, sense_type: int, name: str): + def set_slot_tag_nick_name(self, slot: SlotNumber, sense_type: TagSenseType, name: str): """ 设置MF1的模拟卡的防冲撞资源信息 :param slot: 卡槽号码 @@ -395,11 +446,11 @@ class BaseChameleonCMD: :return: """ data = bytearray() - data.extend([slot, sense_type]) + data.extend([SlotNumber.fix(slot), sense_type]) data.extend(name.encode(encoding="gbk")) return self.device.send_cmd_sync(DATA_CMD_SET_SLOT_TAG_NICK, 0x00, data) - def get_slot_tag_nick_name(self, slot: int, sense_type: int): + def get_slot_tag_nick_name(self, slot: SlotNumber, sense_type: TagSenseType): """ 设置MF1的模拟卡的防冲撞资源信息 :param slot: 卡槽号码 @@ -408,7 +459,7 @@ class BaseChameleonCMD: :return: """ data = bytearray() - data.extend([slot, sense_type]) + data.extend([SlotNumber.fix(slot), sense_type]) return self.device.send_cmd_sync(DATA_CMD_GET_SLOT_TAG_NICK, 0x00, data) def update_slot_data_config(self): From e916e10c66286f2a65e42c3e6006e919f5bae70a Mon Sep 17 00:00:00 2001 From: DXL <64101226@qq.com> Date: Fri, 11 Aug 2023 22:24:57 +0800 Subject: [PATCH 07/28] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 124db27..d46f334 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ Downloading a GUI https://www.youtube.com/watch?v=rHH7iqbX3nY Link to the GUI + https://github.com/GameTec-live/ChameleonUltraGUI # Hardware Pictures From 83811861cc160561ec011643257a0fcc8e63f20c Mon Sep 17 00:00:00 2001 From: Nemanja Nedeljkovic Date: Fri, 11 Aug 2023 18:01:02 +0200 Subject: [PATCH 08/28] Add git version command --- firmware/Makefile.defs | 4 ++++ firmware/application/Makefile | 3 +++ firmware/application/src/app_cmd.c | 8 ++++++++ firmware/application/src/data_cmd.h | 1 + 4 files changed, 16 insertions(+) diff --git a/firmware/Makefile.defs b/firmware/Makefile.defs index 89fec0a..7023b1d 100644 --- a/firmware/Makefile.defs +++ b/firmware/Makefile.defs @@ -22,4 +22,8 @@ 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)" diff --git a/firmware/application/Makefile b/firmware/application/Makefile index f248a1a..9ca868a 100644 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -311,6 +311,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 diff --git a/firmware/application/src/app_cmd.c b/firmware/application/src/app_cmd.c index 2eb7559..c33f50d 100644 --- a/firmware/application/src/app_cmd.c +++ b/firmware/application/src/app_cmd.c @@ -27,6 +27,13 @@ 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) { + uint32_t* version = (uint32_t*)GIT_VERSION; + return data_frame_make(cmd, status, 7, (uint8_t*)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) { @@ -524,6 +531,7 @@ 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_GET_GIT_VERSION, NULL, cmd_processor_get_git_version, NULL }, #if defined(PROJECT_CHAMELEON_ULTRA) diff --git a/firmware/application/src/data_cmd.h b/firmware/application/src/data_cmd.h index e5437ae..9a5e8c8 100644 --- a/firmware/application/src/data_cmd.h +++ b/firmware/application/src/data_cmd.h @@ -20,6 +20,7 @@ #define DATA_CMD_ENTER_BOOTLOADER (1010) #define DATA_CMD_GET_DEVICE_CHIP_ID (1011) #define DATA_CMD_GET_DEVICE_ADDRESS (1012) +#define DATA_CMD_GET_GIT_VERSION (1013) // // ****************************************************************** From ee8990aacd75849b64c1551b8344a4b6f835ab16 Mon Sep 17 00:00:00 2001 From: Augusto Zanellato Date: Fri, 11 Aug 2023 18:55:29 +0200 Subject: [PATCH 09/28] fw git version fixes, client support Fix git version string length handling Add git to docker fw-builder image Add git version command to client Add client support --- firmware/Dockerfile | 3 ++- firmware/application/src/app_cmd.c | 3 +-- software/script/chameleon_cli_main.py | 1 + software/script/chameleon_cli_unit.py | 10 ++++++++++ software/script/chameleon_cmd.py | 6 +++++- 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/firmware/Dockerfile b/firmware/Dockerfile index bc38922..1646b91 100644 --- a/firmware/Dockerfile +++ b/firmware/Dockerfile @@ -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; \ diff --git a/firmware/application/src/app_cmd.c b/firmware/application/src/app_cmd.c index c33f50d..ef48978 100644 --- a/firmware/application/src/app_cmd.c +++ b/firmware/application/src/app_cmd.c @@ -29,8 +29,7 @@ data_frame_tx_t* cmd_processor_get_version(uint16_t cmd, uint16_t status, uint16 data_frame_tx_t* cmd_processor_get_git_version(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { - uint32_t* version = (uint32_t*)GIT_VERSION; - return data_frame_make(cmd, status, 7, (uint8_t*)version); + return data_frame_make(cmd, status, strlen(GIT_VERSION), (uint8_t*)GIT_VERSION); } diff --git a/software/script/chameleon_cli_main.py b/software/script/chameleon_cli_main.py index 83fba87..53289bf 100755 --- a/software/script/chameleon_cli_main.py +++ b/software/script/chameleon_cli_main.py @@ -86,6 +86,7 @@ class ChameleonCLI: 'openall': new_uint(chameleon_cli_unit.HWSlotOpenAll, "Open all slot and set to default data"), 'help': "Emulation tag slot.", }, + 'version': new_uint(chameleon_cli_unit.HWVersion, "Get current device firmware version"), 'dfu': new_uint(chameleon_cli_unit.HWDFU, "Restart application to bootloader mode(Not yet implement dfu)."), 'help': "hardware controller", }, diff --git a/software/script/chameleon_cli_unit.py b/software/script/chameleon_cli_unit.py index 4cb0ded..0a8aabe 100644 --- a/software/script/chameleon_cli_unit.py +++ b/software/script/chameleon_cli_unit.py @@ -253,6 +253,16 @@ class HWAddressGet(DeviceRequiredUnit): def on_exec(self, args: argparse.Namespace): print(f' - Device address: ' + self.cmd_positive.get_device_address()) +class HWVersion(DeviceRequiredUnit): + + def args_parser(self) -> ArgumentParserNoExit or None: + return None + + def on_exec(self, args: argparse.Namespace): + fw_version_int = self.cmd_positive.get_firmware_version() + fw_version = f'v{fw_version_int // 256}.{fw_version_int % 256}' + git_version = self.cmd_positive.get_git_version() + print(f' - Version: {fw_version} ({git_version})') class HF14AScan(ReaderRequiredUint): def args_parser(self) -> ArgumentParserNoExit or None: diff --git a/software/script/chameleon_cmd.py b/software/script/chameleon_cmd.py index 0f793d5..cb32228 100644 --- a/software/script/chameleon_cmd.py +++ b/software/script/chameleon_cmd.py @@ -19,6 +19,7 @@ DATA_CMD_SLOT_DATA_CONFIG_SAVE = 1009 DATA_CMD_ENTER_BOOTLOADER = 1010 DATA_CMD_GET_DEVICE_CHIP_ID = 1011 DATA_CMD_GET_DEVICE_ADDRESS = 1012 +DATA_CMD_GET_GIT_VERSION = 1013 DATA_CMD_SCAN_14A_TAG = 2000 DATA_CMD_MF1_SUPPORT_DETECT = 2001 @@ -108,7 +109,10 @@ class BaseChameleonCMD: """ resp = self.device.send_cmd_sync(DATA_CMD_GET_DEVICE_ADDRESS, 0x00, None) return resp.data[::-1].hex() - + + def get_git_version(self) -> str: + resp = self.device.send_cmd_sync(DATA_CMD_GET_GIT_VERSION, 0x00, None) + return resp.data.decode('utf-8') def is_reader_device_mode(self) -> bool: """ From 6e81b5917e58f9bfe8ecb99989421671e1433eca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Szyma=C5=84ski?= Date: Tue, 15 Aug 2023 22:56:53 +0200 Subject: [PATCH 10/28] Add version field, make it bitfield struct --- firmware/application/src/rfid/nfctag/tag_emulation.h | 3 +-- firmware/application/src/settings.c | 5 ++--- firmware/application/src/settings.h | 12 +++++++----- firmware/common/utils.h | 7 +++++++ 4 files changed, 17 insertions(+), 10 deletions(-) create mode 100644 firmware/common/utils.h diff --git a/firmware/application/src/rfid/nfctag/tag_emulation.h b/firmware/application/src/rfid/nfctag/tag_emulation.h index 1be4573..789424f 100644 --- a/firmware/application/src/rfid/nfctag/tag_emulation.h +++ b/firmware/application/src/rfid/nfctag/tag_emulation.h @@ -5,12 +5,11 @@ #include #include +#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; diff --git a/firmware/application/src/settings.c b/firmware/application/src/settings.c index 52db9bf..73cd281 100644 --- a/firmware/application/src/settings.c +++ b/firmware/application/src/settings.c @@ -53,11 +53,10 @@ uint8_t settings_save_config(void) uint8_t settings_get_animation_config() { - return config & 0x3; + return config.animation_config; } void settings_set_animation_config(uint8_t value) { - config &= ~(0x3); - config |= value; + config.animation_config = value; } diff --git a/firmware/application/src/settings.h b/firmware/application/src/settings.h index a42baa3..b0dcadd 100644 --- a/firmware/application/src/settings.h +++ b/firmware/application/src/settings.h @@ -3,15 +3,17 @@ #include +#include "utils.h" + #define SETTINGS_ANIMATION_FULL 0 #define SETTINGS_ANIMATION_MINIMAL 1 #define SETTINGS_ANIMATION_NONE 2 -/* - * bits [0-1]: animation config - * bits [2-31]: reserved - */ -typedef uint32_t settings_data_t; + +typedef struct ALIGN_U32 { + uint16_t version; + uint16_t animation_config : 2; +} settings_data_t; void settings_load_config(void); uint8_t settings_save_config(void); diff --git a/firmware/common/utils.h b/firmware/common/utils.h new file mode 100644 index 0000000..00ecf46 --- /dev/null +++ b/firmware/common/utils.h @@ -0,0 +1,7 @@ +#ifndef UTILS_H_ +#define UTILS_H_ + +// u32 size align. +#define ALIGN_U32 __attribute__((aligned(4))) + +#endif \ No newline at end of file From 2ed37d9c2a709b69d62dda6a0d86c50b0604308f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Szyma=C5=84ski?= Date: Wed, 16 Aug 2023 01:17:45 +0200 Subject: [PATCH 11/28] Fix log messages --- firmware/application/src/settings.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/firmware/application/src/settings.c b/firmware/application/src/settings.c index 73cd281..eba29b5 100644 --- a/firmware/application/src/settings.c +++ b/firmware/application/src/settings.c @@ -33,19 +33,19 @@ uint8_t settings_save_config(void) uint16_t new_calc_crc; calc_14a_crc_lut((uint8_t *)&config, sizeof(config), (uint8_t *)&new_calc_crc); if (new_calc_crc != m_config_crc) { // Before saving, make sure that the configuration has changed - NRF_LOG_INFO("Save tag slot config start."); + NRF_LOG_INFO("Save config start."); bool ret = fds_write_sync(FDS_SETTINGS_ID, FDS_SETTINGS_KEY, sizeof(config) / 4, (uint8_t *)&config); if (ret) { - NRF_LOG_INFO("Save tag slot config success."); + NRF_LOG_INFO("Save config success."); m_config_crc = new_calc_crc; // store new CRC so we know that we've updated the configuration } else { - NRF_LOG_ERROR("Save tag slot config error."); + NRF_LOG_ERROR("Save config error."); return STATUS_FLASH_WRITE_FAIL; } } else { - NRF_LOG_INFO("Tag slot config no change."); + NRF_LOG_INFO("Config no change."); } return STATUS_DEVICE_SUCCESS; From 707136a241868def2b264e07546aa0045155128f Mon Sep 17 00:00:00 2001 From: Augusto Zanellato Date: Wed, 16 Aug 2023 18:04:06 +0200 Subject: [PATCH 12/28] Add settings init, reset and migration logic Align settings size to uint32_t Add 78 reserved bits to settings Use an enum for animation mode --- firmware/application/src/app_cmd.c | 7 +++ firmware/application/src/app_main.c | 9 ++-- firmware/application/src/data_cmd.h | 5 +- firmware/application/src/settings.c | 71 ++++++++++++++++++++++++--- firmware/application/src/settings.h | 20 +++++--- software/script/chameleon_cli_main.py | 1 + software/script/chameleon_cli_unit.py | 12 +++++ software/script/chameleon_cmd.py | 11 ++++- 8 files changed, 113 insertions(+), 23 deletions(-) diff --git a/firmware/application/src/app_cmd.c b/firmware/application/src/app_cmd.c index 27e2e52..4ea39a0 100644 --- a/firmware/application/src/app_cmd.c +++ b/firmware/application/src/app_cmd.c @@ -86,6 +86,12 @@ data_frame_tx_t* cmd_processor_save_settings(uint16_t cmd, uint16_t status, uint 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]); @@ -546,6 +552,7 @@ static cmd_data_map_t m_data_cmd_map[] = { { 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 }, diff --git a/firmware/application/src/app_main.c b/firmware/application/src/app_main.c index 387bd5e..99a016b 100644 --- a/firmware/application/src/app_main.c +++ b/firmware/application/src/app_main.c @@ -222,7 +222,7 @@ static void system_off_enter(void) { nrf_gpio_pin_clear(p_led_array[i]); } uint8_t animation_config = settings_get_animation_config(); - if (animation_config == SETTINGS_ANIMATION_FULL) { + if (animation_config == SettingsAnimationModeFull) { uint8_t slot = tag_emulation_get_slot(); // Power off animation uint8_t dir = slot > 3 ? 1 : 0; @@ -352,13 +352,12 @@ static void check_wakeup_src(void) { // Button wake-up boot animation uint8_t animation_config = settings_get_animation_config(); - if (animation_config == SETTINGS_ANIMATION_FULL) + if (animation_config == SettingsAnimationModeFull) { ledblink2(color, !dir, 11); ledblink2(color, dir, 11); ledblink2(color, !dir, dir ? slot : 7 - slot); - } - else if (animation_config == SETTINGS_ANIMATION_MINIMAL) { + } else if (animation_config == SettingsAnimationModeMinimal) { ledblink2(color, !dir, dir ? slot : 7 - slot); } @@ -388,7 +387,7 @@ static void check_wakeup_src(void) { TAG_FIELD_LED_ON(); uint8_t animation_config = settings_get_animation_config(); - if (animation_config == SETTINGS_ANIMATION_FULL) { + 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); } diff --git a/firmware/application/src/data_cmd.h b/firmware/application/src/data_cmd.h index 89284f2..a653574 100644 --- a/firmware/application/src/data_cmd.h +++ b/firmware/application/src/data_cmd.h @@ -21,8 +21,9 @@ #define DATA_CMD_GET_DEVICE_CHIP_ID (1011) #define DATA_CMD_GET_DEVICE_ADDRESS (1012) #define DATA_CMD_SAVE_SETTINGS (1013) -#define DATA_CMD_SET_ANIMATION_MODE (1014) -#define DATA_CMD_GET_ANIMATION_MODE (1015) +#define DATA_CMD_RESET_SETTINGS (1014) +#define DATA_CMD_SET_ANIMATION_MODE (1015) +#define DATA_CMD_GET_ANIMATION_MODE (1016) // // ****************************************************************** diff --git a/firmware/application/src/settings.c b/firmware/application/src/settings.c index eba29b5..944060c 100644 --- a/firmware/application/src/settings.c +++ b/firmware/application/src/settings.c @@ -15,29 +15,84 @@ 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_ID, FDS_SETTINGS_KEY, sizeof(config), (uint8_t *)&config); if (ret) { - // 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 - calc_14a_crc_lut((uint8_t *)&config, sizeof(config), (uint8_t *)&m_config_crc); 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_INFO("config no exists."); + 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 - uint16_t new_calc_crc; - calc_14a_crc_lut((uint8_t *)&config, sizeof(config), (uint8_t *)&new_calc_crc); - if (new_calc_crc != m_config_crc) { // Before saving, make sure that the configuration has changed + 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_ID, FDS_SETTINGS_KEY, sizeof(config) / 4, (uint8_t *)&config); if (ret) { NRF_LOG_INFO("Save config success."); - m_config_crc = new_calc_crc; // store new CRC so we know that we've updated the configuration + update_config_crc(); } else { @@ -45,7 +100,7 @@ uint8_t settings_save_config(void) return STATUS_FLASH_WRITE_FAIL; } } else { - NRF_LOG_INFO("Config no change."); + NRF_LOG_INFO("Config did not change."); } return STATUS_DEVICE_SUCCESS; diff --git a/firmware/application/src/settings.h b/firmware/application/src/settings.h index b0dcadd..d8cf545 100644 --- a/firmware/application/src/settings.h +++ b/firmware/application/src/settings.h @@ -5,19 +5,27 @@ #include "utils.h" -#define SETTINGS_ANIMATION_FULL 0 -#define SETTINGS_ANIMATION_MINIMAL 1 -#define SETTINGS_ANIMATION_NONE 2 +#define SETTINGS_CURRENT_VERSION 1 +typedef enum { + SettingsAnimationModeFull = 0, + SettingsAnimationModeMinimal = 1, + SettingsAnimationModeNone = 2, +} settings_animation_mode_t; typedef struct ALIGN_U32 { uint16_t version; - uint16_t animation_config : 2; + 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(); +uint8_t settings_get_animation_config(void); void settings_set_animation_config(uint8_t value); -#endif \ No newline at end of file +#endif diff --git a/software/script/chameleon_cli_main.py b/software/script/chameleon_cli_main.py index 212fa34..c3bc0aa 100755 --- a/software/script/chameleon_cli_main.py +++ b/software/script/chameleon_cli_main.py @@ -94,6 +94,7 @@ class ChameleonCLI: 'help': 'Manage wake-up and sleep animation mode' }, 'store': new_uint(chameleon_cli_unit.HWSettingsStore, "Store current settings to flash"), + 'reset': new_uint(chameleon_cli_unit.HWSettingsReset, "Reset settings to default values"), 'help': "Chameleon settings management" }, 'help': "hardware controller", diff --git a/software/script/chameleon_cli_unit.py b/software/script/chameleon_cli_unit.py index aec53f8..378c922 100644 --- a/software/script/chameleon_cli_unit.py +++ b/software/script/chameleon_cli_unit.py @@ -1032,3 +1032,15 @@ class HWSettingsStore(DeviceRequiredUnit): print(" - Store success @.@~") else: print(" - Store failed") + +class HWSettingsReset(DeviceRequiredUnit): + def args_parser(self) -> ArgumentParserNoExit or None: + return None + + def on_exec(self, args: argparse.Namespace): + print("Initializing settings...") + resp: chameleon_com.Response = self.cmd_standard.reset_settings() + if resp.status == chameleon_status.Device.STATUS_DEVICE_SUCCESS: + print(" - Reset success @.@~") + else: + print(" - Reset failed") diff --git a/software/script/chameleon_cmd.py b/software/script/chameleon_cmd.py index 924ff33..ab9e94a 100644 --- a/software/script/chameleon_cmd.py +++ b/software/script/chameleon_cmd.py @@ -21,8 +21,9 @@ DATA_CMD_GET_DEVICE_CHIP_ID = 1011 DATA_CMD_GET_DEVICE_ADDRESS = 1012 DATA_CMD_SAVE_SETTINGS = 1013 -DATA_CMD_SET_ANIMATION_MODE = 1014 -DATA_CMD_GET_ANIMATION_MODE = 1015 +DATA_CMD_RESET_SETTINGS = 1014 +DATA_CMD_SET_ANIMATION_MODE = 1015 +DATA_CMD_GET_ANIMATION_MODE = 1016 DATA_CMD_SCAN_14A_TAG = 2000 DATA_CMD_MF1_SUPPORT_DETECT = 2001 @@ -441,6 +442,12 @@ class BaseChameleonCMD: """ return self.device.send_cmd_sync(DATA_CMD_SET_ANIMATION_MODE, 0x00, bytearray([value])) + def reset_settings(self): + """ + Reset settings stored in flash memory + """ + return self.device.send_cmd_sync(DATA_CMD_RESET_SETTINGS, 0x00) + def store_settings(self): """ Store settings to flash memory From b0233538b0c59d989306bc38a8567e69b46947c1 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 16 Aug 2023 20:14:57 +0200 Subject: [PATCH 13/28] little fix for mode 2 to light up the slot LED on button press --- firmware/application/src/app_main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/firmware/application/src/app_main.c b/firmware/application/src/app_main.c index 99a016b..1e92c1b 100644 --- a/firmware/application/src/app_main.c +++ b/firmware/application/src/app_main.c @@ -359,6 +359,8 @@ static void check_wakeup_src(void) { 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 From e3e6b63117af1586fb1b5a2389e3adb1fbd6d52b Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 16 Aug 2023 19:07:00 +0200 Subject: [PATCH 14/28] Force tag_specific_type_t enum to be 32b and allocate banks so size and mapping won't change when we add new types --- firmware/application/src/rfid/nfctag/tag_base_type.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/firmware/application/src/rfid/nfctag/tag_base_type.h b/firmware/application/src/rfid/nfctag/tag_base_type.h index 224b1e2..0f28bd7 100644 --- a/firmware/application/src/rfid/nfctag/tag_base_type.h +++ b/firmware/application/src/rfid/nfctag/tag_base_type.h @@ -22,14 +22,14 @@ typedef enum { // 特定的且必须存在的标志不存在的类型 TAG_TYPE_UNKNOWN, // 125khz(ID卡)系列 - TAG_TYPE_EM410X, + TAG_TYPE_EM410X = 0x10000, // Mifare系列 - TAG_TYPE_MIFARE_Mini, + TAG_TYPE_MIFARE_Mini = 0x20000, TAG_TYPE_MIFARE_1024, TAG_TYPE_MIFARE_2048, TAG_TYPE_MIFARE_4096, // NTAG系列 - TAG_TYPE_NTAG_213, + TAG_TYPE_NTAG_213 = 0x20100, TAG_TYPE_NTAG_215, TAG_TYPE_NTAG_216, } tag_specific_type_t; From 5afd3332bdf314901b22c604a336120c47d49a0e Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 16 Aug 2023 23:20:42 +0200 Subject: [PATCH 15/28] Suppress GCC 12 linker warnings about missing stubs --- firmware/application/Makefile | 1 + firmware/bootloader/Makefile | 1 + firmware/common/libc_nano_stubs.c | 51 +++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 firmware/common/libc_nano_stubs.c diff --git a/firmware/application/Makefile b/firmware/application/Makefile index f248a1a..6027cd6 100644 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -7,6 +7,7 @@ $(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 \ diff --git a/firmware/bootloader/Makefile b/firmware/bootloader/Makefile index 8086414..d2cdba7 100644 --- a/firmware/bootloader/Makefile +++ b/firmware/bootloader/Makefile @@ -10,6 +10,7 @@ SRC_FILES += \ $(PROJ_DIR)/main.c \ $(PROJ_DIR)/dfu_public_key.c \ $(SRC_COMMON)/hw_connect.c \ + $(SRC_COMMON)/libc_nano_stubs.c \ $(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_clock.c \ $(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_power.c \ $(SDK_ROOT)/modules/nrfx/drivers/src/nrfx_systick.c \ diff --git a/firmware/common/libc_nano_stubs.c b/firmware/common/libc_nano_stubs.c new file mode 100644 index 0000000..0558de5 --- /dev/null +++ b/firmware/common/libc_nano_stubs.c @@ -0,0 +1,51 @@ +/* +Flag --specs=nano.specs forces linking against libc_nano which contains .gnu.warnings since GCC 11.3 like: + arm-gnu-toolchain-12.2.rel1-x86_64-arm-none-eabi/arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc_nano.a(libc_a-closer.o): in function `_close_r': + closer.c:(.text._close_r+0xc): warning: _close is not implemented and will always fail +So we are providing stubs to suppress these warnings +See also https://stackoverflow.com/questions/73742774/gcc-arm-none-eabi-11-3-is-not-implemented-and-will-always-fail +*/ + +#include +#include +#undef errno +extern int errno; + +int _close(int file) { + errno = EINVAL; + return -1; +} + +int _fstat(int file, struct stat *st) { + errno = EINVAL; + return -1; +} + +int _getpid(void) { + return 1; +} + +int _isatty(int file) { + errno = EINVAL; + return 0; +} + +int _kill(int pid, int sig) { + errno = EINVAL; + return -1; +} + +int _lseek(int file, int ptr, int dir) { + errno = EINVAL; + return -1; +} + +int _read(int file, char *ptr, int len) { + errno = EINVAL; + return -1; +} + +int _write(int file, char *ptr, int len) { + errno = EINVAL; + return -1; +} From 92a3f0966f1b12972479661524873d651d1baa9b Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 16 Aug 2023 23:21:13 +0200 Subject: [PATCH 16/28] suppress GCC warnings in nRF SDK and restore -Warray-bounds and -Wsizeof-array-div --- firmware/application/Makefile | 9 ++++----- firmware/bootloader/Makefile | 11 +++++++++-- .../libraries/experimental_section_vars/nrf_section.h | 2 ++ firmware/nrf52_sdk/modules/nrfx/hal/nrf_pwm.h | 4 ++++ 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/firmware/application/Makefile b/firmware/application/Makefile index 6027cd6..1cb7d19 100644 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -367,14 +367,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))) diff --git a/firmware/bootloader/Makefile b/firmware/bootloader/Makefile index d2cdba7..e88f044 100644 --- a/firmware/bootloader/Makefile +++ b/firmware/bootloader/Makefile @@ -198,8 +198,6 @@ CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 # keep every function in a separate section, this allows linker to discard unused ones CFLAGS += -ffunction-sections -fdata-sections -fno-strict-aliasing CFLAGS += -fno-builtin -fshort-enums -# fix newer compilator versions -CFLAGS += -Wno-error=array-bounds # C++ flags common to all targets CXXFLAGS += $(OPT) @@ -254,6 +252,15 @@ TEMPLATE_PATH := $(SDK_ROOT)/components/toolchain/gcc 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) +ifeq ($(shell expr $(CC_VERSION) \>= 12), 1) + # avoid a couple of false warnings in nRF SDK + CFLAGS += --param=min-pagesize=0 +endif + $(foreach target, $(TARGETS), $(call define_target, $(target))) .PHONY: flash flash_softdevice erase diff --git a/firmware/nrf52_sdk/components/libraries/experimental_section_vars/nrf_section.h b/firmware/nrf52_sdk/components/libraries/experimental_section_vars/nrf_section.h index 1549930..fb0f15d 100644 --- a/firmware/nrf52_sdk/components/libraries/experimental_section_vars/nrf_section.h +++ b/firmware/nrf52_sdk/components/libraries/experimental_section_vars/nrf_section.h @@ -41,6 +41,8 @@ #define NRF_SECTION_H__ #include "nordic_common.h" +// ChameleonUltra: nRF SDK produces a number of GCC warnings due to its NRF_SECTION macros and we want to ignore them +#pragma GCC diagnostic ignored "-Warray-bounds" #ifdef __cplusplus extern "C" { diff --git a/firmware/nrf52_sdk/modules/nrfx/hal/nrf_pwm.h b/firmware/nrf52_sdk/modules/nrfx/hal/nrf_pwm.h index 35567b6..87b5cf9 100644 --- a/firmware/nrf52_sdk/modules/nrfx/hal/nrf_pwm.h +++ b/firmware/nrf52_sdk/modules/nrfx/hal/nrf_pwm.h @@ -64,6 +64,10 @@ extern "C" { /** @brief Number of channels in each PWM instance. */ #define NRF_PWM_CHANNEL_COUNT 4 +// ChameleonUltra: nRF SDK produces a wrong GCC warning as the following macro is not meant to give an array size +#if __GNUC__ >= 12 +#pragma GCC diagnostic ignored "-Wsizeof-array-div" +#endif /** * @brief Helper macro for calculating the number of 16-bit values in the specified * array of duty cycle values. From c6d95f34f7d5bedab6157417ccf96cc72d255264 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 17 Aug 2023 00:14:11 +0200 Subject: [PATCH 17/28] Revert "Force tag_specific_type_t enum to be 32b and allocate banks so size and mapping won't change when we add new types" This reverts commit e3e6b63117af1586fb1b5a2389e3adb1fbd6d52b. --- firmware/application/src/rfid/nfctag/tag_base_type.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/firmware/application/src/rfid/nfctag/tag_base_type.h b/firmware/application/src/rfid/nfctag/tag_base_type.h index 0f28bd7..224b1e2 100644 --- a/firmware/application/src/rfid/nfctag/tag_base_type.h +++ b/firmware/application/src/rfid/nfctag/tag_base_type.h @@ -22,14 +22,14 @@ typedef enum { // 特定的且必须存在的标志不存在的类型 TAG_TYPE_UNKNOWN, // 125khz(ID卡)系列 - TAG_TYPE_EM410X = 0x10000, + TAG_TYPE_EM410X, // Mifare系列 - TAG_TYPE_MIFARE_Mini = 0x20000, + TAG_TYPE_MIFARE_Mini, TAG_TYPE_MIFARE_1024, TAG_TYPE_MIFARE_2048, TAG_TYPE_MIFARE_4096, // NTAG系列 - TAG_TYPE_NTAG_213 = 0x20100, + TAG_TYPE_NTAG_213, TAG_TYPE_NTAG_215, TAG_TYPE_NTAG_216, } tag_specific_type_t; From 997f58d0d0a6d12861eeae0150a3f7f03ba8eddb Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 17 Aug 2023 04:00:47 +0200 Subject: [PATCH 18/28] Fix FDS records conflicts (dumps/nicks/settings overwriting each other) --- .../src/rfid/nfctag/tag_emulation.c | 4 +- .../src/rfid/nfctag/tag_persistence.c | 29 ++++------- firmware/application/src/settings.c | 4 +- firmware/application/src/utils/fds_ids.h | 48 +++++++++++-------- 4 files changed, 41 insertions(+), 44 deletions(-) diff --git a/firmware/application/src/rfid/nfctag/tag_emulation.c b/firmware/application/src/rfid/nfctag/tag_emulation.c index 849cd03..b65da99 100644 --- a/firmware/application/src/rfid/nfctag/tag_emulation.c +++ b/firmware/application/src/rfid/nfctag/tag_emulation.c @@ -384,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); @@ -403,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 { diff --git a/firmware/application/src/rfid/nfctag/tag_persistence.c b/firmware/application/src/rfid/nfctag/tag_persistence.c index 4997be2..dbfa15e 100644 --- a/firmware/application/src/rfid/nfctag/tag_persistence.c +++ b/firmware/application/src/rfid/nfctag/tag_persistence.c @@ -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); } diff --git a/firmware/application/src/settings.c b/firmware/application/src/settings.c index 944060c..aa76743 100644 --- a/firmware/application/src/settings.c +++ b/firmware/application/src/settings.c @@ -62,7 +62,7 @@ void settings_migrate(void) void settings_load_config(void) { - bool ret = fds_read_sync(FDS_SETTINGS_ID, FDS_SETTINGS_KEY, sizeof(config), (uint8_t *)&config); + 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 @@ -89,7 +89,7 @@ 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_ID, FDS_SETTINGS_KEY, sizeof(config) / 4, (uint8_t *)&config); + 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(); diff --git a/firmware/application/src/utils/fds_ids.h b/firmware/application/src/utils/fds_ids.h index ca11e2e..eb8e86b 100644 --- a/firmware/application/src/utils/fds_ids.h +++ b/firmware/application/src/utils/fds_ids.h @@ -2,29 +2,37 @@ #define FDS_IDS_H /* - * 卡槽配置,只有一份,一致即可 + * Card slot configuration, only one, consistent */ -#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 +#define FDS_EMULATION_CONFIG_FILE_ID 0x1000 +#define FDS_EMULATION_CONFIG_RECORD_KEY 0x1 /* * Slot for settings like LED animation mode and future options */ -#define FDS_SETTINGS_KEY 0x1069 -#define FDS_SETTINGS_ID 0x1069 +#define FDS_SETTINGS_FILE_ID 0x1001 +#define FDS_SETTINGS_RECORD_KEY 0x1 -#endif \ No newline at end of file +/* + * Each card slot has two types of data, high and low frequency + * FDS file ID follows the card slot, starting from 0x1100 to 0x1107 + * FDS record key mirrors TAG_SENSE_LF/HF so is 1 for LF, 2 for HF (currently) + */ +#define FDS_SLOT_TAG_DUMP_FILE_ID_BASE 0x1100 + +/* + * Each card slot has two types of data, high and low frequency, so it can get two names + * FDS file ID follows the card slot, starting from 0x1200 to 0x1207 + * FDS record key mirrors TAG_SENSE_LF/HF so is 1 for LF, 2 for HF (currently) + */ +#define FDS_SLOT_TAG_NICK_NAME_FILE_ID_BASE 0x1200 + +// Note that previously assigned records may need to be cleaned from Flash. +// Taking into account the possible overlaps, it boils down to +// ID 0x1066 Keys 0x1066 +// ID 0x1067 Keys 0x1067-0x106e +// ID 0x1068 Keys 0x1067-0x106f +// ID 0x1069 Keys 0x1068-0x1070 + + +#endif From 7e7abc50eae61caa4a432f16cabc2ce34710cec6 Mon Sep 17 00:00:00 2001 From: Sgnusov Date: Thu, 17 Aug 2023 11:13:28 +0000 Subject: [PATCH 19/28] Fix data sanity check --- firmware/application/src/app_cmd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firmware/application/src/app_cmd.c b/firmware/application/src/app_cmd.c index 4ea39a0..f143de5 100644 --- a/firmware/application/src/app_cmd.c +++ b/firmware/application/src/app_cmd.c @@ -407,13 +407,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); } From 913c1540e32250f6505dbe6f98c95b20797800eb Mon Sep 17 00:00:00 2001 From: Foxushka <135865149+Foxushka@users.noreply.github.com> Date: Thu, 17 Aug 2023 21:48:49 +0300 Subject: [PATCH 20/28] Implement "hw slot info" to show which tag type loaded into all slots As suggested by @augustozanellato Fix input text disapperance in some cases Show selected slot Space --- firmware/application/src/app_cmd.c | 19 +++++++++++++ firmware/application/src/data_cmd.h | 2 ++ software/script/chameleon_cli_main.py | 4 +-- software/script/chameleon_cli_unit.py | 12 ++++++++ software/script/chameleon_cmd.py | 40 ++++++++++++++++++++++++++- 5 files changed, 74 insertions(+), 3 deletions(-) diff --git a/firmware/application/src/app_cmd.c b/firmware/application/src/app_cmd.c index 1ab2e93..99c7d01 100644 --- a/firmware/application/src/app_cmd.c +++ b/firmware/application/src/app_cmd.c @@ -340,6 +340,23 @@ 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_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); @@ -588,6 +605,8 @@ 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_SET_EM410X_EMU_ID, NULL, cmd_processor_set_em410x_emu_id, NULL }, diff --git a/firmware/application/src/data_cmd.h b/firmware/application/src/data_cmd.h index e906e6e..32803cf 100644 --- a/firmware/application/src/data_cmd.h +++ b/firmware/application/src/data_cmd.h @@ -25,6 +25,8 @@ #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) // // ****************************************************************** diff --git a/software/script/chameleon_cli_main.py b/software/script/chameleon_cli_main.py index cfb39b1..5241e90 100755 --- a/software/script/chameleon_cli_main.py +++ b/software/script/chameleon_cli_main.py @@ -73,6 +73,7 @@ class ChameleonCLI: 'help': "Device mode get/set" }, 'slot': { + 'info': new_uint(chameleon_cli_unit.HWSlotInfo, "Get information about slots"), 'change': new_uint(chameleon_cli_unit.HWSlotSet, "Set emulation tag slot activated."), 'type': new_uint(chameleon_cli_unit.HWSlotTagType, "Set emulation tag type"), 'init': new_uint(chameleon_cli_unit.HWSlotDataDefault, "Set emulation tag data to default"), @@ -174,9 +175,8 @@ class ChameleonCLI: while True: # wait user input status = f"{colorama.Fore.GREEN}USB" if self.device_com.isOpen() else f"{colorama.Fore.RED}Offline" - print(f"[{status}{colorama.Style.RESET_ALL}] chameleon --> ", end="") try: - cmd_str = input().strip() + cmd_str = input(f"[{status}{colorama.Style.RESET_ALL}] chameleon --> ").strip() except EOFError: print("") closing = True diff --git a/software/script/chameleon_cli_unit.py b/software/script/chameleon_cli_unit.py index cfad334..15f056d 100644 --- a/software/script/chameleon_cli_unit.py +++ b/software/script/chameleon_cli_unit.py @@ -818,6 +818,18 @@ class SenseTypeRequireUint(DeviceRequiredUnit): help="Sense type", metavar="number", choices=slot_choices) return parser +class HWSlotInfo(DeviceRequiredUnit): + def args_parser(self) -> ArgumentParserNoExit or None: + return + + # hw slot info + def on_exec(self, args: argparse.Namespace): + data = self.cmd_positive.get_slot_info().data + selected = self.cmd_positive.get_active_slot().data[0] + for slot in range(8): + print(f' - Slot {slot + 1} data{" (active)" if slot == selected else ""}:') + print(f' HF: {chameleon_cmd.TagSpecificType(data[slot * 2])}') + print(f' LF: {chameleon_cmd.TagSpecificType(data[slot * 2 + 1])}') class HWSlotSet(SlotIndexRequireUint): diff --git a/software/script/chameleon_cmd.py b/software/script/chameleon_cmd.py index d046bad..391f605 100644 --- a/software/script/chameleon_cmd.py +++ b/software/script/chameleon_cmd.py @@ -19,13 +19,17 @@ DATA_CMD_SLOT_DATA_CONFIG_SAVE = 1009 DATA_CMD_ENTER_BOOTLOADER = 1010 DATA_CMD_GET_DEVICE_CHIP_ID = 1011 DATA_CMD_GET_DEVICE_ADDRESS = 1012 -DATA_CMD_GET_GIT_VERSION = 1017 DATA_CMD_SAVE_SETTINGS = 1013 DATA_CMD_RESET_SETTINGS = 1014 DATA_CMD_SET_ANIMATION_MODE = 1015 DATA_CMD_GET_ANIMATION_MODE = 1016 +DATA_CMD_GET_GIT_VERSION = 1017 + +DATA_CMD_GET_ACTIVE_SLOT = 1018 +DATA_CMD_GET_SLOT_INFO = 1019 + DATA_CMD_SCAN_14A_TAG = 2000 DATA_CMD_MF1_SUPPORT_DETECT = 2001 DATA_CMD_MF1_NT_LEVEL_DETECT = 2002 @@ -82,6 +86,26 @@ class TagSpecificType(enum.IntEnum): enum_list.remove(TagSpecificType.TAG_TYPE_UNKNOWN) return enum_list + def __str__(self): + if self.value == TagSpecificType.TAG_TYPE_EM410X: + return "EM410X" + elif self.value == TagSpecificType.TAG_TYPE_MIFARE_Mini: + return "Mifare Mini" + elif self.value == TagSpecificType.TAG_TYPE_MIFARE_1024: + return "Mifare Classic 1k" + elif self.value == TagSpecificType.TAG_TYPE_MIFARE_2048: + return "Mifare Classic 2k" + elif self.value == TagSpecificType.TAG_TYPE_MIFARE_4096: + return "Mifare Classic 4k" + elif self.value == TagSpecificType.TAG_TYPE_NTAG_213: + return "NTAG 213" + elif self.value == TagSpecificType.TAG_TYPE_NTAG_215: + return "NTAG 215" + elif self.value == TagSpecificType.TAG_TYPE_NTAG_216: + return "NTAG 216" + return "Unknown" + + class BaseChameleonCMD: """ @@ -276,6 +300,20 @@ class BaseChameleonCMD: data.extend(key) return self.device.send_cmd_sync(DATA_CMD_WRITE_EM410X_TO_T5577, 0x00, data) + def get_slot_info(self): + """ + Get slots info + :return: + """ + return self.device.send_cmd_sync(DATA_CMD_GET_SLOT_INFO, 0x00, None) + + def get_active_slot(self): + """ + Get selected slot + :return: + """ + return self.device.send_cmd_sync(DATA_CMD_GET_ACTIVE_SLOT, 0x00, None) + def set_slot_activated(self, slot_index): """ 设置当前激活使用的卡槽 From 828d88c273da5e5d194f5823646e0ea685fe49e0 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 18 Aug 2023 17:47:44 +0200 Subject: [PATCH 21/28] Several changes on TagSenseType, TagSpecificType and SlotNumber: * SlotNumber values range from 1 to 8 rather than from 0 to 7 this allows more straightforward usage as ppl can use equivalently SLOT_1 or 1. * SlotNumber.fix -> .to_fw, and add .from_fw * removed unnecessary SLOT_NO * More straightforward use of enums, no need for .value, .__members__, name.replace() etc * Unify usage between TagSenseType and TagSpecificType * Add str representations for TagSenseType * Fixed TagSpecificType related help (e.g. in hw slot type -h) * Removed some redundant error raise * Note: iterations can be done with `for slot in chameleon_cmd.SlotNumber:` --- software/script/chameleon_cli_unit.py | 41 +++++----- software/script/chameleon_cmd.py | 106 +++++++++++--------------- 2 files changed, 67 insertions(+), 80 deletions(-) diff --git a/software/script/chameleon_cli_unit.py b/software/script/chameleon_cli_unit.py index 7783c33..cb135d6 100644 --- a/software/script/chameleon_cli_unit.py +++ b/software/script/chameleon_cli_unit.py @@ -798,7 +798,7 @@ class SlotIndexRequireUint(DeviceRequiredUnit): @staticmethod def add_slot_args(parser: ArgumentParserNoExit): - slot_choices = chameleon_cmd.SlotNumber.list() + slot_choices = [x.value for x in chameleon_cmd.SlotNumber] help_str = f"Slot Indexes: {slot_choices}" parser.add_argument('-s', "--slot", type=int, required=True, @@ -815,14 +815,19 @@ class SenseTypeRequireUint(DeviceRequiredUnit): @staticmethod def add_sense_type_args(parser: ArgumentParserNoExit): - slot_list = chameleon_cmd.TagSenseType.list() - slot_choices = chameleon_cmd.TagSenseType.choices() - help_str = f"Sense Types: {slot_list}" - + sense_choices = chameleon_cmd.TagSenseType.list() + + help_str = "" + for s in chameleon_cmd.TagSenseType: + if s == chameleon_cmd.TagSenseType.TAG_SENSE_NO: + continue + help_str += f"{s.value} = {s}, " + parser.add_argument('-st', "--sense_type", type=int, required=True, - help=help_str, metavar="number", choices=slot_choices) + help=help_str, metavar="number", choices=sense_choices) return parser + class HWSlotInfo(DeviceRequiredUnit): def args_parser(self) -> ArgumentParserNoExit or None: return @@ -830,11 +835,11 @@ class HWSlotInfo(DeviceRequiredUnit): # hw slot info def on_exec(self, args: argparse.Namespace): data = self.cmd_positive.get_slot_info().data - selected = self.cmd_positive.get_active_slot().data[0] - for slot in range(8): - print(f' - Slot {slot + 1} data{" (active)" if slot == selected else ""}:') - print(f' HF: {chameleon_cmd.TagSpecificType(data[slot * 2])}') - print(f' LF: {chameleon_cmd.TagSpecificType(data[slot * 2 + 1])}') + selected = chameleon_cmd.SlotNumber.from_fw(self.cmd_positive.get_active_slot().data[0]) + for slot in chameleon_cmd.SlotNumber: + print(f' - Slot {slot} data{" (active)" if slot == selected else ""}:') + print(f' HF: {chameleon_cmd.TagSpecificType(data[chameleon_cmd.SlotNumber.to_fw(slot) * 2])}') + print(f' LF: {chameleon_cmd.TagSpecificType(data[chameleon_cmd.SlotNumber.to_fw(slot) * 2 + 1])}') class HWSlotSet(SlotIndexRequireUint): @@ -855,10 +860,10 @@ class TagTypeRequiredUint(DeviceRequiredUnit): def add_type_args(parser: ArgumentParserNoExit): type_choices = chameleon_cmd.TagSpecificType.list() help_str = "" - for name, value in chameleon_cmd.TagSpecificType.__members__.items(): - if value == chameleon_cmd.TagSpecificType.TAG_TYPE_UNKNOWN: + for t in chameleon_cmd.TagSpecificType: + if t == chameleon_cmd.TagSpecificType.TAG_TYPE_UNKNOWN: continue - help_str += f"{value} = {name.replace('TAG_TYPE_', '')}, " + help_str += f"{t.value} = {t}, " parser.add_argument('-t', "--type", type=int, required=True, help=help_str, metavar="number", choices=type_choices) return parser @@ -990,8 +995,8 @@ class HWSlotOpenAll(DeviceRequiredUnit): lf_type = chameleon_cmd.TagSpecificType.TAG_TYPE_EM410X # set all slot - for slot in range(1,9): - print(f' Slot{slot} setting...') + for slot in chameleon_cmd.SlotNumber: + print(f' Slot {slot} setting...') # first to set tag type self.cmd_positive.set_slot_tag_type(slot, hf_type) self.cmd_positive.set_slot_tag_type(slot, lf_type) @@ -1000,11 +1005,11 @@ class HWSlotOpenAll(DeviceRequiredUnit): self.cmd_positive.set_slot_data_default(slot, lf_type) # finally, we can enable this slot. self.cmd_positive.set_slot_enable(slot, True) - print(f' Open slot{slot} finish') + print(f' Slot {slot} setting done.') # update config and save to flash self.cmd_positive.update_slot_data_config() - print(f' - Open all slot and set data to default success.') + print(f' - Succeeded opening all slots and setting data to default.') class HWDFU(DeviceRequiredUnit): diff --git a/software/script/chameleon_cmd.py b/software/script/chameleon_cmd.py index 38d7feb..1e964b0 100644 --- a/software/script/chameleon_cmd.py +++ b/software/script/chameleon_cmd.py @@ -54,34 +54,24 @@ DATA_CMD_GET_MF1_DETECTION_RESULT = 5005 @enum.unique class SlotNumber(enum.IntEnum): - SLOT_1 = 0, - SLOT_2 = 1, - SLOT_3 = 2, - SLOT_4 = 3, - SLOT_5 = 4, - SLOT_6 = 5, - SLOT_7 = 6, - SLOT_8 = 7, - SLOT_NO = 8, + SLOT_1 = 1, + SLOT_2 = 2, + SLOT_3 = 3, + SLOT_4 = 4, + SLOT_5 = 5, + SLOT_6 = 6, + SLOT_7 = 7, + SLOT_8 = 8, @staticmethod - def list(exclude_unknown=True): - enum_list = [] - for name, value in SlotNumber.__members__.items(): - if value == SlotNumber.SLOT_NO: - continue - enum_list.append(int(name.replace('SLOT_',''))) - - return enum_list + def to_fw(index: int): # can be int or SlotNumber + # SlotNumber() will raise error for us if index not in slot range + return SlotNumber(index).value - 1 @staticmethod - def fix(index: int): - for name, value in SlotNumber.__members__.items(): - if value == SlotNumber.SLOT_NO: - continue - if index == int(name.replace('SLOT_','')): - return value - + def from_fw(index: int): + # SlotNumber() will raise error for us if index not in fw range + return SlotNumber(index + 1) @enum.unique @@ -93,26 +83,20 @@ class TagSenseType(enum.IntEnum): # 高频13.56mhz场感应 TAG_SENSE_HF = 2, + @staticmethod def list(exclude_unknown=True): - enum_list = [] - for name, value in TagSenseType.__members__.items(): - if value == TagSenseType.TAG_SENSE_NO: - continue - enum_list.append(f"{name.replace('TAG_SENSE_','')} = {value}") - + enum_list = list(map(int, TagSenseType)) + if exclude_unknown: + enum_list.remove(TagSenseType.TAG_SENSE_NO) return enum_list - - @staticmethod - def choices(exclude_unknown=True): - choice_list = [] - for name, value in TagSenseType.__members__.items(): - if value == TagSenseType.TAG_SENSE_NO: - continue - choice_list.append(value) - - return choice_list + def __str__(self): + if self == TagSenseType.TAG_SENSE_LF: + return "LF" + elif self == TagSenseType.TAG_SENSE_HF: + return "HF" + return "None" @enum.unique class TagSpecificType(enum.IntEnum): @@ -138,21 +122,21 @@ class TagSpecificType(enum.IntEnum): return enum_list def __str__(self): - if self.value == TagSpecificType.TAG_TYPE_EM410X: + if self == TagSpecificType.TAG_TYPE_EM410X: return "EM410X" - elif self.value == TagSpecificType.TAG_TYPE_MIFARE_Mini: + elif self == TagSpecificType.TAG_TYPE_MIFARE_Mini: return "Mifare Mini" - elif self.value == TagSpecificType.TAG_TYPE_MIFARE_1024: + elif self == TagSpecificType.TAG_TYPE_MIFARE_1024: return "Mifare Classic 1k" - elif self.value == TagSpecificType.TAG_TYPE_MIFARE_2048: + elif self == TagSpecificType.TAG_TYPE_MIFARE_2048: return "Mifare Classic 2k" - elif self.value == TagSpecificType.TAG_TYPE_MIFARE_4096: + elif self == TagSpecificType.TAG_TYPE_MIFARE_4096: return "Mifare Classic 4k" - elif self.value == TagSpecificType.TAG_TYPE_NTAG_213: + elif self == TagSpecificType.TAG_TYPE_NTAG_213: return "NTAG 213" - elif self.value == TagSpecificType.TAG_TYPE_NTAG_215: + elif self == TagSpecificType.TAG_TYPE_NTAG_215: return "NTAG 215" - elif self.value == TagSpecificType.TAG_TYPE_NTAG_216: + elif self == TagSpecificType.TAG_TYPE_NTAG_216: return "NTAG 216" return "Unknown" @@ -371,10 +355,9 @@ class BaseChameleonCMD: :param slot_index: 卡槽索引,从 1 - 8(不是从0下标开始) :return: """ - if slot_index < 1 or slot_index > 8: - raise ValueError("The slot index range error(1-8)") + # SlotNumber() will raise error for us if slot_index not in slot range data = bytearray() - data.append(SlotNumber.fix(slot_index)) + data.append(SlotNumber.to_fw(slot_index)) return self.device.send_cmd_sync(DATA_CMD_SET_SLOT_ACTIVATED, 0x00, data) def set_slot_tag_type(self, slot_index: SlotNumber, tag_type: TagSpecificType): @@ -385,10 +368,9 @@ class BaseChameleonCMD: :param tag_type: 标签类型 :return: """ - if slot_index < 1 or slot_index > 8: - raise ValueError("The slot index range error(1-8)") + # SlotNumber() will raise error for us if slot_index not in slot range data = bytearray() - data.append(SlotNumber.fix(slot_index)) + data.append(SlotNumber.to_fw(slot_index)) data.append(tag_type) return self.device.send_cmd_sync(DATA_CMD_SET_SLOT_TAG_TYPE, 0x00, data) @@ -400,10 +382,9 @@ class BaseChameleonCMD: :param tag_type: 要设置的缺省标签类型 :return: """ - if slot_index < 1 or slot_index > 8: - raise ValueError("The slot index range error(1-8)") + # SlotNumber() will raise error for us if slot_index not in slot range data = bytearray() - data.append(SlotNumber.fix(slot_index)) + data.append(SlotNumber.to_fw(slot_index)) data.append(tag_type) return self.device.send_cmd_sync(DATA_CMD_SET_SLOT_DATA_DEFAULT, 0x00, data) @@ -414,10 +395,9 @@ class BaseChameleonCMD: :param enable: 是否使能 :return: """ - if slot_index < 1 or slot_index > 8: - raise ValueError("The slot index range error(1-8)") + # SlotNumber() will raise error for us if slot_index not in slot range data = bytearray() - data.append(SlotNumber.fix(slot_index)) + data.append(SlotNumber.to_fw(slot_index)) data.append(0x01 if enable else 0x00) return self.device.send_cmd_sync(DATA_CMD_SET_SLOT_ENABLE, 0X00, data) @@ -492,8 +472,9 @@ class BaseChameleonCMD: :param name: 卡槽昵称 :return: """ + # SlotNumber() will raise error for us if slot not in slot range data = bytearray() - data.extend([SlotNumber.fix(slot), sense_type]) + data.extend([SlotNumber.to_fw(slot), sense_type]) data.extend(name.encode(encoding="gbk")) return self.device.send_cmd_sync(DATA_CMD_SET_SLOT_TAG_NICK, 0x00, data) @@ -505,8 +486,9 @@ class BaseChameleonCMD: :param name: 卡槽昵称 :return: """ + # SlotNumber() will raise error for us if slot not in slot range data = bytearray() - data.extend([SlotNumber.fix(slot), sense_type]) + data.extend([SlotNumber.to_fw(slot), sense_type]) return self.device.send_cmd_sync(DATA_CMD_GET_SLOT_TAG_NICK, 0x00, data) def update_slot_data_config(self): From 4ab131d10a34bb1bde69ae4e1a31da0a3e237849 Mon Sep 17 00:00:00 2001 From: Augusto Zanellato Date: Fri, 18 Aug 2023 22:13:06 +0200 Subject: [PATCH 22/28] Implement wipe fds command used to factory reset --- firmware/application/src/app_cmd.c | 14 +++++ firmware/application/src/data_cmd.h | 1 + firmware/application/src/utils/fds_util.c | 69 ++++++++++++++++++----- firmware/application/src/utils/fds_util.h | 2 + software/script/chameleon_cli_main.py | 1 + software/script/chameleon_cli_unit.py | 26 +++++++++ software/script/chameleon_cmd.py | 8 +++ 7 files changed, 108 insertions(+), 13 deletions(-) diff --git a/firmware/application/src/app_cmd.c b/firmware/application/src/app_cmd.c index 99c7d01..8dba70e 100644 --- a/firmware/application/src/app_cmd.c +++ b/firmware/application/src/app_cmd.c @@ -357,6 +357,19 @@ data_frame_tx_t* cmd_processor_get_slot_info(uint16_t cmd, uint16_t status, uint 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(); + if (!success) { + return data_frame_make(cmd, STATUS_FLASH_WRITE_FAIL, 0, NULL); + } + while (NRF_LOG_PROCESS()); + ret_code_t ret = sd_nvic_SystemReset(); + APP_ERROR_CHECK(ret); + while (1) { + __NOP(); + } +} + 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); @@ -607,6 +620,7 @@ static cmd_data_map_t m_data_cmd_map[] = { { 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 }, diff --git a/firmware/application/src/data_cmd.h b/firmware/application/src/data_cmd.h index 32803cf..2050fa8 100644 --- a/firmware/application/src/data_cmd.h +++ b/firmware/application/src/data_cmd.h @@ -27,6 +27,7 @@ #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) // // ****************************************************************** diff --git a/firmware/application/src/utils/fds_util.c b/firmware/application/src/utils/fds_util.c index 43850b8..7006854 100644 --- a/firmware/application/src/utils/fds_util.c +++ b/firmware/application/src/utils/fds_util.c @@ -10,10 +10,11 @@ NRF_LOG_MODULE_REGISTER(); // current write record info static struct { - uint16_t id; // file id - uint16_t key; // file key - bool success; // task is success - bool waiting; // task waiting done. + uint32_t record_id; // record id, used for sync delete + uint16_t id; // file id + uint16_t key; // file key + bool success; // task is success + bool waiting; // task waiting done. } fds_operation_info; @@ -120,12 +121,7 @@ bool fds_write_sync(uint16_t id, uint16_t key, uint16_t data_length_words, void* } else if (err_code == FDS_ERR_NO_SPACE_IN_FLASH) { // 确保还有空间可以操作,否则需要GC // 当前报错是属于空间不足的报错,可能我们需要进行GC NRF_LOG_INFO("FDS no space, gc auto start."); - err_code = fds_gc(); // 发起GC操作 - APP_ERROR_CHECK(err_code); // 检查GC是否正常执行 - // 等待GC完成 - while(!fds_operation_info.success) { - __NOP(); - }; + fds_gc_sync(); // gc完成后,可以重新进行相应的操作了 NRF_LOG_INFO("FDS auto gc success, write record continue."); @@ -162,6 +158,7 @@ int fds_delete_sync(uint16_t id, uint16_t key) { ret_code_t err_code; while(fds_find_record(id, key, &record_desc)) { fds_operation_info.success = false; + fds_record_id_from_desc(&record_desc, &fds_operation_info.record_id); err_code = fds_record_delete(&record_desc); APP_ERROR_CHECK(err_code); delete_count++; @@ -199,9 +196,13 @@ static void fds_evt_handler(fds_evt_t const * p_evt) { } break; case FDS_EVT_DEL_RECORD: { if (p_evt->result == NRF_SUCCESS) { - NRF_LOG_INFO("Record remove: FileID: 0x%04x, RecordKey: 0x%04x", p_evt->del.file_id, p_evt->del.record_key); - if (p_evt->write.file_id == fds_operation_info.id && p_evt->write.record_key == fds_operation_info.key) { - // 上面的逻辑已经确保是我们当前删除记录的任务完成了! + NRF_LOG_INFO( + "Record remove: FileID: 0x%04x, RecordKey: 0x%04x, RecordID: %08x", + p_evt->del.file_id, p_evt->del.record_key, p_evt->del.record_id + ); + if (p_evt->del.record_id == fds_operation_info.record_id) { + // Only check record id because fileID and recordKey aren't available + // if deleting via fds_record_iterate. record id is guaranteed to be unique. fds_operation_info.success = true; } } else { @@ -234,3 +235,45 @@ void fds_util_init() { err_code = fds_init(); APP_ERROR_CHECK(err_code); } + +void fds_gc_sync(void) { + fds_operation_info.success = false; + ret_code_t err_code = fds_gc(); + APP_ERROR_CHECK(err_code); + while(!fds_operation_info.success) { + __NOP(); + }; +} + +static bool fds_next_record_delete_sync() { + fds_find_token_t tok = {0}; + fds_record_desc_t desc = {0}; + if (fds_record_iterate(&desc, &tok) != NRF_SUCCESS) { + NRF_LOG_INFO("No more records to delete"); + return false; + } + + fds_record_id_from_desc(&desc, &fds_operation_info.record_id); + NRF_LOG_INFO("Deleting record with id=%08x", fds_operation_info.record_id); + + fds_operation_info.success = false; + ret_code_t rc = fds_record_delete(&desc); + if (rc != NRF_SUCCESS) { + NRF_LOG_WARNING("Record id=%08x deletion failed with rc=%d!", fds_operation_info.record_id, rc); + return false; + } + + while(!fds_operation_info.success) { + __NOP(); + } + + NRF_LOG_INFO("Record id=%08x deleted successfully", fds_operation_info.record_id); + return true; +} + +bool fds_wipe(void) { + NRF_LOG_INFO("Full fds wipe requested"); + while (fds_next_record_delete_sync()) {} + fds_gc_sync(); + return true; +} diff --git a/firmware/application/src/utils/fds_util.h b/firmware/application/src/utils/fds_util.h index 706ca42..df1b832 100644 --- a/firmware/application/src/utils/fds_util.h +++ b/firmware/application/src/utils/fds_util.h @@ -9,5 +9,7 @@ bool fds_write_sync(uint16_t id, uint16_t key, uint16_t data_length_words, void* int fds_delete_sync(uint16_t id, uint16_t key); bool fds_is_exists(uint16_t id, uint16_t key); void fds_util_init(void); +void fds_gc_sync(void); +bool fds_wipe(void); #endif diff --git a/software/script/chameleon_cli_main.py b/software/script/chameleon_cli_main.py index 5241e90..5519eb8 100755 --- a/software/script/chameleon_cli_main.py +++ b/software/script/chameleon_cli_main.py @@ -99,6 +99,7 @@ class ChameleonCLI: 'reset': new_uint(chameleon_cli_unit.HWSettingsReset, "Reset settings to default values"), 'help': "Chameleon settings management" }, + 'factory_reset': new_uint(chameleon_cli_unit.HWFactoryReset, "Wipe all data and return to factory settings"), 'help': "hardware controller", }, 'hf': { diff --git a/software/script/chameleon_cli_unit.py b/software/script/chameleon_cli_unit.py index 15f056d..7bd0fa7 100644 --- a/software/script/chameleon_cli_unit.py +++ b/software/script/chameleon_cli_unit.py @@ -1066,3 +1066,29 @@ class HWSettingsReset(DeviceRequiredUnit): print(" - Reset success @.@~") else: print(" - Reset failed") + +class HWFactoryReset(DeviceRequiredUnit): + def args_parser(self) -> ArgumentParserNoExit: + parser = ArgumentParserNoExit() + parser.description = "Permanently wipes Chameleon to factory settings. " \ + "This will delete all your slot data and custom settings. " \ + "There's no going back." + parser.add_argument( + "--i-know-what-im-doing", + default=False, + action="store_true", + help="Just to be sure :)" + ) + return parser + def on_exec(self, args: argparse.Namespace): + if not args.i_know_what_im_doing: + print("This time your data's safe. Read the command documentation next time.") + return + try: + resp = self.cmd_positive.factory_reset() + if resp.status != chameleon_status.Device.STATUS_DEVICE_SUCCESS: + print(" - Reset failed!") + return + except KeyError: + print(" - A Serial Error above is normal, please ignore it") + print(" - Reset successful! Please reconnect.") diff --git a/software/script/chameleon_cmd.py b/software/script/chameleon_cmd.py index 391f605..284be24 100644 --- a/software/script/chameleon_cmd.py +++ b/software/script/chameleon_cmd.py @@ -30,6 +30,8 @@ DATA_CMD_GET_GIT_VERSION = 1017 DATA_CMD_GET_ACTIVE_SLOT = 1018 DATA_CMD_GET_SLOT_INFO = 1019 +DATA_CMD_WIPE_FDS = 1020 + DATA_CMD_SCAN_14A_TAG = 2000 DATA_CMD_MF1_SUPPORT_DETECT = 2001 DATA_CMD_MF1_NT_LEVEL_DETECT = 2002 @@ -495,6 +497,12 @@ class BaseChameleonCMD: Store settings to flash memory """ return self.device.send_cmd_sync(DATA_CMD_SAVE_SETTINGS, 0x00) + + def factory_reset(self): + """ + Reset to factory settings + """ + return self.device.send_cmd_sync(DATA_CMD_WIPE_FDS, 0x00) class NegativeResponseError(Exception): From bbf5f3027bc8e11558fefdfa487c29f602003dc2 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 18 Aug 2023 21:56:35 +0200 Subject: [PATCH 23/28] NRF_LOG: add option to activate UART backend on SWO pin, see How_to_use_Firmware.md --- How_to_use_Firmware.md | 11 +++++++++++ firmware/Makefile.defs | 3 +++ firmware/application/Makefile | 17 +++++++++++++++++ firmware/application/src/sdk_config.h | 7 ++++--- 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/How_to_use_Firmware.md b/How_to_use_Firmware.md index 14dd727..7775ec7 100644 --- a/How_to_use_Firmware.md +++ b/How_to_use_Firmware.md @@ -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. diff --git a/firmware/Makefile.defs b/firmware/Makefile.defs index 7023b1d..6bc5f44 100644 --- a/firmware/Makefile.defs +++ b/firmware/Makefile.defs @@ -27,3 +27,6 @@ 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 diff --git a/firmware/application/Makefile b/firmware/application/Makefile index 05a1d4a..0857b49 100644 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -288,6 +288,23 @@ else $(error Chameleon : 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 : enable NRF_LOG on UART via SWO pin.) +endif # Optimization flags OPT = -O3 -g3 diff --git a/firmware/application/src/sdk_config.h b/firmware/application/src/sdk_config.h index 1e990e4..aa7f8eb 100644 --- a/firmware/application/src/sdk_config.h +++ b/firmware/application/src/sdk_config.h @@ -5868,9 +5868,10 @@ // 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 // UART_DEFAULT_CONFIG_HWFC - Hardware Flow Control // <0=> Disabled From 7b76aefd5ee488400bf34f30e845792f2d9ec9c3 Mon Sep 17 00:00:00 2001 From: Augusto Zanellato Date: Fri, 18 Aug 2023 22:35:39 +0200 Subject: [PATCH 24/28] ACK command and use delayed reset --- firmware/application/Makefile | 1 + firmware/application/src/app_cmd.c | 13 +++------- .../application/src/utils/delayed_reset.c | 26 +++++++++++++++++++ .../application/src/utils/delayed_reset.h | 3 +++ software/script/chameleon_cli_unit.py | 12 ++++----- 5 files changed, 39 insertions(+), 16 deletions(-) create mode 100644 firmware/application/src/utils/delayed_reset.c create mode 100644 firmware/application/src/utils/delayed_reset.h diff --git a/firmware/application/Makefile b/firmware/application/Makefile index 05a1d4a..cbabcbc 100644 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -30,6 +30,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 \ diff --git a/firmware/application/src/app_cmd.c b/firmware/application/src/app_cmd.c index 8dba70e..d9df5f7 100644 --- a/firmware/application/src/app_cmd.c +++ b/firmware/application/src/app_cmd.c @@ -13,6 +13,7 @@ #include "tag_persistence.h" #include "nrf_pwr_mgmt.h" #include "settings.h" +#include "delayed_reset.h" #define NRF_LOG_MODULE_NAME app_cmd @@ -359,15 +360,9 @@ data_frame_tx_t* cmd_processor_get_slot_info(uint16_t cmd, uint16_t status, uint data_frame_tx_t* cmd_processor_wipe_fds(uint16_t cmd, uint16_t status, uint16_t length, uint8_t *data) { bool success = fds_wipe(); - if (!success) { - return data_frame_make(cmd, STATUS_FLASH_WRITE_FAIL, 0, NULL); - } - while (NRF_LOG_PROCESS()); - ret_code_t ret = sd_nvic_SystemReset(); - APP_ERROR_CHECK(ret); - while (1) { - __NOP(); - } + 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) { diff --git a/firmware/application/src/utils/delayed_reset.c b/firmware/application/src/utils/delayed_reset.c new file mode 100644 index 0000000..1dc4c89 --- /dev/null +++ b/firmware/application/src/utils/delayed_reset.c @@ -0,0 +1,26 @@ +#include "app_timer.h" +#include "delayed_reset.h" + +#include "nrf_log.h" +#include "nrf_log_ctrl.h" +#include "nrf_log_default_backends.h" + +APP_TIMER_DEF(m_reset_timer); + +static void delayed_reset_event_handler(void* ctx) { + while (NRF_LOG_PROCESS()); + ret_code_t ret = sd_nvic_SystemReset(); + APP_ERROR_CHECK(ret); + while (1) { + __NOP(); + } +} + +void delayed_reset(uint32_t delay) { + NRF_LOG_INFO("Resetting in %d ms...", delay); + ret_code_t ret; + ret = app_timer_create(&m_reset_timer, APP_TIMER_MODE_SINGLE_SHOT, delayed_reset_event_handler); + APP_ERROR_CHECK(ret); + ret = app_timer_start(m_reset_timer, APP_TIMER_TICKS(delay), NULL); + APP_ERROR_CHECK(ret); +} diff --git a/firmware/application/src/utils/delayed_reset.h b/firmware/application/src/utils/delayed_reset.h new file mode 100644 index 0000000..6be37ad --- /dev/null +++ b/firmware/application/src/utils/delayed_reset.h @@ -0,0 +1,3 @@ +#pragma once + +void delayed_reset(uint32_t delay); \ No newline at end of file diff --git a/software/script/chameleon_cli_unit.py b/software/script/chameleon_cli_unit.py index 7bd0fa7..d4cc599 100644 --- a/software/script/chameleon_cli_unit.py +++ b/software/script/chameleon_cli_unit.py @@ -1084,11 +1084,9 @@ class HWFactoryReset(DeviceRequiredUnit): if not args.i_know_what_im_doing: print("This time your data's safe. Read the command documentation next time.") return - try: - resp = self.cmd_positive.factory_reset() - if resp.status != chameleon_status.Device.STATUS_DEVICE_SUCCESS: - print(" - Reset failed!") - return - except KeyError: - print(" - A Serial Error above is normal, please ignore it") + resp = self.cmd_positive.factory_reset() + if resp.status == chameleon_status.Device.STATUS_DEVICE_SUCCESS: print(" - Reset successful! Please reconnect.") + print(" - A Serial Error below is normal, please ignore it") + else: + print(" - Reset failed!") From 8e093d00b678c60f125b07af439eb74fde6460f0 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 18 Aug 2023 21:49:56 +0200 Subject: [PATCH 25/28] Enable watchdog --- firmware/application/Makefile | 2 ++ firmware/application/src/app_main.c | 5 ++++- firmware/application/src/bsp/bsp_wdt.c | 30 ++++++++++++++++++++++++++ firmware/application/src/bsp/bsp_wdt.h | 15 +++++++++++++ firmware/application/src/sdk_config.h | 13 +++++------ 5 files changed, 58 insertions(+), 7 deletions(-) create mode 100644 firmware/application/src/bsp/bsp_wdt.c create mode 100644 firmware/application/src/bsp/bsp_wdt.h diff --git a/firmware/application/Makefile b/firmware/application/Makefile index 0857b49..4208e15 100644 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -17,6 +17,7 @@ SRC_FILES += \ $(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 \ @@ -93,6 +94,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 \ diff --git a/firmware/application/src/app_main.c b/firmware/application/src/app_main.c index 1e92c1b..192a156 100644 --- a/firmware/application/src/app_main.c +++ b/firmware/application/src/app_main.c @@ -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" @@ -38,7 +39,6 @@ NRF_LOG_MODULE_REGISTER(); #include "settings.h" - // Defining soft timers APP_TIMER_DEF(m_button_check_timer); // Timer for button debounce static bool m_is_read_btn_press = false; @@ -545,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) { @@ -558,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. diff --git a/firmware/application/src/bsp/bsp_wdt.c b/firmware/application/src/bsp/bsp_wdt.c new file mode 100644 index 0000000..5405bf2 --- /dev/null +++ b/firmware/application/src/bsp/bsp_wdt.c @@ -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); +} diff --git a/firmware/application/src/bsp/bsp_wdt.h b/firmware/application/src/bsp/bsp_wdt.h new file mode 100644 index 0000000..0b19764 --- /dev/null +++ b/firmware/application/src/bsp/bsp_wdt.h @@ -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__ diff --git a/firmware/application/src/sdk_config.h b/firmware/application/src/sdk_config.h index aa7f8eb..c65803f 100644 --- a/firmware/application/src/sdk_config.h +++ b/firmware/application/src/sdk_config.h @@ -4630,7 +4630,7 @@ // NRFX_WDT_ENABLED - nrfx_wdt - WDT peripheral driver //========================================================== #ifndef NRFX_WDT_ENABLED -#define NRFX_WDT_ENABLED 0 +#define NRFX_WDT_ENABLED 1 #endif // 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 // NRFX_WDT_CONFIG_NO_IRQ - Remove WDT IRQ handling from WDT driver @@ -4677,7 +4677,7 @@ // 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 // NRFX_WDT_CONFIG_LOG_LEVEL - Default Severity level @@ -6019,9 +6019,10 @@ // 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 // WDT_CONFIG_BEHAVIOUR - WDT behavior in CPU SLEEP or HALT mode // <1=> Run in SLEEP, Pause in HALT From 3bfc52432ac995cb26ccfefee9d9d18b13b69dab Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 19 Aug 2023 00:13:43 +0200 Subject: [PATCH 26/28] change slot nicknames encoding: gbk -> utf8 --- firmware/application/src/app_cmd.c | 2 -- software/script/chameleon_cli_unit.py | 7 ++++--- software/script/chameleon_cmd.py | 6 +++--- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/firmware/application/src/app_cmd.c b/firmware/application/src/app_cmd.c index 99c7d01..dbe49d3 100644 --- a/firmware/application/src/app_cmd.c +++ b/firmware/application/src/app_cmd.c @@ -473,7 +473,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 { @@ -498,7 +497,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 { diff --git a/software/script/chameleon_cli_unit.py b/software/script/chameleon_cli_unit.py index 15f056d..a6964aa 100644 --- a/software/script/chameleon_cli_unit.py +++ b/software/script/chameleon_cli_unit.py @@ -940,9 +940,10 @@ class HWSlotNickSet(SlotIndexRequireUint, SenseTypeRequireUint): slot_num = args.slot sense_type = args.sense_type name: str = args.name - if len(name.encode(encoding="gbk")) > 32: + uname = name.encode(encoding="utf8") + if len(uname) > 32: raise ValueError("Your tag nick name too long.") - self.cmd_positive.set_slot_tag_nick_name(slot_num, sense_type, name) + self.cmd_positive.set_slot_tag_nick_name(slot_num, sense_type, uname) print(f' - Set tag nick name for slot {slot_num} success.') @@ -958,7 +959,7 @@ class HWSlotNickGet(SlotIndexRequireUint, SenseTypeRequireUint): slot_num = args.slot sense_type = args.sense_type res = self.cmd_positive.get_slot_tag_nick_name(slot_num, sense_type) - print(f' - Get tag nick name for slot {slot_num}: {res.data.decode(encoding="gbk")}') + print(f' - Get tag nick name for slot {slot_num}: {res.data.decode(encoding="utf8")}') class HWSlotUpdate(DeviceRequiredUnit): diff --git a/software/script/chameleon_cmd.py b/software/script/chameleon_cmd.py index 391f605..88ab7de 100644 --- a/software/script/chameleon_cmd.py +++ b/software/script/chameleon_cmd.py @@ -433,7 +433,7 @@ class BaseChameleonCMD: data.extend(uid) return self.device.send_cmd_sync(DATA_CMD_SET_MF1_ANTI_COLLISION_RES, 0X00, data) - def set_slot_tag_nick_name(self, slot: int, sense_type: int, name: str): + def set_slot_tag_nick_name(self, slot: int, sense_type: int, name: bytes): """ 设置MF1的模拟卡的防冲撞资源信息 :param slot: 卡槽号码 @@ -443,7 +443,7 @@ class BaseChameleonCMD: """ data = bytearray() data.extend([slot, sense_type]) - data.extend(name.encode(encoding="gbk")) + data.extend(name) return self.device.send_cmd_sync(DATA_CMD_SET_SLOT_TAG_NICK, 0x00, data) def get_slot_tag_nick_name(self, slot: int, sense_type: int): @@ -620,7 +620,7 @@ class PositiveChameleonCMD(BaseChameleonCMD): self.check_status(ret.status, chameleon_status.Device.STATUS_DEVICE_SUCCESS) return ret - def set_slot_tag_nick_name(self, slot: int, sense_type: int, name: str): + def set_slot_tag_nick_name(self, slot: int, sense_type: int, name: bytes): ret = super(PositiveChameleonCMD, self).set_slot_tag_nick_name(slot, sense_type, name) self.check_status(ret.status, chameleon_status.Device.STATUS_DEVICE_SUCCESS) return ret From 28572958a7946a7ad737a3b85b916f53bf434dda Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 19 Aug 2023 00:20:17 +0200 Subject: [PATCH 27/28] thinner logo to fit 80col terms --- software/script/chameleon_cli_main.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/software/script/chameleon_cli_main.py b/software/script/chameleon_cli_main.py index 5241e90..7bc9e85 100755 --- a/software/script/chameleon_cli_main.py +++ b/software/script/chameleon_cli_main.py @@ -27,13 +27,12 @@ LITE = r""" # create by http://patorjk.com/software/taag/#p=display&f=ANSI%20Shadow&t=Chameleon%20Ultra BANNER = f""" - ██████╗██╗ ██╗ █████╗ ███╗ ███╗███████╗██╗ ███████╗ ██████╗ ███╗ ██╗ -██╔════╝██║ ██║██╔══██╗████╗ ████║██╔════╝██║ ██╔════╝██╔═══██╗████╗ ██║ -██║ ███████║███████║██╔████╔██║█████╗ ██║ █████╗ ██║ ██║██╔██╗ ██║ -██║ ██╔══██║██╔══██║██║╚██╔╝██║██╔══╝ ██║ ██╔══╝ ██║ ██║██║╚██╗██║ -╚██████╗██║ ██║██║ ██║██║ ╚═╝ ██║███████╗███████╗███████╗╚██████╔╝██║ ╚████║ - ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝ ╚═════╝ ╚═╝ ╚═══╝ - + ██████╗██╗ ██╗ █████╗ ██╗ ██╗███████╗██╗ ███████╗ █████╗ ██╗ ██╗ +██╔════╝██║ ██║██╔══██╗███╗ ███║██╔════╝██║ ██╔════╝██╔══██╗███╗ ██║ +██║ ███████║███████║████████║█████╗ ██║ █████╗ ██║ ██║████╗██║ +██║ ██╔══██║██╔══██║██╔██╔██║██╔══╝ ██║ ██╔══╝ ██║ ██║██╔████║ +╚██████╗██║ ██║██║ ██║██║╚═╝██║███████╗███████╗███████╗╚█████╔╝██║╚███║ + ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝ ╚════╝ ╚═╝ ╚══╝ """ From ae48829a152c6569a358488f007ea104c92e5300 Mon Sep 17 00:00:00 2001 From: Augusto Zanellato Date: Sat, 19 Aug 2023 02:08:24 +0200 Subject: [PATCH 28/28] Use single release for dev builds Fix workflow using deprecated stuff --- .github/workflows/firmware.yml | 61 ++++++++++++---------------------- 1 file changed, 22 insertions(+), 39 deletions(-) diff --git a/.github/workflows/firmware.yml b/.github/workflows/firmware.yml index f54f507..9fd6b6e 100644 --- a/.github/workflows/firmware.yml +++ b/.github/workflows/firmware.yml @@ -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