diff --git a/CHANGELOG.md b/CHANGELOG.md index a16fc8256..23e815ba9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,42 +1,20 @@ ### New changes -* **Warning! After installing, Desktop settings (Favoutite apps, PIN Code, AutoLock time..) will be resetted to default due to OFW changes, Please set your PIN code, Favourite apps again in Settings->Desktop** -* New way of changing device name -> **Now can be changed in Settings->Desktop** (by @xMasterX and @Willy-JL) -* Plugins: BadBT plugin (BT version of BadKB) [(by Willy-JL, ClaraCrazy, XFW contributors)](https://github.com/ClaraCrazy/Flipper-Xtreme/tree/dev/applications/main/bad_kb) -* Plugins: WiFi Marauder -> Added sniff pmkid on selected aps from 0.10.4 update (by @clipboard1) -* Plugins: SubGHz Bruteforcer -> Increase delay just a little bit to fix some cases when receiver will not get codes and decrease manual transmit delay -* Plugins: UART Terminal -> Fix crashes on plugin load with RX connected -* NFC: Mifare mini with SAK 0x89 support -* SubGHz: **CAME Atomo - Add manually support and custom buttons support** -* SubGHz: Fix crashes when deleting signals using right arrow button in `Read` mode -* SubGHz: Restore Rx indication after deletion after Memory is FULL (by @wosk | PR #464) -* SubGHz: **App refactoring** (OFW code ported + our code was refactored/cleaned up too) (by @gid9798 and @xMasterX | PR #461) -* SubGHz: Using scene manager functions in DecodeRAW (by @gid9798 | PR #462) -* SubGHz: Protocols and custom buttons refactoring (by @gid9798 | PR #465) -* SubGHz: Move `counter increase` setting out of debug, change max value -* GUI: Submenu locked elements (by @Willy-JL and @giacomoferretti) -* GUI: Text Input improvements, added cursor and ability to set minimal length (by @Willy-JL) -* BT API: Functions that allow to change bt mac address and device broadcasted name (by @Willy-JL and XFW contributors) -* Infrared: `External output` move out of debug and add power option for external modules -* Infrared: Updated universal remote assets (by @amec0e | PR #474) -* Extra pack: Some app fixes -* FBT: Fix vscode example config for debug builds - please run `./fbt vscode_dist` again if you had issues with debug builds size -* OFW PR 2316: NFC V support (by @g3gg0 & @nvx) -* OFW PR 2669: nfc: Fix MFUL tearing flags read (by @GMMan) -* OFW PR 2666: BadUSB: Add fr-FR-mac key layout (by @FelixLgr) -* OFW: api: added lib/nfc/protocols/nfc_util.h -* OFW: fix PIN retry count reset on reboot -* OFW: fbt: allow strings for fap_version field in app manifests -* OFW: Rpc: add desktop service. Desktop: refactor locking routine. **Now PIN lock is actually cannot be bypassed by reboot!** / **Desktop settings will be reset, please set your PIN and favourite apps again!** -* OFW: Part 2 of hooking C2 IPC -* OFW: ble: attempt to handle hardfaulted c2 -* OFW: Add Mfkey32 application -* OFW: Added DigitalSequence and PulseReader -* OFW: Debug: revert cortex debug to lxml and drop DWT **(reapply your VSCode launch.json from example folder)** -* OFW: furi_crash: added C2 status; added fw-version gdb command -* OFW: Removed STM32CubeWB module -* OFW: API version in UI -* OFW: ufbt: deploying sample ufbt automation for new apps; added `source "ufbt -s env"` for toolchain access -* OFW: Fix storage.py exist_dir logic +* SubGHz Remote: Full refactoring, app was re-made from scratch (by @gid9798) +* API: Cleanup, mini refactoring of some apps (+6k of free flash space) +* SubGHz: Various fixes (by @gid9798) +* SubGHz: Fix counter settings in debug +* SubGHz: Move dangerous_settings check (by @gid9798 | PR #475) +* Misc: Name changer code moved to proper place, load after system startup + extra checks +* Plugins: NMEA GPS UART - stability fix +* Plugins: Port XFW keyboard with extra symbols to WiFi Marauder instead of using UART Term keyboard (thanks to @Willy-JL) +* Plugins: Update NMEA GPS UART [(by ezod)](https://github.com/ezod/flipperzero-gps) +* Plugins: Update WiFi Marauder [(by 0xchocolate)](https://github.com/0xchocolate/flipperzero-firmware-with-wifi-marauder-companion) +* OFW: Services: remove deallocator for persistent services +* OFW: Storage: common_rename is now POSIX compliant +* OFW: Removed user-specific data from tar artifacts +* OFW: fbt: Fix tar uid overflow when packaging +* OFW: fbt: Use union for old py (Fix builds if using older python versions) +* OFW PR 2682: USB HID report timeout (by nminaylov) #### [🎲 Download latest extra apps pack](https://github.com/xMasterX/all-the-plugins/archive/refs/heads/main.zip) diff --git a/ReadMe.md b/ReadMe.md index 596891d6e..fe6c7fb34 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -145,7 +145,7 @@ You can support us by using links or addresses below: - ESP32: WiFi Marauder companion plugin [(by 0xchocolate)](https://github.com/0xchocolate/flipperzero-firmware-with-wifi-marauder-companion) - Saving .pcap on flipper microSD [by tcpassos](https://github.com/tcpassos/flipperzero-firmware-with-wifi-marauder-companion) -> Only with custom marauder build (It is necessary to uncomment "#define WRITE_PACKETS_SERIAL" in configs.h (in marauder fw) and compile the firmware for the wifi board.) Or download precompiled build -> [Download esp32_marauder_ver_flipper_sd_serial.bin](https://github.com/justcallmekoko/ESP32Marauder/releases/latest) - NRF24: Sniffer & MouseJacker (with changes) [(by mothball187)](https://github.com/mothball187/flipperzero-nrf24/tree/main/mousejacker) - Simple Clock (timer by GMMan) [(original by CompaqDisc)](https://gist.github.com/CompaqDisc/4e329c501bd03c1e801849b81f48ea61) -- **Sub-GHz Remote** (UniversalRF Remix) [(by @darmiel & @xMasterX)](https://github.com/darmiel/flipper-playlist/tree/feat/unirf-protocols) (original by @ESurge) +- **Sub-GHz Remote** [(by @gid9798)](https://github.com/gid9798) - Spectrum Analyzer (with changes) [(by jolcese)](https://github.com/jolcese/flipperzero-firmware/tree/spectrum/applications/spectrum_analyzer) - [Ultra Narrow mode & scan channels non-consecutively](https://github.com/theY4Kman/flipperzero-firmware/commits?author=theY4Kman) - Metronome [(by panki27)](https://github.com/panki27/Metronome) - DTMF Dolphin [(by litui)](https://github.com/litui/dtmf_dolphin) diff --git a/applications/external/gps_nmea_uart/gps_uart.c b/applications/external/gps_nmea_uart/gps_uart.c index ada8f04f9..d44cf22ef 100644 --- a/applications/external/gps_nmea_uart/gps_uart.c +++ b/applications/external/gps_nmea_uart/gps_uart.c @@ -66,6 +66,19 @@ static void gps_uart_parse_nmea(GpsUart* gps_uart, char* line) { } } break; + case MINMEA_SENTENCE_GLL: { + struct minmea_sentence_gll frame; + if(minmea_parse_gll(&frame, line)) { + gps_uart->status.latitude = minmea_tocoord(&frame.latitude); + gps_uart->status.longitude = minmea_tocoord(&frame.longitude); + gps_uart->status.time_hours = frame.time.hours; + gps_uart->status.time_minutes = frame.time.minutes; + gps_uart->status.time_seconds = frame.time.seconds; + + notification_message_block(gps_uart->notifications, &sequence_blink_red_10); + } + } break; + default: break; } @@ -88,35 +101,53 @@ static int32_t gps_uart_worker(void* context) { if(events & WorkerEvtRxDone) { size_t len = 0; do { + // receive serial bytes into rx_buf, starting at rx_offset from the start of the buffer + // the maximum we can receive is RX_BUF_SIZE - 1 - rx_offset len = furi_stream_buffer_receive( gps_uart->rx_stream, gps_uart->rx_buf + rx_offset, RX_BUF_SIZE - 1 - rx_offset, 0); if(len > 0) { + // increase rx_offset by the number of bytes received, and null-terminate rx_buf rx_offset += len; gps_uart->rx_buf[rx_offset] = '\0'; + // look for strings ending in newlines, starting at the start of rx_buf char* line_current = (char*)gps_uart->rx_buf; while(1) { + // skip null characters while(*line_current == '\0' && line_current < (char*)gps_uart->rx_buf + rx_offset - 1) { line_current++; } + // find the next newline char* newline = strchr(line_current, '\n'); - if(newline) { + if(newline) // newline found + { + // put a null terminator in place of the newline, to delimit the line string *newline = '\0'; + + // attempt to parse the line as a NMEA sentence gps_uart_parse_nmea(gps_uart, line_current); + + // move the cursor to the character after the newline line_current = newline + 1; - } else { - if(line_current > (char*)gps_uart->rx_buf) { + } else // no more newlines found + { + if(line_current > + (char*)gps_uart->rx_buf) // at least one line was found + { + // clear parsed lines, and move any leftover bytes to the start of rx_buf rx_offset = 0; - while(*line_current) { + while( + *line_current) // stop when the original rx_offset terminator is reached + { gps_uart->rx_buf[rx_offset++] = *(line_current++); } } - break; + break; // go back to receiving bytes from the serial stream } } } diff --git a/applications/external/nfc_magic/lib/magic/classic_gen1.c b/applications/external/nfc_magic/lib/magic/classic_gen1.c new file mode 100644 index 000000000..ebd2b0805 --- /dev/null +++ b/applications/external/nfc_magic/lib/magic/classic_gen1.c @@ -0,0 +1,175 @@ +#include "classic_gen1.h" + +#include + +#define TAG "Magic" + +#define MAGIC_CMD_WUPA (0x40) +#define MAGIC_CMD_WIPE (0x41) +#define MAGIC_CMD_ACCESS (0x43) + +#define MAGIC_MIFARE_READ_CMD (0x30) +#define MAGIC_MIFARE_WRITE_CMD (0xA0) + +#define MAGIC_ACK (0x0A) + +#define MAGIC_BUFFER_SIZE (32) + +bool magic_gen1_wupa() { + bool magic_activated = false; + uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; + uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; + uint16_t rx_len = 0; + FuriHalNfcReturn ret = 0; + + do { + // Start communication + tx_data[0] = MAGIC_CMD_WUPA; + ret = furi_hal_nfc_ll_txrx_bits( + tx_data, + 7, + rx_data, + sizeof(rx_data), + &rx_len, + FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL | FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | + FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP, + furi_hal_nfc_ll_ms2fc(20)); + if(ret != FuriHalNfcReturnIncompleteByte) break; + if(rx_len != 4) break; + if(rx_data[0] != MAGIC_ACK) break; + magic_activated = true; + } while(false); + + return magic_activated; +} + +bool magic_gen1_data_access_cmd() { + bool write_cmd_success = false; + uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; + uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; + uint16_t rx_len = 0; + FuriHalNfcReturn ret = 0; + + do { + tx_data[0] = MAGIC_CMD_ACCESS; + ret = furi_hal_nfc_ll_txrx_bits( + tx_data, + 8, + rx_data, + sizeof(rx_data), + &rx_len, + FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL | FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | + FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP, + furi_hal_nfc_ll_ms2fc(20)); + if(ret != FuriHalNfcReturnIncompleteByte) break; + if(rx_len != 4) break; + if(rx_data[0] != MAGIC_ACK) break; + + write_cmd_success = true; + } while(false); + + return write_cmd_success; +} + +bool magic_gen1_read_block(uint8_t block_num, MfClassicBlock* data) { + furi_assert(data); + + bool read_success = false; + + uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; + uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; + uint16_t rx_len = 0; + FuriHalNfcReturn ret = 0; + + do { + tx_data[0] = MAGIC_MIFARE_READ_CMD; + tx_data[1] = block_num; + ret = furi_hal_nfc_ll_txrx_bits( + tx_data, + 2 * 8, + rx_data, + sizeof(rx_data), + &rx_len, + FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON, + furi_hal_nfc_ll_ms2fc(20)); + + if(ret != FuriHalNfcReturnOk) break; + if(rx_len != 16 * 8) break; + memcpy(data->value, rx_data, sizeof(data->value)); + read_success = true; + } while(false); + + return read_success; +} + +bool magic_gen1_write_blk(uint8_t block_num, MfClassicBlock* data) { + furi_assert(data); + + bool write_success = false; + uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; + uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; + uint16_t rx_len = 0; + FuriHalNfcReturn ret = 0; + + do { + tx_data[0] = MAGIC_MIFARE_WRITE_CMD; + tx_data[1] = block_num; + ret = furi_hal_nfc_ll_txrx_bits( + tx_data, + 2 * 8, + rx_data, + sizeof(rx_data), + &rx_len, + FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP, + furi_hal_nfc_ll_ms2fc(20)); + if(ret != FuriHalNfcReturnIncompleteByte) break; + if(rx_len != 4) break; + if(rx_data[0] != MAGIC_ACK) break; + + memcpy(tx_data, data->value, sizeof(data->value)); + ret = furi_hal_nfc_ll_txrx_bits( + tx_data, + 16 * 8, + rx_data, + sizeof(rx_data), + &rx_len, + FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP, + furi_hal_nfc_ll_ms2fc(20)); + if(ret != FuriHalNfcReturnIncompleteByte) break; + if(rx_len != 4) break; + if(rx_data[0] != MAGIC_ACK) break; + + write_success = true; + } while(false); + + return write_success; +} + +bool magic_gen1_wipe() { + bool wipe_success = false; + uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; + uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; + uint16_t rx_len = 0; + FuriHalNfcReturn ret = 0; + + do { + tx_data[0] = MAGIC_CMD_WIPE; + ret = furi_hal_nfc_ll_txrx_bits( + tx_data, + 8, + rx_data, + sizeof(rx_data), + &rx_len, + FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_TX_MANUAL | FURI_HAL_NFC_LL_TXRX_FLAGS_AGC_ON | + FURI_HAL_NFC_LL_TXRX_FLAGS_CRC_RX_KEEP, + furi_hal_nfc_ll_ms2fc(2000)); + + if(ret != FuriHalNfcReturnIncompleteByte) break; + if(rx_len != 4) break; + if(rx_data[0] != MAGIC_ACK) break; + + wipe_success = true; + } while(false); + + return wipe_success; +} \ No newline at end of file diff --git a/applications/external/nfc_magic/lib/magic/classic_gen1.h b/applications/external/nfc_magic/lib/magic/classic_gen1.h new file mode 100644 index 000000000..6d4ff6dcd --- /dev/null +++ b/applications/external/nfc_magic/lib/magic/classic_gen1.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +bool magic_gen1_wupa(); + +bool magic_gen1_read_block(uint8_t block_num, MfClassicBlock* data); + +bool magic_gen1_data_access_cmd(); + +bool magic_gen1_write_blk(uint8_t block_num, MfClassicBlock* data); + +bool magic_gen1_wipe(); \ No newline at end of file diff --git a/applications/external/nfc_magic/lib/magic/common.c b/applications/external/nfc_magic/lib/magic/common.c new file mode 100644 index 000000000..0ea3cb218 --- /dev/null +++ b/applications/external/nfc_magic/lib/magic/common.c @@ -0,0 +1,33 @@ +#include "common.h" + +#include + +#define REQA (0x26) +#define CL1_PREFIX (0x93) +#define SELECT (0x70) + +#define MAGIC_BUFFER_SIZE (32) + +bool magic_activate() { + FuriHalNfcReturn ret = 0; + + // Setup nfc poller + furi_hal_nfc_exit_sleep(); + furi_hal_nfc_ll_txrx_on(); + furi_hal_nfc_ll_poll(); + ret = furi_hal_nfc_ll_set_mode( + FuriHalNfcModePollNfca, FuriHalNfcBitrate106, FuriHalNfcBitrate106); + if(ret != FuriHalNfcReturnOk) return false; + + furi_hal_nfc_ll_set_fdt_listen(FURI_HAL_NFC_LL_FDT_LISTEN_NFCA_POLLER); + furi_hal_nfc_ll_set_fdt_poll(FURI_HAL_NFC_LL_FDT_POLL_NFCA_POLLER); + furi_hal_nfc_ll_set_error_handling(FuriHalNfcErrorHandlingNfc); + furi_hal_nfc_ll_set_guard_time(FURI_HAL_NFC_LL_GT_NFCA); + + return true; +} + +void magic_deactivate() { + furi_hal_nfc_ll_txrx_off(); + furi_hal_nfc_sleep(); +} \ No newline at end of file diff --git a/applications/external/nfc_magic/lib/magic/common.h b/applications/external/nfc_magic/lib/magic/common.h new file mode 100644 index 000000000..bef166c8f --- /dev/null +++ b/applications/external/nfc_magic/lib/magic/common.h @@ -0,0 +1,19 @@ +#pragma once + +#include +#include + +typedef enum { + MagicTypeClassicGen1, + MagicTypeClassicDirectWrite, + MagicTypeClassicAPDU, + MagicTypeUltralightGen1, + MagicTypeUltralightDirectWrite, + MagicTypeUltralightC_Gen1, + MagicTypeUltralightC_DirectWrite, + MagicTypeGen4, +} MagicType; + +bool magic_activate(); + +void magic_deactivate(); \ No newline at end of file diff --git a/applications/external/nfc_magic/lib/magic/gen4.c b/applications/external/nfc_magic/lib/magic/gen4.c new file mode 100644 index 000000000..31be649a0 --- /dev/null +++ b/applications/external/nfc_magic/lib/magic/gen4.c @@ -0,0 +1,199 @@ +#include "gen4.h" + +#include +#include + +#define TAG "Magic" + +#define MAGIC_CMD_PREFIX (0xCF) + +#define MAGIC_CMD_GET_CFG (0xC6) +#define MAGIC_CMD_WRITE (0xCD) +#define MAGIC_CMD_READ (0xCE) +#define MAGIC_CMD_SET_CFG (0xF0) +#define MAGIC_CMD_FUSE_CFG (0xF1) +#define MAGIC_CMD_SET_PWD (0xFE) + +#define MAGIC_BUFFER_SIZE (40) + +const uint8_t MAGIC_DEFAULT_CONFIG[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x09, 0x78, 0x00, 0x91, 0x02, 0xDA, 0xBC, 0x19, 0x10, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x04, 0x00, 0x08, 0x00 +}; + +const uint8_t MAGIC_DEFAULT_BLOCK0[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +const uint8_t MAGIC_EMPTY_BLOCK[16] = { 0 }; + +const uint8_t MAGIC_DEFAULT_SECTOR_TRAILER[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +static bool magic_gen4_is_block_num_trailer(uint8_t n) { + n++; + if (n < 32 * 4) { + return (n % 4 == 0); + } + + return (n % 16 == 0); +} + +bool magic_gen4_get_cfg(uint32_t pwd, uint8_t* config) { + bool is_valid_config_len = false; + uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; + uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; + uint16_t rx_len = 0; + FuriHalNfcReturn ret = 0; + + do { + // Start communication + tx_data[0] = MAGIC_CMD_PREFIX; + tx_data[1] = (uint8_t)(pwd >> 24); + tx_data[2] = (uint8_t)(pwd >> 16); + tx_data[3] = (uint8_t)(pwd >> 8); + tx_data[4] = (uint8_t)pwd; + tx_data[5] = MAGIC_CMD_GET_CFG; + ret = furi_hal_nfc_ll_txrx( + tx_data, + 6, + rx_data, + sizeof(rx_data), + &rx_len, + FURI_HAL_NFC_TXRX_DEFAULT, + furi_hal_nfc_ll_ms2fc(20)); + if(ret != FuriHalNfcReturnOk) break; + if(rx_len != 30 && rx_len != 32) break; + memcpy(config, rx_data, rx_len); + is_valid_config_len = true; + } while(false); + + return is_valid_config_len; +} + +bool magic_gen4_set_cfg(uint32_t pwd, const uint8_t* config, uint8_t config_length, bool fuse) { + bool write_success = false; + uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; + uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; + uint16_t rx_len = 0; + FuriHalNfcReturn ret = 0; + + do { + // Start communication + tx_data[0] = MAGIC_CMD_PREFIX; + tx_data[1] = (uint8_t)(pwd >> 24); + tx_data[2] = (uint8_t)(pwd >> 16); + tx_data[3] = (uint8_t)(pwd >> 8); + tx_data[4] = (uint8_t)pwd; + tx_data[5] = fuse ? MAGIC_CMD_FUSE_CFG : MAGIC_CMD_SET_CFG; + memcpy(tx_data + 6, config, config_length); + ret = furi_hal_nfc_ll_txrx( + tx_data, + 6 + config_length, + rx_data, + sizeof(rx_data), + &rx_len, + FURI_HAL_NFC_TXRX_DEFAULT, + furi_hal_nfc_ll_ms2fc(20)); + if(ret != FuriHalNfcReturnOk) break; + if(rx_len != 2) break; + write_success = true; + } while(false); + + return write_success; +} + +bool magic_gen4_set_pwd(uint32_t old_pwd, uint32_t new_pwd) { + bool change_success = false; + uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; + uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; + uint16_t rx_len = 0; + FuriHalNfcReturn ret = 0; + + do { + // Start communication + tx_data[0] = MAGIC_CMD_PREFIX; + tx_data[1] = (uint8_t)(old_pwd >> 24); + tx_data[2] = (uint8_t)(old_pwd >> 16); + tx_data[3] = (uint8_t)(old_pwd >> 8); + tx_data[4] = (uint8_t)old_pwd; + tx_data[5] = MAGIC_CMD_SET_PWD; + tx_data[6] = (uint8_t)(new_pwd >> 24); + tx_data[7] = (uint8_t)(new_pwd >> 16); + tx_data[8] = (uint8_t)(new_pwd >> 8); + tx_data[9] = (uint8_t)new_pwd; + ret = furi_hal_nfc_ll_txrx( + tx_data, + 10, + rx_data, + sizeof(rx_data), + &rx_len, + FURI_HAL_NFC_TXRX_DEFAULT, + furi_hal_nfc_ll_ms2fc(20)); + FURI_LOG_I(TAG, "ret %d, len %d", ret, rx_len); + if(ret != FuriHalNfcReturnOk) break; + if(rx_len != 2) break; + change_success = true; + } while(false); + + return change_success; +} + +bool magic_gen4_write_blk(uint32_t pwd, uint8_t block_num, const uint8_t* data) { + bool write_success = false; + uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; + uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; + uint16_t rx_len = 0; + FuriHalNfcReturn ret = 0; + + do { + // Start communication + tx_data[0] = MAGIC_CMD_PREFIX; + tx_data[1] = (uint8_t)(pwd >> 24); + tx_data[2] = (uint8_t)(pwd >> 16); + tx_data[3] = (uint8_t)(pwd >> 8); + tx_data[4] = (uint8_t)pwd; + tx_data[5] = MAGIC_CMD_WRITE; + tx_data[6] = block_num; + memcpy(tx_data + 7, data, 16); + ret = furi_hal_nfc_ll_txrx( + tx_data, + 23, + rx_data, + sizeof(rx_data), + &rx_len, + FURI_HAL_NFC_TXRX_DEFAULT, + furi_hal_nfc_ll_ms2fc(200)); + if(ret != FuriHalNfcReturnOk) break; + if(rx_len != 2) break; + write_success = true; + } while(false); + + return write_success; +} + +bool magic_gen4_wipe(uint32_t pwd) { + if(!magic_gen4_set_cfg(pwd, MAGIC_DEFAULT_CONFIG, sizeof(MAGIC_DEFAULT_CONFIG), false)) { + FURI_LOG_E(TAG, "Set config failed"); + return false; + } + if(!magic_gen4_write_blk(pwd, 0, MAGIC_DEFAULT_BLOCK0)) { + FURI_LOG_E(TAG, "Block 0 write failed"); + return false; + } + for(size_t i = 1; i < 64; i++) { + const uint8_t* block = magic_gen4_is_block_num_trailer(i) ? MAGIC_DEFAULT_SECTOR_TRAILER : MAGIC_EMPTY_BLOCK; + if(!magic_gen4_write_blk(pwd, i, block)) { + FURI_LOG_E(TAG, "Block %d write failed", i); + return false; + } + } + for(size_t i = 65; i < 256; i++) { + if(!magic_gen4_write_blk(pwd, i, MAGIC_EMPTY_BLOCK)) { + FURI_LOG_E(TAG, "Block %d write failed", i); + return false; + } + } + + return true; +} \ No newline at end of file diff --git a/applications/external/nfc_magic/lib/magic/gen4.h b/applications/external/nfc_magic/lib/magic/gen4.h new file mode 100644 index 000000000..c515af820 --- /dev/null +++ b/applications/external/nfc_magic/lib/magic/gen4.h @@ -0,0 +1,48 @@ +#pragma once + +#include + +#define MAGIC_GEN4_DEFAULT_PWD 0x00000000 +#define MAGIC_GEN4_CONFIG_LEN 32 + +#define NFCID1_SINGLE_SIZE 4 +#define NFCID1_DOUBLE_SIZE 7 +#define NFCID1_TRIPLE_SIZE 10 + +typedef enum { + MagicGen4UIDLengthSingle = 0x00, + MagicGen4UIDLengthDouble = 0x01, + MagicGen4UIDLengthTriple = 0x02 +} MagicGen4UIDLength; + +typedef enum { + MagicGen4UltralightModeUL_EV1 = 0x00, + MagicGen4UltralightModeNTAG = 0x01, + MagicGen4UltralightModeUL_C = 0x02, + MagicGen4UltralightModeUL = 0x03 +} MagicGen4UltralightMode; + +typedef enum { + // for writing original (shadow) data + MagicGen4ShadowModePreWrite = 0x00, + // written data can be read once before restored to original + MagicGen4ShadowModeRestore = 0x01, + // written data is discarded + MagicGen4ShadowModeIgnore = 0x02, + // apparently for UL? + MagicGen4ShadowModeHighSpeedIgnore = 0x03 +} MagicGen4ShadowMode; + +bool magic_gen4_get_cfg(uint32_t pwd, uint8_t* config); + +bool magic_gen4_set_cfg(uint32_t pwd, const uint8_t* config, uint8_t config_length, bool fuse); + +bool magic_gen4_set_pwd(uint32_t old_pwd, uint32_t new_pwd); + +bool magic_gen4_read_blk(uint32_t pwd, uint8_t block_num, uint8_t* data); + +bool magic_gen4_write_blk(uint32_t pwd, uint8_t block_num, const uint8_t* data); + +bool magic_gen4_wipe(uint32_t pwd); + +void magic_gen4_deactivate(); diff --git a/applications/external/nfc_magic/lib/magic/magic.c b/applications/external/nfc_magic/lib/magic/magic.c index 9a71daaa0..ebd2b0805 100644 --- a/applications/external/nfc_magic/lib/magic/magic.c +++ b/applications/external/nfc_magic/lib/magic/magic.c @@ -1,4 +1,4 @@ -#include "magic.h" +#include "classic_gen1.h" #include @@ -15,7 +15,7 @@ #define MAGIC_BUFFER_SIZE (32) -bool magic_wupa() { +bool magic_gen1_wupa() { bool magic_activated = false; uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; @@ -23,19 +23,6 @@ bool magic_wupa() { FuriHalNfcReturn ret = 0; do { - // Setup nfc poller - furi_hal_nfc_exit_sleep(); - furi_hal_nfc_ll_txrx_on(); - furi_hal_nfc_ll_poll(); - ret = furi_hal_nfc_ll_set_mode( - FuriHalNfcModePollNfca, FuriHalNfcBitrate106, FuriHalNfcBitrate106); - if(ret != FuriHalNfcReturnOk) break; - - furi_hal_nfc_ll_set_fdt_listen(FURI_HAL_NFC_LL_FDT_LISTEN_NFCA_POLLER); - furi_hal_nfc_ll_set_fdt_poll(FURI_HAL_NFC_LL_FDT_POLL_NFCA_POLLER); - furi_hal_nfc_ll_set_error_handling(FuriHalNfcErrorHandlingNfc); - furi_hal_nfc_ll_set_guard_time(FURI_HAL_NFC_LL_GT_NFCA); - // Start communication tx_data[0] = MAGIC_CMD_WUPA; ret = furi_hal_nfc_ll_txrx_bits( @@ -53,15 +40,10 @@ bool magic_wupa() { magic_activated = true; } while(false); - if(!magic_activated) { - furi_hal_nfc_ll_txrx_off(); - furi_hal_nfc_start_sleep(); - } - return magic_activated; } -bool magic_data_access_cmd() { +bool magic_gen1_data_access_cmd() { bool write_cmd_success = false; uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; @@ -86,15 +68,10 @@ bool magic_data_access_cmd() { write_cmd_success = true; } while(false); - if(!write_cmd_success) { - furi_hal_nfc_ll_txrx_off(); - furi_hal_nfc_start_sleep(); - } - return write_cmd_success; } -bool magic_read_block(uint8_t block_num, MfClassicBlock* data) { +bool magic_gen1_read_block(uint8_t block_num, MfClassicBlock* data) { furi_assert(data); bool read_success = false; @@ -122,15 +99,10 @@ bool magic_read_block(uint8_t block_num, MfClassicBlock* data) { read_success = true; } while(false); - if(!read_success) { - furi_hal_nfc_ll_txrx_off(); - furi_hal_nfc_start_sleep(); - } - return read_success; } -bool magic_write_blk(uint8_t block_num, MfClassicBlock* data) { +bool magic_gen1_write_blk(uint8_t block_num, MfClassicBlock* data) { furi_assert(data); bool write_success = false; @@ -170,15 +142,10 @@ bool magic_write_blk(uint8_t block_num, MfClassicBlock* data) { write_success = true; } while(false); - if(!write_success) { - furi_hal_nfc_ll_txrx_off(); - furi_hal_nfc_start_sleep(); - } - return write_success; } -bool magic_wipe() { +bool magic_gen1_wipe() { bool wipe_success = false; uint8_t tx_data[MAGIC_BUFFER_SIZE] = {}; uint8_t rx_data[MAGIC_BUFFER_SIZE] = {}; @@ -205,9 +172,4 @@ bool magic_wipe() { } while(false); return wipe_success; -} - -void magic_deactivate() { - furi_hal_nfc_ll_txrx_off(); - furi_hal_nfc_sleep(); -} +} \ No newline at end of file diff --git a/applications/external/nfc_magic/lib/magic/magic.h b/applications/external/nfc_magic/lib/magic/magic.h deleted file mode 100644 index 64c60a0a7..000000000 --- a/applications/external/nfc_magic/lib/magic/magic.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include - -bool magic_wupa(); - -bool magic_read_block(uint8_t block_num, MfClassicBlock* data); - -bool magic_data_access_cmd(); - -bool magic_write_blk(uint8_t block_num, MfClassicBlock* data); - -bool magic_wipe(); - -void magic_deactivate(); diff --git a/applications/external/nfc_magic/lib/magic/types.c b/applications/external/nfc_magic/lib/magic/types.c new file mode 100644 index 000000000..77c6c0a4e --- /dev/null +++ b/applications/external/nfc_magic/lib/magic/types.c @@ -0,0 +1,23 @@ +#include "types.h" + +const char* nfc_magic_type(MagicType type) { + if(type == MagicTypeClassicGen1) { + return "Classic Gen 1A/B"; + } else if(type == MagicTypeClassicDirectWrite) { + return "Classic DirectWrite"; + } else if(type == MagicTypeClassicAPDU) { + return "Classic APDU"; + } else if(type == MagicTypeUltralightGen1) { + return "Ultralight Gen 1"; + } else if(type == MagicTypeUltralightDirectWrite) { + return "Ultralight DirectWrite"; + } else if(type == MagicTypeUltralightC_Gen1) { + return "Ultralight-C Gen 1"; + } else if(type == MagicTypeUltralightC_DirectWrite) { + return "Ultralight-C DirectWrite"; + } else if(type == MagicTypeGen4) { + return "Gen 4 GTU"; + } else { + return "Unknown"; + } +} diff --git a/applications/external/nfc_magic/lib/magic/types.h b/applications/external/nfc_magic/lib/magic/types.h new file mode 100644 index 000000000..dbf554063 --- /dev/null +++ b/applications/external/nfc_magic/lib/magic/types.h @@ -0,0 +1,5 @@ +#pragma once + +#include "common.h" + +const char* nfc_magic_type(MagicType type); \ No newline at end of file diff --git a/applications/external/nfc_magic/nfc_magic.c b/applications/external/nfc_magic/nfc_magic.c index 1805f35ed..68c9a65b5 100644 --- a/applications/external/nfc_magic/nfc_magic.c +++ b/applications/external/nfc_magic/nfc_magic.c @@ -48,8 +48,9 @@ NfcMagic* nfc_magic_alloc() { nfc_magic->view_dispatcher, nfc_magic_tick_event_callback, 100); // Nfc device - nfc_magic->nfc_dev = nfc_device_alloc(); - furi_string_set(nfc_magic->nfc_dev->folder, NFC_APP_FOLDER); + nfc_magic->dev = malloc(sizeof(NfcMagicDevice)); + nfc_magic->source_dev = nfc_device_alloc(); + furi_string_set(nfc_magic->source_dev->folder, NFC_APP_FOLDER); // Open GUI record nfc_magic->gui = furi_record_open(RECORD_GUI); @@ -81,6 +82,13 @@ NfcMagic* nfc_magic_alloc() { NfcMagicViewTextInput, text_input_get_view(nfc_magic->text_input)); + // Byte Input + nfc_magic->byte_input = byte_input_alloc(); + view_dispatcher_add_view( + nfc_magic->view_dispatcher, + NfcMagicViewByteInput, + byte_input_get_view(nfc_magic->byte_input)); + // Custom Widget nfc_magic->widget = widget_alloc(); view_dispatcher_add_view( @@ -93,7 +101,8 @@ void nfc_magic_free(NfcMagic* nfc_magic) { furi_assert(nfc_magic); // Nfc device - nfc_device_free(nfc_magic->nfc_dev); + free(nfc_magic->dev); + nfc_device_free(nfc_magic->source_dev); // Submenu view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewMenu); @@ -107,10 +116,14 @@ void nfc_magic_free(NfcMagic* nfc_magic) { view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewLoading); loading_free(nfc_magic->loading); - // TextInput + // Text Input view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewTextInput); text_input_free(nfc_magic->text_input); + // Byte Input + view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewByteInput); + byte_input_free(nfc_magic->byte_input); + // Custom Widget view_dispatcher_remove_view(nfc_magic->view_dispatcher, NfcMagicViewWidget); widget_free(nfc_magic->widget); @@ -164,6 +177,7 @@ int32_t nfc_magic_app(void* p) { view_dispatcher_run(nfc_magic->view_dispatcher); + magic_deactivate(); nfc_magic_free(nfc_magic); return 0; diff --git a/applications/external/nfc_magic/nfc_magic.h b/applications/external/nfc_magic/nfc_magic.h index 1abf1371e..f9cf395d8 100644 --- a/applications/external/nfc_magic/nfc_magic.h +++ b/applications/external/nfc_magic/nfc_magic.h @@ -1,3 +1,5 @@ #pragma once +typedef struct NfcMagicDevice NfcMagicDevice; + typedef struct NfcMagic NfcMagic; diff --git a/applications/external/nfc_magic/nfc_magic_i.h b/applications/external/nfc_magic/nfc_magic_i.h index 378912e5b..4d6b89103 100644 --- a/applications/external/nfc_magic/nfc_magic_i.h +++ b/applications/external/nfc_magic/nfc_magic_i.h @@ -3,7 +3,10 @@ #include "nfc_magic.h" #include "nfc_magic_worker.h" -#include "lib/magic/magic.h" +#include "lib/magic/common.h" +#include "lib/magic/types.h" +#include "lib/magic/classic_gen1.h" +#include "lib/magic/gen4.h" #include #include @@ -15,6 +18,7 @@ #include #include #include +#include #include #include @@ -39,14 +43,22 @@ enum NfcMagicCustomEvent { NfcMagicCustomEventTextInputDone, }; +struct NfcMagicDevice { + MagicType type; + uint32_t cuid; + uint32_t password; +}; + struct NfcMagic { NfcMagicWorker* worker; ViewDispatcher* view_dispatcher; Gui* gui; NotificationApp* notifications; SceneManager* scene_manager; - // NfcMagicDevice* dev; - NfcDevice* nfc_dev; + struct NfcMagicDevice* dev; + NfcDevice* source_dev; + + uint32_t new_password; FuriString* text_box_store; @@ -55,6 +67,7 @@ struct NfcMagic { Popup* popup; Loading* loading; TextInput* text_input; + ByteInput* byte_input; Widget* widget; }; @@ -63,6 +76,7 @@ typedef enum { NfcMagicViewPopup, NfcMagicViewLoading, NfcMagicViewTextInput, + NfcMagicViewByteInput, NfcMagicViewWidget, } NfcMagicView; diff --git a/applications/external/nfc_magic/nfc_magic_worker.c b/applications/external/nfc_magic/nfc_magic_worker.c index 1564c87cd..cc13476c4 100644 --- a/applications/external/nfc_magic/nfc_magic_worker.c +++ b/applications/external/nfc_magic/nfc_magic_worker.c @@ -1,6 +1,9 @@ #include "nfc_magic_worker_i.h" -#include "lib/magic/magic.h" +#include "nfc_magic_i.h" +#include "lib/magic/common.h" +#include "lib/magic/classic_gen1.h" +#include "lib/magic/gen4.h" #define TAG "NfcMagicWorker" @@ -43,10 +46,13 @@ void nfc_magic_worker_stop(NfcMagicWorker* nfc_magic_worker) { void nfc_magic_worker_start( NfcMagicWorker* nfc_magic_worker, NfcMagicWorkerState state, + NfcMagicDevice* magic_dev, NfcDeviceData* dev_data, + uint32_t new_password, NfcMagicWorkerCallback callback, void* context) { furi_assert(nfc_magic_worker); + furi_assert(magic_dev); furi_assert(dev_data); furi_hal_nfc_deinit(); @@ -54,7 +60,9 @@ void nfc_magic_worker_start( nfc_magic_worker->callback = callback; nfc_magic_worker->context = context; + nfc_magic_worker->magic_dev = magic_dev; nfc_magic_worker->dev_data = dev_data; + nfc_magic_worker->new_password = new_password; nfc_magic_worker_change_state(nfc_magic_worker, state); furi_thread_start(nfc_magic_worker->thread); } @@ -66,6 +74,8 @@ int32_t nfc_magic_worker_task(void* context) { nfc_magic_worker_check(nfc_magic_worker); } else if(nfc_magic_worker->state == NfcMagicWorkerStateWrite) { nfc_magic_worker_write(nfc_magic_worker); + } else if(nfc_magic_worker->state == NfcMagicWorkerStateRekey) { + nfc_magic_worker_rekey(nfc_magic_worker); } else if(nfc_magic_worker->state == NfcMagicWorkerStateWipe) { nfc_magic_worker_wipe(nfc_magic_worker); } @@ -77,59 +87,245 @@ int32_t nfc_magic_worker_task(void* context) { void nfc_magic_worker_write(NfcMagicWorker* nfc_magic_worker) { bool card_found_notified = false; + bool done = false; FuriHalNfcDevData nfc_data = {}; - MfClassicData* src_data = &nfc_magic_worker->dev_data->mf_classic_data; + NfcMagicDevice* magic_dev = nfc_magic_worker->magic_dev; + NfcDeviceData* dev_data = nfc_magic_worker->dev_data; + NfcProtocol dev_protocol = dev_data->protocol; while(nfc_magic_worker->state == NfcMagicWorkerStateWrite) { - if(furi_hal_nfc_detect(&nfc_data, 200)) { - if(!card_found_notified) { - nfc_magic_worker->callback( - NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); - card_found_notified = true; - } - furi_hal_nfc_sleep(); - if(!magic_wupa()) { - FURI_LOG_E(TAG, "No card response to WUPA (not a magic card)"); - nfc_magic_worker->callback( - NfcMagicWorkerEventWrongCard, nfc_magic_worker->context); - break; - } - furi_hal_nfc_sleep(); - } - if(magic_wupa()) { - if(!magic_data_access_cmd()) { - FURI_LOG_E(TAG, "No card response to data access command (not a magic card)"); - nfc_magic_worker->callback( - NfcMagicWorkerEventWrongCard, nfc_magic_worker->context); - break; - } - for(size_t i = 0; i < 64; i++) { - FURI_LOG_D(TAG, "Writing block %d", i); - if(!magic_write_blk(i, &src_data->block[i])) { - FURI_LOG_E(TAG, "Failed to write %d block", i); - nfc_magic_worker->callback(NfcMagicWorkerEventFail, nfc_magic_worker->context); + do { + if(furi_hal_nfc_detect(&nfc_data, 200)) { + if(nfc_data.cuid != magic_dev->cuid) break; + if(!card_found_notified) { + nfc_magic_worker->callback( + NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); + card_found_notified = true; + } + furi_hal_nfc_sleep(); + + magic_activate(); + if(magic_dev->type == MagicTypeClassicGen1) { + if(dev_protocol != NfcDeviceProtocolMifareClassic) break; + MfClassicData* mfc_data = &dev_data->mf_classic_data; + + if(mfc_data->type != MfClassicType1k) break; + if(!magic_gen1_wupa()) { + FURI_LOG_E(TAG, "Not Magic card"); + nfc_magic_worker->callback( + NfcMagicWorkerEventWrongCard, nfc_magic_worker->context); + done = true; + break; + } + if(!magic_gen1_data_access_cmd()) { + FURI_LOG_E(TAG, "Not Magic card"); + nfc_magic_worker->callback( + NfcMagicWorkerEventWrongCard, nfc_magic_worker->context); + done = true; + break; + } + for(size_t i = 0; i < 64; i++) { + FURI_LOG_D(TAG, "Writing block %d", i); + if(!magic_gen1_write_blk(i, &mfc_data->block[i])) { + FURI_LOG_E(TAG, "Failed to write %d block", i); + nfc_magic_worker->callback( + NfcMagicWorkerEventFail, nfc_magic_worker->context); + done = true; + break; + } + } + + nfc_magic_worker->callback( + NfcMagicWorkerEventSuccess, nfc_magic_worker->context); + done = true; + break; + } else if(magic_dev->type == MagicTypeGen4) { + uint8_t gen4_config[28]; + uint32_t password = magic_dev->password; + + uint32_t cuid; + if(dev_protocol == NfcDeviceProtocolMifareClassic) { + gen4_config[0] = 0x00; + gen4_config[27] = 0x00; + } else if(dev_protocol == NfcDeviceProtocolMifareUl) { + MfUltralightData* mf_ul_data = &dev_data->mf_ul_data; + gen4_config[0] = 0x01; + switch(mf_ul_data->type) { + case MfUltralightTypeUL11: + case MfUltralightTypeUL21: + // UL-C? + // UL? + default: + gen4_config[27] = MagicGen4UltralightModeUL_EV1; + break; + case MfUltralightTypeNTAG203: + case MfUltralightTypeNTAG213: + case MfUltralightTypeNTAG215: + case MfUltralightTypeNTAG216: + case MfUltralightTypeNTAGI2C1K: + case MfUltralightTypeNTAGI2C2K: + case MfUltralightTypeNTAGI2CPlus1K: + case MfUltralightTypeNTAGI2CPlus2K: + gen4_config[27] = MagicGen4UltralightModeNTAG; + break; + } + } + + if(dev_data->nfc_data.uid_len == 4) { + gen4_config[1] = MagicGen4UIDLengthSingle; + } else if(dev_data->nfc_data.uid_len == 7) { + gen4_config[1] = MagicGen4UIDLengthDouble; + } else { + FURI_LOG_E(TAG, "Unexpected UID length %d", dev_data->nfc_data.uid_len); + nfc_magic_worker->callback( + NfcMagicWorkerEventFail, nfc_magic_worker->context); + done = true; + break; + } + + gen4_config[2] = (uint8_t)(password >> 24); + gen4_config[3] = (uint8_t)(password >> 16); + gen4_config[4] = (uint8_t)(password >> 8); + gen4_config[5] = (uint8_t)password; + + if(dev_protocol == NfcDeviceProtocolMifareUl) { + gen4_config[6] = MagicGen4ShadowModeHighSpeedIgnore; + } else { + gen4_config[6] = MagicGen4ShadowModeIgnore; + } + gen4_config[7] = 0x00; + memset(gen4_config + 8, 0, 16); + gen4_config[24] = dev_data->nfc_data.atqa[0]; + gen4_config[25] = dev_data->nfc_data.atqa[1]; + gen4_config[26] = dev_data->nfc_data.sak; + + furi_hal_nfc_activate_nfca(200, &cuid); + if(!magic_gen4_set_cfg(password, gen4_config, sizeof(gen4_config), false)) { + nfc_magic_worker->callback( + NfcMagicWorkerEventFail, nfc_magic_worker->context); + done = true; + break; + } + if(dev_protocol == NfcDeviceProtocolMifareClassic) { + MfClassicData* mfc_data = &dev_data->mf_classic_data; + size_t block_count = 64; + if(mfc_data->type == MfClassicType4k) block_count = 256; + for(size_t i = 0; i < block_count; i++) { + FURI_LOG_D(TAG, "Writing block %d", i); + if(!magic_gen4_write_blk(password, i, mfc_data->block[i].value)) { + FURI_LOG_E(TAG, "Failed to write %d block", i); + nfc_magic_worker->callback( + NfcMagicWorkerEventFail, nfc_magic_worker->context); + done = true; + break; + } + } + } else if(dev_protocol == NfcDeviceProtocolMifareUl) { + MfUltralightData* mf_ul_data = &dev_data->mf_ul_data; + for(size_t i = 0; (i * 4) < mf_ul_data->data_read; i++) { + size_t data_offset = i * 4; + FURI_LOG_D( + TAG, + "Writing page %zu (%zu/%u)", + i, + data_offset, + mf_ul_data->data_read); + uint8_t* block = mf_ul_data->data + data_offset; + if(!magic_gen4_write_blk(password, i, block)) { + FURI_LOG_E(TAG, "Failed to write %zu page", i); + nfc_magic_worker->callback( + NfcMagicWorkerEventFail, nfc_magic_worker->context); + done = true; + break; + } + } + + uint8_t buffer[16] = {0}; + + for(size_t i = 0; i < 8; i++) { + memcpy(buffer, &mf_ul_data->signature[i * 4], 4); //-V1086 + if(!magic_gen4_write_blk(password, 0xF2 + i, buffer)) { + FURI_LOG_E(TAG, "Failed to write signature block %d", i); + nfc_magic_worker->callback( + NfcMagicWorkerEventFail, nfc_magic_worker->context); + done = true; + break; + } + } + + buffer[0] = mf_ul_data->version.header; + buffer[1] = mf_ul_data->version.vendor_id; + buffer[2] = mf_ul_data->version.prod_type; + buffer[3] = mf_ul_data->version.prod_subtype; + if(!magic_gen4_write_blk(password, 0xFA, buffer)) { + FURI_LOG_E(TAG, "Failed to write version block 0"); + nfc_magic_worker->callback( + NfcMagicWorkerEventFail, nfc_magic_worker->context); + done = true; + break; + } + + buffer[0] = mf_ul_data->version.prod_ver_major; + buffer[1] = mf_ul_data->version.prod_ver_minor; + buffer[2] = mf_ul_data->version.storage_size; + buffer[3] = mf_ul_data->version.protocol_type; + if(!magic_gen4_write_blk(password, 0xFB, buffer)) { + FURI_LOG_E(TAG, "Failed to write version block 1"); + nfc_magic_worker->callback( + NfcMagicWorkerEventFail, nfc_magic_worker->context); + done = true; + break; + } + } + + nfc_magic_worker->callback( + NfcMagicWorkerEventSuccess, nfc_magic_worker->context); + done = true; break; } } - nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); - break; - } else { - if(card_found_notified) { - nfc_magic_worker->callback( - NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context); - card_found_notified = false; - } + } while(false); + + if(done) break; + + if(card_found_notified) { + nfc_magic_worker->callback( + NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context); + card_found_notified = false; } + furi_delay_ms(300); } magic_deactivate(); } void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker) { + NfcMagicDevice* magic_dev = nfc_magic_worker->magic_dev; bool card_found_notified = false; + uint8_t gen4_config[MAGIC_GEN4_CONFIG_LEN]; while(nfc_magic_worker->state == NfcMagicWorkerStateCheck) { - if(magic_wupa()) { + magic_activate(); + if(magic_gen1_wupa()) { + magic_dev->type = MagicTypeClassicGen1; + if(!card_found_notified) { + nfc_magic_worker->callback( + NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); + card_found_notified = true; + } + + furi_hal_nfc_activate_nfca(200, &magic_dev->cuid); + nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); + break; + } + + magic_deactivate(); + furi_delay_ms(300); + magic_activate(); + + furi_hal_nfc_activate_nfca(200, &magic_dev->cuid); + if(magic_gen4_get_cfg(magic_dev->password, gen4_config)) { + magic_dev->type = MagicTypeGen4; if(!card_found_notified) { nfc_magic_worker->callback( NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); @@ -138,12 +334,56 @@ void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker) { nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); break; - } else { + } + + if(card_found_notified) { + nfc_magic_worker->callback( + NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context); + card_found_notified = false; + } + + magic_deactivate(); + furi_delay_ms(300); + } + + magic_deactivate(); +} + +void nfc_magic_worker_rekey(NfcMagicWorker* nfc_magic_worker) { + NfcMagicDevice* magic_dev = nfc_magic_worker->magic_dev; + bool card_found_notified = false; + + if(magic_dev->type != MagicTypeGen4) { + nfc_magic_worker->callback(NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); + return; + } + + while(nfc_magic_worker->state == NfcMagicWorkerStateRekey) { + magic_activate(); + uint32_t cuid; + furi_hal_nfc_activate_nfca(200, &cuid); + if(cuid != magic_dev->cuid) { if(card_found_notified) { nfc_magic_worker->callback( NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context); card_found_notified = false; } + continue; + } + + nfc_magic_worker->callback(NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); + card_found_notified = true; + + if(magic_gen4_set_pwd(magic_dev->password, nfc_magic_worker->new_password)) { + magic_dev->password = nfc_magic_worker->new_password; + nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); + break; + } + + if(card_found_notified) { //-V547 + nfc_magic_worker->callback( + NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context); + card_found_notified = false; } furi_delay_ms(300); } @@ -151,6 +391,10 @@ void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker) { } void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker) { + NfcMagicDevice* magic_dev = nfc_magic_worker->magic_dev; + bool card_found_notified = false; + bool card_wiped = false; + MfClassicBlock block; memset(&block, 0, sizeof(MfClassicBlock)); block.value[0] = 0x01; @@ -162,14 +406,48 @@ void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker) { block.value[6] = 0x04; while(nfc_magic_worker->state == NfcMagicWorkerStateWipe) { - magic_deactivate(); - furi_delay_ms(300); - if(!magic_wupa()) continue; - if(!magic_wipe()) continue; - if(!magic_data_access_cmd()) continue; - if(!magic_write_blk(0, &block)) continue; - nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); - break; + do { + magic_deactivate(); + furi_delay_ms(300); + if(!magic_activate()) break; + if(magic_dev->type == MagicTypeClassicGen1) { + if(!magic_gen1_wupa()) break; + if(!card_found_notified) { + nfc_magic_worker->callback( + NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); + card_found_notified = true; + } + + if(!magic_gen1_wipe()) break; + if(!magic_gen1_data_access_cmd()) break; + if(!magic_gen1_write_blk(0, &block)) break; + + card_wiped = true; + nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); + } else if(magic_dev->type == MagicTypeGen4) { + uint32_t cuid; + if(!furi_hal_nfc_activate_nfca(200, &cuid)) break; + if(cuid != magic_dev->cuid) break; + if(!card_found_notified) { + nfc_magic_worker->callback( + NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); + card_found_notified = true; + } + + if(!magic_gen4_wipe(magic_dev->password)) break; + + card_wiped = true; + nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); + } + } while(false); + + if(card_wiped) break; + + if(card_found_notified) { + nfc_magic_worker->callback( + NfcMagicWorkerEventNoCardDetected, nfc_magic_worker->context); + card_found_notified = false; + } } magic_deactivate(); } diff --git a/applications/external/nfc_magic/nfc_magic_worker.h b/applications/external/nfc_magic/nfc_magic_worker.h index 9d29bb3a8..51ff4ee43 100644 --- a/applications/external/nfc_magic/nfc_magic_worker.h +++ b/applications/external/nfc_magic/nfc_magic_worker.h @@ -1,6 +1,7 @@ #pragma once #include +#include "nfc_magic.h" typedef struct NfcMagicWorker NfcMagicWorker; @@ -9,6 +10,7 @@ typedef enum { NfcMagicWorkerStateCheck, NfcMagicWorkerStateWrite, + NfcMagicWorkerStateRekey, NfcMagicWorkerStateWipe, NfcMagicWorkerStateStop, @@ -33,6 +35,8 @@ void nfc_magic_worker_stop(NfcMagicWorker* nfc_magic_worker); void nfc_magic_worker_start( NfcMagicWorker* nfc_magic_worker, NfcMagicWorkerState state, + NfcMagicDevice* magic_dev, NfcDeviceData* dev_data, + uint32_t new_password, NfcMagicWorkerCallback callback, void* context); diff --git a/applications/external/nfc_magic/nfc_magic_worker_i.h b/applications/external/nfc_magic/nfc_magic_worker_i.h index 0cde2e712..a354f8047 100644 --- a/applications/external/nfc_magic/nfc_magic_worker_i.h +++ b/applications/external/nfc_magic/nfc_magic_worker_i.h @@ -3,11 +3,14 @@ #include #include "nfc_magic_worker.h" +#include "lib/magic/common.h" struct NfcMagicWorker { FuriThread* thread; + NfcMagicDevice* magic_dev; NfcDeviceData* dev_data; + uint32_t new_password; NfcMagicWorkerCallback callback; void* context; @@ -21,4 +24,6 @@ void nfc_magic_worker_check(NfcMagicWorker* nfc_magic_worker); void nfc_magic_worker_write(NfcMagicWorker* nfc_magic_worker); +void nfc_magic_worker_rekey(NfcMagicWorker* nfc_magic_worker); + void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker); diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_actions.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_actions.c new file mode 100644 index 000000000..675262a9b --- /dev/null +++ b/applications/external/nfc_magic/scenes/nfc_magic_scene_actions.c @@ -0,0 +1,50 @@ +#include "../nfc_magic_i.h" +enum SubmenuIndex { + SubmenuIndexWrite, + SubmenuIndexWipe, +}; + +void nfc_magic_scene_actions_submenu_callback(void* context, uint32_t index) { + NfcMagic* nfc_magic = context; + view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, index); +} + +void nfc_magic_scene_actions_on_enter(void* context) { + NfcMagic* nfc_magic = context; + + Submenu* submenu = nfc_magic->submenu; + submenu_add_item( + submenu, "Write", SubmenuIndexWrite, nfc_magic_scene_actions_submenu_callback, nfc_magic); + submenu_add_item( + submenu, "Wipe", SubmenuIndexWipe, nfc_magic_scene_actions_submenu_callback, nfc_magic); + + submenu_set_selected_item( + submenu, scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneActions)); + view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewMenu); +} + +bool nfc_magic_scene_actions_on_event(void* context, SceneManagerEvent event) { + NfcMagic* nfc_magic = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubmenuIndexWrite) { + scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneFileSelect); + consumed = true; + } else if(event.event == SubmenuIndexWipe) { + scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWipe); + consumed = true; + } + scene_manager_set_scene_state(nfc_magic->scene_manager, NfcMagicSceneActions, event.event); + } else if(event.type == SceneManagerEventTypeBack) { + consumed = scene_manager_search_and_switch_to_previous_scene( + nfc_magic->scene_manager, NfcMagicSceneStart); + } + + return consumed; +} + +void nfc_magic_scene_actions_on_exit(void* context) { + NfcMagic* nfc_magic = context; + submenu_reset(nfc_magic->submenu); +} diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_check.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_check.c index d51797242..90b43d7d3 100644 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_check.c +++ b/applications/external/nfc_magic/scenes/nfc_magic_scene_check.c @@ -42,7 +42,9 @@ void nfc_magic_scene_check_on_enter(void* context) { nfc_magic_worker_start( nfc_magic->worker, NfcMagicWorkerStateCheck, - &nfc_magic->nfc_dev->dev_data, + nfc_magic->dev, + &nfc_magic->source_dev->dev_data, + nfc_magic->new_password, nfc_magic_check_worker_callback, nfc_magic); nfc_magic_blink_start(nfc_magic); diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_config.h b/applications/external/nfc_magic/scenes/nfc_magic_scene_config.h index 557e26914..2f9860d96 100644 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_config.h +++ b/applications/external/nfc_magic/scenes/nfc_magic_scene_config.h @@ -1,4 +1,8 @@ ADD_SCENE(nfc_magic, start, Start) +ADD_SCENE(nfc_magic, key_input, KeyInput) +ADD_SCENE(nfc_magic, actions, Actions) +ADD_SCENE(nfc_magic, gen4_actions, Gen4Actions) +ADD_SCENE(nfc_magic, new_key_input, NewKeyInput) ADD_SCENE(nfc_magic, file_select, FileSelect) ADD_SCENE(nfc_magic, write_confirm, WriteConfirm) ADD_SCENE(nfc_magic, wrong_card, WrongCard) @@ -8,5 +12,7 @@ ADD_SCENE(nfc_magic, success, Success) ADD_SCENE(nfc_magic, check, Check) ADD_SCENE(nfc_magic, not_magic, NotMagic) ADD_SCENE(nfc_magic, magic_info, MagicInfo) +ADD_SCENE(nfc_magic, rekey, Rekey) +ADD_SCENE(nfc_magic, rekey_fail, RekeyFail) ADD_SCENE(nfc_magic, wipe, Wipe) ADD_SCENE(nfc_magic, wipe_fail, WipeFail) diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_file_select.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_file_select.c index d78422eeb..baa6bcccc 100644 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_file_select.c +++ b/applications/external/nfc_magic/scenes/nfc_magic_scene_file_select.c @@ -1,22 +1,60 @@ #include "../nfc_magic_i.h" -static bool nfc_magic_scene_file_select_is_file_suitable(NfcDevice* nfc_dev) { - return (nfc_dev->format == NfcDeviceSaveFormatMifareClassic) && - (nfc_dev->dev_data.mf_classic_data.type == MfClassicType1k) && - (nfc_dev->dev_data.nfc_data.uid_len == 4); +static bool nfc_magic_scene_file_select_is_file_suitable(NfcMagic* nfc_magic) { + NfcDevice* nfc_dev = nfc_magic->source_dev; + if(nfc_dev->format == NfcDeviceSaveFormatMifareClassic) { + switch(nfc_magic->dev->type) { + case MagicTypeClassicGen1: + case MagicTypeClassicDirectWrite: + case MagicTypeClassicAPDU: + if((nfc_dev->dev_data.mf_classic_data.type != MfClassicType1k) || + (nfc_dev->dev_data.nfc_data.uid_len != 4)) { + return false; + } + return true; + + case MagicTypeGen4: + return true; + default: + return false; + } + } else if( + (nfc_dev->format == NfcDeviceSaveFormatMifareUl) && + (nfc_dev->dev_data.nfc_data.uid_len == 7)) { + switch(nfc_magic->dev->type) { + case MagicTypeUltralightGen1: + case MagicTypeUltralightDirectWrite: + case MagicTypeUltralightC_Gen1: + case MagicTypeUltralightC_DirectWrite: + case MagicTypeGen4: + switch(nfc_dev->dev_data.mf_ul_data.type) { + case MfUltralightTypeNTAGI2C1K: + case MfUltralightTypeNTAGI2C2K: + case MfUltralightTypeNTAGI2CPlus1K: + case MfUltralightTypeNTAGI2CPlus2K: + return false; + default: + return true; + } + default: + return false; + } + } + + return false; } void nfc_magic_scene_file_select_on_enter(void* context) { NfcMagic* nfc_magic = context; // Process file_select return - nfc_device_set_loading_callback(nfc_magic->nfc_dev, nfc_magic_show_loading_popup, nfc_magic); + nfc_device_set_loading_callback( + nfc_magic->source_dev, nfc_magic_show_loading_popup, nfc_magic); - if(!furi_string_size(nfc_magic->nfc_dev->load_path)) { - furi_string_set_str(nfc_magic->nfc_dev->load_path, NFC_APP_FOLDER); + if(!furi_string_size(nfc_magic->source_dev->load_path)) { + furi_string_set_str(nfc_magic->source_dev->load_path, NFC_APP_FOLDER); } - - if(nfc_file_select(nfc_magic->nfc_dev)) { - if(nfc_magic_scene_file_select_is_file_suitable(nfc_magic->nfc_dev)) { + if(nfc_file_select(nfc_magic->source_dev)) { + if(nfc_magic_scene_file_select_is_file_suitable(nfc_magic)) { scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWriteConfirm); } else { scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWrongCard); @@ -34,5 +72,5 @@ bool nfc_magic_scene_file_select_on_event(void* context, SceneManagerEvent event void nfc_magic_scene_file_select_on_exit(void* context) { NfcMagic* nfc_magic = context; - nfc_device_set_loading_callback(nfc_magic->nfc_dev, NULL, nfc_magic); + nfc_device_set_loading_callback(nfc_magic->source_dev, NULL, nfc_magic); } diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_gen4_actions.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_gen4_actions.c new file mode 100644 index 000000000..ceaa33e29 --- /dev/null +++ b/applications/external/nfc_magic/scenes/nfc_magic_scene_gen4_actions.c @@ -0,0 +1,70 @@ +#include "../nfc_magic_i.h" +enum SubmenuIndex { + SubmenuIndexWrite, + SubmenuIndexChangePassword, + SubmenuIndexWipe, +}; + +void nfc_magic_scene_gen4_actions_submenu_callback(void* context, uint32_t index) { + NfcMagic* nfc_magic = context; + view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, index); +} + +void nfc_magic_scene_gen4_actions_on_enter(void* context) { + NfcMagic* nfc_magic = context; + + Submenu* submenu = nfc_magic->submenu; + submenu_add_item( + submenu, + "Write", + SubmenuIndexWrite, + nfc_magic_scene_gen4_actions_submenu_callback, + nfc_magic); + submenu_add_item( + submenu, + "Change password", + SubmenuIndexChangePassword, + nfc_magic_scene_gen4_actions_submenu_callback, + nfc_magic); + submenu_add_item( + submenu, + "Wipe", + SubmenuIndexWipe, + nfc_magic_scene_gen4_actions_submenu_callback, + nfc_magic); + + submenu_set_selected_item( + submenu, + scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneGen4Actions)); + view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewMenu); +} + +bool nfc_magic_scene_gen4_actions_on_event(void* context, SceneManagerEvent event) { + NfcMagic* nfc_magic = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubmenuIndexWrite) { + scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneFileSelect); + consumed = true; + } else if(event.event == SubmenuIndexChangePassword) { + scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneNewKeyInput); + consumed = true; + } else if(event.event == SubmenuIndexWipe) { + scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWipe); + consumed = true; + } + scene_manager_set_scene_state( + nfc_magic->scene_manager, NfcMagicSceneGen4Actions, event.event); + } else if(event.type == SceneManagerEventTypeBack) { + consumed = scene_manager_search_and_switch_to_previous_scene( + nfc_magic->scene_manager, NfcMagicSceneStart); + } + + return consumed; +} + +void nfc_magic_scene_gen4_actions_on_exit(void* context) { + NfcMagic* nfc_magic = context; + submenu_reset(nfc_magic->submenu); +} diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_key_input.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_key_input.c new file mode 100644 index 000000000..58b487a09 --- /dev/null +++ b/applications/external/nfc_magic/scenes/nfc_magic_scene_key_input.c @@ -0,0 +1,45 @@ +#include "../nfc_magic_i.h" + +void nfc_magic_scene_key_input_byte_input_callback(void* context) { + NfcMagic* nfc_magic = context; + + view_dispatcher_send_custom_event( + nfc_magic->view_dispatcher, NfcMagicCustomEventByteInputDone); +} + +void nfc_magic_scene_key_input_on_enter(void* context) { + NfcMagic* nfc_magic = context; + + // Setup view + ByteInput* byte_input = nfc_magic->byte_input; + byte_input_set_header_text(byte_input, "Enter the password in hex"); + byte_input_set_result_callback( + byte_input, + nfc_magic_scene_key_input_byte_input_callback, + NULL, + nfc_magic, + (uint8_t*)&nfc_magic->dev->password, + 4); + view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewByteInput); +} + +bool nfc_magic_scene_key_input_on_event(void* context, SceneManagerEvent event) { + NfcMagic* nfc_magic = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == NfcMagicCustomEventByteInputDone) { + scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneCheck); + consumed = true; + } + } + return consumed; +} + +void nfc_magic_scene_key_input_on_exit(void* context) { + NfcMagic* nfc_magic = context; + + // Clear view + byte_input_set_result_callback(nfc_magic->byte_input, NULL, NULL, NULL, NULL, 0); + byte_input_set_header_text(nfc_magic->byte_input, ""); +} diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_magic_info.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_magic_info.c index e9b226b3a..c147ac438 100644 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_magic_info.c +++ b/applications/external/nfc_magic/scenes/nfc_magic_scene_magic_info.c @@ -1,4 +1,5 @@ #include "../nfc_magic_i.h" +#include "../lib/magic/types.h" void nfc_magic_scene_magic_info_widget_callback( GuiButtonType result, @@ -13,14 +14,18 @@ void nfc_magic_scene_magic_info_widget_callback( void nfc_magic_scene_magic_info_on_enter(void* context) { NfcMagic* nfc_magic = context; Widget* widget = nfc_magic->widget; + const char* card_type = nfc_magic_type(nfc_magic->dev->type); notification_message(nfc_magic->notifications, &sequence_success); widget_add_icon_element(widget, 73, 17, &I_DolphinCommon_56x48); widget_add_string_element( widget, 3, 4, AlignLeft, AlignTop, FontPrimary, "Magic card detected"); + widget_add_string_element(widget, 3, 17, AlignLeft, AlignTop, FontSecondary, card_type); widget_add_button_element( widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_magic_info_widget_callback, nfc_magic); + widget_add_button_element( + widget, GuiButtonTypeRight, "More", nfc_magic_scene_magic_info_widget_callback, nfc_magic); // Setup and start worker view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget); @@ -33,6 +38,15 @@ bool nfc_magic_scene_magic_info_on_event(void* context, SceneManagerEvent event) if(event.type == SceneManagerEventTypeCustom) { if(event.event == GuiButtonTypeLeft) { consumed = scene_manager_previous_scene(nfc_magic->scene_manager); + } else if(event.event == GuiButtonTypeRight) { + MagicType type = nfc_magic->dev->type; + if(type == MagicTypeGen4) { + scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneGen4Actions); + consumed = true; + } else { + scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneActions); + consumed = true; + } } } return consumed; diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_new_key_input.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_new_key_input.c new file mode 100644 index 000000000..b5247f6c5 --- /dev/null +++ b/applications/external/nfc_magic/scenes/nfc_magic_scene_new_key_input.c @@ -0,0 +1,45 @@ +#include "../nfc_magic_i.h" + +void nfc_magic_scene_new_key_input_byte_input_callback(void* context) { + NfcMagic* nfc_magic = context; + + view_dispatcher_send_custom_event( + nfc_magic->view_dispatcher, NfcMagicCustomEventByteInputDone); +} + +void nfc_magic_scene_new_key_input_on_enter(void* context) { + NfcMagic* nfc_magic = context; + + // Setup view + ByteInput* byte_input = nfc_magic->byte_input; + byte_input_set_header_text(byte_input, "Enter the password in hex"); + byte_input_set_result_callback( + byte_input, + nfc_magic_scene_new_key_input_byte_input_callback, + NULL, + nfc_magic, + (uint8_t*)&nfc_magic->new_password, + 4); + view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewByteInput); +} + +bool nfc_magic_scene_new_key_input_on_event(void* context, SceneManagerEvent event) { + NfcMagic* nfc_magic = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == NfcMagicCustomEventByteInputDone) { + scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneRekey); + consumed = true; + } + } + return consumed; +} + +void nfc_magic_scene_new_key_input_on_exit(void* context) { + NfcMagic* nfc_magic = context; + + // Clear view + byte_input_set_result_callback(nfc_magic->byte_input, NULL, NULL, NULL, NULL, 0); + byte_input_set_header_text(nfc_magic->byte_input, ""); +} diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_rekey.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_rekey.c new file mode 100644 index 000000000..259dc78ea --- /dev/null +++ b/applications/external/nfc_magic/scenes/nfc_magic_scene_rekey.c @@ -0,0 +1,95 @@ +#include "../nfc_magic_i.h" + +enum { + NfcMagicSceneRekeyStateCardSearch, + NfcMagicSceneRekeyStateCardFound, +}; + +bool nfc_magic_rekey_worker_callback(NfcMagicWorkerEvent event, void* context) { + furi_assert(context); + + NfcMagic* nfc_magic = context; + view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, event); + + return true; +} + +static void nfc_magic_scene_rekey_setup_view(NfcMagic* nfc_magic) { + Popup* popup = nfc_magic->popup; + popup_reset(popup); + uint32_t state = scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneRekey); + + if(state == NfcMagicSceneRekeyStateCardSearch) { + popup_set_text( + nfc_magic->popup, + "Apply the\nsame card\nto the back", + 128, + 32, + AlignRight, + AlignCenter); + popup_set_icon(nfc_magic->popup, 0, 8, &I_NFC_manual_60x50); + } else { + popup_set_icon(popup, 12, 23, &I_Loading_24); + popup_set_header(popup, "Writing\nDon't move...", 52, 32, AlignLeft, AlignCenter); + } + + view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewPopup); +} + +void nfc_magic_scene_rekey_on_enter(void* context) { + NfcMagic* nfc_magic = context; + + scene_manager_set_scene_state( + nfc_magic->scene_manager, NfcMagicSceneRekey, NfcMagicSceneRekeyStateCardSearch); + nfc_magic_scene_rekey_setup_view(nfc_magic); + + // Setup and start worker + nfc_magic_worker_start( + nfc_magic->worker, + NfcMagicWorkerStateRekey, + nfc_magic->dev, + &nfc_magic->source_dev->dev_data, + nfc_magic->new_password, + nfc_magic_rekey_worker_callback, + nfc_magic); + nfc_magic_blink_start(nfc_magic); +} + +bool nfc_magic_scene_rekey_on_event(void* context, SceneManagerEvent event) { + NfcMagic* nfc_magic = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == NfcMagicWorkerEventSuccess) { + nfc_magic->dev->password = nfc_magic->new_password; + scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneSuccess); + consumed = true; + } else if(event.event == NfcMagicWorkerEventFail) { + scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneRekeyFail); + consumed = true; + } else if(event.event == NfcMagicWorkerEventCardDetected) { + scene_manager_set_scene_state( + nfc_magic->scene_manager, NfcMagicSceneRekey, NfcMagicSceneRekeyStateCardFound); + nfc_magic_scene_rekey_setup_view(nfc_magic); + consumed = true; + } else if(event.event == NfcMagicWorkerEventNoCardDetected) { + scene_manager_set_scene_state( + nfc_magic->scene_manager, NfcMagicSceneRekey, NfcMagicSceneRekeyStateCardSearch); + nfc_magic_scene_rekey_setup_view(nfc_magic); + consumed = true; + } + } + return consumed; +} + +void nfc_magic_scene_rekey_on_exit(void* context) { + NfcMagic* nfc_magic = context; + + nfc_magic_worker_stop(nfc_magic->worker); + scene_manager_set_scene_state( + nfc_magic->scene_manager, NfcMagicSceneRekey, NfcMagicSceneRekeyStateCardSearch); + // Clear view + popup_reset(nfc_magic->popup); + + nfc_magic_blink_stop(nfc_magic); +} diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_rekey_fail.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_rekey_fail.c new file mode 100644 index 000000000..d30ee57bc --- /dev/null +++ b/applications/external/nfc_magic/scenes/nfc_magic_scene_rekey_fail.c @@ -0,0 +1,50 @@ +#include "../nfc_magic_i.h" + +void nfc_magic_scene_rekey_fail_widget_callback( + GuiButtonType result, + InputType type, + void* context) { + NfcMagic* nfc_magic = context; + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(nfc_magic->view_dispatcher, result); + } +} + +void nfc_magic_scene_rekey_fail_on_enter(void* context) { + NfcMagic* nfc_magic = context; + Widget* widget = nfc_magic->widget; + + notification_message(nfc_magic->notifications, &sequence_error); + + widget_add_icon_element(widget, 72, 17, &I_DolphinCommon_56x48); + widget_add_string_element( + widget, 7, 4, AlignLeft, AlignTop, FontPrimary, "Can't change password!"); + + widget_add_button_element( + widget, GuiButtonTypeLeft, "Finish", nfc_magic_scene_rekey_fail_widget_callback, nfc_magic); + + // Setup and start worker + view_dispatcher_switch_to_view(nfc_magic->view_dispatcher, NfcMagicViewWidget); +} + +bool nfc_magic_scene_rekey_fail_on_event(void* context, SceneManagerEvent event) { + NfcMagic* nfc_magic = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == GuiButtonTypeLeft) { + consumed = scene_manager_search_and_switch_to_previous_scene( + nfc_magic->scene_manager, NfcMagicSceneStart); + } + } else if(event.type == SceneManagerEventTypeBack) { + consumed = scene_manager_search_and_switch_to_previous_scene( + nfc_magic->scene_manager, NfcMagicSceneStart); + } + return consumed; +} + +void nfc_magic_scene_rekey_fail_on_exit(void* context) { + NfcMagic* nfc_magic = context; + + widget_reset(nfc_magic->widget); +} diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_start.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_start.c index a70eb8acc..b5861629e 100644 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_start.c +++ b/applications/external/nfc_magic/scenes/nfc_magic_scene_start.c @@ -1,8 +1,7 @@ #include "../nfc_magic_i.h" enum SubmenuIndex { SubmenuIndexCheck, - SubmenuIndexWriteGen1A, - SubmenuIndexWipe, + SubmenuIndexAuthenticateGen4, }; void nfc_magic_scene_start_submenu_callback(void* context, uint32_t index) { @@ -22,12 +21,10 @@ void nfc_magic_scene_start_on_enter(void* context) { nfc_magic); submenu_add_item( submenu, - "Write Gen1A", - SubmenuIndexWriteGen1A, + "Authenticate Gen4", + SubmenuIndexAuthenticateGen4, nfc_magic_scene_start_submenu_callback, nfc_magic); - submenu_add_item( - submenu, "Wipe", SubmenuIndexWipe, nfc_magic_scene_start_submenu_callback, nfc_magic); submenu_set_selected_item( submenu, scene_manager_get_scene_state(nfc_magic->scene_manager, NfcMagicSceneStart)); @@ -40,23 +37,13 @@ bool nfc_magic_scene_start_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubmenuIndexCheck) { + nfc_magic->dev->password = MAGIC_GEN4_DEFAULT_PWD; scene_manager_set_scene_state( nfc_magic->scene_manager, NfcMagicSceneStart, SubmenuIndexCheck); scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneCheck); consumed = true; - } else if(event.event == SubmenuIndexWriteGen1A) { - // Explicitly save state in each branch so that the - // correct option is reselected if the user cancels - // loading a file. - scene_manager_set_scene_state( - nfc_magic->scene_manager, NfcMagicSceneStart, SubmenuIndexWriteGen1A); - scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneFileSelect); - consumed = true; - } else if(event.event == SubmenuIndexWipe) { - scene_manager_set_scene_state( - nfc_magic->scene_manager, NfcMagicSceneStart, SubmenuIndexWipe); - scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneWipe); - consumed = true; + } else if(event.event == SubmenuIndexAuthenticateGen4) { + scene_manager_next_scene(nfc_magic->scene_manager, NfcMagicSceneKeyInput); } } diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_wipe.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_wipe.c index 1ca194286..29640f89c 100644 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_wipe.c +++ b/applications/external/nfc_magic/scenes/nfc_magic_scene_wipe.c @@ -22,7 +22,12 @@ static void nfc_magic_scene_wipe_setup_view(NfcMagic* nfc_magic) { if(state == NfcMagicSceneWipeStateCardSearch) { popup_set_icon(nfc_magic->popup, 0, 8, &I_NFC_manual_60x50); popup_set_text( - nfc_magic->popup, "Apply card to\nthe back", 128, 32, AlignRight, AlignCenter); + nfc_magic->popup, + "Apply the\nsame card\nto the back", + 128, + 32, + AlignRight, + AlignCenter); } else { popup_set_icon(popup, 12, 23, &I_Loading_24); popup_set_header(popup, "Wiping\nDon't move...", 52, 32, AlignLeft, AlignCenter); @@ -42,7 +47,9 @@ void nfc_magic_scene_wipe_on_enter(void* context) { nfc_magic_worker_start( nfc_magic->worker, NfcMagicWorkerStateWipe, - &nfc_magic->nfc_dev->dev_data, + nfc_magic->dev, + &nfc_magic->source_dev->dev_data, + nfc_magic->new_password, nfc_magic_wipe_worker_callback, nfc_magic); nfc_magic_blink_start(nfc_magic); diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_write.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_write.c index c3e6f962a..45c54557f 100644 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_write.c +++ b/applications/external/nfc_magic/scenes/nfc_magic_scene_write.c @@ -21,7 +21,12 @@ static void nfc_magic_scene_write_setup_view(NfcMagic* nfc_magic) { if(state == NfcMagicSceneWriteStateCardSearch) { popup_set_text( - nfc_magic->popup, "Apply card to\nthe back", 128, 32, AlignRight, AlignCenter); + nfc_magic->popup, + "Apply the\nsame card\nto the back", + 128, + 32, + AlignRight, + AlignCenter); popup_set_icon(nfc_magic->popup, 0, 8, &I_NFC_manual_60x50); } else { popup_set_icon(popup, 12, 23, &I_Loading_24); @@ -42,7 +47,9 @@ void nfc_magic_scene_write_on_enter(void* context) { nfc_magic_worker_start( nfc_magic->worker, NfcMagicWorkerStateWrite, - &nfc_magic->nfc_dev->dev_data, + nfc_magic->dev, + &nfc_magic->source_dev->dev_data, + nfc_magic->new_password, nfc_magic_write_worker_callback, nfc_magic); nfc_magic_blink_start(nfc_magic); diff --git a/applications/external/nfc_magic/scenes/nfc_magic_scene_wrong_card.c b/applications/external/nfc_magic/scenes/nfc_magic_scene_wrong_card.c index 4b8089693..857d50c1f 100644 --- a/applications/external/nfc_magic/scenes/nfc_magic_scene_wrong_card.c +++ b/applications/external/nfc_magic/scenes/nfc_magic_scene_wrong_card.c @@ -26,7 +26,7 @@ void nfc_magic_scene_wrong_card_on_enter(void* context) { AlignLeft, AlignTop, FontSecondary, - "Writing is supported\nonly for 4 bytes UID\nMifare Classic 1k"); + "Writing this file is\nnot supported for\nthis magic card."); widget_add_button_element( widget, GuiButtonTypeLeft, "Retry", nfc_magic_scene_wrong_card_widget_callback, nfc_magic); diff --git a/applications/external/totp/features_config.h b/applications/external/totp/features_config.h index 683eff2fc..c789af27b 100644 --- a/applications/external/totp/features_config.h +++ b/applications/external/totp/features_config.h @@ -7,8 +7,8 @@ // List of compatible firmwares #define TOTP_FIRMWARE_OFFICIAL_STABLE 1 #define TOTP_FIRMWARE_OFFICIAL_DEV 2 -#define TOTP_FIRMWARE_XTREME 3 +#define TOTP_FIRMWARE_UL_XFW 3 // XFW and UL now has same bluetooth mac/advname changing API // End of list // Target firmware to build for -#define TOTP_TARGET_FIRMWARE TOTP_FIRMWARE_XTREME \ No newline at end of file +#define TOTP_TARGET_FIRMWARE TOTP_FIRMWARE_UL_XFW diff --git a/applications/external/totp/services/config/config.c b/applications/external/totp/services/config/config.c index f97bc6b26..7b935e1ea 100644 --- a/applications/external/totp/services/config/config.c +++ b/applications/external/totp/services/config/config.c @@ -177,6 +177,10 @@ static bool totp_open_config_file(Storage* storage, FlipperFormat** file) { flipper_format_write_uint32( fff_data_file, TOTP_CONFIG_KEY_AUTOMATION_METHOD, &tmp_uint32, 1); + // Default Font = 0 + tmp_uint32 = 0; + flipper_format_write_uint32(fff_data_file, TOTP_CONFIG_KEY_SELECTED_FONT, &tmp_uint32, 1); + if(!flipper_format_rewind(fff_data_file)) { totp_close_config_file(fff_data_file); FURI_LOG_E(LOGGING_TAG, "Rewind error"); @@ -259,6 +263,24 @@ bool totp_config_file_update_automation_method(const PluginState* plugin_state) return update_result; } +bool totp_config_file_update_selected_font(const PluginState* plugin_state) { + FlipperFormat* file = plugin_state->config_file_context->config_file; + flipper_format_rewind(file); + bool update_result = false; + + do { + uint32_t tmp_uint32 = plugin_state->selected_font; + if(!flipper_format_insert_or_update_uint32( + file, TOTP_CONFIG_KEY_SELECTED_FONT, &tmp_uint32, 1)) { + break; + } + + update_result = true; + } while(false); + + return update_result; +} + bool totp_config_file_update_user_settings(const PluginState* plugin_state) { FlipperFormat* file = plugin_state->config_file_context->config_file; flipper_format_rewind(file); @@ -280,6 +302,12 @@ bool totp_config_file_update_user_settings(const PluginState* plugin_state) { break; } + tmp_uint32 = plugin_state->selected_font; + if(!flipper_format_insert_or_update_uint32( + file, TOTP_CONFIG_KEY_SELECTED_FONT, &tmp_uint32, 1)) { + break; + } + update_result = true; } while(false); @@ -428,6 +456,16 @@ bool totp_config_file_load(PluginState* const plugin_state) { plugin_state->automation_method = tmp_uint32; + // Load selected font + flipper_format_rewind(fff_data_file); + + if(!flipper_format_read_uint32( + fff_data_file, TOTP_CONFIG_KEY_SELECTED_FONT, &tmp_uint32, 1)) { + tmp_uint32 = 0; + } + + plugin_state->selected_font = tmp_uint32; + plugin_state->config_file_context = malloc(sizeof(ConfigFileContext)); furi_check(plugin_state->config_file_context != NULL); plugin_state->config_file_context->storage = storage; diff --git a/applications/external/totp/services/config/config.h b/applications/external/totp/services/config/config.h index d2fe957c6..cc278ab5a 100644 --- a/applications/external/totp/services/config/config.h +++ b/applications/external/totp/services/config/config.h @@ -44,6 +44,13 @@ bool totp_config_file_update_notification_method(const PluginState* plugin_state */ bool totp_config_file_update_automation_method(const PluginState* plugin_state); +/** + * @brief Updates selected font in an application config file + * @param plugin_state application state + * @return Config file update result + */ +bool totp_config_file_update_selected_font(const PluginState* plugin_state); + /** * @brief Updates application user settings * @param plugin_state application state diff --git a/applications/external/totp/services/config/constants.h b/applications/external/totp/services/config/constants.h index 3a33c80b3..27a4f56c4 100644 --- a/applications/external/totp/services/config/constants.h +++ b/applications/external/totp/services/config/constants.h @@ -18,3 +18,4 @@ #define TOTP_CONFIG_KEY_PINSET "PinIsSet" #define TOTP_CONFIG_KEY_NOTIFICATION_METHOD "NotificationMethod" #define TOTP_CONFIG_KEY_AUTOMATION_METHOD "AutomationMethod" +#define TOTP_CONFIG_KEY_SELECTED_FONT "SelectedFont" diff --git a/applications/external/totp/services/config/migrations/common_migration.c b/applications/external/totp/services/config/migrations/common_migration.c index 07026fb1f..9cee422a5 100644 --- a/applications/external/totp/services/config/migrations/common_migration.c +++ b/applications/external/totp/services/config/migrations/common_migration.c @@ -58,6 +58,15 @@ bool totp_config_migrate_to_latest( flipper_format_rewind(fff_backup_data_file); + // Font + + if(flipper_format_read_string( + fff_backup_data_file, TOTP_CONFIG_KEY_SELECTED_FONT, temp_str)) { + flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_SELECTED_FONT, temp_str); + } + + flipper_format_rewind(fff_backup_data_file); + while(true) { if(!flipper_format_read_string( fff_backup_data_file, TOTP_CONFIG_KEY_TOKEN_NAME, temp_str)) { diff --git a/applications/external/totp/totp_app.c b/applications/external/totp/totp_app.c index f620a3b48..8b0a8c1fa 100644 --- a/applications/external/totp/totp_app.c +++ b/applications/external/totp/totp_app.c @@ -107,6 +107,7 @@ static bool totp_activate_initial_scene(PluginState* const plugin_state) { } static bool totp_plugin_state_init(PluginState* const plugin_state) { + plugin_state->selected_font = 0; plugin_state->gui = furi_record_open(RECORD_GUI); plugin_state->notification_app = furi_record_open(RECORD_NOTIFICATION); plugin_state->dialogs_app = furi_record_open(RECORD_DIALOGS); diff --git a/applications/external/totp/types/plugin_state.h b/applications/external/totp/types/plugin_state.h index c20594f37..97d126330 100644 --- a/applications/external/totp/types/plugin_state.h +++ b/applications/external/totp/types/plugin_state.h @@ -80,6 +80,11 @@ typedef struct { */ NotificationMethod notification_method; + /** + * @brief Numbers Font + */ + uint8_t selected_font; + /** * @brief Main rendering loop mutex */ diff --git a/applications/external/totp/ui/fonts/712serif/712serif.c b/applications/external/totp/ui/fonts/712serif/712serif.c new file mode 100644 index 000000000..0fe73378c --- /dev/null +++ b/applications/external/totp/ui/fonts/712serif/712serif.c @@ -0,0 +1,940 @@ +#include "712serif.h" + +/* GENERATED BY https://github.com/pavius/the-dot-factory */ + +/* +** Font data for 7:12 Serif 24pt +*/ + +/* Character bitmaps for 7:12 Serif 24pt */ +const uint8_t _712Serif_24ptBitmaps[] = { + /* @0 '-' (14 pixels wide) */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xFC, + 0x0F, + 0xFC, + 0x0F, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + + /* @28 '0' (14 pixels wide) */ + 0xF0, + 0x03, + 0xF0, + 0x03, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0xF0, + 0x03, + 0xF0, + 0x03, + + /* @56 '1' (14 pixels wide) */ + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xFC, + 0x00, + 0xFC, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xFC, + 0x0F, + 0xFC, + 0x0F, + + /* @84 '2' (14 pixels wide) */ + 0xF0, + 0x03, + 0xF0, + 0x03, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0xC0, + 0x03, + 0xC0, + 0x03, + 0x30, + 0x00, + 0x30, + 0x00, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0xFC, + 0x0F, + 0xFC, + 0x0F, + + /* @112 '3' (14 pixels wide) */ + 0xF0, + 0x03, + 0xF0, + 0x03, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0xC0, + 0x03, + 0xC0, + 0x03, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0xF0, + 0x03, + 0xF0, + 0x03, + + /* @140 '4' (14 pixels wide) */ + 0x30, + 0x03, + 0x30, + 0x03, + 0x30, + 0x03, + 0x30, + 0x03, + 0x0C, + 0x03, + 0x0C, + 0x03, + 0x0C, + 0x03, + 0x0C, + 0x03, + 0xFC, + 0x0F, + 0xFC, + 0x0F, + 0x00, + 0x03, + 0x00, + 0x03, + 0xC0, + 0x0F, + 0xC0, + 0x0F, + + /* @168 '5' (14 pixels wide) */ + 0xFC, + 0x0F, + 0xFC, + 0x0F, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0xFC, + 0x03, + 0xFC, + 0x03, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0xF0, + 0x03, + 0xF0, + 0x03, + + /* @196 '6' (14 pixels wide) */ + 0xF0, + 0x03, + 0xF0, + 0x03, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0xFC, + 0x03, + 0xFC, + 0x03, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0xF0, + 0x03, + 0xF0, + 0x03, + + /* @224 '7' (14 pixels wide) */ + 0xFC, + 0x0F, + 0xFC, + 0x0F, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + + /* @252 '8' (14 pixels wide) */ + 0xF0, + 0x03, + 0xF0, + 0x03, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0xF0, + 0x03, + 0xF0, + 0x03, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0xF0, + 0x03, + 0xF0, + 0x03, + + /* @280 '9' (14 pixels wide) */ + 0xF0, + 0x03, + 0xF0, + 0x03, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0xF0, + 0x0F, + 0xF0, + 0x0F, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0xF0, + 0x03, + 0xF0, + 0x03, + + /* @308 'B' (14 pixels wide) */ + 0xFF, + 0x00, + 0xFF, + 0x00, + 0x0C, + 0x03, + 0x0C, + 0x03, + 0x0C, + 0x03, + 0x0C, + 0x03, + 0xFC, + 0x0F, + 0xFC, + 0x0F, + 0x0C, + 0x30, + 0x0C, + 0x30, + 0x0C, + 0x30, + 0x0C, + 0x30, + 0xFF, + 0x0F, + 0xFF, + 0x0F, + + /* @336 'C' (14 pixels wide) */ + 0xF0, + 0x33, + 0xF0, + 0x33, + 0x0C, + 0x3C, + 0x0C, + 0x3C, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x30, + 0x03, + 0x30, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0xF0, + 0x03, + 0xF0, + 0x03, + + /* @364 'D' (14 pixels wide) */ + 0xFF, + 0x03, + 0xFF, + 0x03, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x30, + 0x0C, + 0x30, + 0x0C, + 0x30, + 0x0C, + 0x30, + 0x0C, + 0x30, + 0x0C, + 0x30, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0xFF, + 0x03, + 0xFF, + 0x03, + + /* @392 'F' (14 pixels wide) */ + 0xFF, + 0x3F, + 0xFF, + 0x3F, + 0x0C, + 0x30, + 0x0C, + 0x30, + 0x0C, + 0x03, + 0x0C, + 0x03, + 0xFC, + 0x03, + 0xFC, + 0x03, + 0x0C, + 0x03, + 0x0C, + 0x03, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x3F, + 0x00, + 0x3F, + 0x00, + + /* @420 'G' (14 pixels wide) */ + 0xF0, + 0x33, + 0xF0, + 0x33, + 0x0C, + 0x3C, + 0x0C, + 0x3C, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x3F, + 0x03, + 0x3F, + 0x03, + 0x30, + 0x03, + 0x30, + 0x0C, + 0x3C, + 0x0C, + 0x3C, + 0xF0, + 0x33, + 0xF0, + 0x33, + + /* @448 'H' (14 pixels wide) */ + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0xFC, + 0x0F, + 0xFC, + 0x0F, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + + /* @476 'J' (14 pixels wide) */ + 0x00, + 0x3F, + 0x00, + 0x3F, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0xF0, + 0x03, + 0xF0, + 0x03, + + /* @504 'K' (14 pixels wide) */ + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x03, + 0x0C, + 0x03, + 0xFC, + 0x00, + 0xFC, + 0x00, + 0x0C, + 0x03, + 0x0C, + 0x03, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + + /* @532 'M' (14 pixels wide) */ + 0x0F, + 0x3C, + 0x0F, + 0x3C, + 0x3C, + 0x0F, + 0x3C, + 0x0F, + 0xCC, + 0x0C, + 0xCC, + 0x0C, + 0xCC, + 0x0C, + 0xCC, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + + /* @560 'N' (14 pixels wide) */ + 0x0F, + 0x3F, + 0x0F, + 0x3F, + 0x3C, + 0x0C, + 0x3C, + 0x0C, + 0xCC, + 0x0C, + 0xCC, + 0x0C, + 0xCC, + 0x0C, + 0xCC, + 0x0C, + 0xCC, + 0x0C, + 0xCC, + 0x0C, + 0x0C, + 0x0F, + 0x0C, + 0x0F, + 0x3F, + 0x0C, + 0x3F, + 0x0C, + + /* @588 'P' (14 pixels wide) */ + 0xFF, + 0x0F, + 0xFF, + 0x0F, + 0x0C, + 0x30, + 0x0C, + 0x30, + 0x0C, + 0x30, + 0x0C, + 0x30, + 0x3C, + 0x30, + 0x3C, + 0x30, + 0xCC, + 0x0F, + 0xCC, + 0x0F, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x3F, + 0x00, + 0x3F, + 0x00, + + /* @616 'Q' (14 pixels wide) */ + 0xF0, + 0x03, + 0xF0, + 0x03, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x03, + 0x30, + 0x03, + 0x30, + 0xF3, + 0x30, + 0xF3, + 0x30, + 0x03, + 0x33, + 0x03, + 0x33, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0xF0, + 0x33, + 0xF0, + 0x33, + + /* @644 'R' (14 pixels wide) */ + 0xFF, + 0x0F, + 0xFF, + 0x0F, + 0x0C, + 0x30, + 0x0C, + 0x30, + 0x0C, + 0x30, + 0x0C, + 0x30, + 0xFC, + 0x0F, + 0xFC, + 0x0F, + 0x0C, + 0x03, + 0x0C, + 0x03, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + + /* @672 'T' (14 pixels wide) */ + 0xFF, + 0x3F, + 0xFF, + 0x3F, + 0xC3, + 0x30, + 0xC3, + 0x30, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xF0, + 0x03, + 0xF0, + 0x03, + + /* @700 'V' (14 pixels wide) */ + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x30, + 0x03, + 0x30, + 0x03, + 0x30, + 0x03, + 0x30, + 0x03, + 0xC0, + 0x00, + 0xC0, + 0x00, + + /* @728 'W' (14 pixels wide) */ + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0xCC, + 0x0C, + 0xCC, + 0x0C, + 0xCC, + 0x0C, + 0xCC, + 0x0C, + 0x30, + 0x03, + 0x30, + 0x03, + 0x30, + 0x03, + 0x30, + 0x03, + + /* @756 'X' (14 pixels wide) */ + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x30, + 0x03, + 0x30, + 0x03, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0x30, + 0x03, + 0x30, + 0x03, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x3F, + 0x3F, + 0x3F, + 0x3F, + + /* @784 'Y' (14 pixels wide) */ + 0x3F, + 0x3F, + 0x3F, + 0x3F, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x30, + 0x03, + 0x30, + 0x03, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xF0, + 0x03, + 0xF0, + 0x03, +}; + +/* Character descriptors for 7:12 Serif 24pt */ +/* { [Char width in bits], [Offset into _712Serif_24ptCharBitmaps in bytes] } */ +const FONT_CHAR_INFO _712Serif_24ptDescriptors[] = { + {14, 0}, /* - */ + {0, 0}, /* . */ + {0, 0}, /* / */ + {14, 28}, /* 0 */ + {14, 56}, /* 1 */ + {14, 84}, /* 2 */ + {14, 112}, /* 3 */ + {14, 140}, /* 4 */ + {14, 168}, /* 5 */ + {14, 196}, /* 6 */ + {14, 224}, /* 7 */ + {14, 252}, /* 8 */ + {14, 280}, /* 9 */ + {0, 0}, /* : */ + {0, 0}, /* ; */ + {0, 0}, /* < */ + {0, 0}, /* = */ + {0, 0}, /* > */ + {0, 0}, /* ? */ + {0, 0}, /* @ */ + {0, 0}, /* A */ + {14, 308}, /* B */ + {14, 336}, /* C */ + {14, 364}, /* D */ + {0, 0}, /* E */ + {14, 392}, /* F */ + {14, 420}, /* G */ + {14, 448}, /* H */ + {0, 0}, /* I */ + {14, 476}, /* J */ + {14, 504}, /* K */ + {0, 0}, /* L */ + {14, 532}, /* M */ + {14, 560}, /* N */ + {0, 0}, /* O */ + {14, 588}, /* P */ + {14, 616}, /* Q */ + {14, 644}, /* R */ + {0, 0}, /* S */ + {14, 672}, /* T */ + {0, 0}, /* U */ + {14, 700}, /* V */ + {14, 728}, /* W */ + {14, 756}, /* X */ + {14, 784}, /* Y */ +}; + +/* Font information for 7:12 Serif 24pt */ +const FONT_INFO _712Serif_24ptFontInfo = { + 14, /* Character height */ + '-', /* Start character */ + 'Y', /* End character */ + 2, /* Width, in pixels, of space character */ + _712Serif_24ptDescriptors, /* Character descriptor array */ + _712Serif_24ptBitmaps, /* Character bitmap array */ +}; diff --git a/applications/external/totp/ui/fonts/712serif/712serif.h b/applications/external/totp/ui/fonts/712serif/712serif.h new file mode 100644 index 000000000..81959064d --- /dev/null +++ b/applications/external/totp/ui/fonts/712serif/712serif.h @@ -0,0 +1,8 @@ +#pragma once + +/* GENERATED BY https://github.com/pavius/the-dot-factory */ + +#include "../font_info.h" + +/* Font data for 7:12 Serif 24pt */ +extern const FONT_INFO _712Serif_24ptFontInfo; diff --git a/applications/external/totp/ui/fonts/active_font.h b/applications/external/totp/ui/fonts/active_font.h new file mode 100644 index 000000000..054fa4a55 --- /dev/null +++ b/applications/external/totp/ui/fonts/active_font.h @@ -0,0 +1,12 @@ +#pragma once + +#include "../../features_config.h" +#include "font_info.h" + +#include "mode_nine/mode_nine.h" +#include "redhat_mono/redhat_mono.h" +#include "bedstead/bedstead.h" +#include "zector/zector.h" +#include "712serif/712serif.h" +#include "graph35pix/graph35pix.h" +#include "karma_future/karma_future.h" diff --git a/applications/external/totp/ui/fonts/bedstead/bedstead.c b/applications/external/totp/ui/fonts/bedstead/bedstead.c new file mode 100644 index 000000000..ec6680fab --- /dev/null +++ b/applications/external/totp/ui/fonts/bedstead/bedstead.c @@ -0,0 +1,1056 @@ +#include "bedstead.h" + +/* GENERATED BY https://github.com/pavius/the-dot-factory */ + +/* +** Font data for Bedstead 17pt +*/ + +/* Character bitmaps for Bedstead 17pt */ +const uint8_t bedstead_17ptBitmaps[] = { + /* @0 '-' (13 pixels wide) */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xF8, + 0x07, + 0xF8, + 0x07, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + + /* @32 '0' (13 pixels wide) */ + 0xE0, + 0x00, + 0xF0, + 0x01, + 0xF8, + 0x03, + 0xBC, + 0x07, + 0x1E, + 0x0F, + 0x0F, + 0x1E, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x0F, + 0x1E, + 0x1E, + 0x0F, + 0xBC, + 0x07, + 0xF8, + 0x03, + 0xF0, + 0x01, + 0xE0, + 0x00, + + /* @64 '1' (13 pixels wide) */ + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xF8, + 0x00, + 0xF8, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xF8, + 0x03, + 0xF8, + 0x03, + + /* @96 '2' (13 pixels wide) */ + 0xF0, + 0x07, + 0xFC, + 0x0F, + 0x1E, + 0x1E, + 0x1E, + 0x1C, + 0x0E, + 0x1C, + 0x00, + 0x1C, + 0x00, + 0x1E, + 0xC0, + 0x0F, + 0xE0, + 0x07, + 0xF0, + 0x00, + 0x7C, + 0x00, + 0x3E, + 0x00, + 0x1E, + 0x00, + 0x0E, + 0x00, + 0xFE, + 0x1F, + 0xFE, + 0x1F, + + /* @128 '3' (13 pixels wide) */ + 0xFE, + 0x1F, + 0xFE, + 0x1F, + 0x00, + 0x1C, + 0x00, + 0x1E, + 0x00, + 0x0F, + 0x00, + 0x0F, + 0x00, + 0x07, + 0xE0, + 0x07, + 0xE0, + 0x0F, + 0x00, + 0x1E, + 0x00, + 0x1C, + 0x0E, + 0x1C, + 0x1E, + 0x1C, + 0x3E, + 0x0E, + 0xFC, + 0x0F, + 0xF8, + 0x07, + + /* @160 '4' (13 pixels wide) */ + 0x80, + 0x03, + 0x80, + 0x03, + 0xE0, + 0x03, + 0xF0, + 0x03, + 0xF8, + 0x03, + 0xBC, + 0x03, + 0x9E, + 0x03, + 0x8F, + 0x03, + 0x87, + 0x03, + 0xFF, + 0x0F, + 0xFF, + 0x0F, + 0x80, + 0x03, + 0x80, + 0x03, + 0x80, + 0x03, + 0x80, + 0x03, + 0x80, + 0x03, + + /* @192 '5' (13 pixels wide) */ + 0xFF, + 0x1F, + 0xFF, + 0x1F, + 0x07, + 0x00, + 0x07, + 0x00, + 0xFF, + 0x07, + 0xFF, + 0x0F, + 0x00, + 0x1E, + 0x00, + 0x1C, + 0x00, + 0x1C, + 0x00, + 0x1C, + 0x00, + 0x1C, + 0x07, + 0x1C, + 0x0F, + 0x1E, + 0xFE, + 0x0F, + 0xFC, + 0x07, + 0xFC, + 0x07, + + /* @224 '6' (13 pixels wide) */ + 0xE0, + 0x07, + 0xF0, + 0x07, + 0x78, + 0x00, + 0x3C, + 0x00, + 0x1E, + 0x00, + 0x0F, + 0x00, + 0x07, + 0x00, + 0xFF, + 0x07, + 0xFF, + 0x0F, + 0x07, + 0x1E, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x0F, + 0x1E, + 0x1E, + 0x0F, + 0xFE, + 0x0F, + 0xFC, + 0x07, + + /* @256 '7' (13 pixels wide) */ + 0xFE, + 0x1F, + 0xFE, + 0x1F, + 0x00, + 0x1C, + 0x00, + 0x1E, + 0x00, + 0x0F, + 0x80, + 0x07, + 0xC0, + 0x03, + 0xE0, + 0x01, + 0xF0, + 0x00, + 0x78, + 0x00, + 0x38, + 0x00, + 0x38, + 0x00, + 0x38, + 0x00, + 0x38, + 0x00, + 0x38, + 0x00, + 0x38, + 0x00, + + /* @288 '8' (13 pixels wide) */ + 0xFC, + 0x07, + 0xFE, + 0x0F, + 0x0F, + 0x1E, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x0F, + 0x1E, + 0xFE, + 0x0F, + 0xFE, + 0x0F, + 0x0F, + 0x1E, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x0F, + 0x1E, + 0x1E, + 0x0F, + 0xFE, + 0x0F, + 0xFC, + 0x07, + + /* @320 '9' (13 pixels wide) */ + 0xFC, + 0x07, + 0xFE, + 0x0F, + 0x0F, + 0x1E, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x0F, + 0x1C, + 0xFE, + 0x1F, + 0xFC, + 0x1F, + 0x00, + 0x1C, + 0x00, + 0x1E, + 0x00, + 0x0F, + 0x80, + 0x07, + 0xC0, + 0x03, + 0xFC, + 0x01, + 0xFC, + 0x00, + + /* @352 'B' (13 pixels wide) */ + 0xFF, + 0x07, + 0xFF, + 0x0F, + 0x07, + 0x1E, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1E, + 0xFF, + 0x0F, + 0xFF, + 0x0F, + 0x07, + 0x1E, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1E, + 0x07, + 0x0F, + 0xFF, + 0x0F, + 0xFF, + 0x07, + + /* @384 'C' (13 pixels wide) */ + 0xFC, + 0x01, + 0xFE, + 0x07, + 0x0F, + 0x0F, + 0x07, + 0x0F, + 0x07, + 0x0E, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x0F, + 0x8F, + 0x0F, + 0xFE, + 0x07, + 0xFC, + 0x03, + + /* @416 'D' (13 pixels wide) */ + 0xFF, + 0x07, + 0xFF, + 0x0F, + 0x07, + 0x1E, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1E, + 0x07, + 0x0F, + 0xFF, + 0x0F, + 0xFF, + 0x07, + + /* @448 'F' (13 pixels wide) */ + 0xFF, + 0x0F, + 0xFF, + 0x0F, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0xFF, + 0x03, + 0xFF, + 0x03, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + + /* @480 'G' (13 pixels wide) */ + 0xFC, + 0x07, + 0xFE, + 0x0F, + 0x0F, + 0x1F, + 0x0F, + 0x1E, + 0x07, + 0x1C, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x87, + 0x1F, + 0x87, + 0x1F, + 0x07, + 0x1C, + 0x0F, + 0x1C, + 0xFE, + 0x1F, + 0xFC, + 0x1F, + 0xFC, + 0x1F, + + /* @512 'H' (13 pixels wide) */ + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0xFF, + 0x1F, + 0xFF, + 0x1F, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + + /* @544 'J' (13 pixels wide) */ + 0x00, + 0x1C, + 0x00, + 0x1C, + 0x00, + 0x1C, + 0x00, + 0x1C, + 0x00, + 0x1C, + 0x00, + 0x1C, + 0x00, + 0x1C, + 0x00, + 0x1C, + 0x00, + 0x1C, + 0x00, + 0x1C, + 0x00, + 0x1C, + 0x0E, + 0x1C, + 0x1E, + 0x1C, + 0x3E, + 0x1E, + 0xFC, + 0x0F, + 0xF8, + 0x07, + + /* @576 'K' (13 pixels wide) */ + 0x07, + 0x0E, + 0x07, + 0x0F, + 0x87, + 0x07, + 0xC7, + 0x03, + 0xE7, + 0x01, + 0xF7, + 0x00, + 0x7F, + 0x00, + 0x3F, + 0x00, + 0x3F, + 0x00, + 0x7F, + 0x00, + 0xF7, + 0x00, + 0xE7, + 0x01, + 0xC7, + 0x03, + 0x87, + 0x07, + 0x07, + 0x0F, + 0x07, + 0x0E, + + /* @608 'M' (13 pixels wide) */ + 0x07, + 0x1C, + 0x07, + 0x1C, + 0xBF, + 0x1F, + 0xFF, + 0x1F, + 0xFF, + 0x1F, + 0xE7, + 0x1C, + 0xE7, + 0x1C, + 0xE7, + 0x1C, + 0xE7, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + + /* @640 'N' (13 pixels wide) */ + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x3F, + 0x1C, + 0x7F, + 0x1C, + 0xFF, + 0x1C, + 0xE7, + 0x1F, + 0xC7, + 0x1F, + 0x87, + 0x1F, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + + /* @672 'P' (13 pixels wide) */ + 0xFF, + 0x07, + 0xFF, + 0x0F, + 0x07, + 0x1E, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1E, + 0xFF, + 0x0F, + 0xFF, + 0x07, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + 0x07, + 0x00, + + /* @704 'Q' (13 pixels wide) */ + 0xFC, + 0x07, + 0xFE, + 0x0F, + 0x0F, + 0x1E, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0xE7, + 0x1C, + 0xE7, + 0x1F, + 0xC7, + 0x0F, + 0x8F, + 0x07, + 0xDE, + 0x0F, + 0xFE, + 0x1F, + 0xFC, + 0x1C, + + /* @736 'R' (13 pixels wide) */ + 0xFF, + 0x07, + 0xFF, + 0x0F, + 0x07, + 0x1E, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1E, + 0xFF, + 0x0F, + 0xFF, + 0x07, + 0xE7, + 0x00, + 0xE7, + 0x01, + 0xC7, + 0x03, + 0x87, + 0x07, + 0x07, + 0x0F, + 0x07, + 0x1E, + 0x07, + 0x1C, + + /* @768 'T' (13 pixels wide) */ + 0xFF, + 0x1F, + 0xFF, + 0x1F, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + + /* @800 'V' (13 pixels wide) */ + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x1F, + 0x1F, + 0xBC, + 0x07, + 0xB8, + 0x03, + 0xB8, + 0x03, + 0xF8, + 0x07, + 0xF0, + 0x03, + 0xE0, + 0x01, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + + /* @832 'W' (13 pixels wide) */ + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0xE7, + 0x1C, + 0xE7, + 0x1C, + 0xE7, + 0x1C, + 0xE7, + 0x1C, + 0xE7, + 0x1C, + 0xFF, + 0x1F, + 0xFE, + 0x0F, + 0xFE, + 0x0F, + 0xBC, + 0x07, + + /* @864 'X' (13 pixels wide) */ + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x0F, + 0x1E, + 0x1E, + 0x0F, + 0xBC, + 0x07, + 0xF8, + 0x03, + 0xF0, + 0x01, + 0xF0, + 0x01, + 0xF8, + 0x03, + 0xBC, + 0x07, + 0x1E, + 0x0F, + 0x0F, + 0x1E, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + + /* @896 'Y' (13 pixels wide) */ + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x0F, + 0x1E, + 0x1E, + 0x0F, + 0xBC, + 0x07, + 0xF8, + 0x03, + 0xF0, + 0x01, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, +}; + +/* Character descriptors for Bedstead 17pt */ +/* { [Char width in bits], [Offset into bedstead_17ptCharBitmaps in bytes] } */ +const FONT_CHAR_INFO bedstead_17ptDescriptors[] = { + {13, 0}, /* - */ + {0, 0}, /* . */ + {0, 0}, /* / */ + {13, 32}, /* 0 */ + {13, 64}, /* 1 */ + {13, 96}, /* 2 */ + {13, 128}, /* 3 */ + {13, 160}, /* 4 */ + {13, 192}, /* 5 */ + {13, 224}, /* 6 */ + {13, 256}, /* 7 */ + {13, 288}, /* 8 */ + {13, 320}, /* 9 */ + {0, 0}, /* : */ + {0, 0}, /* ; */ + {0, 0}, /* < */ + {0, 0}, /* = */ + {0, 0}, /* > */ + {0, 0}, /* ? */ + {0, 0}, /* @ */ + {0, 0}, /* A */ + {13, 352}, /* B */ + {13, 384}, /* C */ + {13, 416}, /* D */ + {0, 0}, /* E */ + {13, 448}, /* F */ + {13, 480}, /* G */ + {13, 512}, /* H */ + {0, 0}, /* I */ + {13, 544}, /* J */ + {13, 576}, /* K */ + {0, 0}, /* L */ + {13, 608}, /* M */ + {13, 640}, /* N */ + {0, 0}, /* O */ + {13, 672}, /* P */ + {13, 704}, /* Q */ + {13, 736}, /* R */ + {0, 0}, /* S */ + {13, 768}, /* T */ + {0, 0}, /* U */ + {13, 800}, /* V */ + {13, 832}, /* W */ + {13, 864}, /* X */ + {13, 896}, /* Y */ +}; + +/* Font information for Bedstead 17pt */ +const FONT_INFO bedstead_17ptFontInfo = { + 16, /* Character height */ + '-', /* Start character */ + 'Y', /* End character */ + 2, /* Width, in pixels, of space character */ + bedstead_17ptDescriptors, /* Character descriptor array */ + bedstead_17ptBitmaps, /* Character bitmap array */ +}; diff --git a/applications/external/totp/ui/fonts/bedstead/bedstead.h b/applications/external/totp/ui/fonts/bedstead/bedstead.h new file mode 100644 index 000000000..0f4c10949 --- /dev/null +++ b/applications/external/totp/ui/fonts/bedstead/bedstead.h @@ -0,0 +1,8 @@ +#pragma once + +/* GENERATED BY https://github.com/pavius/the-dot-factory */ + +#include "../font_info.h" + +/* Font data for Bedstead 17pt */ +extern const FONT_INFO bedstead_17ptFontInfo; diff --git a/applications/external/totp/ui/fonts/graph35pix/graph35pix.c b/applications/external/totp/ui/fonts/graph35pix/graph35pix.c new file mode 100644 index 000000000..fd93d4de9 --- /dev/null +++ b/applications/external/totp/ui/fonts/graph35pix/graph35pix.c @@ -0,0 +1,940 @@ +#include "graph35pix.h" + +/* GENERATED BY https://github.com/pavius/the-dot-factory */ + +/* +** Font data for Graph 35+ pix 12pt +*/ + +/* Character bitmaps for Graph 35+ pix 12pt */ +const uint8_t graph35pix_12ptBitmaps[] = { + /* @0 '-' (10 pixels wide) */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xFF, + 0x03, + 0xFF, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + + /* @28 '0' (10 pixels wide) */ + 0xFC, + 0x00, + 0xFC, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0xC3, + 0x03, + 0xC3, + 0x03, + 0x33, + 0x03, + 0x33, + 0x03, + 0x0F, + 0x03, + 0x0F, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xFC, + 0x00, + 0xFC, + 0x00, + + /* @56 '1' (10 pixels wide) */ + 0x30, + 0x00, + 0x30, + 0x00, + 0x3C, + 0x00, + 0x3C, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0xFC, + 0x00, + 0xFC, + 0x00, + + /* @84 '2' (10 pixels wide) */ + 0xFC, + 0x00, + 0xFC, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0xFF, + 0x03, + 0xFF, + 0x03, + + /* @112 '3' (10 pixels wide) */ + 0xFF, + 0x03, + 0xFF, + 0x03, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0x00, + 0x03, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xFC, + 0x00, + 0xFC, + 0x00, + + /* @140 '4' (10 pixels wide) */ + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xF0, + 0x00, + 0xF0, + 0x00, + 0xCC, + 0x00, + 0xCC, + 0x00, + 0xC3, + 0x00, + 0xC3, + 0x00, + 0xFF, + 0x03, + 0xFF, + 0x03, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + + /* @168 '5' (10 pixels wide) */ + 0xFF, + 0x03, + 0xFF, + 0x03, + 0x03, + 0x00, + 0x03, + 0x00, + 0xFF, + 0x00, + 0xFF, + 0x00, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xFC, + 0x00, + 0xFC, + 0x00, + + /* @196 '6' (10 pixels wide) */ + 0xF0, + 0x00, + 0xF0, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0xFF, + 0x00, + 0xFF, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xFC, + 0x00, + 0xFC, + 0x00, + + /* @224 '7' (10 pixels wide) */ + 0xFF, + 0x03, + 0xFF, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + + /* @252 '8' (10 pixels wide) */ + 0xFC, + 0x00, + 0xFC, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xFC, + 0x00, + 0xFC, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xFC, + 0x00, + 0xFC, + 0x00, + + /* @280 '9' (10 pixels wide) */ + 0xFC, + 0x00, + 0xFC, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xFC, + 0x03, + 0xFC, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0x3C, + 0x00, + 0x3C, + 0x00, + + /* @308 'B' (10 pixels wide) */ + 0xFF, + 0x00, + 0xFF, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xFF, + 0x00, + 0xFF, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xFF, + 0x00, + 0xFF, + 0x00, + + /* @336 'C' (10 pixels wide) */ + 0xFC, + 0x00, + 0xFC, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0xFC, + 0x00, + 0xFC, + 0x00, + + /* @364 'D' (10 pixels wide) */ + 0x3F, + 0x00, + 0x3F, + 0x00, + 0xC3, + 0x00, + 0xC3, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xC3, + 0x00, + 0xC3, + 0x00, + 0x3F, + 0x00, + 0x3F, + 0x00, + + /* @392 'F' (10 pixels wide) */ + 0xFF, + 0x03, + 0xFF, + 0x03, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0xFF, + 0x00, + 0xFF, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + + /* @420 'G' (10 pixels wide) */ + 0xFC, + 0x00, + 0xFC, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x00, + 0x03, + 0x00, + 0xF3, + 0x03, + 0xF3, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xFC, + 0x03, + 0xFC, + 0x03, + + /* @448 'H' (10 pixels wide) */ + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xFF, + 0x03, + 0xFF, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + + /* @476 'J' (10 pixels wide) */ + 0xF0, + 0x03, + 0xF0, + 0x03, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC0, + 0x00, + 0xC3, + 0x00, + 0xC3, + 0x00, + 0x3C, + 0x00, + 0x3C, + 0x00, + + /* @504 'K' (10 pixels wide) */ + 0x03, + 0x03, + 0x03, + 0x03, + 0xC3, + 0x00, + 0xC3, + 0x00, + 0x33, + 0x00, + 0x33, + 0x00, + 0x0F, + 0x00, + 0x0F, + 0x00, + 0x33, + 0x00, + 0x33, + 0x00, + 0xC3, + 0x00, + 0xC3, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + + /* @532 'M' (10 pixels wide) */ + 0x03, + 0x03, + 0x03, + 0x03, + 0xCF, + 0x03, + 0xCF, + 0x03, + 0x33, + 0x03, + 0x33, + 0x03, + 0x33, + 0x03, + 0x33, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + + /* @560 'N' (10 pixels wide) */ + 0x03, + 0x03, + 0x03, + 0x03, + 0x0F, + 0x03, + 0x0F, + 0x03, + 0x0F, + 0x03, + 0x0F, + 0x03, + 0x33, + 0x03, + 0x33, + 0x03, + 0xC3, + 0x03, + 0xC3, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + + /* @588 'P' (10 pixels wide) */ + 0xFF, + 0x00, + 0xFF, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xFF, + 0x00, + 0xFF, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + + /* @616 'Q' (10 pixels wide) */ + 0xFC, + 0x00, + 0xFC, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x33, + 0x03, + 0x33, + 0x03, + 0xC3, + 0x00, + 0xC3, + 0x00, + 0x3C, + 0x03, + 0x3C, + 0x03, + + /* @644 'R' (10 pixels wide) */ + 0xFF, + 0x00, + 0xFF, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xFF, + 0x00, + 0xFF, + 0x00, + 0x33, + 0x00, + 0x33, + 0x00, + 0xC3, + 0x00, + 0xC3, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + + /* @672 'T' (10 pixels wide) */ + 0xFF, + 0x03, + 0xFF, + 0x03, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + + /* @700 'V' (10 pixels wide) */ + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xCC, + 0x00, + 0xCC, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + + /* @728 'W' (10 pixels wide) */ + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x33, + 0x03, + 0x33, + 0x03, + 0x33, + 0x03, + 0x33, + 0x03, + 0x33, + 0x03, + 0x33, + 0x03, + 0xCC, + 0x00, + 0xCC, + 0x00, + + /* @756 'X' (10 pixels wide) */ + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xCC, + 0x00, + 0xCC, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0xCC, + 0x00, + 0xCC, + 0x00, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + + /* @784 'Y' (10 pixels wide) */ + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0x03, + 0xCC, + 0x00, + 0xCC, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, + 0x30, + 0x00, +}; + +/* Character descriptors for Graph 35+ pix 12pt */ +/* { [Char width in bits], [Offset into graph35pix_12ptCharBitmaps in bytes] } */ +const FONT_CHAR_INFO graph35pix_12ptDescriptors[] = { + {10, 0}, /* - */ + {0, 0}, /* . */ + {0, 0}, /* / */ + {10, 28}, /* 0 */ + {10, 56}, /* 1 */ + {10, 84}, /* 2 */ + {10, 112}, /* 3 */ + {10, 140}, /* 4 */ + {10, 168}, /* 5 */ + {10, 196}, /* 6 */ + {10, 224}, /* 7 */ + {10, 252}, /* 8 */ + {10, 280}, /* 9 */ + {0, 0}, /* : */ + {0, 0}, /* ; */ + {0, 0}, /* < */ + {0, 0}, /* = */ + {0, 0}, /* > */ + {0, 0}, /* ? */ + {0, 0}, /* @ */ + {0, 0}, /* A */ + {10, 308}, /* B */ + {10, 336}, /* C */ + {10, 364}, /* D */ + {0, 0}, /* E */ + {10, 392}, /* F */ + {10, 420}, /* G */ + {10, 448}, /* H */ + {0, 0}, /* I */ + {10, 476}, /* J */ + {10, 504}, /* K */ + {0, 0}, /* L */ + {10, 532}, /* M */ + {10, 560}, /* N */ + {0, 0}, /* O */ + {10, 588}, /* P */ + {10, 616}, /* Q */ + {10, 644}, /* R */ + {0, 0}, /* S */ + {10, 672}, /* T */ + {0, 0}, /* U */ + {10, 700}, /* V */ + {10, 728}, /* W */ + {10, 756}, /* X */ + {10, 784}, /* Y */ +}; + +/* Font information for Graph 35+ pix 12pt */ +const FONT_INFO graph35pix_12ptFontInfo = { + 14, /* Character height */ + '-', /* Start character */ + 'Y', /* End character */ + 2, /* Width, in pixels, of space character */ + graph35pix_12ptDescriptors, /* Character descriptor array */ + graph35pix_12ptBitmaps, /* Character bitmap array */ +}; diff --git a/applications/external/totp/ui/fonts/graph35pix/graph35pix.h b/applications/external/totp/ui/fonts/graph35pix/graph35pix.h new file mode 100644 index 000000000..07838e3ba --- /dev/null +++ b/applications/external/totp/ui/fonts/graph35pix/graph35pix.h @@ -0,0 +1,8 @@ +#pragma once + +/* GENERATED BY https://github.com/pavius/the-dot-factory */ + +#include "../font_info.h" + +/* Font data for Graph 35+ pix 12pt */ +extern const FONT_INFO graph35pix_12ptFontInfo; diff --git a/applications/external/totp/ui/fonts/karma_future/karma_future.c b/applications/external/totp/ui/fonts/karma_future/karma_future.c new file mode 100644 index 000000000..ed6201441 --- /dev/null +++ b/applications/external/totp/ui/fonts/karma_future/karma_future.c @@ -0,0 +1,1172 @@ +#include "karma_future.h" + +/* GENERATED BY https://github.com/pavius/the-dot-factory */ + +/* +** Font data for Karma Future 14pt +*/ + +/* Character bitmaps for Karma Future 14pt */ +const uint8_t karmaFuture_14ptBitmaps[] = { + /* @0 '-' (12 pixels wide) */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xFE, + 0x03, + 0x02, + 0x02, + 0x02, + 0x02, + 0xFE, + 0x03, + 0xFC, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + + /* @36 '0' (12 pixels wide) */ + 0xF8, + 0x01, + 0x0E, + 0x03, + 0x02, + 0x06, + 0xF3, + 0x06, + 0xF9, + 0x0C, + 0x79, + 0x0C, + 0x39, + 0x0D, + 0x99, + 0x0C, + 0xC9, + 0x0C, + 0xE9, + 0x0C, + 0xF1, + 0x0C, + 0xF1, + 0x0C, + 0xF1, + 0x0C, + 0xF3, + 0x0E, + 0x02, + 0x0E, + 0x0E, + 0x07, + 0xFC, + 0x07, + 0xF8, + 0x01, + + /* @72 '1' (12 pixels wide) */ + 0x70, + 0x00, + 0xD8, + 0x00, + 0xCE, + 0x00, + 0xC2, + 0x00, + 0xC2, + 0x00, + 0xDE, + 0x00, + 0xDC, + 0x00, + 0xDC, + 0x00, + 0xD0, + 0x00, + 0xD0, + 0x00, + 0xD0, + 0x00, + 0xD0, + 0x00, + 0xD0, + 0x00, + 0xDE, + 0x03, + 0x02, + 0x02, + 0x02, + 0x02, + 0xFE, + 0x03, + 0xFC, + 0x03, + + /* @108 '2' (12 pixels wide) */ + 0xFC, + 0x03, + 0x06, + 0x03, + 0x03, + 0x06, + 0xF1, + 0x04, + 0xF9, + 0x0C, + 0xF9, + 0x0C, + 0x7F, + 0x0E, + 0x3E, + 0x0F, + 0x1E, + 0x0F, + 0x90, + 0x07, + 0xC8, + 0x03, + 0xE4, + 0x01, + 0xE6, + 0x00, + 0xF3, + 0x07, + 0x01, + 0x0C, + 0x01, + 0x0C, + 0xFF, + 0x0F, + 0xFE, + 0x0F, + + /* @144 '3' (12 pixels wide) */ + 0xFC, + 0x03, + 0x06, + 0x03, + 0x03, + 0x06, + 0xF1, + 0x04, + 0xF9, + 0x0C, + 0xFF, + 0x0C, + 0xFE, + 0x0C, + 0x0E, + 0x0E, + 0x08, + 0x0F, + 0xF8, + 0x0E, + 0xF8, + 0x04, + 0xFF, + 0x0C, + 0xF9, + 0x0C, + 0xF1, + 0x0C, + 0x03, + 0x0E, + 0x06, + 0x0F, + 0xFC, + 0x07, + 0xFC, + 0x03, + + /* @180 '4' (12 pixels wide) */ + 0xE0, + 0x03, + 0x30, + 0x03, + 0x10, + 0x03, + 0x08, + 0x03, + 0x4C, + 0x03, + 0x64, + 0x03, + 0x72, + 0x03, + 0x73, + 0x03, + 0x79, + 0x03, + 0x01, + 0x04, + 0x01, + 0x0C, + 0x7F, + 0x0F, + 0x7E, + 0x0F, + 0x7E, + 0x0F, + 0x40, + 0x03, + 0x40, + 0x03, + 0xC0, + 0x03, + 0x80, + 0x03, + + /* @216 '5' (12 pixels wide) */ + 0xFF, + 0x07, + 0x01, + 0x0C, + 0x01, + 0x0C, + 0xF9, + 0x0F, + 0xF9, + 0x0F, + 0xF9, + 0x0F, + 0x01, + 0x03, + 0x03, + 0x06, + 0xFE, + 0x04, + 0xFE, + 0x0C, + 0xFC, + 0x0C, + 0xFF, + 0x0C, + 0xF9, + 0x0C, + 0xF1, + 0x0C, + 0x03, + 0x0E, + 0x06, + 0x0F, + 0xFC, + 0x07, + 0xF8, + 0x03, + + /* @252 '6' (12 pixels wide) */ + 0xF0, + 0x03, + 0x10, + 0x03, + 0x08, + 0x03, + 0xCC, + 0x03, + 0xE6, + 0x03, + 0xF2, + 0x03, + 0xF2, + 0x00, + 0x01, + 0x03, + 0x01, + 0x06, + 0xF1, + 0x04, + 0xF9, + 0x0C, + 0xF9, + 0x0C, + 0xF9, + 0x0C, + 0xF1, + 0x0C, + 0x03, + 0x0E, + 0x06, + 0x0F, + 0xFC, + 0x07, + 0xF8, + 0x03, + + /* @288 '7' (12 pixels wide) */ + 0xFF, + 0x07, + 0x01, + 0x0C, + 0x01, + 0x0C, + 0xFF, + 0x0E, + 0xFE, + 0x0E, + 0x7E, + 0x0F, + 0x40, + 0x07, + 0x60, + 0x07, + 0x20, + 0x03, + 0x30, + 0x03, + 0x90, + 0x01, + 0x90, + 0x01, + 0xD0, + 0x00, + 0xC8, + 0x00, + 0xE8, + 0x00, + 0xE8, + 0x00, + 0x78, + 0x00, + 0x78, + 0x00, + + /* @324 '8' (12 pixels wide) */ + 0xF8, + 0x01, + 0x0C, + 0x01, + 0x06, + 0x03, + 0x72, + 0x06, + 0xF2, + 0x06, + 0xF2, + 0x06, + 0x72, + 0x06, + 0x06, + 0x07, + 0x02, + 0x06, + 0xF1, + 0x04, + 0xF9, + 0x0C, + 0xF9, + 0x0C, + 0xF9, + 0x0C, + 0xF1, + 0x0C, + 0x03, + 0x0E, + 0x06, + 0x0F, + 0xFC, + 0x07, + 0xF8, + 0x03, + + /* @360 '9' (12 pixels wide) */ + 0xFC, + 0x03, + 0x06, + 0x03, + 0x03, + 0x06, + 0xF1, + 0x04, + 0xF9, + 0x0C, + 0xF9, + 0x0C, + 0xF1, + 0x0C, + 0x03, + 0x0C, + 0x06, + 0x0C, + 0xFE, + 0x0E, + 0x7C, + 0x0E, + 0x38, + 0x0F, + 0x30, + 0x07, + 0x1C, + 0x07, + 0x84, + 0x03, + 0xC4, + 0x01, + 0xFC, + 0x00, + 0xF8, + 0x00, + + /* @396 'B' (12 pixels wide) */ + 0xFE, + 0x01, + 0x02, + 0x03, + 0x02, + 0x02, + 0x72, + 0x06, + 0xF2, + 0x06, + 0xF2, + 0x06, + 0x72, + 0x06, + 0x02, + 0x06, + 0x02, + 0x06, + 0xF2, + 0x0C, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0C, + 0x02, + 0x0E, + 0x02, + 0x0E, + 0xFE, + 0x07, + 0xFC, + 0x03, + + /* @432 'C' (12 pixels wide) */ + 0xF0, + 0x03, + 0x18, + 0x02, + 0x0C, + 0x06, + 0xE4, + 0x0C, + 0xE6, + 0x0D, + 0xF2, + 0x0F, + 0x72, + 0x0F, + 0x32, + 0x0F, + 0x12, + 0x00, + 0x12, + 0x00, + 0x12, + 0x00, + 0x32, + 0x07, + 0xA6, + 0x0D, + 0xE4, + 0x0C, + 0x08, + 0x0E, + 0x18, + 0x0E, + 0xF0, + 0x07, + 0xF0, + 0x03, + + /* @468 'D' (12 pixels wide) */ + 0xFE, + 0x01, + 0x02, + 0x03, + 0x02, + 0x02, + 0x72, + 0x06, + 0xF2, + 0x06, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0E, + 0xF2, + 0x0E, + 0x72, + 0x0E, + 0x02, + 0x06, + 0x02, + 0x07, + 0xFE, + 0x03, + 0xFC, + 0x01, + + /* @504 'F' (12 pixels wide) */ + 0xFE, + 0x07, + 0x02, + 0x0C, + 0x02, + 0x0C, + 0xF2, + 0x0F, + 0xF2, + 0x0F, + 0xF2, + 0x0F, + 0x12, + 0x00, + 0xF2, + 0x03, + 0x02, + 0x02, + 0xF2, + 0x03, + 0xF2, + 0x03, + 0xF2, + 0x03, + 0x12, + 0x00, + 0x12, + 0x00, + 0x12, + 0x00, + 0x12, + 0x00, + 0x1E, + 0x00, + 0x1C, + 0x00, + + /* @540 'G' (12 pixels wide) */ + 0xF0, + 0x07, + 0x18, + 0x06, + 0x0C, + 0x0C, + 0xE4, + 0x0D, + 0xE6, + 0x0F, + 0xF2, + 0x0F, + 0xF2, + 0x0F, + 0x32, + 0x04, + 0x32, + 0x0C, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xE6, + 0x0D, + 0xE6, + 0x0D, + 0xE4, + 0x0D, + 0x08, + 0x0C, + 0x18, + 0x0C, + 0xF0, + 0x0F, + 0xF0, + 0x0F, + + /* @576 'H' (12 pixels wide) */ + 0x1E, + 0x07, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0xF2, + 0x0D, + 0x02, + 0x0C, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x1E, + 0x0F, + 0x1C, + 0x0F, + + /* @612 'J' (12 pixels wide) */ + 0x80, + 0x03, + 0x80, + 0x06, + 0x80, + 0x06, + 0x80, + 0x06, + 0x80, + 0x06, + 0x80, + 0x06, + 0x80, + 0x06, + 0x80, + 0x06, + 0x80, + 0x06, + 0x80, + 0x06, + 0x8E, + 0x06, + 0x8A, + 0x06, + 0xDA, + 0x06, + 0x72, + 0x06, + 0x02, + 0x06, + 0x06, + 0x03, + 0xFC, + 0x03, + 0xF8, + 0x01, + + /* @648 'K' (12 pixels wide) */ + 0x1E, + 0x07, + 0x92, + 0x0D, + 0xD2, + 0x0C, + 0x72, + 0x0E, + 0x32, + 0x0E, + 0x12, + 0x0F, + 0x92, + 0x07, + 0xC2, + 0x03, + 0xC2, + 0x01, + 0x92, + 0x01, + 0x12, + 0x01, + 0x32, + 0x02, + 0x32, + 0x02, + 0x72, + 0x06, + 0xD2, + 0x0C, + 0x92, + 0x0D, + 0x9E, + 0x0F, + 0x1C, + 0x0F, + + /* @684 'M' (12 pixels wide) */ + 0x1E, + 0x07, + 0x92, + 0x0D, + 0xA2, + 0x0C, + 0xE2, + 0x0C, + 0x62, + 0x0C, + 0x62, + 0x0C, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x92, + 0x0D, + 0x92, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x1E, + 0x0F, + 0x1C, + 0x0F, + + /* @720 'N' (12 pixels wide) */ + 0x1E, + 0x07, + 0x12, + 0x0D, + 0x22, + 0x0D, + 0x62, + 0x0D, + 0x62, + 0x0D, + 0xD2, + 0x0D, + 0xD2, + 0x0D, + 0x92, + 0x0D, + 0x92, + 0x0D, + 0x32, + 0x0D, + 0x32, + 0x0D, + 0x72, + 0x0C, + 0x52, + 0x0C, + 0xD2, + 0x0C, + 0x92, + 0x0C, + 0x92, + 0x0D, + 0x1E, + 0x0F, + 0x1C, + 0x0F, + + /* @756 'P' (12 pixels wide) */ + 0xFE, + 0x03, + 0x02, + 0x02, + 0x02, + 0x06, + 0xF2, + 0x0C, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0C, + 0x02, + 0x0E, + 0x02, + 0x0E, + 0xF2, + 0x0F, + 0xF2, + 0x07, + 0xF2, + 0x03, + 0x12, + 0x00, + 0x12, + 0x00, + 0x12, + 0x00, + 0x1E, + 0x00, + 0x1C, + 0x00, + + /* @792 'Q' (12 pixels wide) */ + 0xF0, + 0x01, + 0x18, + 0x03, + 0x0C, + 0x02, + 0x64, + 0x06, + 0xE6, + 0x06, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0x32, + 0x0D, + 0x26, + 0x0E, + 0x26, + 0x0E, + 0x64, + 0x0E, + 0x08, + 0x0C, + 0x18, + 0x0D, + 0xF0, + 0x0F, + 0xF0, + 0x0F, + + /* @828 'R' (12 pixels wide) */ + 0xFE, + 0x03, + 0x02, + 0x02, + 0x02, + 0x06, + 0xF2, + 0x0C, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0D, + 0xF2, + 0x0C, + 0x02, + 0x0E, + 0x02, + 0x0E, + 0x12, + 0x0F, + 0x32, + 0x06, + 0x32, + 0x06, + 0x72, + 0x06, + 0xD2, + 0x0C, + 0x92, + 0x0D, + 0x9E, + 0x0F, + 0x1C, + 0x0F, + + /* @864 'T' (12 pixels wide) */ + 0xFE, + 0x03, + 0x02, + 0x02, + 0x02, + 0x02, + 0xDE, + 0x03, + 0xDC, + 0x03, + 0xDC, + 0x03, + 0xD0, + 0x00, + 0xD0, + 0x00, + 0xD0, + 0x00, + 0xD0, + 0x00, + 0xD0, + 0x00, + 0xD0, + 0x00, + 0xD0, + 0x00, + 0xD0, + 0x00, + 0xD0, + 0x00, + 0xD0, + 0x00, + 0xF0, + 0x00, + 0xF0, + 0x00, + + /* @900 'V' (12 pixels wide) */ + 0x1E, + 0x07, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x92, + 0x0D, + 0xA6, + 0x0E, + 0xA4, + 0x0E, + 0xA4, + 0x0E, + 0xE4, + 0x06, + 0x6C, + 0x06, + 0x68, + 0x06, + 0x68, + 0x02, + 0x18, + 0x03, + 0x10, + 0x03, + 0x10, + 0x01, + 0x90, + 0x01, + 0x90, + 0x01, + 0xE0, + 0x01, + 0xE0, + 0x01, + + /* @936 'W' (12 pixels wide) */ + 0x1E, + 0x07, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0x12, + 0x0D, + 0xF2, + 0x0D, + 0x92, + 0x0D, + 0x12, + 0x0D, + 0x62, + 0x0C, + 0x62, + 0x0C, + 0xE2, + 0x0C, + 0xE2, + 0x0C, + 0xB2, + 0x0D, + 0x3E, + 0x0F, + 0x1C, + 0x0F, + + /* @972 'X' (12 pixels wide) */ + 0x1E, + 0x07, + 0x12, + 0x0D, + 0xB2, + 0x0D, + 0xA6, + 0x0E, + 0xE4, + 0x0E, + 0x6C, + 0x0E, + 0x18, + 0x07, + 0x98, + 0x07, + 0x90, + 0x03, + 0x10, + 0x01, + 0x68, + 0x02, + 0xE4, + 0x02, + 0xE4, + 0x06, + 0xE6, + 0x06, + 0xB2, + 0x0D, + 0x32, + 0x0D, + 0x1E, + 0x0F, + 0x1C, + 0x0E, + + /* @1008 'Y' (12 pixels wide) */ + 0x1E, + 0x07, + 0x12, + 0x0D, + 0xB2, + 0x0D, + 0xA6, + 0x0E, + 0xE4, + 0x0E, + 0x6C, + 0x0E, + 0x68, + 0x06, + 0x18, + 0x07, + 0x18, + 0x03, + 0x90, + 0x03, + 0x90, + 0x01, + 0x90, + 0x01, + 0xA0, + 0x01, + 0xA0, + 0x01, + 0xA0, + 0x01, + 0xE0, + 0x01, + 0xE0, + 0x01, + 0xE0, + 0x01, +}; + +/* Character descriptors for Karma Future 14pt */ +/* { [Char width in bits], [Offset into karmaFuture_14ptCharBitmaps in bytes] } */ +const FONT_CHAR_INFO karmaFuture_14ptDescriptors[] = { + {12, 0}, /* - */ + {0, 0}, /* . */ + {0, 0}, /* / */ + {12, 36}, /* 0 */ + {12, 72}, /* 1 */ + {12, 108}, /* 2 */ + {12, 144}, /* 3 */ + {12, 180}, /* 4 */ + {12, 216}, /* 5 */ + {12, 252}, /* 6 */ + {12, 288}, /* 7 */ + {12, 324}, /* 8 */ + {12, 360}, /* 9 */ + {0, 0}, /* : */ + {0, 0}, /* ; */ + {0, 0}, /* < */ + {0, 0}, /* = */ + {0, 0}, /* > */ + {0, 0}, /* ? */ + {0, 0}, /* @ */ + {0, 0}, /* A */ + {12, 396}, /* B */ + {12, 432}, /* C */ + {12, 468}, /* D */ + {0, 0}, /* E */ + {12, 504}, /* F */ + {12, 540}, /* G */ + {12, 576}, /* H */ + {0, 0}, /* I */ + {12, 612}, /* J */ + {12, 648}, /* K */ + {0, 0}, /* L */ + {12, 684}, /* M */ + {12, 720}, /* N */ + {0, 0}, /* O */ + {12, 756}, /* P */ + {12, 792}, /* Q */ + {12, 828}, /* R */ + {0, 0}, /* S */ + {12, 864}, /* T */ + {0, 0}, /* U */ + {12, 900}, /* V */ + {12, 936}, /* W */ + {12, 972}, /* X */ + {12, 1008}, /* Y */ +}; + +/* Font information for Karma Future 14pt */ +const FONT_INFO karmaFuture_14ptFontInfo = { + 18, /* Character height */ + '-', /* Start character */ + 'Y', /* End character */ + 2, /* Width, in pixels, of space character */ + karmaFuture_14ptDescriptors, /* Character descriptor array */ + karmaFuture_14ptBitmaps, /* Character bitmap array */ +}; diff --git a/applications/external/totp/ui/fonts/karma_future/karma_future.h b/applications/external/totp/ui/fonts/karma_future/karma_future.h new file mode 100644 index 000000000..3a6352ef1 --- /dev/null +++ b/applications/external/totp/ui/fonts/karma_future/karma_future.h @@ -0,0 +1,8 @@ +#pragma once + +/* GENERATED BY https://github.com/pavius/the-dot-factory */ + +#include "../font_info.h" + +/* Font data for Karma Future 14pt */ +extern const FONT_INFO karmaFuture_14ptFontInfo; diff --git a/applications/external/totp/ui/fonts/mode-nine/mode_nine.c b/applications/external/totp/ui/fonts/mode_nine/mode_nine.c similarity index 100% rename from applications/external/totp/ui/fonts/mode-nine/mode_nine.c rename to applications/external/totp/ui/fonts/mode_nine/mode_nine.c diff --git a/applications/external/totp/ui/fonts/mode-nine/mode_nine.h b/applications/external/totp/ui/fonts/mode_nine/mode_nine.h similarity index 100% rename from applications/external/totp/ui/fonts/mode-nine/mode_nine.h rename to applications/external/totp/ui/fonts/mode_nine/mode_nine.h diff --git a/applications/external/totp/ui/fonts/redhat_mono/redhat_mono.c b/applications/external/totp/ui/fonts/redhat_mono/redhat_mono.c new file mode 100644 index 000000000..77f639d4a --- /dev/null +++ b/applications/external/totp/ui/fonts/redhat_mono/redhat_mono.c @@ -0,0 +1,1057 @@ +#include "redhat_mono.h" +#include + +/* GENERATED BY https://github.com/pavius/the-dot-factory */ + +/* +** Font data for Red Hat Mono 16pt +*/ + +/* Character bitmaps for Red Hat Mono 16pt */ +const uint8_t redHatMono_16ptBitmaps[] = { + /* @0 '-' (12 pixels wide) */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xF8, + 0x03, + 0xF8, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + + /* @32 '0' (12 pixels wide) */ + 0xF0, + 0x00, + 0xF8, + 0x03, + 0x1C, + 0x07, + 0x0E, + 0x07, + 0x8E, + 0x07, + 0x86, + 0x0E, + 0xC6, + 0x0C, + 0x66, + 0x0C, + 0x66, + 0x0C, + 0x36, + 0x0E, + 0x36, + 0x0E, + 0x1E, + 0x06, + 0x1C, + 0x07, + 0xF8, + 0x03, + 0xF0, + 0x01, + 0x00, + 0x00, + + /* @64 '1' (12 pixels wide) */ + 0x40, + 0x00, + 0x78, + 0x00, + 0x7E, + 0x00, + 0x66, + 0x00, + 0x60, + 0x00, + 0x60, + 0x00, + 0x60, + 0x00, + 0x60, + 0x00, + 0x60, + 0x00, + 0x60, + 0x00, + 0x60, + 0x00, + 0x60, + 0x00, + 0x60, + 0x00, + 0xFE, + 0x07, + 0xFE, + 0x07, + 0x00, + 0x00, + + /* @96 '2' (12 pixels wide) */ + 0xF0, + 0x01, + 0xFC, + 0x03, + 0x0E, + 0x07, + 0x04, + 0x06, + 0x00, + 0x06, + 0x00, + 0x07, + 0x00, + 0x03, + 0x80, + 0x03, + 0xC0, + 0x01, + 0xE0, + 0x00, + 0x70, + 0x00, + 0x38, + 0x00, + 0x1C, + 0x00, + 0xFE, + 0x07, + 0xFE, + 0x07, + 0x00, + 0x00, + + /* @128 '3' (12 pixels wide) */ + 0xF0, + 0x00, + 0xFC, + 0x03, + 0x0E, + 0x07, + 0x04, + 0x06, + 0x00, + 0x06, + 0x00, + 0x06, + 0x80, + 0x03, + 0xE0, + 0x00, + 0xE0, + 0x03, + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x0E, + 0x06, + 0x07, + 0xFE, + 0x07, + 0xF8, + 0x01, + 0x00, + 0x00, + + /* @160 '4' (12 pixels wide) */ + 0x00, + 0x03, + 0x80, + 0x03, + 0xC0, + 0x03, + 0xE0, + 0x03, + 0x70, + 0x03, + 0x30, + 0x03, + 0x18, + 0x03, + 0x0C, + 0x03, + 0x0E, + 0x03, + 0xFF, + 0x0F, + 0xFF, + 0x0F, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x03, + 0x00, + 0x00, + + /* @192 '5' (12 pixels wide) */ + 0xFC, + 0x07, + 0xFC, + 0x07, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0xFC, + 0x01, + 0xFE, + 0x07, + 0x00, + 0x07, + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x06, + 0x06, + 0x07, + 0xFE, + 0x03, + 0xF8, + 0x01, + 0x00, + 0x00, + + /* @224 '6' (12 pixels wide) */ + 0xE0, + 0x03, + 0xF8, + 0x07, + 0x3C, + 0x06, + 0x0C, + 0x00, + 0x0E, + 0x00, + 0x06, + 0x00, + 0xE6, + 0x03, + 0xFE, + 0x07, + 0x0E, + 0x0E, + 0x06, + 0x0C, + 0x06, + 0x0C, + 0x0E, + 0x0E, + 0x1C, + 0x06, + 0xF8, + 0x07, + 0xF0, + 0x03, + 0x00, + 0x00, + + /* @256 '7' (12 pixels wide) */ + 0xFE, + 0x0F, + 0xFE, + 0x0F, + 0x00, + 0x0E, + 0x00, + 0x06, + 0x00, + 0x07, + 0x00, + 0x03, + 0x80, + 0x01, + 0xC0, + 0x01, + 0xC0, + 0x00, + 0xE0, + 0x00, + 0x60, + 0x00, + 0x70, + 0x00, + 0x30, + 0x00, + 0x38, + 0x00, + 0x1C, + 0x00, + 0x00, + 0x00, + + /* @288 '8' (12 pixels wide) */ + 0xF0, + 0x01, + 0xFC, + 0x03, + 0x1C, + 0x07, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0C, + 0x06, + 0xBC, + 0x03, + 0xF0, + 0x01, + 0x1C, + 0x07, + 0x0E, + 0x06, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x0E, + 0x06, + 0xFC, + 0x07, + 0xF8, + 0x03, + 0x00, + 0x00, + + /* @320 '9' (12 pixels wide) */ + 0xF8, + 0x01, + 0xFC, + 0x03, + 0x0C, + 0x07, + 0x0E, + 0x0E, + 0x06, + 0x0C, + 0x06, + 0x0C, + 0x0E, + 0x0E, + 0xFC, + 0x0F, + 0xF8, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0E, + 0x00, + 0x06, + 0x8C, + 0x07, + 0xFC, + 0x03, + 0xF8, + 0x00, + 0x00, + 0x00, + + /* @352 'B' (12 pixels wide) */ + 0xFC, + 0x00, + 0xFC, + 0x03, + 0x8C, + 0x07, + 0x0C, + 0x06, + 0x0C, + 0x06, + 0x0C, + 0x07, + 0xFC, + 0x03, + 0xFC, + 0x01, + 0x8C, + 0x07, + 0x0C, + 0x06, + 0x0C, + 0x0E, + 0x0C, + 0x0E, + 0x0C, + 0x07, + 0xFC, + 0x07, + 0xFC, + 0x01, + 0x00, + 0x00, + + /* @384 'C' (12 pixels wide) */ + 0xF0, + 0x01, + 0xF8, + 0x03, + 0xBC, + 0x07, + 0x0C, + 0x06, + 0x0E, + 0x0E, + 0x0E, + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x0E, + 0x0E, + 0x0E, + 0x0E, + 0x1C, + 0x07, + 0xF8, + 0x03, + 0xF0, + 0x01, + 0x00, + 0x00, + + /* @416 'D' (12 pixels wide) */ + 0x7E, + 0x00, + 0xFE, + 0x01, + 0xCE, + 0x03, + 0x0E, + 0x07, + 0x0E, + 0x06, + 0x0E, + 0x0E, + 0x0E, + 0x0E, + 0x0E, + 0x0E, + 0x0C, + 0x0E, + 0x0C, + 0x0E, + 0x0C, + 0x06, + 0x0C, + 0x07, + 0x8C, + 0x07, + 0xFC, + 0x03, + 0xFC, + 0x00, + 0x00, + 0x00, + + /* @448 'F' (12 pixels wide) */ + 0xFC, + 0x0F, + 0xFC, + 0x0F, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0xFC, + 0x01, + 0xFC, + 0x01, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x00, + 0x00, + + /* @480 'G' (12 pixels wide) */ + 0xF0, + 0x01, + 0xF8, + 0x03, + 0xBC, + 0x07, + 0x0C, + 0x06, + 0x0E, + 0x0E, + 0x06, + 0x00, + 0x06, + 0x00, + 0x86, + 0x0F, + 0x86, + 0x0F, + 0x06, + 0x0C, + 0x0E, + 0x0E, + 0x0E, + 0x06, + 0x1C, + 0x07, + 0xF8, + 0x03, + 0xF0, + 0x01, + 0x00, + 0x00, + + /* @512 'H' (12 pixels wide) */ + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0xFE, + 0x07, + 0xFE, + 0x07, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x00, + 0x00, + + /* @544 'J' (12 pixels wide) */ + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x06, + 0x00, + 0x06, + 0x04, + 0x06, + 0x07, + 0x07, + 0x8E, + 0x07, + 0xFC, + 0x03, + 0xF8, + 0x01, + 0x00, + 0x00, + + /* @576 'K' (12 pixels wide) */ + 0x0E, + 0x0E, + 0x0E, + 0x07, + 0x0E, + 0x03, + 0x8E, + 0x01, + 0xCE, + 0x01, + 0xEE, + 0x00, + 0x7E, + 0x00, + 0x3E, + 0x00, + 0x7E, + 0x00, + 0xEE, + 0x00, + 0xCE, + 0x01, + 0x8E, + 0x03, + 0x8E, + 0x03, + 0x0E, + 0x07, + 0x0E, + 0x0E, + 0x00, + 0x00, + + /* @608 'M' (12 pixels wide) */ + 0x0E, + 0x0E, + 0x0E, + 0x0F, + 0x1E, + 0x0F, + 0x9E, + 0x0F, + 0xB6, + 0x0F, + 0xB6, + 0x0F, + 0xF6, + 0x0E, + 0xE6, + 0x0E, + 0x66, + 0x0E, + 0x46, + 0x0E, + 0x26, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x00, + 0x00, + + /* @640 'N' (12 pixels wide) */ + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x1E, + 0x06, + 0x3E, + 0x06, + 0x3E, + 0x06, + 0x76, + 0x06, + 0x66, + 0x06, + 0xE6, + 0x06, + 0xC6, + 0x06, + 0xC6, + 0x07, + 0x86, + 0x07, + 0x86, + 0x07, + 0x06, + 0x07, + 0x06, + 0x07, + 0x06, + 0x06, + 0x00, + 0x00, + + /* @672 'P' (12 pixels wide) */ + 0xFC, + 0x00, + 0xFC, + 0x03, + 0x8C, + 0x07, + 0x0C, + 0x0E, + 0x0C, + 0x0E, + 0x0C, + 0x0E, + 0x0C, + 0x06, + 0xFC, + 0x07, + 0xFC, + 0x03, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x0C, + 0x00, + 0x00, + 0x00, + + /* @704 'Q' (12 pixels wide) */ + 0xF0, + 0x00, + 0xF8, + 0x03, + 0x9C, + 0x07, + 0x0E, + 0x07, + 0x0E, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0x06, + 0x0E, + 0xEE, + 0x0E, + 0xCE, + 0x07, + 0x9C, + 0x07, + 0xFC, + 0x07, + 0xF0, + 0x07, + 0x00, + 0x0A, + + /* @736 'R' (12 pixels wide) */ + 0xFC, + 0x00, + 0xFC, + 0x03, + 0x8C, + 0x07, + 0x0C, + 0x06, + 0x0C, + 0x0E, + 0x0C, + 0x0E, + 0x0C, + 0x07, + 0xFC, + 0x07, + 0xFC, + 0x01, + 0x8C, + 0x01, + 0x8C, + 0x03, + 0x0C, + 0x03, + 0x0C, + 0x07, + 0x0C, + 0x06, + 0x0C, + 0x0E, + 0x00, + 0x00, + + /* @768 'T' (12 pixels wide) */ + 0xFF, + 0x0F, + 0xFF, + 0x0F, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0x00, + 0x00, + + /* @800 'V' (12 pixels wide) */ + 0x07, + 0x0C, + 0x06, + 0x0C, + 0x06, + 0x0E, + 0x0E, + 0x06, + 0x0C, + 0x06, + 0x0C, + 0x07, + 0x1C, + 0x03, + 0x1C, + 0x03, + 0x98, + 0x03, + 0x98, + 0x03, + 0xB8, + 0x01, + 0xB0, + 0x01, + 0xF0, + 0x01, + 0xF0, + 0x00, + 0xE0, + 0x00, + 0x00, + 0x00, + + /* @832 'W' (12 pixels wide) */ + 0x67, + 0x0C, + 0xE6, + 0x0C, + 0xE6, + 0x0C, + 0xE6, + 0x0C, + 0xE6, + 0x0C, + 0xF6, + 0x0C, + 0xB6, + 0x0E, + 0xB6, + 0x07, + 0xB6, + 0x07, + 0x96, + 0x07, + 0x9C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x1C, + 0x07, + 0x0C, + 0x07, + 0x00, + 0x00, + + /* @864 'X' (12 pixels wide) */ + 0x0E, + 0x0E, + 0x0E, + 0x06, + 0x1C, + 0x07, + 0x98, + 0x03, + 0xB8, + 0x01, + 0xF0, + 0x01, + 0xF0, + 0x00, + 0xE0, + 0x00, + 0xF0, + 0x00, + 0xF0, + 0x01, + 0xB8, + 0x03, + 0x9C, + 0x03, + 0x0C, + 0x07, + 0x0E, + 0x06, + 0x07, + 0x0E, + 0x00, + 0x00, + + /* @896 'Y' (12 pixels wide) */ + 0x07, + 0x0C, + 0x0E, + 0x0E, + 0x0E, + 0x06, + 0x1C, + 0x07, + 0x18, + 0x03, + 0xB8, + 0x03, + 0xF0, + 0x01, + 0xF0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0xE0, + 0x00, + 0x00, + 0x00, +}; + +/* Character descriptors for Red Hat Mono 16pt */ +/* { [Char width in bits], [Offset into redHatMono_16ptCharBitmaps in bytes] } */ +const FONT_CHAR_INFO redHatMono_16ptDescriptors[] = { + {12, 0}, /* - */ + {0, 0}, /* . */ + {0, 0}, /* / */ + {12, 32}, /* 0 */ + {12, 64}, /* 1 */ + {12, 96}, /* 2 */ + {12, 128}, /* 3 */ + {12, 160}, /* 4 */ + {12, 192}, /* 5 */ + {12, 224}, /* 6 */ + {12, 256}, /* 7 */ + {12, 288}, /* 8 */ + {12, 320}, /* 9 */ + {0, 0}, /* : */ + {0, 0}, /* ; */ + {0, 0}, /* < */ + {0, 0}, /* = */ + {0, 0}, /* > */ + {0, 0}, /* ? */ + {0, 0}, /* @ */ + {0, 0}, /* A */ + {12, 352}, /* B */ + {12, 384}, /* C */ + {12, 416}, /* D */ + {0, 0}, /* E */ + {12, 448}, /* F */ + {12, 480}, /* G */ + {12, 512}, /* H */ + {0, 0}, /* I */ + {12, 544}, /* J */ + {12, 576}, /* K */ + {0, 0}, /* L */ + {12, 608}, /* M */ + {12, 640}, /* N */ + {0, 0}, /* O */ + {12, 672}, /* P */ + {12, 704}, /* Q */ + {12, 736}, /* R */ + {0, 0}, /* S */ + {12, 768}, /* T */ + {0, 0}, /* U */ + {12, 800}, /* V */ + {12, 832}, /* W */ + {12, 864}, /* X */ + {12, 896}, /* Y */ +}; + +/* Font information for Red Hat Mono 16pt */ +const FONT_INFO redHatMono_16ptFontInfo = { + 16, /* Character height */ + '-', /* Start character */ + 'Y', /* End character */ + 2, /* Width, in pixels, of space character */ + redHatMono_16ptDescriptors, /* Character descriptor array */ + redHatMono_16ptBitmaps, /* Character bitmap array */ +}; diff --git a/applications/external/totp/ui/fonts/redhat_mono/redhat_mono.h b/applications/external/totp/ui/fonts/redhat_mono/redhat_mono.h new file mode 100644 index 000000000..ac9214d6b --- /dev/null +++ b/applications/external/totp/ui/fonts/redhat_mono/redhat_mono.h @@ -0,0 +1,8 @@ +#pragma once + +/* GENERATED BY https://github.com/pavius/the-dot-factory */ + +#include "../font_info.h" + +/* Font data for Redhat Mono 16pt */ +extern const FONT_INFO redHatMono_16ptFontInfo; \ No newline at end of file diff --git a/applications/external/totp/ui/fonts/zector/zector.c b/applications/external/totp/ui/fonts/zector/zector.c new file mode 100644 index 000000000..f49d8b306 --- /dev/null +++ b/applications/external/totp/ui/fonts/zector/zector.c @@ -0,0 +1,1056 @@ +#include "zector.h" + +/* GENERATED BY https://github.com/pavius/the-dot-factory */ + +/* +** Font data for Zector 18pt +*/ + +/* Character bitmaps for Zector 18pt */ +const uint8_t zector_18ptBitmaps[] = { + /* @0 '-' (9 pixels wide) */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xFF, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + + /* @32 '0' (9 pixels wide) */ + 0x3C, + 0x00, + 0xC2, + 0x00, + 0x83, + 0x00, + 0x85, + 0x00, + 0x85, + 0x00, + 0x89, + 0x00, + 0x89, + 0x00, + 0x91, + 0x00, + 0x91, + 0x00, + 0xA1, + 0x00, + 0xA1, + 0x00, + 0xC1, + 0x00, + 0xC1, + 0x00, + 0x81, + 0x00, + 0x42, + 0x00, + 0x3C, + 0x00, + + /* @64 '1' (9 pixels wide) */ + 0x10, + 0x00, + 0x18, + 0x00, + 0x18, + 0x00, + 0x14, + 0x00, + 0x14, + 0x00, + 0x12, + 0x00, + 0x12, + 0x00, + 0x11, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0xFF, + 0x00, + + /* @96 '2' (9 pixels wide) */ + 0x3C, + 0x00, + 0x42, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x40, + 0x00, + 0x20, + 0x00, + 0x20, + 0x00, + 0x10, + 0x00, + 0x08, + 0x00, + 0x08, + 0x00, + 0x04, + 0x00, + 0x02, + 0x00, + 0x02, + 0x00, + 0xFF, + 0x00, + + /* @128 '3' (9 pixels wide) */ + 0xFF, + 0x01, + 0x80, + 0x00, + 0x80, + 0x00, + 0x40, + 0x00, + 0x40, + 0x00, + 0x20, + 0x00, + 0x20, + 0x00, + 0x10, + 0x00, + 0x60, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x00, + 0x01, + 0x01, + 0x01, + 0x81, + 0x00, + 0x42, + 0x00, + 0x3C, + 0x00, + + /* @160 '4' (9 pixels wide) */ + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0xFF, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + + /* @192 '5' (9 pixels wide) */ + 0xFF, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x3F, + 0x00, + 0x40, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0xC2, + 0x00, + 0x3C, + 0x00, + + /* @224 '6' (9 pixels wide) */ + 0x3C, + 0x00, + 0x42, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x3D, + 0x00, + 0x43, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0xC2, + 0x00, + 0x3C, + 0x00, + + /* @256 '7' (9 pixels wide) */ + 0xFF, + 0x01, + 0x80, + 0x00, + 0x80, + 0x00, + 0x40, + 0x00, + 0x40, + 0x00, + 0x20, + 0x00, + 0x20, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x08, + 0x00, + 0x08, + 0x00, + 0x04, + 0x00, + 0x04, + 0x00, + 0x02, + 0x00, + 0x02, + 0x00, + 0x01, + 0x00, + + /* @288 '8' (9 pixels wide) */ + 0x3C, + 0x00, + 0xC2, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x42, + 0x00, + 0x3C, + 0x00, + 0x42, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x42, + 0x00, + 0x3C, + 0x00, + + /* @320 '9' (9 pixels wide) */ + 0x3C, + 0x00, + 0x42, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0xC2, + 0x00, + 0xBC, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x42, + 0x00, + 0x3C, + 0x00, + + /* @352 'B' (9 pixels wide) */ + 0x3F, + 0x00, + 0xC1, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x41, + 0x00, + 0x3F, + 0x00, + 0x41, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x41, + 0x00, + 0x3F, + 0x00, + + /* @384 'C' (9 pixels wide) */ + 0x3C, + 0x00, + 0x42, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x42, + 0x00, + 0x3C, + 0x00, + + /* @416 'D' (9 pixels wide) */ + 0x3F, + 0x00, + 0x41, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x41, + 0x00, + 0x3F, + 0x00, + + /* @448 'F' (9 pixels wide) */ + 0xFF, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0xFF, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + + /* @480 'G' (9 pixels wide) */ + 0x3C, + 0x00, + 0xC2, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0xF1, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x42, + 0x00, + 0x3C, + 0x00, + + /* @512 'H' (9 pixels wide) */ + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0xFF, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + + /* @544 'J' (9 pixels wide) */ + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x80, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x42, + 0x00, + 0x3C, + 0x00, + + /* @576 'K' (9 pixels wide) */ + 0x81, + 0x00, + 0xC1, + 0x00, + 0x61, + 0x00, + 0x21, + 0x00, + 0x11, + 0x00, + 0x09, + 0x00, + 0x05, + 0x00, + 0x03, + 0x00, + 0x01, + 0x00, + 0x03, + 0x00, + 0x05, + 0x00, + 0x09, + 0x00, + 0x11, + 0x00, + 0x21, + 0x00, + 0x41, + 0x00, + 0x81, + 0x00, + + /* @608 'M' (9 pixels wide) */ + 0x81, + 0x00, + 0x81, + 0x00, + 0x83, + 0x00, + 0xC3, + 0x00, + 0xC5, + 0x00, + 0xA5, + 0x00, + 0xA9, + 0x00, + 0x91, + 0x00, + 0x91, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + + /* @640 'N' (9 pixels wide) */ + 0x81, + 0x00, + 0x81, + 0x00, + 0x83, + 0x00, + 0x83, + 0x00, + 0x85, + 0x00, + 0x85, + 0x00, + 0x89, + 0x00, + 0x89, + 0x00, + 0x91, + 0x00, + 0xA1, + 0x00, + 0xA1, + 0x00, + 0xC1, + 0x00, + 0xC1, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + + /* @672 'P' (9 pixels wide) */ + 0x3F, + 0x00, + 0x41, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x41, + 0x00, + 0x3F, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + 0x01, + 0x00, + + /* @704 'Q' (9 pixels wide) */ + 0x3C, + 0x00, + 0x42, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x91, + 0x00, + 0xA1, + 0x00, + 0xC2, + 0x00, + 0xBC, + 0x00, + + /* @736 'R' (9 pixels wide) */ + 0x3F, + 0x00, + 0x41, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x41, + 0x00, + 0x3F, + 0x00, + 0x03, + 0x00, + 0x05, + 0x00, + 0x09, + 0x00, + 0x11, + 0x00, + 0x21, + 0x00, + 0x41, + 0x00, + 0x81, + 0x00, + + /* @768 'T' (9 pixels wide) */ + 0xFF, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + + /* @800 'V' (9 pixels wide) */ + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x82, + 0x00, + 0x42, + 0x00, + 0x44, + 0x00, + 0x24, + 0x00, + 0x28, + 0x00, + 0x18, + 0x00, + 0x10, + 0x00, + + /* @832 'W' (9 pixels wide) */ + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + 0x91, + 0x00, + 0x91, + 0x00, + 0x99, + 0x00, + 0xA9, + 0x00, + 0xA5, + 0x00, + 0xC5, + 0x00, + 0x83, + 0x00, + 0x81, + 0x00, + 0x81, + 0x00, + + /* @864 'X' (9 pixels wide) */ + 0x81, + 0x00, + 0x82, + 0x00, + 0x82, + 0x00, + 0x44, + 0x00, + 0x44, + 0x00, + 0x28, + 0x00, + 0x28, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x28, + 0x00, + 0x28, + 0x00, + 0x44, + 0x00, + 0x44, + 0x00, + 0x82, + 0x00, + 0x82, + 0x00, + 0x81, + 0x00, + + /* @896 'Y' (9 pixels wide) */ + 0x81, + 0x00, + 0x82, + 0x00, + 0x82, + 0x00, + 0x44, + 0x00, + 0x44, + 0x00, + 0x28, + 0x00, + 0x28, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, + 0x10, + 0x00, +}; + +/* Character descriptors for Zector 18pt */ +/* { [Char width in bits], [Offset into zector_18ptCharBitmaps in bytes] } */ +const FONT_CHAR_INFO zector_18ptDescriptors[] = { + {9, 0}, /* - */ + {0, 0}, /* . */ + {0, 0}, /* / */ + {9, 32}, /* 0 */ + {9, 64}, /* 1 */ + {9, 96}, /* 2 */ + {9, 128}, /* 3 */ + {9, 160}, /* 4 */ + {9, 192}, /* 5 */ + {9, 224}, /* 6 */ + {9, 256}, /* 7 */ + {9, 288}, /* 8 */ + {9, 320}, /* 9 */ + {0, 0}, /* : */ + {0, 0}, /* ; */ + {0, 0}, /* < */ + {0, 0}, /* = */ + {0, 0}, /* > */ + {0, 0}, /* ? */ + {0, 0}, /* @ */ + {0, 0}, /* A */ + {9, 352}, /* B */ + {9, 384}, /* C */ + {9, 416}, /* D */ + {0, 0}, /* E */ + {9, 448}, /* F */ + {9, 480}, /* G */ + {9, 512}, /* H */ + {0, 0}, /* I */ + {9, 544}, /* J */ + {9, 576}, /* K */ + {0, 0}, /* L */ + {9, 608}, /* M */ + {9, 640}, /* N */ + {0, 0}, /* O */ + {9, 672}, /* P */ + {9, 704}, /* Q */ + {9, 736}, /* R */ + {0, 0}, /* S */ + {9, 768}, /* T */ + {0, 0}, /* U */ + {9, 800}, /* V */ + {9, 832}, /* W */ + {9, 864}, /* X */ + {9, 896}, /* Y */ +}; + +/* Font information for Zector 18pt */ +const FONT_INFO zector_18ptFontInfo = { + 16, /* Character height */ + '-', /* Start character */ + 'Y', /* End character */ + 2, /* Width, in pixels, of space character */ + zector_18ptDescriptors, /* Character descriptor array */ + zector_18ptBitmaps, /* Character bitmap array */ +}; diff --git a/applications/external/totp/ui/fonts/zector/zector.h b/applications/external/totp/ui/fonts/zector/zector.h new file mode 100644 index 000000000..2a5cf5907 --- /dev/null +++ b/applications/external/totp/ui/fonts/zector/zector.h @@ -0,0 +1,8 @@ +#pragma once + +/* GENERATED BY https://github.com/pavius/the-dot-factory */ + +#include "../font_info.h" + +/* Font information for Zector 18pt */ +extern const FONT_INFO zector_18ptFontInfo; \ No newline at end of file diff --git a/applications/external/totp/ui/scenes/add_new_token/totp_input_text.c b/applications/external/totp/ui/scenes/add_new_token/totp_input_text.c index bbe0b7726..5eb1231d9 100644 --- a/applications/external/totp/ui/scenes/add_new_token/totp_input_text.c +++ b/applications/external/totp/ui/scenes/add_new_token/totp_input_text.c @@ -29,7 +29,7 @@ void view_unlock_model(View* view) { static void commit_text_input_callback(void* context) { InputTextSceneState* text_input_state = (InputTextSceneState*)context; - if(text_input_state->callback != 0) { + if(text_input_state->callback != NULL) { InputTextSceneCallbackResult* result = malloc(sizeof(InputTextSceneCallbackResult)); furi_check(result != NULL); result->user_input_length = diff --git a/applications/external/totp/ui/scenes/add_new_token/totp_scene_add_new_token.c b/applications/external/totp/ui/scenes/add_new_token/totp_scene_add_new_token.c index d525e3399..327185cf7 100644 --- a/applications/external/totp/ui/scenes/add_new_token/totp_scene_add_new_token.c +++ b/applications/external/totp/ui/scenes/add_new_token/totp_scene_add_new_token.c @@ -36,7 +36,7 @@ typedef struct { InputTextSceneContext* token_name_input_context; InputTextSceneContext* token_secret_input_context; InputTextSceneState* input_state; - uint32_t input_started_at; + bool text_input_mode; int16_t screen_y_offset; TokenHashAlgo algo; uint8_t digits_count_index; @@ -56,7 +56,7 @@ static void on_token_name_user_comitted(InputTextSceneCallbackResult* result) { free(scene_state->token_name); scene_state->token_name = result->user_input; scene_state->token_name_length = result->user_input_length; - scene_state->input_started_at = 0; + scene_state->text_input_mode = false; free(result); } @@ -65,7 +65,7 @@ static void on_token_secret_user_comitted(InputTextSceneCallbackResult* result) free(scene_state->token_secret); scene_state->token_secret = result->user_input; scene_state->token_secret_length = result->user_input_length; - scene_state->input_started_at = 0; + scene_state->text_input_mode = false; free(result); } @@ -127,8 +127,8 @@ void totp_scene_add_new_token_activate(PluginState* plugin_state) { } void totp_scene_add_new_token_render(Canvas* const canvas, PluginState* plugin_state) { - SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - if(scene_state->input_started_at > 0) { + SceneState* scene_state = plugin_state->current_scene_state; + if(scene_state->text_input_mode) { totp_input_text_render(canvas, scene_state->input_state); return; } @@ -200,63 +200,81 @@ bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState return true; } - SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - if(scene_state->input_started_at > 0 && - furi_get_tick() - scene_state->input_started_at > 300) { + SceneState* scene_state = plugin_state->current_scene_state; + + if(event->input.type == InputTypeLong && event->input.key == InputKeyBack) { + if(scene_state->text_input_mode) { + scene_state->text_input_mode = false; + } else { + return false; + } + } + + if(scene_state->text_input_mode) { + if(event->input.type == InputTypeShort && event->input.key == InputKeyBack) { + PluginEvent long_back_cb_evt = { + .type = event->type, .input.key = InputKeyBack, .input.type = InputTypeLong}; + return totp_input_text_handle_event(&long_back_cb_evt, scene_state->input_state); + } + return totp_input_text_handle_event(event, scene_state->input_state); } - if(event->input.type == InputTypeLong && event->input.key == InputKeyBack) { - return false; - } - - if(event->input.type != InputTypePress) { - return true; - } - - switch(event->input.key) { - case InputKeyUp: - totp_roll_value_uint8_t( - &scene_state->selected_control, - -1, - TokenNameTextBox, - ConfirmButton, - RollOverflowBehaviorStop); - update_screen_y_offset(scene_state); - break; - case InputKeyDown: - totp_roll_value_uint8_t( - &scene_state->selected_control, - 1, - TokenNameTextBox, - ConfirmButton, - RollOverflowBehaviorStop); - update_screen_y_offset(scene_state); - break; - case InputKeyRight: - if(scene_state->selected_control == TokenAlgoSelect) { - totp_roll_value_uint8_t(&scene_state->algo, 1, SHA1, STEAM, RollOverflowBehaviorRoll); - } else if(scene_state->selected_control == TokenLengthSelect) { + if(event->input.type == InputTypePress) { + switch(event->input.key) { + case InputKeyUp: totp_roll_value_uint8_t( - &scene_state->digits_count_index, 1, 0, 2, RollOverflowBehaviorRoll); - } else if(scene_state->selected_control == TokenDurationSelect) { - totp_roll_value_uint8_t(&scene_state->duration, 15, 15, 255, RollOverflowBehaviorStop); - update_duration_text(scene_state); + &scene_state->selected_control, + -1, + TokenNameTextBox, + ConfirmButton, + RollOverflowBehaviorStop); + update_screen_y_offset(scene_state); + break; + case InputKeyDown: + totp_roll_value_uint8_t( + &scene_state->selected_control, + 1, + TokenNameTextBox, + ConfirmButton, + RollOverflowBehaviorStop); + update_screen_y_offset(scene_state); + break; + case InputKeyRight: + if(scene_state->selected_control == TokenAlgoSelect) { + totp_roll_value_uint8_t( + &scene_state->algo, 1, SHA1, STEAM, RollOverflowBehaviorRoll); + } else if(scene_state->selected_control == TokenLengthSelect) { + totp_roll_value_uint8_t( + &scene_state->digits_count_index, 1, 0, 2, RollOverflowBehaviorRoll); + } else if(scene_state->selected_control == TokenDurationSelect) { + totp_roll_value_uint8_t( + &scene_state->duration, 15, 15, 255, RollOverflowBehaviorStop); + update_duration_text(scene_state); + } + break; + case InputKeyLeft: + if(scene_state->selected_control == TokenAlgoSelect) { + totp_roll_value_uint8_t( + &scene_state->algo, -1, SHA1, STEAM, RollOverflowBehaviorRoll); + } else if(scene_state->selected_control == TokenLengthSelect) { + totp_roll_value_uint8_t( + &scene_state->digits_count_index, -1, 0, 2, RollOverflowBehaviorRoll); + } else if(scene_state->selected_control == TokenDurationSelect) { + totp_roll_value_uint8_t( + &scene_state->duration, -15, 15, 255, RollOverflowBehaviorStop); + update_duration_text(scene_state); + } + break; + case InputKeyOk: + break; + case InputKeyBack: + totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken); + break; + default: + break; } - break; - case InputKeyLeft: - if(scene_state->selected_control == TokenAlgoSelect) { - totp_roll_value_uint8_t(&scene_state->algo, -1, SHA1, STEAM, RollOverflowBehaviorRoll); - } else if(scene_state->selected_control == TokenLengthSelect) { - totp_roll_value_uint8_t( - &scene_state->digits_count_index, -1, 0, 2, RollOverflowBehaviorRoll); - } else if(scene_state->selected_control == TokenDurationSelect) { - totp_roll_value_uint8_t( - &scene_state->duration, -15, 15, 255, RollOverflowBehaviorStop); - update_duration_text(scene_state); - } - break; - case InputKeyOk: + } else if(event->input.type == InputTypeRelease && event->input.key == InputKeyOk) { switch(scene_state->selected_control) { case TokenNameTextBox: if(scene_state->input_state != NULL) { @@ -264,7 +282,8 @@ bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState } scene_state->input_state = totp_input_text_activate(scene_state->token_name_input_context); - scene_state->input_started_at = furi_get_tick(); + + scene_state->text_input_mode = true; break; case TokenSecretTextBox: if(scene_state->input_state != NULL) { @@ -272,7 +291,8 @@ bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState } scene_state->input_state = totp_input_text_activate(scene_state->token_secret_input_context); - scene_state->input_started_at = furi_get_tick(); + + scene_state->text_input_mode = true; break; case TokenAlgoSelect: break; @@ -313,12 +333,6 @@ bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState default: break; } - break; - case InputKeyBack: - totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken); - break; - default: - break; } return true; diff --git a/applications/external/totp/ui/scenes/app_settings/totp_app_settings.c b/applications/external/totp/ui/scenes/app_settings/totp_app_settings.c index 6dcf0dbc9..0bdc7aee3 100644 --- a/applications/external/totp/ui/scenes/app_settings/totp_app_settings.c +++ b/applications/external/totp/ui/scenes/app_settings/totp_app_settings.c @@ -22,6 +22,7 @@ typedef enum { MinutesInput, Sound, Vibro, + FontSelector, BadUsb, #ifdef TOTP_BADBT_TYPE_ENABLED BadBt, @@ -34,6 +35,7 @@ typedef struct { uint8_t tz_offset_minutes; bool notification_sound; bool notification_vibro; + uint8_t selected_font; bool badusb_enabled; #ifdef TOTP_BADBT_TYPE_ENABLED bool badbt_enabled; @@ -54,23 +56,24 @@ void totp_scene_app_settings_activate(PluginState* plugin_state) { scene_state->notification_sound = plugin_state->notification_method & NotificationMethodSound; scene_state->notification_vibro = plugin_state->notification_method & NotificationMethodVibro; scene_state->badusb_enabled = plugin_state->automation_method & AutomationMethodBadUsb; + scene_state->selected_font = plugin_state->selected_font; #ifdef TOTP_BADBT_TYPE_ENABLED scene_state->badbt_enabled = plugin_state->automation_method & AutomationMethodBadBt; #endif } static void two_digit_to_str(int8_t num, char* str) { - uint8_t index = 0; + char* s = str; if(num < 0) { - str[index++] = '-'; + *(s++) = '-'; num = -num; } uint8_t d1 = (num / 10) % 10; uint8_t d2 = num % 10; - str[index++] = CONVERT_DIGIT_TO_CHAR(d1); - str[index++] = CONVERT_DIGIT_TO_CHAR(d2); - str[index++] = '\0'; + *(s++) = CONVERT_DIGIT_TO_CHAR(d1); + *(s++) = CONVERT_DIGIT_TO_CHAR(d2); + *(s++) = '\0'; } void totp_scene_app_settings_render(Canvas* const canvas, const PluginState* plugin_state) { @@ -111,27 +114,38 @@ void totp_scene_app_settings_render(Canvas* const canvas, const PluginState* plu canvas_set_font(canvas, FontPrimary); canvas_draw_str_aligned( - canvas, 0, 64 - scene_state->y_offset, AlignLeft, AlignTop, "Notifications"); + canvas, 0, 64 - scene_state->y_offset, AlignLeft, AlignTop, "Notifications / UI"); canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned(canvas, 0, 81 - scene_state->y_offset, AlignLeft, AlignTop, "Sound:"); + canvas_draw_str_aligned(canvas, 0, 78 - scene_state->y_offset, AlignLeft, AlignTop, "Sound:"); ui_control_select_render( canvas, 36, - 74 - scene_state->y_offset, + 71 - scene_state->y_offset, SCREEN_WIDTH - 36, YES_NO_LIST[scene_state->notification_sound], scene_state->selected_control == Sound); - canvas_draw_str_aligned(canvas, 0, 99 - scene_state->y_offset, AlignLeft, AlignTop, "Vibro:"); + canvas_draw_str_aligned(canvas, 0, 94 - scene_state->y_offset, AlignLeft, AlignTop, "Vibro:"); ui_control_select_render( canvas, 36, - 92 - scene_state->y_offset, + 87 - scene_state->y_offset, SCREEN_WIDTH - 36, YES_NO_LIST[scene_state->notification_vibro], scene_state->selected_control == Vibro); + two_digit_to_str(scene_state->selected_font, &tmp_str[0]); + canvas_draw_str_aligned( + canvas, 0, 110 - scene_state->y_offset, AlignLeft, AlignTop, "UI Font:"); + ui_control_select_render( + canvas, + 36, + 103 - scene_state->y_offset, + SCREEN_WIDTH - 36, + &tmp_str[0], + scene_state->selected_control == FontSelector); + canvas_draw_icon( canvas, SCREEN_WIDTH_CENTER - 5, 123 - scene_state->y_offset, &I_totp_arrow_bottom_10x5); @@ -183,116 +197,126 @@ bool totp_scene_app_settings_handle_event( } SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - if(event->input.type != InputTypePress && event->input.type != InputTypeRepeat) { - return true; - } - - switch(event->input.key) { - case InputKeyUp: - totp_roll_value_uint8_t( - &scene_state->selected_control, - -1, - HoursInput, - ConfirmButton, - RollOverflowBehaviorStop); - if(scene_state->selected_control > Vibro) { - scene_state->y_offset = 128; - } else if(scene_state->selected_control > MinutesInput) { - scene_state->y_offset = 64; - } else { - scene_state->y_offset = 0; - } - break; - case InputKeyDown: - totp_roll_value_uint8_t( - &scene_state->selected_control, 1, HoursInput, ConfirmButton, RollOverflowBehaviorStop); - if(scene_state->selected_control > Vibro) { - scene_state->y_offset = 128; - } else if(scene_state->selected_control > MinutesInput) { - scene_state->y_offset = 64; - } else { - scene_state->y_offset = 0; - } - break; - case InputKeyRight: - if(scene_state->selected_control == HoursInput) { - totp_roll_value_int8_t( - &scene_state->tz_offset_hours, 1, -12, 12, RollOverflowBehaviorStop); - } else if(scene_state->selected_control == MinutesInput) { + if(event->input.type == InputTypePress || event->input.type == InputTypeRepeat) { + switch(event->input.key) { + case InputKeyUp: totp_roll_value_uint8_t( - &scene_state->tz_offset_minutes, 15, 0, 45, RollOverflowBehaviorRoll); - } else if(scene_state->selected_control == Sound) { - scene_state->notification_sound = !scene_state->notification_sound; - } else if(scene_state->selected_control == Vibro) { - scene_state->notification_vibro = !scene_state->notification_vibro; - } else if(scene_state->selected_control == BadUsb) { - scene_state->badusb_enabled = !scene_state->badusb_enabled; - } -#ifdef TOTP_BADBT_TYPE_ENABLED - else if(scene_state->selected_control == BadBt) { - scene_state->badbt_enabled = !scene_state->badbt_enabled; - } -#endif - break; - case InputKeyLeft: - if(scene_state->selected_control == HoursInput) { - totp_roll_value_int8_t( - &scene_state->tz_offset_hours, -1, -12, 12, RollOverflowBehaviorStop); - } else if(scene_state->selected_control == MinutesInput) { - totp_roll_value_uint8_t( - &scene_state->tz_offset_minutes, -15, 0, 45, RollOverflowBehaviorRoll); - } else if(scene_state->selected_control == Sound) { - scene_state->notification_sound = !scene_state->notification_sound; - } else if(scene_state->selected_control == Vibro) { - scene_state->notification_vibro = !scene_state->notification_vibro; - } else if(scene_state->selected_control == BadUsb) { - scene_state->badusb_enabled = !scene_state->badusb_enabled; - } -#ifdef TOTP_BADBT_TYPE_ENABLED - else if(scene_state->selected_control == BadBt) { - scene_state->badbt_enabled = !scene_state->badbt_enabled; - } -#endif - break; - case InputKeyOk: - if(scene_state->selected_control == ConfirmButton) { - plugin_state->timezone_offset = (float)scene_state->tz_offset_hours + - (float)scene_state->tz_offset_minutes / 60.0f; - - plugin_state->notification_method = - (scene_state->notification_sound ? NotificationMethodSound : - NotificationMethodNone) | - (scene_state->notification_vibro ? NotificationMethodVibro : - NotificationMethodNone); - - plugin_state->automation_method = - scene_state->badusb_enabled ? AutomationMethodBadUsb : AutomationMethodNone; -#ifdef TOTP_BADBT_TYPE_ENABLED - plugin_state->automation_method |= scene_state->badbt_enabled ? AutomationMethodBadBt : - AutomationMethodNone; -#endif - - if(!totp_config_file_update_user_settings(plugin_state)) { - totp_dialogs_config_updating_error(plugin_state); - return false; + &scene_state->selected_control, + -1, + HoursInput, + ConfirmButton, + RollOverflowBehaviorStop); + if(scene_state->selected_control > FontSelector) { + scene_state->y_offset = 128; + } else if(scene_state->selected_control > MinutesInput) { + scene_state->y_offset = 64; + } else { + scene_state->y_offset = 0; + } + break; + case InputKeyDown: + totp_roll_value_uint8_t( + &scene_state->selected_control, + 1, + HoursInput, + ConfirmButton, + RollOverflowBehaviorStop); + if(scene_state->selected_control > FontSelector) { + scene_state->y_offset = 128; + } else if(scene_state->selected_control > MinutesInput) { + scene_state->y_offset = 64; + } else { + scene_state->y_offset = 0; + } + break; + case InputKeyRight: + if(scene_state->selected_control == HoursInput) { + totp_roll_value_int8_t( + &scene_state->tz_offset_hours, 1, -12, 12, RollOverflowBehaviorStop); + } else if(scene_state->selected_control == MinutesInput) { + totp_roll_value_uint8_t( + &scene_state->tz_offset_minutes, 15, 0, 45, RollOverflowBehaviorRoll); + } else if(scene_state->selected_control == Sound) { + scene_state->notification_sound = !scene_state->notification_sound; + } else if(scene_state->selected_control == Vibro) { + scene_state->notification_vibro = !scene_state->notification_vibro; + } else if(scene_state->selected_control == BadUsb) { + scene_state->badusb_enabled = !scene_state->badusb_enabled; } - #ifdef TOTP_BADBT_TYPE_ENABLED - if(!scene_state->badbt_enabled && plugin_state->bt_type_code_worker_context != NULL) { - totp_bt_type_code_worker_free(plugin_state->bt_type_code_worker_context); - plugin_state->bt_type_code_worker_context = NULL; + else if(scene_state->selected_control == BadBt) { + scene_state->badbt_enabled = !scene_state->badbt_enabled; } #endif - + else if(scene_state->selected_control == FontSelector) { + totp_roll_value_uint8_t( + &scene_state->selected_font, 1, 0, 6, RollOverflowBehaviorStop); + } + break; + case InputKeyLeft: + if(scene_state->selected_control == HoursInput) { + totp_roll_value_int8_t( + &scene_state->tz_offset_hours, -1, -12, 12, RollOverflowBehaviorStop); + } else if(scene_state->selected_control == MinutesInput) { + totp_roll_value_uint8_t( + &scene_state->tz_offset_minutes, -15, 0, 45, RollOverflowBehaviorRoll); + } else if(scene_state->selected_control == Sound) { + scene_state->notification_sound = !scene_state->notification_sound; + } else if(scene_state->selected_control == Vibro) { + scene_state->notification_vibro = !scene_state->notification_vibro; + } else if(scene_state->selected_control == BadUsb) { + scene_state->badusb_enabled = !scene_state->badusb_enabled; + } +#ifdef TOTP_BADBT_TYPE_ENABLED + else if(scene_state->selected_control == BadBt) { + scene_state->badbt_enabled = !scene_state->badbt_enabled; + } +#endif + else if(scene_state->selected_control == FontSelector) { + totp_roll_value_uint8_t( + &scene_state->selected_font, -1, 0, 6, RollOverflowBehaviorStop); + } + break; + case InputKeyOk: + break; + case InputKeyBack: { totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu); + break; } - break; - case InputKeyBack: { + default: + break; + } + } else if( + event->input.type == InputTypeRelease && event->input.key == InputKeyOk && + scene_state->selected_control == ConfirmButton) { + plugin_state->timezone_offset = + (float)scene_state->tz_offset_hours + (float)scene_state->tz_offset_minutes / 60.0f; + + plugin_state->notification_method = + (scene_state->notification_sound ? NotificationMethodSound : NotificationMethodNone) | + (scene_state->notification_vibro ? NotificationMethodVibro : NotificationMethodNone); + + plugin_state->automation_method = scene_state->badusb_enabled ? AutomationMethodBadUsb : + AutomationMethodNone; +#ifdef TOTP_BADBT_TYPE_ENABLED + plugin_state->automation_method |= scene_state->badbt_enabled ? AutomationMethodBadBt : + AutomationMethodNone; +#endif + plugin_state->selected_font = scene_state->selected_font; + + if(!totp_config_file_update_user_settings(plugin_state)) { + totp_dialogs_config_updating_error(plugin_state); + return false; + } + +#ifdef TOTP_BADBT_TYPE_ENABLED + if(!scene_state->badbt_enabled && plugin_state->bt_type_code_worker_context != NULL) { + totp_bt_type_code_worker_free(plugin_state->bt_type_code_worker_context); + plugin_state->bt_type_code_worker_context = NULL; + } +#endif + totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu); - break; - } - default: - break; } return true; diff --git a/applications/external/totp/ui/scenes/authenticate/totp_scene_authenticate.c b/applications/external/totp/ui/scenes/authenticate/totp_scene_authenticate.c index 86e1e8e2b..218e5e397 100644 --- a/applications/external/totp/ui/scenes/authenticate/totp_scene_authenticate.c +++ b/applications/external/totp/ui/scenes/authenticate/totp_scene_authenticate.c @@ -83,38 +83,45 @@ bool totp_scene_authenticate_handle_event( return false; } - if(event->input.type != InputTypePress) { - return true; - } - - SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - - switch(event->input.key) { - case InputKeyUp: - if(scene_state->code_length < MAX_CODE_LENGTH) { - scene_state->code_input[scene_state->code_length] = PinCodeArrowUp; - scene_state->code_length++; + SceneState* scene_state = plugin_state->current_scene_state; + if(event->input.type == InputTypePress) { + switch(event->input.key) { + case InputKeyUp: + if(scene_state->code_length < MAX_CODE_LENGTH) { + scene_state->code_input[scene_state->code_length] = PinCodeArrowUp; + scene_state->code_length++; + } + break; + case InputKeyDown: + if(scene_state->code_length < MAX_CODE_LENGTH) { + scene_state->code_input[scene_state->code_length] = PinCodeArrowDown; + scene_state->code_length++; + } + break; + case InputKeyRight: + if(scene_state->code_length < MAX_CODE_LENGTH) { + scene_state->code_input[scene_state->code_length] = PinCodeArrowRight; + scene_state->code_length++; + } + break; + case InputKeyLeft: + if(scene_state->code_length < MAX_CODE_LENGTH) { + scene_state->code_input[scene_state->code_length] = PinCodeArrowLeft; + scene_state->code_length++; + } + break; + case InputKeyOk: + break; + case InputKeyBack: + if(scene_state->code_length > 0) { + scene_state->code_input[scene_state->code_length - 1] = 0; + scene_state->code_length--; + } + break; + default: + break; } - break; - case InputKeyDown: - if(scene_state->code_length < MAX_CODE_LENGTH) { - scene_state->code_input[scene_state->code_length] = PinCodeArrowDown; - scene_state->code_length++; - } - break; - case InputKeyRight: - if(scene_state->code_length < MAX_CODE_LENGTH) { - scene_state->code_input[scene_state->code_length] = PinCodeArrowRight; - scene_state->code_length++; - } - break; - case InputKeyLeft: - if(scene_state->code_length < MAX_CODE_LENGTH) { - scene_state->code_input[scene_state->code_length] = PinCodeArrowLeft; - scene_state->code_length++; - } - break; - case InputKeyOk: { + } else if(event->input.type == InputTypeRelease && event->input.key == InputKeyOk) { CryptoSeedIVResult seed_result = totp_crypto_seed_iv( plugin_state, &scene_state->code_input[0], scene_state->code_length); @@ -145,16 +152,6 @@ bool totp_scene_authenticate_handle_event( dialog_message_show(plugin_state->dialogs_app, message); dialog_message_free(message); } - break; - } - case InputKeyBack: - if(scene_state->code_length > 0) { - scene_state->code_input[scene_state->code_length - 1] = 0; - scene_state->code_length--; - } - break; - default: - break; } return true; diff --git a/applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.c b/applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.c index b111242dc..e55f34ea2 100644 --- a/applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.c +++ b/applications/external/totp/ui/scenes/generate_token/totp_scene_generate_token.c @@ -16,7 +16,7 @@ #ifdef TOTP_BADBT_TYPE_ENABLED #include "../../../workers/bt_type_code/bt_type_code.h" #endif -#include "../../fonts/mode-nine/mode_nine.h" +#include "../../fonts/active_font.h" #define PROGRESS_BAR_MARGIN (3) #define PROGRESS_BAR_HEIGHT (4) @@ -142,19 +142,46 @@ static void draw_totp_code(Canvas* const canvas, const PluginState* const plugin totp_config_get_token_iterator_context(plugin_state); uint8_t code_length = totp_token_info_iterator_get_current_token(iterator_context)->digits; uint8_t offset_x = scene_state->ui_precalculated_dimensions.code_offset_x; - uint8_t char_width = modeNine_15ptFontInfo.charInfo[0].width; + const FONT_INFO* current_font; + switch(plugin_state->selected_font) { + case 0: + current_font = &modeNine_15ptFontInfo; + break; + case 1: + current_font = &redHatMono_16ptFontInfo; + break; + case 2: + current_font = &bedstead_17ptFontInfo; + break; + case 3: + current_font = &zector_18ptFontInfo; + break; + case 4: + current_font = &_712Serif_24ptFontInfo; + break; + case 5: + current_font = &graph35pix_12ptFontInfo; + break; + case 6: + current_font = &karmaFuture_14ptFontInfo; + break; + default: + current_font = &modeNine_15ptFontInfo; + break; + } + uint8_t char_width = current_font->charInfo[0].width; uint8_t offset_x_inc = scene_state->ui_precalculated_dimensions.code_offset_x_inc; for(uint8_t i = 0; i < code_length; i++) { char ch = scene_state->last_code[i]; - if(ch >= modeNine_15ptFontInfo.startChar && ch <= modeNine_15ptFontInfo.endChar) { - uint8_t char_index = ch - modeNine_15ptFontInfo.startChar; + if(ch >= current_font->startChar && ch <= current_font->endChar) { + uint8_t char_index = ch - current_font->startChar; canvas_draw_xbm( canvas, offset_x, scene_state->ui_precalculated_dimensions.code_offset_y, char_width, - modeNine_15ptFontInfo.height, - &modeNine_15ptFontInfo.data[modeNine_15ptFontInfo.charInfo[char_index].offset]); + current_font->height, + ¤t_font->data[current_font->charInfo[char_index].offset]); } offset_x += offset_x_inc; @@ -172,15 +199,43 @@ static void on_new_token_code_generated(bool time_left, void* context) { SceneState* scene_state = plugin_state->current_scene_state; const TokenInfo* current_token = totp_token_info_iterator_get_current_token(iterator_context); - uint8_t char_width = modeNine_15ptFontInfo.charInfo[0].width; + const FONT_INFO* current_font; + switch(plugin_state->selected_font) { + case 0: + current_font = &modeNine_15ptFontInfo; + break; + case 1: + current_font = &redHatMono_16ptFontInfo; + break; + case 2: + current_font = &bedstead_17ptFontInfo; + break; + case 3: + current_font = &zector_18ptFontInfo; + break; + case 4: + current_font = &_712Serif_24ptFontInfo; + break; + case 5: + current_font = &graph35pix_12ptFontInfo; + break; + case 6: + current_font = &karmaFuture_14ptFontInfo; + break; + default: + current_font = &modeNine_15ptFontInfo; + break; + } + + uint8_t char_width = current_font->charInfo[0].width; scene_state->ui_precalculated_dimensions.code_total_length = - current_token->digits * (char_width + modeNine_15ptFontInfo.spacePixels); + current_token->digits * (char_width + current_font->spacePixels); scene_state->ui_precalculated_dimensions.code_offset_x = (SCREEN_WIDTH - scene_state->ui_precalculated_dimensions.code_total_length) >> 1; scene_state->ui_precalculated_dimensions.code_offset_x_inc = - char_width + modeNine_15ptFontInfo.spacePixels; + char_width + current_font->spacePixels; scene_state->ui_precalculated_dimensions.code_offset_y = - SCREEN_HEIGHT_CENTER - (modeNine_15ptFontInfo.height >> 1); + SCREEN_HEIGHT_CENTER - (current_font->height >> 1); if(time_left) { notification_message( @@ -381,54 +436,51 @@ bool totp_scene_generate_token_handle_event( return true; } #endif - } + } else if(event->input.type == InputTypePress || event->input.type == InputTypeRepeat) { + switch(event->input.key) { + case InputKeyUp: + break; + case InputKeyDown: + break; + case InputKeyRight: { + const TokenInfoIteratorContext* iterator_context = + totp_config_get_token_iterator_context(plugin_state); + size_t current_token_index = + totp_token_info_iterator_get_current_token_index(iterator_context); + totp_roll_value_size_t( + ¤t_token_index, + 1, + 0, + totp_token_info_iterator_get_total_count(iterator_context) - 1, + RollOverflowBehaviorRoll); - if(event->input.type != InputTypePress && event->input.type != InputTypeRepeat) { - return true; - } + update_totp_params(plugin_state, current_token_index); + break; + } + case InputKeyLeft: { + const TokenInfoIteratorContext* iterator_context = + totp_config_get_token_iterator_context(plugin_state); + size_t current_token_index = + totp_token_info_iterator_get_current_token_index(iterator_context); + totp_roll_value_size_t( + ¤t_token_index, + -1, + 0, + totp_token_info_iterator_get_total_count(iterator_context) - 1, + RollOverflowBehaviorRoll); - switch(event->input.key) { - case InputKeyUp: - break; - case InputKeyDown: - break; - case InputKeyRight: { - const TokenInfoIteratorContext* iterator_context = - totp_config_get_token_iterator_context(plugin_state); - size_t current_token_index = - totp_token_info_iterator_get_current_token_index(iterator_context); - totp_roll_value_size_t( - ¤t_token_index, - 1, - 0, - totp_token_info_iterator_get_total_count(iterator_context) - 1, - RollOverflowBehaviorRoll); - - update_totp_params(plugin_state, current_token_index); - break; - } - case InputKeyLeft: { - const TokenInfoIteratorContext* iterator_context = - totp_config_get_token_iterator_context(plugin_state); - size_t current_token_index = - totp_token_info_iterator_get_current_token_index(iterator_context); - totp_roll_value_size_t( - ¤t_token_index, - -1, - 0, - totp_token_info_iterator_get_total_count(iterator_context) - 1, - RollOverflowBehaviorRoll); - - update_totp_params(plugin_state, current_token_index); - break; - } - case InputKeyOk: + update_totp_params(plugin_state, current_token_index); + break; + } + case InputKeyOk: + break; + case InputKeyBack: + break; + default: + break; + } + } else if(event->input.type == InputTypeRelease && event->input.key == InputKeyOk) { totp_scene_director_activate_scene(plugin_state, TotpSceneTokenMenu); - break; - case InputKeyBack: - break; - default: - break; } return true; diff --git a/applications/external/totp/ui/scenes/token_menu/totp_scene_token_menu.c b/applications/external/totp/ui/scenes/token_menu/totp_scene_token_menu.c index a8c8de28a..1340b5a8e 100644 --- a/applications/external/totp/ui/scenes/token_menu/totp_scene_token_menu.c +++ b/applications/external/totp/ui/scenes/token_menu/totp_scene_token_menu.c @@ -82,38 +82,52 @@ bool totp_scene_token_menu_handle_event(const PluginEvent* const event, PluginSt } SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - if(event->input.type != InputTypePress) { - return true; - } - - switch(event->input.key) { - case InputKeyUp: { - const TokenInfoIteratorContext* iterator_context = - totp_config_get_token_iterator_context(plugin_state); - totp_roll_value_uint8_t( - &scene_state->selected_control, -1, AddNewToken, AppSettings, RollOverflowBehaviorRoll); - if(scene_state->selected_control == DeleteToken && - totp_token_info_iterator_get_total_count(iterator_context) == 0) { - scene_state->selected_control--; + if(event->input.type == InputTypePress) { + switch(event->input.key) { + case InputKeyUp: { + const TokenInfoIteratorContext* iterator_context = + totp_config_get_token_iterator_context(plugin_state); + totp_roll_value_uint8_t( + &scene_state->selected_control, + -1, + AddNewToken, + AppSettings, + RollOverflowBehaviorRoll); + if(scene_state->selected_control == DeleteToken && + totp_token_info_iterator_get_total_count(iterator_context) == 0) { + scene_state->selected_control--; + } + break; } - break; - } - case InputKeyDown: { - const TokenInfoIteratorContext* iterator_context = - totp_config_get_token_iterator_context(plugin_state); - totp_roll_value_uint8_t( - &scene_state->selected_control, 1, AddNewToken, AppSettings, RollOverflowBehaviorRoll); - if(scene_state->selected_control == DeleteToken && - totp_token_info_iterator_get_total_count(iterator_context) == 0) { - scene_state->selected_control++; + case InputKeyDown: { + const TokenInfoIteratorContext* iterator_context = + totp_config_get_token_iterator_context(plugin_state); + totp_roll_value_uint8_t( + &scene_state->selected_control, + 1, + AddNewToken, + AppSettings, + RollOverflowBehaviorRoll); + if(scene_state->selected_control == DeleteToken && + totp_token_info_iterator_get_total_count(iterator_context) == 0) { + scene_state->selected_control++; + } + break; } - break; - } - case InputKeyRight: - break; - case InputKeyLeft: - break; - case InputKeyOk: + case InputKeyRight: + break; + case InputKeyLeft: + break; + case InputKeyOk: + break; + case InputKeyBack: { + totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken); + break; + } + default: + break; + } + } else if(event->input.type == InputTypeRelease && event->input.key == InputKeyOk) { switch(scene_state->selected_control) { case AddNewToken: { totp_scene_director_activate_scene(plugin_state, TotpSceneAddNewToken); @@ -153,13 +167,6 @@ bool totp_scene_token_menu_handle_event(const PluginEvent* const event, PluginSt default: break; } - break; - case InputKeyBack: { - totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken); - break; - } - default: - break; } return true; diff --git a/applications/external/totp/workers/bt_type_code/bt_type_code.c b/applications/external/totp/workers/bt_type_code/bt_type_code.c index bf55dba6a..8024dba78 100644 --- a/applications/external/totp/workers/bt_type_code/bt_type_code.c +++ b/applications/external/totp/workers/bt_type_code/bt_type_code.c @@ -13,7 +13,7 @@ #include "../type_code_common.h" #include "../../features_config.h" -#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_XTREME +#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_UL_XFW #define TOTP_BT_WORKER_BT_ADV_NAME_MAX_LEN FURI_HAL_BT_ADV_NAME_LENGTH #define TOTP_BT_WORKER_BT_MAC_ADDRESS_LEN GAP_MAC_ADDR_SIZE #endif @@ -29,7 +29,7 @@ struct TotpBtTypeCodeWorkerContext { Bt* bt; bool is_advertising; bool is_connected; -#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_XTREME +#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_UL_XFW char previous_bt_name[TOTP_BT_WORKER_BT_ADV_NAME_MAX_LEN]; uint8_t previous_bt_mac[TOTP_BT_WORKER_BT_MAC_ADDRESS_LEN]; #endif @@ -39,7 +39,7 @@ static inline bool totp_type_code_worker_stop_requested() { return furi_thread_flags_get() & TotpBtTypeCodeWorkerEventStop; } -#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_XTREME +#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_UL_XFW static void totp_type_code_worker_bt_set_app_mac(uint8_t* mac) { uint8_t max_i; size_t uid_size = furi_hal_version_uid_size(); @@ -161,7 +161,7 @@ TotpBtTypeCodeWorkerContext* totp_bt_type_code_worker_init() { furi_delay_ms(200); bt_keys_storage_set_storage_path(context->bt, HID_BT_KEYS_STORAGE_PATH); -#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_XTREME +#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_UL_XFW memcpy( &context->previous_bt_name[0], furi_hal_bt_get_profile_adv_name(FuriHalBtProfileHidKeyboard), @@ -184,7 +184,7 @@ TotpBtTypeCodeWorkerContext* totp_bt_type_code_worker_init() { furi_hal_bt_start_advertising(); -#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_XTREME +#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_UL_XFW bt_enable_peer_key_update(context->bt); #endif @@ -211,7 +211,7 @@ void totp_bt_type_code_worker_free(TotpBtTypeCodeWorkerContext* context) { furi_delay_ms(200); bt_keys_storage_set_default_path(context->bt); -#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_XTREME +#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_UL_XFW furi_hal_bt_set_profile_adv_name(FuriHalBtProfileHidKeyboard, context->previous_bt_name); furi_hal_bt_set_profile_mac_addr(FuriHalBtProfileHidKeyboard, context->previous_bt_mac); #endif diff --git a/applications/external/totp/workers/generate_totp_code/generate_totp_code.c b/applications/external/totp/workers/generate_totp_code/generate_totp_code.c index 7e9356c45..6dbe329fd 100644 --- a/applications/external/totp/workers/generate_totp_code/generate_totp_code.c +++ b/applications/external/totp/workers/generate_totp_code/generate_totp_code.c @@ -25,18 +25,21 @@ static const char* STEAM_ALGO_ALPHABET = "23456789BCDFGHJKMNPQRTVWXY"; static void int_token_to_str(uint64_t i_token_code, char* str, TokenDigitsCount len, TokenHashAlgo algo) { - str[len] = '\0'; + char* last_char = str + len; + *last_char = '\0'; if(i_token_code == OTP_ERROR) { - memset(&str[0], '-', len); + memset(str, '-', len); } else { if(algo == STEAM) { - for(uint8_t i = 0; i < len; i++) { - str[i] = STEAM_ALGO_ALPHABET[i_token_code % 26]; + char* s = str; + for(uint8_t i = 0; i < len; i++, s++) { + *s = STEAM_ALGO_ALPHABET[i_token_code % 26]; i_token_code = i_token_code / 26; } } else { - for(int8_t i = len - 1; i >= 0; i--) { - str[i] = CONVERT_DIGIT_TO_CHAR(i_token_code % 10); + char* s = --last_char; + for(int8_t i = len - 1; i >= 0; i--, s--) { + *s = CONVERT_DIGIT_TO_CHAR(i_token_code % 10); i_token_code = i_token_code / 10; } } diff --git a/applications/external/totp/workers/type_code_common.c b/applications/external/totp/workers/type_code_common.c index bf5818ab2..bc42fadaa 100644 --- a/applications/external/totp/workers/type_code_common.c +++ b/applications/external/totp/workers/type_code_common.c @@ -47,11 +47,12 @@ void totp_type_code_worker_execute_automation( TokenAutomationFeature features) { furi_delay_ms(500); uint8_t i = 0; + char cb_char; - while(i < code_buffer_size && code_buffer[i] != 0) { - uint8_t char_index = CONVERT_CHAR_TO_DIGIT(code_buffer[i]); + while(i < code_buffer_size && (cb_char = code_buffer[i]) != 0) { + uint8_t char_index = CONVERT_CHAR_TO_DIGIT(cb_char); if(char_index > 9) { - char_index = code_buffer[i] - 0x41 + 10; + char_index = cb_char - 0x41 + 10; } if(char_index > 35) break; diff --git a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c index 28a3ed2a9..b2bd39d3e 100644 --- a/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c +++ b/applications/external/wifi_marauder_companion/scenes/wifi_marauder_scene_start.c @@ -97,6 +97,7 @@ const WifiMarauderItem items[NUM_MENU_ITEMS] = { NO_ARGS, FOCUS_CONSOLE_END, SHOW_STOPSCAN_TIP}, + {"Signal Monitor", {""}, 1, {"sigmon"}, NO_ARGS, FOCUS_CONSOLE_END, SHOW_STOPSCAN_TIP}, {"Channel", {"get", "set"}, 2, diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_app.h b/applications/external/wifi_marauder_companion/wifi_marauder_app.h index 7e3856059..5457f89d8 100644 --- a/applications/external/wifi_marauder_companion/wifi_marauder_app.h +++ b/applications/external/wifi_marauder_companion/wifi_marauder_app.h @@ -4,7 +4,7 @@ extern "C" { #endif -#define WIFI_MARAUDER_APP_VERSION "v0.3.6" +#define WIFI_MARAUDER_APP_VERSION "v0.3.7" typedef struct WifiMarauderApp WifiMarauderApp; diff --git a/applications/external/wifi_marauder_companion/wifi_marauder_app_i.h b/applications/external/wifi_marauder_companion/wifi_marauder_app_i.h index 45e1e5920..2a16522bb 100644 --- a/applications/external/wifi_marauder_companion/wifi_marauder_app_i.h +++ b/applications/external/wifi_marauder_companion/wifi_marauder_app_i.h @@ -26,7 +26,7 @@ #include #include -#define NUM_MENU_ITEMS (17) +#define NUM_MENU_ITEMS (18) #define WIFI_MARAUDER_TEXT_BOX_STORE_SIZE (4096) #define WIFI_MARAUDER_TEXT_INPUT_STORE_SIZE (512) diff --git a/applications/main/infrared/infrared.c b/applications/main/infrared/infrared.c index b2be5f1af..2d35f4805 100644 --- a/applications/main/infrared/infrared.c +++ b/applications/main/infrared/infrared.c @@ -326,7 +326,8 @@ void infrared_tx_start_signal(Infrared* infrared, InfraredSignal* signal) { if(infrared_signal_is_raw(signal)) { InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal); - infrared_worker_set_raw_signal(infrared->worker, raw->timings, raw->timings_size); + infrared_worker_set_raw_signal( + infrared->worker, raw->timings, raw->timings_size, raw->frequency, raw->duty_cycle); } else { InfraredMessage* message = infrared_signal_get_message(signal); infrared_worker_set_decoded_signal(infrared->worker, message); diff --git a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_menu.c b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_menu.c index c511e9dcb..e7a494d27 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_menu.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_menu.c @@ -19,7 +19,7 @@ void nfc_scene_mf_ultralight_menu_on_enter(void* context) { Submenu* submenu = nfc->submenu; MfUltralightData* data = &nfc->dev->dev_data.mf_ul_data; - if(!mf_ul_is_full_capture(data)) { + if(!mf_ul_is_full_capture(data) && data->type != MfUltralightTypeULC) { submenu_add_item( submenu, "Unlock", @@ -29,12 +29,14 @@ void nfc_scene_mf_ultralight_menu_on_enter(void* context) { } submenu_add_item( submenu, "Save", SubmenuIndexSave, nfc_scene_mf_ultralight_menu_submenu_callback, nfc); - submenu_add_item( - submenu, - "Emulate", - SubmenuIndexEmulate, - nfc_scene_mf_ultralight_menu_submenu_callback, - nfc); + if(mf_ul_emulation_supported(data)) { + submenu_add_item( + submenu, + "Emulate", + SubmenuIndexEmulate, + nfc_scene_mf_ultralight_menu_submenu_callback, + nfc); + } submenu_add_item( submenu, "Info", SubmenuIndexInfo, nfc_scene_mf_ultralight_menu_submenu_callback, nfc); diff --git a/applications/main/nfc/scenes/nfc_scene_saved_menu.c b/applications/main/nfc/scenes/nfc_scene_saved_menu.c index 15771bcc3..ae2f5ef6b 100644 --- a/applications/main/nfc/scenes/nfc_scene_saved_menu.c +++ b/applications/main/nfc/scenes/nfc_scene_saved_menu.c @@ -43,7 +43,8 @@ void nfc_scene_saved_menu_on_enter(void* context) { nfc); } } else if( - nfc->dev->format == NfcDeviceSaveFormatMifareUl || + (nfc->dev->format == NfcDeviceSaveFormatMifareUl && + mf_ul_emulation_supported(&nfc->dev->dev_data.mf_ul_data)) || nfc->dev->format == NfcDeviceSaveFormatNfcV || nfc->dev->format == NfcDeviceSaveFormatMifareClassic) { submenu_add_item( @@ -74,6 +75,7 @@ void nfc_scene_saved_menu_on_enter(void* context) { submenu_add_item( submenu, "Info", SubmenuIndexInfo, nfc_scene_saved_menu_submenu_callback, nfc); if(nfc->dev->format == NfcDeviceSaveFormatMifareUl && + nfc->dev->dev_data.mf_ul_data.type != MfUltralightTypeULC && !mf_ul_is_full_capture(&nfc->dev->dev_data.mf_ul_data)) { submenu_add_item( submenu, diff --git a/applications/services/desktop/desktop.c b/applications/services/desktop/desktop.c index 77999dfcc..bad120abc 100644 --- a/applications/services/desktop/desktop.c +++ b/applications/services/desktop/desktop.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "animations/animation_manager.h" #include "desktop/scenes/desktop_scene.h" @@ -48,6 +49,77 @@ static void desktop_dummy_mode_icon_draw_callback(Canvas* canvas, void* context) canvas_draw_icon(canvas, 0, 0, &I_GameMode_11x8); } +static void desktop_toggle_clock_view(Desktop* desktop, bool is_enabled) { + furi_assert(desktop); + + // clock type upd after 1 minute + desktop->clock_type = (locale_get_time_format() == LocaleTimeFormat24h); + + if(is_enabled) { // && !furi_timer_is_running(desktop->update_clock_timer)) { + furi_timer_start(desktop->update_clock_timer, furi_ms_to_ticks(1000)); + } else if(!is_enabled) { //&& furi_timer_is_running(desktop->update_clock_timer)) { + furi_timer_stop(desktop->update_clock_timer); + } + + view_port_enabled_set(desktop->clock_viewport, is_enabled); +} + +static uint8_t desktop_clock_get_num_w(uint8_t num) { + if(num == 1) { + return 3; + } else if(num == 4) { + return 6; + } else { + return 5; + } +} + +static const char* digit[10] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}; + +static void desktop_clock_draw_callback(Canvas* canvas, void* context) { + furi_assert(context); + furi_assert(canvas); + + Desktop* desktop = context; + + uint8_t d[4] = { + desktop->minute % 10, + desktop->minute / 10, + desktop->hour % 10, + desktop->hour / 10, + }; + + canvas_set_font(canvas, FontPrimary); + + uint8_t new_w = desktop_clock_get_num_w(d[0]) + //c1 + desktop_clock_get_num_w(d[1]) + //c2 + desktop_clock_get_num_w(d[2]) + //c3 + desktop_clock_get_num_w(d[3]) + //c4 + 2 + 4; // ":" + 4 separators + + // further away from the battery charge indicator, if the smallest minute is 1 + view_port_set_width(desktop->clock_viewport, new_w - !(d[0] == 1)); + + uint8_t x = new_w; + + uint8_t y = 8; + uint8_t offset_r; + + canvas_draw_str_aligned(canvas, x, y, AlignRight, AlignBottom, digit[d[0]]); + offset_r = desktop_clock_get_num_w(d[0]); + + canvas_draw_str_aligned(canvas, x -= (offset_r + 1), y, AlignRight, AlignBottom, digit[d[1]]); + offset_r = desktop_clock_get_num_w(d[1]); + + canvas_draw_str_aligned(canvas, x -= (offset_r + 1), y - 1, AlignRight, AlignBottom, ":"); + offset_r = 2; + + canvas_draw_str_aligned(canvas, x -= (offset_r + 1), y, AlignRight, AlignBottom, digit[d[2]]); + offset_r = desktop_clock_get_num_w(d[2]); + + canvas_draw_str_aligned(canvas, x -= (offset_r + 1), y, AlignRight, AlignBottom, digit[d[3]]); +} + static void desktop_stealth_mode_icon_draw_callback(Canvas* canvas, void* context) { UNUSED(context); furi_assert(canvas); @@ -68,6 +140,9 @@ static bool desktop_custom_event_callback(void* context, uint32_t event) { // TODO: Implement a message mechanism for loading settings and (optionally) // locking and unlocking DESKTOP_SETTINGS_LOAD(&desktop->settings); + + desktop_toggle_clock_view(desktop, desktop->settings.display_clock); + desktop_auto_lock_arm(desktop); return true; case DesktopGlobalAutoLock: @@ -133,6 +208,31 @@ static void desktop_auto_lock_inhibit(Desktop* desktop) { } } +static void desktop_update_clock_timer_callback(void* context) { + furi_assert(context); + Desktop* desktop = context; + + if(gui_get_count_of_enabled_view_port_in_layer(desktop->gui, GuiLayerStatusBarLeft) < 6) { + FuriHalRtcDateTime curr_dt; + furi_hal_rtc_get_datetime(&curr_dt); + + if(desktop->minute != curr_dt.minute) { + if(desktop->clock_type) { + desktop->hour = curr_dt.hour; + } else { + desktop->hour = (curr_dt.hour > 12) ? curr_dt.hour - 12 : + ((curr_dt.hour == 0) ? 12 : curr_dt.hour); + } + desktop->minute = curr_dt.minute; + view_port_update(desktop->clock_viewport); + } + + view_port_enabled_set(desktop->clock_viewport, true); + } else { + view_port_enabled_set(desktop->clock_viewport, false); + } +} + void desktop_lock(Desktop* desktop) { furi_hal_rtc_set_flag(FuriHalRtcFlagLock); @@ -147,6 +247,9 @@ void desktop_lock(Desktop* desktop) { desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_FIRST_ENTER); scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked); notification_message(desktop->notification, &sequence_display_backlight_off_delay_1000); + + DesktopStatus status = {.locked = true}; + furi_pubsub_publish(desktop->status_pubsub, &status); } void desktop_unlock(Desktop* desktop) { @@ -165,6 +268,9 @@ void desktop_unlock(Desktop* desktop) { cli_session_open(cli, &cli_vcp); furi_record_close(RECORD_CLI); } + + DesktopStatus status = {.locked = false}; + furi_pubsub_publish(desktop->status_pubsub, &status); } void desktop_set_dummy_mode_state(Desktop* desktop, bool enabled) { @@ -279,6 +385,13 @@ Desktop* desktop_alloc() { view_port_enabled_set(desktop->dummy_mode_icon_viewport, false); gui_add_view_port(desktop->gui, desktop->dummy_mode_icon_viewport, GuiLayerStatusBarLeft); + // Clock + desktop->clock_viewport = view_port_alloc(); + view_port_set_width(desktop->clock_viewport, 25); + view_port_draw_callback_set(desktop->clock_viewport, desktop_clock_draw_callback, desktop); + view_port_enabled_set(desktop->clock_viewport, false); + gui_add_view_port(desktop->gui, desktop->clock_viewport, GuiLayerStatusBarRight); + // Stealth mode icon desktop->stealth_mode_icon_viewport = view_port_alloc(); view_port_set_width(desktop->stealth_mode_icon_viewport, icon_get_width(&I_Muted_8x8)); @@ -308,63 +421,27 @@ Desktop* desktop_alloc() { desktop->auto_lock_timer = furi_timer_alloc(desktop_auto_lock_timer_callback, FuriTimerTypeOnce, desktop); + desktop->status_pubsub = furi_pubsub_alloc(); + + desktop->update_clock_timer = + furi_timer_alloc(desktop_update_clock_timer_callback, FuriTimerTypePeriodic, desktop); + + FuriHalRtcDateTime curr_dt; + furi_hal_rtc_get_datetime(&curr_dt); + + if(desktop->clock_type) { + desktop->hour = curr_dt.hour; + } else { + desktop->hour = (curr_dt.hour > 12) ? curr_dt.hour - 12 : + ((curr_dt.hour == 0) ? 12 : curr_dt.hour); + } + desktop->minute = curr_dt.minute; + furi_record_create(RECORD_DESKTOP, desktop); return desktop; } -void desktop_free(Desktop* desktop) { - furi_assert(desktop); - furi_check(furi_record_destroy(RECORD_DESKTOP)); - - furi_pubsub_unsubscribe( - loader_get_pubsub(desktop->loader), desktop->app_start_stop_subscription); - - if(desktop->input_events_subscription) { - furi_pubsub_unsubscribe(desktop->input_events_pubsub, desktop->input_events_subscription); - desktop->input_events_subscription = NULL; - } - - desktop->loader = NULL; - desktop->input_events_pubsub = NULL; - furi_record_close(RECORD_LOADER); - furi_record_close(RECORD_NOTIFICATION); - furi_record_close(RECORD_INPUT_EVENTS); - - view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdMain); - view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdLockMenu); - view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdLocked); - view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdDebug); - view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdHwMismatch); - view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdPinInput); - view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdPinTimeout); - - view_dispatcher_free(desktop->view_dispatcher); - scene_manager_free(desktop->scene_manager); - - animation_manager_free(desktop->animation_manager); - view_stack_free(desktop->main_view_stack); - desktop_main_free(desktop->main_view); - view_stack_free(desktop->locked_view_stack); - desktop_view_locked_free(desktop->locked_view); - desktop_lock_menu_free(desktop->lock_menu); - desktop_view_locked_free(desktop->locked_view); - desktop_debug_free(desktop->debug_view); - popup_free(desktop->hw_mismatch_popup); - desktop_view_pin_timeout_free(desktop->pin_timeout_view); - - furi_record_close(RECORD_GUI); - desktop->gui = NULL; - - furi_thread_free(desktop->scene_thread); - - furi_record_close("menu"); - - furi_timer_free(desktop->auto_lock_timer); - - free(desktop); -} - static bool desktop_check_file_flag(const char* flag_path) { Storage* storage = furi_record_open(RECORD_STORAGE); bool exists = storage_common_stat(storage, flag_path, NULL) == FSE_OK; @@ -383,6 +460,11 @@ void desktop_api_unlock(Desktop* instance) { view_dispatcher_send_custom_event(instance->view_dispatcher, DesktopLockedEventUnlocked); } +FuriPubSub* desktop_api_get_status_pubsub(Desktop* instance) { + furi_assert(instance); + return instance->status_pubsub; +} + int32_t desktop_srv(void* p) { UNUSED(p); @@ -400,6 +482,9 @@ int32_t desktop_srv(void* p) { } view_port_enabled_set(desktop->dummy_mode_icon_viewport, desktop->settings.dummy_mode); + + desktop_toggle_clock_view(desktop, desktop->settings.display_clock); + desktop_main_set_dummy_mode_state(desktop->main_view, desktop->settings.dummy_mode); animation_manager_set_dummy_mode_state( desktop->animation_manager, desktop->settings.dummy_mode); @@ -427,7 +512,8 @@ int32_t desktop_srv(void* p) { } view_dispatcher_run(desktop->view_dispatcher); - desktop_free(desktop); + + furi_crash("That was unexpected"); return 0; } diff --git a/applications/services/desktop/desktop.h b/applications/services/desktop/desktop.h index 5b12647b8..4eab24fcc 100644 --- a/applications/services/desktop/desktop.h +++ b/applications/services/desktop/desktop.h @@ -1,5 +1,7 @@ #pragma once +#include + typedef struct Desktop Desktop; #define RECORD_DESKTOP "desktop" @@ -7,3 +9,9 @@ typedef struct Desktop Desktop; bool desktop_api_is_locked(Desktop* instance); void desktop_api_unlock(Desktop* instance); + +typedef struct { + bool locked; +} DesktopStatus; + +FuriPubSub* desktop_api_get_status_pubsub(Desktop* instance); diff --git a/applications/services/desktop/desktop_i.h b/applications/services/desktop/desktop_i.h index ede6bbcc3..4cac7711d 100644 --- a/applications/services/desktop/desktop_i.h +++ b/applications/services/desktop/desktop_i.h @@ -59,6 +59,7 @@ struct Desktop { ViewPort* lock_icon_viewport; ViewPort* dummy_mode_icon_viewport; + ViewPort* clock_viewport; ViewPort* stealth_mode_icon_viewport; AnimationManager* animation_manager; @@ -70,8 +71,14 @@ struct Desktop { FuriPubSub* input_events_pubsub; FuriPubSubSubscription* input_events_subscription; FuriTimer* auto_lock_timer; + FuriTimer* update_clock_timer; - bool in_transition; + FuriPubSub* status_pubsub; + uint8_t hour; + uint8_t minute; + bool clock_type : 1; // true - 24h false - 12h + + bool in_transition : 1; }; Desktop* desktop_alloc(); diff --git a/applications/services/desktop/desktop_settings.h b/applications/services/desktop/desktop_settings.h index e750c696c..5946873f0 100644 --- a/applications/services/desktop/desktop_settings.h +++ b/applications/services/desktop/desktop_settings.h @@ -8,7 +8,7 @@ #include #include -#define DESKTOP_SETTINGS_VER (9) +#define DESKTOP_SETTINGS_VER (10) #define DESKTOP_SETTINGS_PATH INT_PATH(DESKTOP_SETTINGS_FILE_NAME) #define DESKTOP_SETTINGS_MAGIC (0x17) @@ -43,8 +43,6 @@ #define DISPLAY_BATTERY_RETRO_5 4 #define DISPLAY_BATTERY_BAR_PERCENT 5 -#define FAP_LOADER_APP_NAME "Applications" - typedef struct { InputKey data[MAX_PIN_SIZE]; uint8_t length; @@ -63,4 +61,5 @@ typedef struct { uint32_t auto_lock_delay_ms; uint8_t displayBatteryPercentage; uint8_t dummy_mode; + uint8_t display_clock; } DesktopSettings; diff --git a/applications/services/desktop/scenes/desktop_scene_main.c b/applications/services/desktop/scenes/desktop_scene_main.c index f504646bf..79f17fee7 100644 --- a/applications/services/desktop/scenes/desktop_scene_main.c +++ b/applications/services/desktop/scenes/desktop_scene_main.c @@ -12,6 +12,8 @@ #define TAG "DesktopSrv" +#define FAP_LOADER_APP_NAME "Applications" + static void desktop_scene_main_new_idle_animation_callback(void* context) { furi_assert(context); Desktop* desktop = context; @@ -60,6 +62,34 @@ static void desktop_switch_to_app(Desktop* desktop, const FlipperApplication* fl } #endif +static void desktop_scene_main_open_app_or_profile(Desktop* desktop, const char* path) { + do { + LoaderStatus status = loader_start(desktop->loader, FAP_LOADER_APP_NAME, path); + if(status == LoaderStatusOk) break; + FURI_LOG_E(TAG, "loader_start failed: %d", status); + + status = loader_start(desktop->loader, "Passport", NULL); + if(status != LoaderStatusOk) { + FURI_LOG_E(TAG, "loader_start failed: %d", status); + } + } while(false); +} + +static void desktop_scene_main_start_favorite(Desktop* desktop, FavoriteApp* application) { + LoaderStatus status = LoaderStatusErrorInternal; + if(application->is_external) { + status = loader_start(desktop->loader, FAP_LOADER_APP_NAME, application->name_or_path); + } else if(strlen(application->name_or_path) > 0) { + status = loader_start(desktop->loader, application->name_or_path, NULL); + } else { + status = loader_start(desktop->loader, FAP_LOADER_APP_NAME, NULL); + } + + if(status != LoaderStatusOk) { + FURI_LOG_E(TAG, "loader_start failed: %d", status); + } +} + void desktop_scene_main_callback(DesktopEvent event, void* context) { Desktop* desktop = (Desktop*)context; if(desktop->in_transition) return; @@ -130,59 +160,17 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { case DesktopMainEventOpenFavoritePrimary: DESKTOP_SETTINGS_LOAD(&desktop->settings); - if(desktop->settings.favorite_primary.is_external) { - LoaderStatus status = loader_start( - desktop->loader, - FAP_LOADER_APP_NAME, - desktop->settings.favorite_primary.name_or_path); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); - } - } else { - LoaderStatus status = loader_start( - desktop->loader, desktop->settings.favorite_primary.name_or_path, NULL); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); - } - } + desktop_scene_main_start_favorite(desktop, &desktop->settings.favorite_primary); consumed = true; break; case DesktopMainEventOpenFavoriteSecondary: DESKTOP_SETTINGS_LOAD(&desktop->settings); - if(desktop->settings.favorite_secondary.is_external) { - LoaderStatus status = loader_start( - desktop->loader, - FAP_LOADER_APP_NAME, - desktop->settings.favorite_secondary.name_or_path); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); - } - } else { - LoaderStatus status = loader_start( - desktop->loader, desktop->settings.favorite_secondary.name_or_path, NULL); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); - } - } + desktop_scene_main_start_favorite(desktop, &desktop->settings.favorite_secondary); consumed = true; break; case DesktopMainEventOpenFavoriteTertiary: DESKTOP_SETTINGS_LOAD(&desktop->settings); - if(desktop->settings.favorite_tertiary.is_external) { - LoaderStatus status = loader_start( - desktop->loader, - FAP_LOADER_APP_NAME, - desktop->settings.favorite_tertiary.name_or_path); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); - } - } else { - LoaderStatus status = loader_start( - desktop->loader, desktop->settings.favorite_tertiary.name_or_path, NULL); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); - } - } + desktop_scene_main_start_favorite(desktop, &desktop->settings.favorite_tertiary); consumed = true; break; case DesktopAnimationEventCheckAnimation: @@ -210,51 +198,28 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { break; } case DesktopMainEventOpenGameMenu: { - LoaderStatus status = loader_start( - desktop->loader, FAP_LOADER_APP_NAME, EXT_PATH("/apps/Games/Snake.fap")); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); - } + desktop_scene_main_open_app_or_profile(desktop, EXT_PATH("/apps/Games/Snake.fap")); break; } case DesktopMainEventOpenTetris: { - LoaderStatus status = loader_start( - desktop->loader, FAP_LOADER_APP_NAME, EXT_PATH("/apps/Games/Tetris.fap")); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); - } + desktop_scene_main_open_app_or_profile(desktop, EXT_PATH("/apps/Games/Tetris.fap")); break; } case DesktopMainEventOpenArkanoid: { - LoaderStatus status = loader_start( - desktop->loader, FAP_LOADER_APP_NAME, EXT_PATH("/apps/Games/Arkanoid.fap")); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); - } + desktop_scene_main_open_app_or_profile(desktop, EXT_PATH("/apps/Games/Arkanoid.fap")); break; } case DesktopMainEventOpenDOOM: { - LoaderStatus status = loader_start( - desktop->loader, FAP_LOADER_APP_NAME, EXT_PATH("/apps/Games/DOOM.fap")); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); - } + desktop_scene_main_open_app_or_profile(desktop, EXT_PATH("/apps/Games/DOOM.fap")); break; } case DesktopMainEventOpenZombiez: { - LoaderStatus status = loader_start( - desktop->loader, FAP_LOADER_APP_NAME, EXT_PATH("/apps/Games/Zombiez.fap")); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); - } + desktop_scene_main_open_app_or_profile(desktop, EXT_PATH("/apps/Games/Zombiez.fap")); break; } case DesktopMainEventOpenHeap: { - LoaderStatus status = loader_start( - desktop->loader, FAP_LOADER_APP_NAME, EXT_PATH("/apps/Games/heap_defence.fap")); - if(status != LoaderStatusOk) { - FURI_LOG_E(TAG, "loader_start failed: %d", status); - } + desktop_scene_main_open_app_or_profile( + desktop, EXT_PATH("/apps/Games/heap_defence.fap")); break; } case DesktopLockedEventUpdate: diff --git a/applications/services/dolphin/dolphin.c b/applications/services/dolphin/dolphin.c index dd8b7105f..93a9b3095 100644 --- a/applications/services/dolphin/dolphin.c +++ b/applications/services/dolphin/dolphin.c @@ -89,15 +89,6 @@ Dolphin* dolphin_alloc() { return dolphin; } -void dolphin_free(Dolphin* dolphin) { - furi_assert(dolphin); - - dolphin_state_free(dolphin->state); - furi_message_queue_free(dolphin->event_queue); - - free(dolphin); -} - void dolphin_event_send_async(Dolphin* dolphin, DolphinEvent* event) { furi_assert(dolphin); furi_assert(event); @@ -204,7 +195,7 @@ int32_t dolphin_srv(void* p) { } } - dolphin_free(dolphin); + furi_crash("That was unexpected"); return 0; } diff --git a/applications/services/dolphin/dolphin_i.h b/applications/services/dolphin/dolphin_i.h index 4bb0df08e..ceeff1e1a 100644 --- a/applications/services/dolphin/dolphin_i.h +++ b/applications/services/dolphin/dolphin_i.h @@ -37,8 +37,6 @@ struct Dolphin { Dolphin* dolphin_alloc(); -void dolphin_free(Dolphin* dolphin); - void dolphin_event_send_async(Dolphin* dolphin, DolphinEvent* event); void dolphin_event_send_wait(Dolphin* dolphin, DolphinEvent* event); diff --git a/applications/services/gui/gui.c b/applications/services/gui/gui.c index 392011620..87cc962ca 100644 --- a/applications/services/gui/gui.c +++ b/applications/services/gui/gui.c @@ -17,6 +17,23 @@ ViewPort* gui_view_port_find_enabled(ViewPortArray_t array) { return NULL; } +uint8_t gui_get_count_of_enabled_view_port_in_layer(Gui* gui, GuiLayer layer) { + furi_assert(gui); + furi_check(layer < GuiLayerMAX); + uint8_t ret = 0; + + ViewPortArray_it_t it; + ViewPortArray_it_last(it, gui->layers[layer]); + while(!ViewPortArray_end_p(it)) { + ViewPort* view_port = *ViewPortArray_ref(it); + if(view_port_is_enabled(view_port)) { + ret++; + } + ViewPortArray_previous(it); + } + return ret; +} + void gui_update(Gui* gui) { furi_assert(gui); if(!gui->direct_draw) furi_thread_flags_set(gui->thread_id, GUI_THREAD_FLAG_DRAW); diff --git a/applications/services/gui/gui.h b/applications/services/gui/gui.h index 1b5987eda..a59a4ff6a 100644 --- a/applications/services/gui/gui.h +++ b/applications/services/gui/gui.h @@ -132,6 +132,8 @@ Canvas* gui_direct_draw_acquire(Gui* gui); */ void gui_direct_draw_release(Gui* gui); +uint8_t gui_get_count_of_enabled_view_port_in_layer(Gui* gui, GuiLayer layer); + #ifdef __cplusplus } #endif diff --git a/applications/services/power/power_service/power.c b/applications/services/power/power_service/power.c index e61776060..a495e5d6c 100644 --- a/applications/services/power/power_service/power.c +++ b/applications/services/power/power_service/power.c @@ -268,30 +268,6 @@ Power* power_alloc() { return power; } -void power_free(Power* power) { - furi_assert(power); - - // Gui - view_dispatcher_remove_view(power->view_dispatcher, PowerViewOff); - power_off_free(power->power_off); - view_dispatcher_remove_view(power->view_dispatcher, PowerViewUnplugUsb); - power_unplug_usb_free(power->power_unplug_usb); - - view_port_free(power->battery_view_port); - - // State - furi_mutex_free(power->api_mtx); - - // FuriPubSub - furi_pubsub_free(power->event_pubsub); - - // Records - furi_record_close(RECORD_NOTIFICATION); - furi_record_close(RECORD_GUI); - - free(power); -} - static void power_check_charging_state(Power* power) { if(furi_hal_power_is_charging()) { if((power->info.charge == 100) || (furi_hal_power_is_charging_done())) { @@ -454,7 +430,7 @@ int32_t power_srv(void* p) { furi_delay_ms(1000); } - power_free(power); + furi_crash("That was unexpected"); return 0; } diff --git a/applications/services/rpc/rpc_desktop.c b/applications/services/rpc/rpc_desktop.c index dbf9796ec..0d72b43d5 100644 --- a/applications/services/rpc/rpc_desktop.c +++ b/applications/services/rpc/rpc_desktop.c @@ -8,6 +8,8 @@ typedef struct { RpcSession* session; Desktop* desktop; + FuriPubSub* status_pubsub; + FuriPubSubSubscription* status_subscription; } RpcDesktop; static void rpc_desktop_on_is_locked_request(const PB_Main* request, void* context) { @@ -39,11 +41,63 @@ static void rpc_desktop_on_unlock_request(const PB_Main* request, void* context) rpc_send_and_release_empty(session, request->command_id, PB_CommandStatus_OK); } +static void rpc_desktop_on_desktop_pubsub(const void* message, void* context) { + RpcDesktop* rpc_desktop = context; + RpcSession* session = rpc_desktop->session; + const DesktopStatus* status = message; + + PB_Main rpc_message = { + .command_id = 0, + .command_status = PB_CommandStatus_OK, + .has_next = false, + .which_content = PB_Main_desktop_status_tag, + .content.desktop_status.locked = status->locked, + }; + rpc_send_and_release(session, &rpc_message); +} + +static void rpc_desktop_on_status_subscribe_request(const PB_Main* request, void* context) { + furi_assert(request); + furi_assert(context); + furi_assert(request->which_content == PB_Main_desktop_status_subscribe_request_tag); + + FURI_LOG_D(TAG, "StatusSubscribeRequest"); + RpcDesktop* rpc_desktop = context; + RpcSession* session = rpc_desktop->session; + + if(rpc_desktop->status_subscription) { + rpc_send_and_release_empty(session, request->command_id, PB_CommandStatus_ERROR); + } else { + rpc_desktop->status_subscription = furi_pubsub_subscribe( + rpc_desktop->status_pubsub, rpc_desktop_on_desktop_pubsub, rpc_desktop); + rpc_send_and_release_empty(session, request->command_id, PB_CommandStatus_OK); + } +} + +static void rpc_desktop_on_status_unsubscribe_request(const PB_Main* request, void* context) { + furi_assert(request); + furi_assert(context); + furi_assert(request->which_content == PB_Main_desktop_status_unsubscribe_request_tag); + + FURI_LOG_D(TAG, "StatusUnsubscribeRequest"); + RpcDesktop* rpc_desktop = context; + RpcSession* session = rpc_desktop->session; + + if(rpc_desktop->status_subscription) { + furi_pubsub_unsubscribe(rpc_desktop->status_pubsub, rpc_desktop->status_subscription); + rpc_desktop->status_subscription = NULL; + rpc_send_and_release_empty(session, request->command_id, PB_CommandStatus_OK); + } else { + rpc_send_and_release_empty(session, request->command_id, PB_CommandStatus_ERROR); + } +} + void* rpc_desktop_alloc(RpcSession* session) { furi_assert(session); RpcDesktop* rpc_desktop = malloc(sizeof(RpcDesktop)); rpc_desktop->desktop = furi_record_open(RECORD_DESKTOP); + rpc_desktop->status_pubsub = desktop_api_get_status_pubsub(rpc_desktop->desktop); rpc_desktop->session = session; RpcHandler rpc_handler = { @@ -58,6 +112,12 @@ void* rpc_desktop_alloc(RpcSession* session) { rpc_handler.message_handler = rpc_desktop_on_unlock_request; rpc_add_handler(session, PB_Main_desktop_unlock_request_tag, &rpc_handler); + rpc_handler.message_handler = rpc_desktop_on_status_subscribe_request; + rpc_add_handler(session, PB_Main_desktop_status_subscribe_request_tag, &rpc_handler); + + rpc_handler.message_handler = rpc_desktop_on_status_unsubscribe_request; + rpc_add_handler(session, PB_Main_desktop_status_unsubscribe_request_tag, &rpc_handler); + return rpc_desktop; } @@ -65,6 +125,10 @@ void rpc_desktop_free(void* context) { furi_assert(context); RpcDesktop* rpc_desktop = context; + if(rpc_desktop->status_subscription) { + furi_pubsub_unsubscribe(rpc_desktop->status_pubsub, rpc_desktop->status_subscription); + } + furi_assert(rpc_desktop->desktop); furi_record_close(RECORD_DESKTOP); diff --git a/applications/services/storage/storage.h b/applications/services/storage/storage.h index 5991e765f..bcd1d0df6 100644 --- a/applications/services/storage/storage.h +++ b/applications/services/storage/storage.h @@ -226,7 +226,7 @@ FS_Error storage_common_stat(Storage* storage, const char* path, FileInfo* filei */ FS_Error storage_common_remove(Storage* storage, const char* path); -/** Renames file/directory, file/directory must not be open +/** Renames file/directory, file/directory must not be open. Will overwrite existing file. * @param app pointer to the api * @param old_path old path * @param new_path new path diff --git a/applications/services/storage/storage_external_api.c b/applications/services/storage/storage_external_api.c index bf474bc9d..5fcaa5921 100644 --- a/applications/services/storage/storage_external_api.c +++ b/applications/services/storage/storage_external_api.c @@ -422,12 +422,27 @@ FS_Error storage_common_remove(Storage* storage, const char* path) { } FS_Error storage_common_rename(Storage* storage, const char* old_path, const char* new_path) { - FS_Error error = storage_common_copy(storage, old_path, new_path); - if(error == FSE_OK) { + FS_Error error; + + do { + if(!storage_common_exists(storage, old_path)) { + error = FSE_INVALID_NAME; + break; + } + + if(storage_file_exists(storage, new_path)) { + storage_common_remove(storage, new_path); + } + + error = storage_common_copy(storage, old_path, new_path); + if(error != FSE_OK) { + break; + } + if(!storage_simply_remove_recursive(storage, old_path)) { error = FSE_INTERNAL; } - } + } while(false); return error; } diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c index c014c97f7..25bab6dd6 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c @@ -5,6 +5,9 @@ #include #include +#define EXTERNAL_APPLICATION_NAME ("[External Application]") +#define EXTERNAL_APPLICATION_INDEX (FLIPPER_APPS_COUNT + 1) + static bool favorite_fap_selector_item_callback( FuriString* file_path, void* context, @@ -44,6 +47,20 @@ void desktop_settings_scene_favorite_on_enter(void* context) { uint32_t primary_favorite = scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppSceneFavorite); uint32_t pre_select_item = 0; + FavoriteApp* curr_favorite_app = NULL; + if(primary_favorite == 0) { + curr_favorite_app = &app->settings.favorite_primary; + } else if(primary_favorite == 1) { + curr_favorite_app = &app->settings.favorite_secondary; + } else if(primary_favorite == 2) { + curr_favorite_app = &app->settings.favorite_tertiary; + } else { + curr_favorite_app = &app->settings.favorite_primary; + } + if(curr_favorite_app == NULL) { + // This should not happen! + return; + } for(size_t i = 0; i < FLIPPER_APPS_COUNT; i++) { submenu_add_item( @@ -53,30 +70,29 @@ void desktop_settings_scene_favorite_on_enter(void* context) { desktop_settings_scene_favorite_submenu_callback, app); - if(primary_favorite == 0) { // Select favorite item in submenu - if((app->settings.favorite_primary.is_external && - !strcmp(FLIPPER_APPS[i].name, FAP_LOADER_APP_NAME)) || - (!strcmp(FLIPPER_APPS[i].name, app->settings.favorite_primary.name_or_path))) { - pre_select_item = i; - } - } else if(primary_favorite == 1) { - if((app->settings.favorite_secondary.is_external && - !strcmp(FLIPPER_APPS[i].name, FAP_LOADER_APP_NAME)) || - (!strcmp(FLIPPER_APPS[i].name, app->settings.favorite_secondary.name_or_path))) { - pre_select_item = i; - } - } else if(primary_favorite == 2) { - if((app->settings.favorite_tertiary.is_external && - !strcmp(FLIPPER_APPS[i].name, FAP_LOADER_APP_NAME)) || - (!strcmp(FLIPPER_APPS[i].name, app->settings.favorite_tertiary.name_or_path))) { - pre_select_item = i; - } + // Select favorite item in submenu + if(!curr_favorite_app->is_external && + !strcmp(FLIPPER_APPS[i].name, curr_favorite_app->name_or_path)) { + pre_select_item = i; } } + +#ifdef APP_FAP_LOADER + submenu_add_item( + submenu, + EXTERNAL_APPLICATION_NAME, + EXTERNAL_APPLICATION_INDEX, + desktop_settings_scene_favorite_submenu_callback, + app); + if(curr_favorite_app->is_external) { + pre_select_item = EXTERNAL_APPLICATION_INDEX; + } +#endif + submenu_add_item( submenu, "None (disable)", - FLIPPER_APPS_COUNT + 1, + FLIPPER_APPS_COUNT + 2, desktop_settings_scene_favorite_submenu_callback, app); @@ -99,46 +115,24 @@ bool desktop_settings_scene_favorite_on_event(void* context, SceneManagerEvent e uint32_t primary_favorite = scene_manager_get_scene_state(app->scene_manager, DesktopSettingsAppSceneFavorite); + FavoriteApp* curr_favorite_app = NULL; + if(primary_favorite == 0) { + curr_favorite_app = &app->settings.favorite_primary; + } else if(primary_favorite == 1) { + curr_favorite_app = &app->settings.favorite_secondary; + } else if(primary_favorite == 2) { + curr_favorite_app = &app->settings.favorite_tertiary; + } else { + curr_favorite_app = &app->settings.favorite_primary; + } + if(curr_favorite_app == NULL) { + // This should not happen! + furi_string_free(temp_path); + return consumed; + } if(event.type == SceneManagerEventTypeCustom) { - if(event.event >= (FLIPPER_APPS_COUNT + 1)) { - if(primary_favorite == 0) { - app->settings.favorite_primary.is_external = false; - strncpy(app->settings.favorite_primary.name_or_path, "", MAX_APP_LENGTH); - } else if(primary_favorite == 1) { - app->settings.favorite_secondary.is_external = false; - strncpy(app->settings.favorite_secondary.name_or_path, "", MAX_APP_LENGTH); - } else if(primary_favorite == 2) { - app->settings.favorite_tertiary.is_external = false; - strncpy(app->settings.favorite_tertiary.name_or_path, "", MAX_APP_LENGTH); - } - - scene_manager_previous_scene(app->scene_manager); - consumed = true; - furi_string_free(temp_path); - return consumed; - } - if(strcmp(FLIPPER_APPS[event.event].name, FAP_LOADER_APP_NAME) != 0) { - if(primary_favorite == 0) { - app->settings.favorite_primary.is_external = false; - strncpy( - app->settings.favorite_primary.name_or_path, - FLIPPER_APPS[event.event].name, - MAX_APP_LENGTH); - } else if(primary_favorite == 1) { - app->settings.favorite_secondary.is_external = false; - strncpy( - app->settings.favorite_secondary.name_or_path, - FLIPPER_APPS[event.event].name, - MAX_APP_LENGTH); - } else if(primary_favorite == 2) { - app->settings.favorite_tertiary.is_external = false; - strncpy( - app->settings.favorite_tertiary.name_or_path, - FLIPPER_APPS[event.event].name, - MAX_APP_LENGTH); - } - } else { + if(event.event == EXTERNAL_APPLICATION_INDEX) { const DialogsFileBrowserOptions browser_options = { .extension = ".fap", .icon = &I_unknown_10px, @@ -149,47 +143,29 @@ bool desktop_settings_scene_favorite_on_event(void* context, SceneManagerEvent e .base_path = EXT_PATH("apps"), }; - if(primary_favorite == 0) { // Select favorite fap in file browser - if(favorite_fap_selector_file_exists( - app->settings.favorite_primary.name_or_path)) { - furi_string_set_str(temp_path, app->settings.favorite_primary.name_or_path); - } - } else if(primary_favorite == 1) { - if(favorite_fap_selector_file_exists( - app->settings.favorite_secondary.name_or_path)) { - furi_string_set_str(temp_path, app->settings.favorite_secondary.name_or_path); - } - } else if(primary_favorite == 2) { - if(favorite_fap_selector_file_exists( - app->settings.favorite_tertiary.name_or_path)) { - furi_string_set_str(temp_path, app->settings.favorite_tertiary.name_or_path); - } + // Select favorite fap in file browser + if(favorite_fap_selector_file_exists(curr_favorite_app->name_or_path)) { + furi_string_set_str(temp_path, curr_favorite_app->name_or_path); } - submenu_reset(app->submenu); if(dialog_file_browser_show(app->dialogs, temp_path, temp_path, &browser_options)) { - if(primary_favorite == 0) { - app->settings.favorite_primary.is_external = true; - strncpy( - app->settings.favorite_primary.name_or_path, - furi_string_get_cstr(temp_path), - MAX_APP_LENGTH); - } else if(primary_favorite == 1) { - app->settings.favorite_secondary.is_external = true; - strncpy( - app->settings.favorite_secondary.name_or_path, - furi_string_get_cstr(temp_path), - MAX_APP_LENGTH); - } else if(primary_favorite == 2) { - app->settings.favorite_tertiary.is_external = true; - strncpy( - app->settings.favorite_tertiary.name_or_path, - furi_string_get_cstr(temp_path), - MAX_APP_LENGTH); - } + submenu_reset(app->submenu); // Prevent menu from being shown when we exiting scene + curr_favorite_app->is_external = true; + strncpy( + curr_favorite_app->name_or_path, + furi_string_get_cstr(temp_path), + MAX_APP_LENGTH); + consumed = true; } + } else { + curr_favorite_app->is_external = false; + strncpy( + curr_favorite_app->name_or_path, FLIPPER_APPS[event.event].name, MAX_APP_LENGTH); + consumed = true; } - scene_manager_previous_scene(app->scene_manager); + if(consumed) { + scene_manager_previous_scene(app->scene_manager); + }; consumed = true; } diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c index 9d63f6628..43e86cdc6 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c @@ -11,7 +11,8 @@ #define SCENE_EVENT_SELECT_PIN_SETUP 3 #define SCENE_EVENT_SELECT_AUTO_LOCK_DELAY 4 #define SCENE_EVENT_SELECT_BATTERY_DISPLAY 5 -#define SCENE_EVENT_SELECT_CHANGE_NAME 6 +#define SCENE_EVENT_SELECT_CLOCK_DISPLAY 6 +#define SCENE_EVENT_SELECT_CHANGE_NAME 7 #define AUTO_LOCK_DELAY_COUNT 9 const char* const auto_lock_delay_text[AUTO_LOCK_DELAY_COUNT] = { @@ -29,6 +30,14 @@ const char* const auto_lock_delay_text[AUTO_LOCK_DELAY_COUNT] = { const uint32_t auto_lock_delay_value[AUTO_LOCK_DELAY_COUNT] = {0, 10000, 15000, 30000, 60000, 90000, 120000, 300000, 600000}; +#define CLOCK_ENABLE_COUNT 2 +const char* const clock_enable_text[CLOCK_ENABLE_COUNT] = { + "OFF", + "ON", +}; + +const uint32_t clock_enable_value[CLOCK_ENABLE_COUNT] = {0, 1}; + #define BATTERY_VIEW_COUNT 6 const char* const battery_view_count_text[BATTERY_VIEW_COUNT] = @@ -55,6 +64,14 @@ static void desktop_settings_scene_start_battery_view_changed(VariableItem* item app->settings.displayBatteryPercentage = index; } +static void desktop_settings_scene_start_clock_enable_changed(VariableItem* item) { + DesktopSettingsApp* app = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + variable_item_set_current_value_text(item, clock_enable_text[index]); + app->settings.display_clock = index; +} + static void desktop_settings_scene_start_auto_lock_delay_changed(VariableItem* item) { DesktopSettingsApp* app = variable_item_get_context(item); uint8_t index = variable_item_get_current_value_index(item); @@ -106,6 +123,18 @@ void desktop_settings_scene_start_on_enter(void* context) { variable_item_set_current_value_index(item, value_index); variable_item_set_current_value_text(item, battery_view_count_text[value_index]); + item = variable_item_list_add( + variable_item_list, + "Show Clock", + CLOCK_ENABLE_COUNT, + desktop_settings_scene_start_clock_enable_changed, // + app); + + value_index = + value_index_uint32(app->settings.display_clock, clock_enable_value, CLOCK_ENABLE_COUNT); + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, clock_enable_text[value_index]); + variable_item_list_add(variable_item_list, "Change Flipper Name", 0, NULL, app); view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewVarItemList); @@ -142,6 +171,9 @@ bool desktop_settings_scene_start_on_event(void* context, SceneManagerEvent even case SCENE_EVENT_SELECT_BATTERY_DISPLAY: consumed = true; break; + case SCENE_EVENT_SELECT_CLOCK_DISPLAY: + consumed = true; + break; case SCENE_EVENT_SELECT_CHANGE_NAME: scene_manager_next_scene(app->scene_manager, DesktopSettingsAppSceneChangeName); consumed = true; diff --git a/assets/protobuf b/assets/protobuf index a13c5ddd0..f71c4b7f7 160000 --- a/assets/protobuf +++ b/assets/protobuf @@ -1 +1 @@ -Subproject commit a13c5ddd0397511bd4c6de4afdd1031a5b6f5bca +Subproject commit f71c4b7f750f2539a1fed08925d8da3abdc80ff9 diff --git a/firmware/targets/f18/api_symbols.csv b/firmware/targets/f18/api_symbols.csv index ee1ae1154..68248a6d2 100644 --- a/firmware/targets/f18/api_symbols.csv +++ b/firmware/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,26.3,, +Version,+,27.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -129,6 +129,7 @@ Header,+,lib/one_wire/maxim_crc.h,, Header,+,lib/one_wire/one_wire_host.h,, Header,+,lib/one_wire/one_wire_slave.h,, Header,+,lib/print/wrappers.h,, +Header,+,lib/pulse_reader/pulse_reader.h,, Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_adc.h,, Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_bus.h,, Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_comp.h,, @@ -156,7 +157,7 @@ Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_tim.h,, Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_usart.h,, Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_utils.h,, Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_wwdg.h,, -Header,+,lib/pulse_reader/pulse_reader.h,, +Header,+,lib/toolbox/api_lock.h,, Header,+,lib/toolbox/args.h,, Header,+,lib/toolbox/crc32_calc.h,, Header,+,lib/toolbox/dir_walk.h,, diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 3313f3ecd..ae38d0c84 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,26.3,, +Version,+,27.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -191,6 +191,7 @@ Header,+,lib/subghz/subghz_setting.h,, Header,+,lib/subghz/subghz_tx_rx_worker.h,, Header,+,lib/subghz/subghz_worker.h,, Header,+,lib/subghz/transmitter.h,, +Header,+,lib/toolbox/api_lock.h,, Header,+,lib/toolbox/args.h,, Header,+,lib/toolbox/crc32_calc.h,, Header,+,lib/toolbox/dir_walk.h,, @@ -1658,6 +1659,7 @@ Function,+,gui_add_framebuffer_callback,void,"Gui*, GuiCanvasCommitCallback, voi Function,+,gui_add_view_port,void,"Gui*, ViewPort*, GuiLayer" Function,+,gui_direct_draw_acquire,Canvas*,Gui* Function,+,gui_direct_draw_release,void,Gui* +Function,-,gui_get_count_of_enabled_view_port_in_layer,uint8_t,"Gui*, GuiLayer" Function,+,gui_get_framebuffer_size,size_t,const Gui* Function,+,gui_remove_framebuffer_callback,void,"Gui*, GuiCanvasCommitCallback, void*" Function,+,gui_remove_view_port,void,"Gui*, ViewPort*" @@ -1759,7 +1761,7 @@ Function,+,infrared_worker_rx_set_received_signal_callback,void,"InfraredWorker* Function,+,infrared_worker_rx_start,void,InfraredWorker* Function,+,infrared_worker_rx_stop,void,InfraredWorker* Function,+,infrared_worker_set_decoded_signal,void,"InfraredWorker*, const InfraredMessage*" -Function,+,infrared_worker_set_raw_signal,void,"InfraredWorker*, const uint32_t*, size_t" +Function,+,infrared_worker_set_raw_signal,void,"InfraredWorker*, const uint32_t*, size_t, uint32_t, float" Function,+,infrared_worker_signal_is_decoded,_Bool,const InfraredWorkerSignal* Function,+,infrared_worker_tx_get_signal_steady_callback,InfraredWorkerGetSignalResponse,"void*, InfraredWorker*" Function,+,infrared_worker_tx_set_get_signal_callback,void,"InfraredWorker*, InfraredWorkerGetSignalCallback, void*" @@ -2059,6 +2061,7 @@ Function,-,mf_df_prepare_read_records,uint16_t,"uint8_t*, uint8_t, uint32_t, uin Function,-,mf_df_prepare_select_application,uint16_t,"uint8_t*, uint8_t[3]" Function,-,mf_df_read_card,_Bool,"FuriHalNfcTxRxContext*, MifareDesfireData*" Function,-,mf_ul_check_card_type,_Bool,"uint8_t, uint8_t, uint8_t" +Function,-,mf_ul_emulation_supported,_Bool,MfUltralightData* Function,-,mf_ul_is_full_capture,_Bool,MfUltralightData* Function,-,mf_ul_prepare_emulation,void,"MfUltralightEmulator*, MfUltralightData*" Function,-,mf_ul_prepare_emulation_response,_Bool,"uint8_t*, uint16_t, uint8_t*, uint16_t*, uint32_t*, void*" @@ -2515,7 +2518,7 @@ Function,-,select,int,"int, fd_set*, fd_set*, fd_set*, timeval*" Function,-,serial_svc_is_started,_Bool, Function,-,serial_svc_notify_buffer_is_empty,void, Function,-,serial_svc_set_callbacks,void,"uint16_t, SerialServiceEventCallback, void*" -Function,+,serial_svc_set_rpc_status,void,SerialServiceRpcStatus +Function,-,serial_svc_set_rpc_status,void,SerialServiceRpcStatus Function,-,serial_svc_start,void, Function,-,serial_svc_stop,void, Function,-,serial_svc_update_tx,_Bool,"uint8_t*, uint16_t" diff --git a/firmware/targets/f7/furi_hal/furi_hal_infrared.c b/firmware/targets/f7/furi_hal/furi_hal_infrared.c index 8098f8bd0..e833c4731 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_infrared.c +++ b/firmware/targets/f7/furi_hal/furi_hal_infrared.c @@ -1,7 +1,6 @@ #include #include #include "stm32wbxx_ll_dma.h" -#include "sys/_stdint.h" #include #include @@ -332,8 +331,6 @@ static void furi_hal_infrared_tx_dma_isr() { } static void furi_hal_infrared_configure_tim_pwm_tx(uint32_t freq, float duty_cycle) { - /* LL_DBGMCU_APB2_GRP1_FreezePeriph(LL_DBGMCU_APB2_GRP1_TIM1_STOP); */ - LL_TIM_DisableCounter(TIM1); LL_TIM_SetRepetitionCounter(TIM1, 0); LL_TIM_SetCounter(TIM1, 0); diff --git a/lib/infrared/worker/infrared_worker.c b/lib/infrared/worker/infrared_worker.c index 5add1413e..46effd420 100644 --- a/lib/infrared/worker/infrared_worker.c +++ b/lib/infrared/worker/infrared_worker.c @@ -40,8 +40,12 @@ struct InfraredWorkerSignal { size_t timings_cnt; union { InfraredMessage message; - /* +1 is for pause we add at the beginning */ - uint32_t timings[MAX_TIMINGS_AMOUNT + 1]; + struct { + /* +1 is for pause we add at the beginning */ + uint32_t timings[MAX_TIMINGS_AMOUNT + 1]; + uint32_t frequency; + float duty_cycle; + } raw; }; }; @@ -146,7 +150,7 @@ static void } if(instance->signal.timings_cnt < MAX_TIMINGS_AMOUNT) { - instance->signal.timings[instance->signal.timings_cnt] = duration; + instance->signal.raw.timings[instance->signal.timings_cnt] = duration; ++instance->signal.timings_cnt; } else { uint32_t flags_set = furi_thread_flags_set( @@ -300,7 +304,7 @@ void infrared_worker_get_raw_signal( furi_assert(timings); furi_assert(timings_cnt); - *timings = signal->timings; + *timings = signal->raw.timings; *timings_cnt = signal->timings_cnt; } @@ -390,8 +394,8 @@ static bool infrared_get_new_signal(InfraredWorker* instance) { infrared_get_protocol_duty_cycle(instance->signal.message.protocol); } else { furi_assert(instance->signal.timings_cnt > 1); - new_tx_frequency = INFRARED_COMMON_CARRIER_FREQUENCY; - new_tx_duty_cycle = INFRARED_COMMON_DUTY_CYCLE; + new_tx_frequency = instance->signal.raw.frequency; + new_tx_duty_cycle = instance->signal.raw.duty_cycle; } instance->tx.tx_raw_cnt = 0; @@ -426,7 +430,7 @@ static bool infrared_worker_tx_fill_buffer(InfraredWorker* instance) { if(instance->signal.decoded) { status = infrared_encode(instance->infrared_encoder, &timing.duration, &timing.level); } else { - timing.duration = instance->signal.timings[instance->tx.tx_raw_cnt]; + timing.duration = instance->signal.raw.timings[instance->tx.tx_raw_cnt]; /* raw always starts from Mark, but we fill it with space delay at start */ timing.level = (instance->tx.tx_raw_cnt % 2); ++instance->tx.tx_raw_cnt; @@ -597,15 +601,21 @@ void infrared_worker_set_decoded_signal(InfraredWorker* instance, const Infrared void infrared_worker_set_raw_signal( InfraredWorker* instance, const uint32_t* timings, - size_t timings_cnt) { + size_t timings_cnt, + uint32_t frequency, + float duty_cycle) { furi_assert(instance); furi_assert(timings); furi_assert(timings_cnt > 0); - size_t max_copy_num = COUNT_OF(instance->signal.timings) - 1; + furi_assert((frequency <= INFRARED_MAX_FREQUENCY) && (frequency >= INFRARED_MIN_FREQUENCY)); + furi_assert((duty_cycle < 1.0f) && (duty_cycle > 0.0f)); + size_t max_copy_num = COUNT_OF(instance->signal.raw.timings) - 1; furi_check(timings_cnt <= max_copy_num); - instance->signal.timings[0] = INFRARED_RAW_TX_TIMING_DELAY_US; - memcpy(&instance->signal.timings[1], timings, timings_cnt * sizeof(uint32_t)); + instance->signal.raw.frequency = frequency; + instance->signal.raw.duty_cycle = duty_cycle; + instance->signal.raw.timings[0] = INFRARED_RAW_TX_TIMING_DELAY_US; + memcpy(&instance->signal.raw.timings[1], timings, timings_cnt * sizeof(uint32_t)); instance->signal.decoded = false; instance->signal.timings_cnt = timings_cnt + 1; } diff --git a/lib/infrared/worker/infrared_worker.h b/lib/infrared/worker/infrared_worker.h index 1a8cd9a76..e0e861983 100644 --- a/lib/infrared/worker/infrared_worker.h +++ b/lib/infrared/worker/infrared_worker.h @@ -130,9 +130,9 @@ void infrared_worker_tx_set_signal_sent_callback( /** Callback to pass to infrared_worker_tx_set_get_signal_callback() if signal * is steady and will not be changed between infrared_worker start and stop. * Before starting transmission, desired steady signal must be set with - * infrared_worker_make_decoded_signal() or infrared_worker_make_raw_signal(). + * infrared_worker_set_decoded_signal() or infrared_worker_set_raw_signal(). * - * This function should not be implicitly called. + * This function should not be called directly. * * @param[in] context - context * @param[out] instance - InfraredWorker instance @@ -172,11 +172,15 @@ void infrared_worker_set_decoded_signal(InfraredWorker* instance, const Infrared * @param[out] instance - InfraredWorker instance * @param[in] timings - array of raw timings * @param[in] timings_cnt - size of array of raw timings + * @param[in] frequency - carrier frequency in Hertz + * @param[in] duty_cycle - carrier duty cycle (0.0 - 1.0) */ void infrared_worker_set_raw_signal( InfraredWorker* instance, const uint32_t* timings, - size_t timings_cnt); + size_t timings_cnt, + uint32_t frequency, + float duty_cycle); #ifdef __cplusplus } diff --git a/lib/nfc/nfc_types.c b/lib/nfc/nfc_types.c index 02ca85580..96b92640f 100644 --- a/lib/nfc/nfc_types.c +++ b/lib/nfc/nfc_types.c @@ -45,6 +45,8 @@ const char* nfc_mf_ul_type(MfUltralightType type, bool full_name) { return "NTAG I2C Plus 2K"; } else if(type == MfUltralightTypeNTAG203) { return "NTAG203"; + } else if(type == MfUltralightTypeULC) { + return "Mifare Ultralight C"; } else if(type == MfUltralightTypeUL11 && full_name) { return "Mifare Ultralight 11"; } else if(type == MfUltralightTypeUL21 && full_name) { diff --git a/lib/nfc/protocols/mifare_ultralight.c b/lib/nfc/protocols/mifare_ultralight.c index 6960bd2a1..266b6e2e2 100644 --- a/lib/nfc/protocols/mifare_ultralight.c +++ b/lib/nfc/protocols/mifare_ultralight.c @@ -79,6 +79,8 @@ static MfUltralightFeatures mf_ul_get_features(MfUltralightType type) { MfUltralightSupportSectorSelect; case MfUltralightTypeNTAG203: return MfUltralightSupportCompatWrite | MfUltralightSupportCounterInMemory; + case MfUltralightTypeULC: + return MfUltralightSupportCompatWrite | MfUltralightSupport3DesAuth; default: // Assumed original MFUL 512-bit return MfUltralightSupportCompatWrite; @@ -95,6 +97,11 @@ static void mf_ul_set_version_ntag203(MfUltralightReader* reader, MfUltralightDa reader->pages_to_read = 42; } +static void mf_ul_set_version_ulc(MfUltralightReader* reader, MfUltralightData* data) { + data->type = MfUltralightTypeULC; + reader->pages_to_read = 48; +} + bool mf_ultralight_read_version( FuriHalNfcTxRxContext* tx_rx, MfUltralightReader* reader, @@ -175,7 +182,7 @@ bool mf_ultralight_authenticate(FuriHalNfcTxRxContext* tx_rx, uint32_t key, uint do { FURI_LOG_D(TAG, "Authenticating"); - tx_rx->tx_data[0] = MF_UL_AUTH; + tx_rx->tx_data[0] = MF_UL_PWD_AUTH; nfc_util_num2bytes(key, 4, &tx_rx->tx_data[1]); tx_rx->tx_bits = 40; tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault; @@ -716,6 +723,21 @@ bool mf_ultralight_read_tearing_flags(FuriHalNfcTxRxContext* tx_rx, MfUltralight return flag_read == 2; } +static bool mf_ul_probe_3des_auth(FuriHalNfcTxRxContext* tx_rx) { + tx_rx->tx_data[0] = MF_UL_AUTHENTICATE_1; + tx_rx->tx_data[1] = 0; + tx_rx->tx_bits = 16; + tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault; + bool rc = furi_hal_nfc_tx_rx(tx_rx, 50) && tx_rx->rx_bits == 9 * 8 && + tx_rx->rx_data[0] == 0xAF; + + // Reset just in case, we're not going to finish authenticating and need to if tag doesn't support auth + furi_hal_nfc_sleep(); + furi_hal_nfc_activate_nfca(300, NULL); + + return rc; +} + bool mf_ul_read_card( FuriHalNfcTxRxContext* tx_rx, MfUltralightReader* reader, @@ -733,16 +755,20 @@ bool mf_ul_read_card( mf_ultralight_read_signature(tx_rx, data); } } else { - // No GET_VERSION command, check for NTAG203 by reading last page (41) uint8_t dummy[16]; - if(mf_ultralight_read_pages_direct(tx_rx, 41, dummy)) { + // No GET_VERSION command, check if AUTHENTICATE command available (detect UL C). + if(mf_ul_probe_3des_auth(tx_rx)) { + mf_ul_set_version_ulc(reader, data); + } else if(mf_ultralight_read_pages_direct(tx_rx, 41, dummy)) { + // No AUTHENTICATE, check for NTAG203 by reading last page (41) mf_ul_set_version_ntag203(reader, data); - reader->supported_features = mf_ul_get_features(data->type); } else { // We're really an original Mifare Ultralight, reset tag for safety furi_hal_nfc_sleep(); furi_hal_nfc_activate_nfca(300, NULL); } + + reader->supported_features = mf_ul_get_features(data->type); } card_read = mf_ultralight_read_pages(tx_rx, reader, data); @@ -1228,6 +1254,10 @@ static void mf_ul_emulate_write( emulator->data_changed = true; } +bool mf_ul_emulation_supported(MfUltralightData* data) { + return data->type != MfUltralightTypeULC; +} + void mf_ul_reset_emulation(MfUltralightEmulator* emulator, bool is_power_cycle) { emulator->comp_write_cmd_started = false; emulator->sector_select_cmd_started = false; @@ -1732,7 +1762,7 @@ bool mf_ul_prepare_emulation_response( } } } - } else if(cmd == MF_UL_AUTH) { + } else if(cmd == MF_UL_PWD_AUTH) { if(emulator->supported_features & MfUltralightSupportAuth) { if(buff_rx_len == (1 + 4) * 8) { // Record password sent by PCD diff --git a/lib/nfc/protocols/mifare_ultralight.h b/lib/nfc/protocols/mifare_ultralight.h index 4ab22e89c..d444fa798 100644 --- a/lib/nfc/protocols/mifare_ultralight.h +++ b/lib/nfc/protocols/mifare_ultralight.h @@ -16,7 +16,8 @@ #define MF_UL_COMP_WRITE (0xA0) #define MF_UL_READ_CNT (0x39) #define MF_UL_INC_CNT (0xA5) -#define MF_UL_AUTH (0x1B) +#define MF_UL_AUTHENTICATE_1 (0x1A) +#define MF_UL_PWD_AUTH (0x1B) #define MF_UL_READ_SIG (0x3C) #define MF_UL_CHECK_TEARING (0x3E) #define MF_UL_READ_VCSL (0x4B) @@ -41,6 +42,7 @@ typedef enum { typedef enum { MfUltralightTypeUnknown, MfUltralightTypeNTAG203, + MfUltralightTypeULC, // Below have config pages and GET_VERSION support MfUltralightTypeUL11, MfUltralightTypeUL21, @@ -77,6 +79,7 @@ typedef enum { MfUltralightSupportAsciiMirror = 1 << 11, // NTAG203 counter that's in memory rather than through a command MfUltralightSupportCounterInMemory = 1 << 12, + MfUltralightSupport3DesAuth = 1 << 13, } MfUltralightFeatures; typedef enum { @@ -237,6 +240,8 @@ bool mf_ul_read_card( MfUltralightReader* reader, MfUltralightData* data); +bool mf_ul_emulation_supported(MfUltralightData* data); + void mf_ul_reset_emulation(MfUltralightEmulator* emulator, bool is_power_cycle); void mf_ul_prepare_emulation(MfUltralightEmulator* emulator, MfUltralightData* data); diff --git a/lib/toolbox/SConscript b/lib/toolbox/SConscript index 2d94336a9..fafedfeb4 100644 --- a/lib/toolbox/SConscript +++ b/lib/toolbox/SConscript @@ -8,6 +8,7 @@ env.Append( "#/lib/toolbox", ], SDK_HEADERS=[ + File("api_lock.h"), File("value_index.h"), File("manchester_decoder.h"), File("manchester_encoder.h"), diff --git a/scripts/sconsdist.py b/scripts/sconsdist.py index a3b466898..fc121390d 100644 --- a/scripts/sconsdist.py +++ b/scripts/sconsdist.py @@ -271,7 +271,15 @@ class Main(App): self.note_dist_component( "update", "tgz", self.get_dist_path(bundle_tgz) ) - tar.add(bundle_dir, arcname=bundle_dir_name) + + # Strip uid and gid in case of overflow + def tar_filter(tarinfo): + tarinfo.uid = tarinfo.gid = 0 + tarinfo.mtime = 0 + tarinfo.uname = tarinfo.gname = "furippa" + return tarinfo + + tar.add(bundle_dir, arcname=bundle_dir_name, filter=tar_filter) return bundle_result diff --git a/scripts/update.py b/scripts/update.py index 0f3ee6ea8..9f0d95d94 100755 --- a/scripts/update.py +++ b/scripts/update.py @@ -211,6 +211,9 @@ class Main(App): f"Cannot package resource: name '{tarinfo.name}' too long" ) raise ValueError("Resource name too long") + tarinfo.gid = tarinfo.uid = 0 + tarinfo.mtime = 0 + tarinfo.uname = tarinfo.gname = "furippa" return tarinfo def package_resources(self, srcdir: str, dst_name: str):