From 96412202ba57d7937a4553955f7e9e7d9f89e8e5 Mon Sep 17 00:00:00 2001 From: Alpha <43486986+sudoAlphaX@users.noreply.github.com> Date: Tue, 12 Dec 2023 17:04:08 +0530 Subject: [PATCH 01/44] Fix typo Change Deafult to Default in line 170 --- ReadMe.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ReadMe.md b/ReadMe.md index 05c3cd352..e5da572cc 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -167,7 +167,7 @@ You can support us by using links or addresses below: ## Community apps included ### [🎲 Download Extra plugins for Unleashed](https://github.com/xMasterX/all-the-plugins/releases/latest) -### [List of Extra pack](https://github.com/xMasterX/all-the-plugins/tree/dev#extra-pack) | [List of Base *(Deafult)* pack](https://github.com/xMasterX/all-the-plugins/tree/dev#default-pack) +### [List of Extra pack](https://github.com/xMasterX/all-the-plugins/tree/dev#extra-pack) | [List of Base *(Default)* pack](https://github.com/xMasterX/all-the-plugins/tree/dev#default-pack) See full list and sources here: [xMasterX/all-the-plugins](https://github.com/xMasterX/all-the-plugins/tree/dev) From 7b85e044627d7231a8a0a3f6d6ffd860b751ec80 Mon Sep 17 00:00:00 2001 From: Skorpionm <85568270+Skorpionm@users.noreply.github.com> Date: Tue, 12 Dec 2023 17:59:22 +0400 Subject: [PATCH 02/44] [FL-3681] SubGhz: changed the name of the button when sending RAW to SubGHz (#3275) --- applications/main/subghz/views/subghz_read_raw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/main/subghz/views/subghz_read_raw.c b/applications/main/subghz/views/subghz_read_raw.c index b074cdc9f..d630d47ec 100644 --- a/applications/main/subghz/views/subghz_read_raw.c +++ b/applications/main/subghz/views/subghz_read_raw.c @@ -329,7 +329,7 @@ void subghz_read_raw_draw(Canvas* canvas, SubGhzReadRAWModel* model) { case SubGhzReadRAWStatusLoadKeyTX: case SubGhzReadRAWStatusLoadKeyTXRepeat: graphics_mode = 0; - elements_button_center(canvas, "Send"); + elements_button_center(canvas, "Hold to repeat"); break; case SubGhzReadRAWStatusStart: From e2e3663524961b58ea71851887e9e8521108555c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=81=8F?= Date: Tue, 12 Dec 2023 14:39:14 +0000 Subject: [PATCH 03/44] FuriHal: various GPIO improvements (#3260) * FuriHal: add alternative gpio pulls that covers special cases, extra checks and crash on inalid parameters. * FuriHal: optimize pwr_XX selection in gpio_init * FuriHal: cleanup gpio param validation crash routine --- targets/f7/furi_hal/furi_hal_gpio.c | 46 +++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/targets/f7/furi_hal/furi_hal_gpio.c b/targets/f7/furi_hal/furi_hal_gpio.c index afd482f2f..d5221aba9 100644 --- a/targets/f7/furi_hal/furi_hal_gpio.c +++ b/targets/f7/furi_hal/furi_hal_gpio.c @@ -3,14 +3,21 @@ #include #include #include +#include -#define GET_SYSCFG_EXTI_PORT(gpio) \ - (((gpio) == (GPIOA)) ? LL_SYSCFG_EXTI_PORTA : \ - ((gpio) == (GPIOB)) ? LL_SYSCFG_EXTI_PORTB : \ - ((gpio) == (GPIOC)) ? LL_SYSCFG_EXTI_PORTC : \ - ((gpio) == (GPIOD)) ? LL_SYSCFG_EXTI_PORTD : \ - ((gpio) == (GPIOE)) ? LL_SYSCFG_EXTI_PORTE : \ - LL_SYSCFG_EXTI_PORTH) +static uint32_t furi_hal_gpio_invalid_argument_crash() { + furi_crash("Invalid argument"); + return 0; +} + +#define GPIO_PORT_MAP(port, prefix) \ + (((port) == (GPIOA)) ? prefix##A : \ + ((port) == (GPIOB)) ? prefix##B : \ + ((port) == (GPIOC)) ? prefix##C : \ + ((port) == (GPIOD)) ? prefix##D : \ + ((port) == (GPIOE)) ? prefix##E : \ + ((port) == (GPIOH)) ? prefix##H : \ + furi_hal_gpio_invalid_argument_crash()) #define GPIO_PIN_MAP(pin, prefix) \ (((pin) == (LL_GPIO_PIN_0)) ? prefix##0 : \ @@ -28,11 +35,16 @@ ((pin) == (LL_GPIO_PIN_12)) ? prefix##12 : \ ((pin) == (LL_GPIO_PIN_13)) ? prefix##13 : \ ((pin) == (LL_GPIO_PIN_14)) ? prefix##14 : \ - prefix##15) + ((pin) == (LL_GPIO_PIN_15)) ? prefix##15 : \ + furi_hal_gpio_invalid_argument_crash()) +#define GET_SYSCFG_EXTI_PORT(port) GPIO_PORT_MAP(port, LL_SYSCFG_EXTI_PORT) #define GET_SYSCFG_EXTI_LINE(pin) GPIO_PIN_MAP(pin, LL_SYSCFG_EXTI_LINE) #define GET_EXTI_LINE(pin) GPIO_PIN_MAP(pin, LL_EXTI_LINE_) +#define GET_PWR_PORT(port) GPIO_PORT_MAP(port, LL_PWR_GPIO_) +#define GET_PWR_PIN(pin) GPIO_PIN_MAP(pin, LL_PWR_GPIO_BIT_) + static volatile GpioInterrupt gpio_interrupt[GPIO_NUMBER]; static uint8_t furi_hal_gpio_get_pin_num(const GpioPin* gpio) { @@ -65,9 +77,11 @@ void furi_hal_gpio_init_ex( const GpioPull pull, const GpioSpeed speed, const GpioAltFn alt_fn) { - uint32_t sys_exti_port = GET_SYSCFG_EXTI_PORT(gpio->port); - uint32_t sys_exti_line = GET_SYSCFG_EXTI_LINE(gpio->pin); - uint32_t exti_line = GET_EXTI_LINE(gpio->pin); + const uint32_t sys_exti_port = GET_SYSCFG_EXTI_PORT(gpio->port); + const uint32_t sys_exti_line = GET_SYSCFG_EXTI_LINE(gpio->pin); + const uint32_t exti_line = GET_EXTI_LINE(gpio->pin); + const uint32_t pwr_port = GET_PWR_PORT(gpio->port); + const uint32_t pwr_pin = GET_PWR_PIN(gpio->pin); // Configure gpio with interrupts disabled FURI_CRITICAL_ENTER(); @@ -92,13 +106,21 @@ void furi_hal_gpio_init_ex( switch(pull) { case GpioPullNo: LL_GPIO_SetPinPull(gpio->port, gpio->pin, LL_GPIO_PULL_NO); + LL_PWR_DisableGPIOPullUp(pwr_port, pwr_pin); + LL_PWR_DisableGPIOPullDown(pwr_port, pwr_pin); break; case GpioPullUp: LL_GPIO_SetPinPull(gpio->port, gpio->pin, LL_GPIO_PULL_UP); + LL_PWR_DisableGPIOPullDown(pwr_port, pwr_pin); + LL_PWR_EnableGPIOPullUp(pwr_port, pwr_pin); break; case GpioPullDown: LL_GPIO_SetPinPull(gpio->port, gpio->pin, LL_GPIO_PULL_DOWN); + LL_PWR_DisableGPIOPullUp(pwr_port, pwr_pin); + LL_PWR_EnableGPIOPullDown(pwr_port, pwr_pin); break; + default: + furi_crash("Incorrect GpioPull"); } // Set gpio mode @@ -166,7 +188,7 @@ void furi_hal_gpio_init_ex( LL_GPIO_SetPinMode(gpio->port, gpio->pin, LL_GPIO_MODE_ANALOG); break; default: - break; + furi_crash("Incorrect GpioMode"); } } FURI_CRITICAL_EXIT(); From 90cb1c4f2e80759017a129f0737d2a3c68e8a789 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=81=8F?= Date: Tue, 12 Dec 2023 15:12:57 +0000 Subject: [PATCH 04/44] FuriHal: RTC register reset API. New factory reset routine that wipes all RTC backup registers content. (#3288) --- applications/services/rpc/rpc_system.c | 3 ++- applications/services/storage/storage_cli.c | 3 ++- .../services/storage/storages/storage_int.c | 4 ++-- .../storage_settings_scene_factory_reset.c | 3 ++- .../updater/util/update_task_worker_flasher.c | 2 +- targets/f18/api_symbols.csv | 3 ++- targets/f7/api_symbols.csv | 5 +++-- targets/f7/furi_hal/furi_hal_rtc.c | 20 ++++++++++++------- targets/f7/src/recovery.c | 5 ++--- targets/furi_hal_include/furi_hal_rtc.h | 5 ++++- 10 files changed, 33 insertions(+), 20 deletions(-) diff --git a/applications/services/rpc/rpc_system.c b/applications/services/rpc/rpc_system.c index 77dca4a1a..96a189ad3 100644 --- a/applications/services/rpc/rpc_system.c +++ b/applications/services/rpc/rpc_system.c @@ -179,7 +179,8 @@ static void rpc_system_system_factory_reset_process(const PB_Main* request, void RpcSession* session = (RpcSession*)context; furi_assert(session); - furi_hal_rtc_set_flag(FuriHalRtcFlagFactoryReset); + furi_hal_rtc_reset_registers(); + furi_hal_rtc_set_flag(FuriHalRtcFlagStorageFormatInternal); power_reboot(PowerBootModeNormal); (void)session; diff --git a/applications/services/storage/storage_cli.c b/applications/services/storage/storage_cli.c index 2927022a3..52c911c57 100644 --- a/applications/services/storage/storage_cli.c +++ b/applications/services/storage/storage_cli.c @@ -603,7 +603,8 @@ static void storage_cli_factory_reset(Cli* cli, FuriString* args, void* context) char c = cli_getc(cli); if(c == 'y' || c == 'Y') { printf("Data will be wiped after reboot.\r\n"); - furi_hal_rtc_set_flag(FuriHalRtcFlagFactoryReset); + furi_hal_rtc_reset_registers(); + furi_hal_rtc_set_flag(FuriHalRtcFlagStorageFormatInternal); power_reboot(PowerBootModeNormal); } else { printf("Safe choice.\r\n"); diff --git a/applications/services/storage/storages/storage_int.c b/applications/services/storage/storages/storage_int.c index 39b092c1d..ea6fa68ef 100644 --- a/applications/services/storage/storages/storage_int.c +++ b/applications/services/storage/storages/storage_int.c @@ -189,7 +189,7 @@ static void storage_int_lfs_mount(LFSData* lfs_data, StorageData* storage) { lfs_t* lfs = &lfs_data->lfs; bool was_fingerprint_outdated = storage_int_check_and_set_fingerprint(lfs_data); - bool need_format = furi_hal_rtc_is_flag_set(FuriHalRtcFlagFactoryReset) || + bool need_format = furi_hal_rtc_is_flag_set(FuriHalRtcFlagStorageFormatInternal) || was_fingerprint_outdated; if(need_format) { @@ -197,7 +197,7 @@ static void storage_int_lfs_mount(LFSData* lfs_data, StorageData* storage) { err = lfs_format(lfs, &lfs_data->config); if(err == 0) { FURI_LOG_I(TAG, "Factory reset: Format successful, trying to mount"); - furi_hal_rtc_reset_flag(FuriHalRtcFlagFactoryReset); + furi_hal_rtc_reset_flag(FuriHalRtcFlagStorageFormatInternal); err = lfs_mount(lfs, &lfs_data->config); if(err == 0) { FURI_LOG_I(TAG, "Factory reset: Mounted"); diff --git a/applications/settings/storage_settings/scenes/storage_settings_scene_factory_reset.c b/applications/settings/storage_settings/scenes/storage_settings_scene_factory_reset.c index 865ee48d4..5832c6589 100644 --- a/applications/settings/storage_settings/scenes/storage_settings_scene_factory_reset.c +++ b/applications/settings/storage_settings/scenes/storage_settings_scene_factory_reset.c @@ -63,7 +63,8 @@ bool storage_settings_scene_factory_reset_on_event(void* context, SceneManagerEv scene_manager_set_scene_state( app->scene_manager, StorageSettingsFactoryReset, counter); } else { - furi_hal_rtc_set_flag(FuriHalRtcFlagFactoryReset); + furi_hal_rtc_reset_registers(); + furi_hal_rtc_set_flag(FuriHalRtcFlagStorageFormatInternal); power_reboot(PowerBootModeNormal); } diff --git a/applications/system/updater/util/update_task_worker_flasher.c b/applications/system/updater/util/update_task_worker_flasher.c index 1b4b07900..40f58f462 100644 --- a/applications/system/updater/util/update_task_worker_flasher.c +++ b/applications/system/updater/util/update_task_worker_flasher.c @@ -343,7 +343,7 @@ int32_t update_task_worker_flash_writer(void* context) { furi_hal_rtc_set_boot_mode(FuriHalRtcBootModePostUpdate); // Format LFS before restoring backup on next boot - furi_hal_rtc_set_flag(FuriHalRtcFlagFactoryReset); + furi_hal_rtc_set_flag(FuriHalRtcFlagStorageFormatInternal); #ifdef FURI_NDEBUG // Production furi_hal_rtc_set_log_level(FuriLogLevelDefault); diff --git a/targets/f18/api_symbols.csv b/targets/f18/api_symbols.csv index cb34f969a..d684cc9e9 100644 --- a/targets/f18/api_symbols.csv +++ b/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,49.1,, +Version,+,49.2,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -1247,6 +1247,7 @@ Function,-,furi_hal_rtc_init_early,void, Function,+,furi_hal_rtc_is_flag_set,_Bool,FuriHalRtcFlag Function,+,furi_hal_rtc_is_leap_year,_Bool,uint16_t Function,+,furi_hal_rtc_reset_flag,void,FuriHalRtcFlag +Function,+,furi_hal_rtc_reset_registers,void, Function,+,furi_hal_rtc_set_boot_mode,void,FuriHalRtcBootMode Function,+,furi_hal_rtc_set_datetime,void,FuriHalRtcDateTime* Function,+,furi_hal_rtc_set_fault_data,void,uint32_t diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index 439fc7bf5..61c1903de 100644 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,49.1,, +Version,+,49.2,, Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, @@ -1414,6 +1414,7 @@ Function,-,furi_hal_rtc_init_early,void, Function,+,furi_hal_rtc_is_flag_set,_Bool,FuriHalRtcFlag Function,+,furi_hal_rtc_is_leap_year,_Bool,uint16_t Function,+,furi_hal_rtc_reset_flag,void,FuriHalRtcFlag +Function,+,furi_hal_rtc_reset_registers,void, Function,+,furi_hal_rtc_set_boot_mode,void,FuriHalRtcBootMode Function,+,furi_hal_rtc_set_datetime,void,FuriHalRtcDateTime* Function,+,furi_hal_rtc_set_fault_data,void,uint32_t @@ -2289,8 +2290,8 @@ Function,+,mf_classic_is_value_block,_Bool,"MfClassicSectorTrailer*, uint8_t" Function,+,mf_classic_load,_Bool,"MfClassicData*, FlipperFormat*, uint32_t" Function,+,mf_classic_poller_auth,MfClassicError,"MfClassicPoller*, uint8_t, MfClassicKey*, MfClassicKeyType, MfClassicAuthContext*" Function,+,mf_classic_poller_auth_nested,MfClassicError,"MfClassicPoller*, uint8_t, MfClassicKey*, MfClassicKeyType, MfClassicAuthContext*" -Function,+,mf_classic_poller_get_nt_nested,MfClassicError,"MfClassicPoller*, uint8_t, MfClassicKeyType, MfClassicNt*" Function,+,mf_classic_poller_get_nt,MfClassicError,"MfClassicPoller*, uint8_t, MfClassicKeyType, MfClassicNt*" +Function,+,mf_classic_poller_get_nt_nested,MfClassicError,"MfClassicPoller*, uint8_t, MfClassicKeyType, MfClassicNt*" Function,+,mf_classic_poller_halt,MfClassicError,MfClassicPoller* Function,+,mf_classic_poller_read_block,MfClassicError,"MfClassicPoller*, uint8_t, MfClassicBlock*" Function,+,mf_classic_poller_sync_auth,MfClassicError,"Nfc*, uint8_t, MfClassicKey*, MfClassicKeyType, MfClassicAuthContext*" diff --git a/targets/f7/furi_hal/furi_hal_rtc.c b/targets/f7/furi_hal/furi_hal_rtc.c index a8e25faad..cb8065bed 100644 --- a/targets/f7/furi_hal/furi_hal_rtc.c +++ b/targets/f7/furi_hal/furi_hal_rtc.c @@ -132,13 +132,7 @@ void furi_hal_rtc_init_early() { uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterHeader); FuriHalRtcHeader* data = (FuriHalRtcHeader*)&data_reg; if(data->magic != FURI_HAL_RTC_HEADER_MAGIC || data->version != FURI_HAL_RTC_HEADER_VERSION) { - // Reset all our registers to ensure consistency - for(size_t i = 0; i < FuriHalRtcRegisterMAX; i++) { - furi_hal_rtc_set_register(i, 0); - } - data->magic = FURI_HAL_RTC_HEADER_MAGIC; - data->version = FURI_HAL_RTC_HEADER_VERSION; - furi_hal_rtc_set_register(FuriHalRtcRegisterHeader, data_reg); + furi_hal_rtc_reset_registers(); } if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { @@ -171,6 +165,18 @@ void furi_hal_rtc_sync_shadow() { } } +void furi_hal_rtc_reset_registers() { + for(size_t i = 0; i < RTC_BKP_NUMBER; i++) { + furi_hal_rtc_set_register(i, 0); + } + + uint32_t data_reg = 0; + FuriHalRtcHeader* data = (FuriHalRtcHeader*)&data_reg; + data->magic = FURI_HAL_RTC_HEADER_MAGIC; + data->version = FURI_HAL_RTC_HEADER_VERSION; + furi_hal_rtc_set_register(FuriHalRtcRegisterHeader, data_reg); +} + uint32_t furi_hal_rtc_get_register(FuriHalRtcRegister reg) { return LL_RTC_BAK_GetRegister(RTC, reg); } diff --git a/targets/f7/src/recovery.c b/targets/f7/src/recovery.c index 49d780d47..848236815 100644 --- a/targets/f7/src/recovery.c +++ b/targets/f7/src/recovery.c @@ -56,8 +56,7 @@ void flipper_boot_recovery_exec() { } if(!counter) { - furi_hal_rtc_set_flag(FuriHalRtcFlagFactoryReset); - furi_hal_rtc_set_pin_fails(0); - furi_hal_rtc_reset_flag(FuriHalRtcFlagLock); + furi_hal_rtc_reset_registers(); + furi_hal_rtc_set_flag(FuriHalRtcFlagStorageFormatInternal); } } diff --git a/targets/furi_hal_include/furi_hal_rtc.h b/targets/furi_hal_include/furi_hal_rtc.h index c457b6903..98b23466c 100644 --- a/targets/furi_hal_include/furi_hal_rtc.h +++ b/targets/furi_hal_include/furi_hal_rtc.h @@ -26,7 +26,7 @@ typedef struct { typedef enum { FuriHalRtcFlagDebug = (1 << 0), - FuriHalRtcFlagFactoryReset = (1 << 1), + FuriHalRtcFlagStorageFormatInternal = (1 << 1), FuriHalRtcFlagLock = (1 << 2), FuriHalRtcFlagC2Update = (1 << 3), FuriHalRtcFlagHandOrient = (1 << 4), @@ -91,6 +91,9 @@ void furi_hal_rtc_init(); /** Force sync shadow registers */ void furi_hal_rtc_sync_shadow(); +/** Reset ALL RTC registers content */ +void furi_hal_rtc_reset_registers(); + /** Get RTC register content * * @param[in] reg The register identifier From 155e4e9fa4c1bf504179f9de1f55e5c44d9fb29d Mon Sep 17 00:00:00 2001 From: gornekich Date: Tue, 12 Dec 2023 19:24:06 +0400 Subject: [PATCH 05/44] [FL-3706], [FL-3674] NFC NTAG and ISO14443-3b reading fix (#3285) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * mf ultralight poller: reset field after reading tearing flags * iso14443-3b poller: change cid comparison in ATTRIB cmd Co-authored-by: あく --- lib/nfc/protocols/iso14443_3b/iso14443_3b_poller_i.c | 12 ++++++------ .../protocols/mf_ultralight/mf_ultralight_poller.c | 7 ++++++- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/nfc/protocols/iso14443_3b/iso14443_3b_poller_i.c b/lib/nfc/protocols/iso14443_3b/iso14443_3b_poller_i.c index 15fc609db..1266e2482 100644 --- a/lib/nfc/protocols/iso14443_3b/iso14443_3b_poller_i.c +++ b/lib/nfc/protocols/iso14443_3b/iso14443_3b_poller_i.c @@ -117,12 +117,13 @@ Iso14443_3bError iso14443_3b_poller_activate(Iso14443_3bPoller* instance, Iso144 bit_buffer_reset(instance->rx_buffer); // Send ATTRIB + uint8_t cid = 0; bit_buffer_append_byte(instance->tx_buffer, 0x1d); bit_buffer_append_bytes(instance->tx_buffer, data->uid, ISO14443_3B_UID_SIZE); bit_buffer_append_byte(instance->tx_buffer, 0x00); bit_buffer_append_byte(instance->tx_buffer, ISO14443_3B_ATTRIB_FRAME_SIZE_256); bit_buffer_append_byte(instance->tx_buffer, 0x01); - bit_buffer_append_byte(instance->tx_buffer, 0x00); + bit_buffer_append_byte(instance->tx_buffer, cid); ret = iso14443_3b_poller_frame_exchange( instance, instance->tx_buffer, instance->rx_buffer, iso14443_3b_get_fwt_fc_max(data)); @@ -138,11 +139,10 @@ Iso14443_3bError iso14443_3b_poller_activate(Iso14443_3bPoller* instance, Iso144 bit_buffer_get_size_bytes(instance->rx_buffer)); } - if(bit_buffer_get_byte(instance->rx_buffer, 0) != 0) { - FURI_LOG_D( - TAG, - "Incorrect CID in ATTRIB response: %02X", - bit_buffer_get_byte(instance->rx_buffer, 0)); + uint8_t cid_received = bit_buffer_get_byte(instance->rx_buffer, 0); + // 15 bit is RFU + if((cid_received & 0x7f) != cid) { + FURI_LOG_D(TAG, "Incorrect CID in ATTRIB response: %02X", cid_received); instance->state = Iso14443_3bPollerStateActivationFailed; ret = Iso14443_3bErrorCommunication; break; diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c index 619cd8c5f..f7f814270 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.c @@ -371,11 +371,14 @@ static NfcCommand mf_ultralight_poller_handler_read_counters(MfUltralightPoller* } static NfcCommand mf_ultralight_poller_handler_read_tearing_flags(MfUltralightPoller* instance) { + NfcCommand command = NfcCommandContinue; + if(mf_ultralight_support_feature( instance->feature_set, MfUltralightFeatureSupportCheckTearingFlag | MfUltralightFeatureSupportSingleCounter)) { if(instance->tearing_flag_read == instance->tearing_flag_total) { instance->state = MfUltralightPollerStateTryDefaultPass; + command = NfcCommandReset; } else { bool single_counter = mf_ultralight_support_feature( instance->feature_set, MfUltralightFeatureSupportSingleCounter); @@ -391,6 +394,7 @@ static NfcCommand mf_ultralight_poller_handler_read_tearing_flags(MfUltralightPo } else if(instance->error != MfUltralightErrorNone) { FURI_LOG_D(TAG, "Reading tearing flag %d failed", instance->tearing_flag_read); instance->state = MfUltralightPollerStateTryDefaultPass; + command = NfcCommandReset; } else { instance->tearing_flag_read++; } @@ -398,9 +402,10 @@ static NfcCommand mf_ultralight_poller_handler_read_tearing_flags(MfUltralightPo } else { FURI_LOG_D(TAG, "Skip reading tearing flags"); instance->state = MfUltralightPollerStateTryDefaultPass; + command = NfcCommandReset; } - return NfcCommandContinue; + return command; } static NfcCommand mf_ultralight_poller_handler_auth(MfUltralightPoller* instance) { From 3dde11267615db62172415df20c3d89e5fb93ba3 Mon Sep 17 00:00:00 2001 From: Nathan N Date: Tue, 12 Dec 2023 11:17:33 -0500 Subject: [PATCH 06/44] Fix edge case -- 0.5% of UIDs got wrong result --- applications/main/nfc/plugins/supported_cards/saflok.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/applications/main/nfc/plugins/supported_cards/saflok.c b/applications/main/nfc/plugins/supported_cards/saflok.c index 55edd2efa..1b40d5de8 100644 --- a/applications/main/nfc/plugins/supported_cards/saflok.c +++ b/applications/main/nfc/plugins/supported_cards/saflok.c @@ -62,8 +62,8 @@ void generate_saflok_key(const uint8_t* uid, uint8_t* key) { uint8_t carry_sum = 0; for(int i = KEY_LENGTH - 1; i >= 0; i--, magickal_index--) { - uint16_t keysum = temp_key[i] + magic_table[magickal_index]; - temp_key[i] = (keysum & 0xFF) + carry_sum; + uint16_t keysum = temp_key[i] + magic_table[magickal_index] + carry_sum; + temp_key[i] = (keysum & 0xFF); carry_sum = keysum >> 8; } From 73145e0bebf5fa8b7069d5df9b7528091592e0f2 Mon Sep 17 00:00:00 2001 From: gornekich Date: Wed, 13 Dec 2023 23:01:17 +0400 Subject: [PATCH 07/44] mf classic listener: reset state before sleep and after nack --- lib/nfc/protocols/mf_classic/mf_classic_listener.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/nfc/protocols/mf_classic/mf_classic_listener.c b/lib/nfc/protocols/mf_classic/mf_classic_listener.c index 3423e89e4..bd25aba23 100644 --- a/lib/nfc/protocols/mf_classic/mf_classic_listener.c +++ b/lib/nfc/protocols/mf_classic/mf_classic_listener.c @@ -40,10 +40,11 @@ static void mf_classic_listener_reset_state(MfClassicListener* instance) { static MfClassicListenerCommand mf_classic_listener_halt_handler(MfClassicListener* instance, BitBuffer* buff) { + UNUSED(instance); + MfClassicListenerCommand command = MfClassicListenerCommandNack; if(bit_buffer_get_byte(buff, 1) == MF_CLASSIC_CMD_HALT_LSB) { - mf_classic_listener_reset_state(instance); command = MfClassicListenerCommandSleep; } @@ -59,10 +60,7 @@ static MfClassicListenerCommand mf_classic_listener_auth_first_part_handler( do { instance->state = MfClassicListenerStateIdle; - if(block_num >= instance->total_block_num) { - mf_classic_listener_reset_state(instance); - break; - } + if(block_num >= instance->total_block_num) break; uint8_t sector_num = mf_classic_get_sector_by_block(block_num); @@ -135,7 +133,7 @@ static MfClassicListenerCommand instance->cmd_in_progress = false; if(bit_buffer_get_size_bytes(buff) != (sizeof(MfClassicNr) + sizeof(MfClassicAr))) { - mf_classic_listener_reset_state(instance); + command = MfClassicListenerCommandSleep; break; } bit_buffer_write_bytes_mid(buff, instance->auth_context.nr.data, 0, sizeof(MfClassicNr)); @@ -157,7 +155,7 @@ static MfClassicListenerCommand if(secret_poller != prng_successor(nt_num, 64)) { FURI_LOG_T( TAG, "Wrong reader key: %08lX != %08lX", secret_poller, prng_successor(nt_num, 64)); - mf_classic_listener_reset_state(instance); + command = MfClassicListenerCommandSleep; break; } @@ -610,9 +608,11 @@ NfcCommand mf_classic_listener_run(NfcGenericEvent event, void* context) { } mf_classic_listener_send_short_frame(instance, nack); + mf_classic_listener_reset_state(instance); } else if(mfc_command == MfClassicListenerCommandSilent) { command = NfcCommandReset; } else if(mfc_command == MfClassicListenerCommandSleep) { + mf_classic_listener_reset_state(instance); command = NfcCommandSleep; } } else if(iso3_event->type == Iso14443_3aListenerEventTypeHalted) { From 2d860b4a2255b1a6d400c169d2cd5ab51744e32c Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Thu, 14 Dec 2023 01:14:08 +0300 Subject: [PATCH 08/44] fix key display newline --- lib/subghz/protocols/came_atomo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/subghz/protocols/came_atomo.c b/lib/subghz/protocols/came_atomo.c index 0d9545020..87927e362 100644 --- a/lib/subghz/protocols/came_atomo.c +++ b/lib/subghz/protocols/came_atomo.c @@ -718,7 +718,7 @@ void subghz_protocol_decoder_came_atomo_get_string(void* context, FuriString* ou furi_string_cat_printf( output, "%s %db\r\n" - "Key:0x%08lX%08lX\r\n" + "Key:%08lX%08lX\r\n" "Sn:0x%08lX Btn:%01X\r\n" "Pcl_Cnt:0x%04lX\r\n" "Btn_Cnt:0x%02X", From ccbb3a34984075c291299516e5dcd42700e123de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=81=8F?= Date: Thu, 14 Dec 2023 11:14:21 +0000 Subject: [PATCH 09/44] [FL-3715] Update CLI MOTD (#3292) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add Carrier 42QG5A580SC * Cli: update motd --------- Co-authored-by: Gustavo de León --- applications/services/cli/cli.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/applications/services/cli/cli.c b/applications/services/cli/cli.c index ad3bbd665..55a603a20 100644 --- a/applications/services/cli/cli.c +++ b/applications/services/cli/cli.c @@ -118,7 +118,8 @@ void cli_motd() { "|_| |____||___||_| |_| |___||_|_\\ \\___||____||___|\r\n" "\r\n" "Welcome to Flipper Zero Command Line Interface!\r\n" - "Read Manual https://docs.flipperzero.one\r\n" + "Read the manual: https://docs.flipper.net/development/cli\r\n" + "Run `help` or `?` to list available commands\r\n" "\r\n"); const Version* firmware_version = furi_hal_version_get_firmware_version(); From 78b731005773bd2cb533a964cf443ccfeb4b397a Mon Sep 17 00:00:00 2001 From: Augusto Zanellato Date: Thu, 14 Dec 2023 14:54:58 +0100 Subject: [PATCH 10/44] Add MyKey parser (#3262) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- applications/main/nfc/application.fam | 9 ++ .../main/nfc/plugins/supported_cards/mykey.c | 130 ++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 applications/main/nfc/plugins/supported_cards/mykey.c diff --git a/applications/main/nfc/application.fam b/applications/main/nfc/application.fam index 07e97c0c9..775f2cda8 100644 --- a/applications/main/nfc/application.fam +++ b/applications/main/nfc/application.fam @@ -38,6 +38,15 @@ App( sources=["plugins/supported_cards/opal.c"], ) +App( + appid="mykey_parser", + apptype=FlipperAppType.PLUGIN, + entry_point="mykey_plugin_ep", + targets=["f7"], + requires=["nfc"], + sources=["plugins/supported_cards/mykey.c"], +) + App( appid="myki_parser", apptype=FlipperAppType.PLUGIN, diff --git a/applications/main/nfc/plugins/supported_cards/mykey.c b/applications/main/nfc/plugins/supported_cards/mykey.c new file mode 100644 index 000000000..69fd18ee3 --- /dev/null +++ b/applications/main/nfc/plugins/supported_cards/mykey.c @@ -0,0 +1,130 @@ +#include "nfc_supported_card_plugin.h" + +#include +#include +#include + +#define TAG "MyKey" + +const uint32_t blankBlock18 = 0x480FCD8F, blankBlock19 = 0x070082C0; + +static bool mykey_is_blank(const St25tbData* data) { + return data->blocks[0x18] == blankBlock18 && data->blocks[0x19] == blankBlock19; +} + +static bool mykey_has_lockid(const St25tbData* data) { + return (data->blocks[5] & 0xFF) == 0x7F; +} + +static bool mykey_parse(const NfcDevice* device, FuriString* parsed_data) { + furi_assert(device); + furi_assert(parsed_data); + + const St25tbData* data = nfc_device_get_data(device, NfcProtocolSt25tb); + + if(data->type != St25tbType04k && data->type != St25tbTypeX4k) { + FURI_LOG_D(TAG, "bad type"); + return false; + } + + for(int i = 0; i < 5; i++) { + if(data->blocks[i] != 0xFFFFFFFF) { + FURI_LOG_D(TAG, "bad otp block %d", i); + return false; + } + } + + if((data->blocks[8] >> 16 & 0xFF) > 0x31 || (data->blocks[8] >> 8 & 0xFF) > 0x12) { + FURI_LOG_D(TAG, "bad mfg date"); + return false; + } + + if(data->system_otp_block != 0xFEFFFFFF) { + FURI_LOG_D(TAG, "bad sys otp block"); + return false; + } + + furi_string_cat(parsed_data, "\e#MyKey\n"); + + if(data->blocks[6] == 0) { // Tag is actually a MyKey but it has been bricked by a reader + furi_string_cat(parsed_data, "\e#Bricked!\nBlock 6 is 0!"); + return true; + } + + bool is_blank = mykey_is_blank(data); + furi_string_cat_printf(parsed_data, "Serial#: %08lX\n", __bswap32(data->blocks[7])); + furi_string_cat_printf(parsed_data, "Blank: %s\n", is_blank ? "yes" : "no"); + furi_string_cat_printf(parsed_data, "LockID: %s\n", mykey_has_lockid(data) ? "maybe" : "no"); + + uint32_t block8 = data->blocks[8]; + furi_string_cat_printf( + parsed_data, + "Prod. date: %02lX/%02lX/%04lX", + block8 >> 16 & 0xFF, + block8 >> 8 & 0xFF, + 0x2000 + (block8 & 0xFF)); + + if(!is_blank) { + furi_string_cat_printf( + parsed_data, "\nOp. count: %ld\n", __bswap32(data->blocks[0x12] & 0xFFFFFF00)); + + uint32_t block3C = data->blocks[0x3C]; + if(block3C == 0xFFFFFFFF) { + furi_string_cat(parsed_data, "No history available!"); + } else { + block3C ^= data->blocks[0x07]; + uint32_t startingOffset = ((block3C & 0x30000000) >> 28) | + ((block3C & 0x00100000) >> 18); + furi_check(startingOffset < 8); + for(int txnOffset = 8; txnOffset > 0; txnOffset--) { + uint32_t txnBlock = + __bswap32(data->blocks[0x34 + ((startingOffset + txnOffset) % 8)]); + + if(txnBlock == 0xFFFFFFFF) { + break; + } + + uint8_t day = txnBlock >> 27; + uint8_t month = txnBlock >> 23 & 0xF; + uint16_t year = 2000 + (txnBlock >> 16 & 0x7F); + uint16_t credit = txnBlock & 0xFFFF; + + if(txnOffset == 8) { + furi_string_cat_printf( + parsed_data, "Current credit: %d.%02d euros\n", credit / 100, credit % 100); + furi_string_cat(parsed_data, "Op. history (newest first):"); + } + + furi_string_cat_printf( + parsed_data, + "\n %02d/%02d/%04d %d.%02d", + day, + month, + year, + credit / 100, + credit % 100); + } + } + } + return true; +} + +/* Actual implementation of app<>plugin interface */ +static const NfcSupportedCardsPlugin mykey_plugin = { + .protocol = NfcProtocolSt25tb, + .verify = NULL, + .read = NULL, + .parse = mykey_parse, +}; + +/* Plugin descriptor to comply with basic plugin specification */ +static const FlipperAppPluginDescriptor mykey_plugin_descriptor = { + .appid = NFC_SUPPORTED_CARD_PLUGIN_APP_ID, + .ep_api_version = NFC_SUPPORTED_CARD_PLUGIN_API_VERSION, + .entry_point = &mykey_plugin, +}; + +/* Plugin entry point - must return a pointer to const descriptor */ +const FlipperAppPluginDescriptor* mykey_plugin_ep() { + return &mykey_plugin_descriptor; +} From 0af74fb7551ae6262d0dac4316480d9518aece56 Mon Sep 17 00:00:00 2001 From: Leptopt1los <53914086+Leptopt1los@users.noreply.github.com> Date: Thu, 14 Dec 2023 23:02:40 +0900 Subject: [PATCH 11/44] Umarsh transport cards parser (#3277) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Umarsh transport card parser added * Volna transport cards keys added Co-authored-by: あく --- applications/main/nfc/application.fam | 9 + .../main/nfc/plugins/supported_cards/umarsh.c | 155 ++++++++++++++++++ .../resources/nfc/assets/mf_classic_dict.nfc | 4 + 3 files changed, 168 insertions(+) create mode 100644 applications/main/nfc/plugins/supported_cards/umarsh.c diff --git a/applications/main/nfc/application.fam b/applications/main/nfc/application.fam index 775f2cda8..ecb61fe60 100644 --- a/applications/main/nfc/application.fam +++ b/applications/main/nfc/application.fam @@ -92,6 +92,15 @@ App( sources=["plugins/supported_cards/aime.c"], ) +App( + appid="umarsh_parser", + apptype=FlipperAppType.PLUGIN, + entry_point="umarsh_plugin_ep", + targets=["f7"], + requires=["nfc"], + sources=["plugins/supported_cards/umarsh.c"], +) + App( appid="nfc_start", targets=["f7"], diff --git a/applications/main/nfc/plugins/supported_cards/umarsh.c b/applications/main/nfc/plugins/supported_cards/umarsh.c new file mode 100644 index 000000000..a85c056f6 --- /dev/null +++ b/applications/main/nfc/plugins/supported_cards/umarsh.c @@ -0,0 +1,155 @@ +/* + * Parser for Umarsh card (Russia). + * + * Copyright 2023 Leptoptilos + * Thanks https://github.com/krolchonok for the provided dumps and their analysis + * + * Note: All meaningful data is stored in sectors 0, 8 and 12, reading data + * from which is possible only with the B key. The key B for these sectors + * is unique for each card. To get it, you should use a nested attack. + * More info about Umarsh cards: https://github.com/metrodroid/metrodroid/wiki/Umarsh + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "core/core_defines.h" +#include "nfc_supported_card_plugin.h" + +#include "protocols/mf_classic/mf_classic.h" +#include + +#include +#include +#include +#include +#include +#include + +#define TAG "Umarsh" + +bool parse_datetime(uint16_t date, FuriHalRtcDateTime* result) { + result->year = 2000 + (date >> 9); + result->month = date >> 5 & 0x0F; + result->day = date & 0x1F; + return (date != 0); +} + +static bool umarsh_parse(const NfcDevice* device, FuriString* parsed_data) { + furi_assert(device); + + const MfClassicData* data = nfc_device_get_data(device, NfcProtocolMfClassic); + + bool parsed = false; + + do { + // Verify card type + if(data->type != MfClassicType1k) break; + + const uint8_t ticket_sector = 8; + + const uint8_t ticket_sector_start_block_number = + mf_classic_get_first_block_num_of_sector(ticket_sector); + + // Validate specific for Umarsh ticket sector header + const uint8_t* block_start_ptr = &data->block[ticket_sector_start_block_number].data[0]; + + const uint32_t header_part_0 = nfc_util_bytes2num(block_start_ptr, 4); + const uint32_t header_part_1 = nfc_util_bytes2num(block_start_ptr + 4, 4); + if((header_part_0 + header_part_1) != 0xFFFFFFFF) break; + + // Data parsing from block 1 + block_start_ptr = &data->block[ticket_sector_start_block_number + 1].data[0]; + const uint16_t expiry_date = nfc_util_bytes2num(block_start_ptr + 1, 2); + const uint8_t region_number = (((block_start_ptr[8] >> 5) & 0x07) << 4) | + (block_start_ptr[12] & 0x0F); + const uint8_t refill_counter = nfc_util_bytes2num(block_start_ptr + 7, 1); + const uint32_t card_number = nfc_util_bytes2num(block_start_ptr + 8, 4) & 0x3FFFFFFF; + + if(card_number == 0) break; + + // Data parsing from block 2 + block_start_ptr = &data->block[ticket_sector_start_block_number + 2].data[0]; + const uint16_t valid_to = nfc_util_bytes2num(block_start_ptr, 2); + const uint32_t terminal_number = nfc_util_bytes2num(block_start_ptr + 3, 3); + const uint16_t last_refill_date = nfc_util_bytes2num(block_start_ptr + 6, 2); + const uint16_t balance_rub = (nfc_util_bytes2num(block_start_ptr + 8, 2)) & 0x7FFF; + const uint8_t balance_kop = nfc_util_bytes2num(block_start_ptr + 10, 1) & 0x7F; + + FuriHalRtcDateTime expiry_datetime; + bool is_expiry_datetime_valid = parse_datetime(expiry_date, &expiry_datetime); + + FuriHalRtcDateTime valid_to_datetime; + bool is_valid_to_datetime_valid = parse_datetime(valid_to, &valid_to_datetime); + + FuriHalRtcDateTime last_refill_datetime; + bool is_last_refill_datetime_valid = + parse_datetime(last_refill_date, &last_refill_datetime); + + furi_string_cat_printf( + parsed_data, + "\e#Umarsh\nCard number: %lu\nRegion: %02u\nTerminal number: %lu\nRefill counter: %u\nBalance: %u.%02u RUR", + card_number, + region_number, + terminal_number, + refill_counter, + balance_rub, + balance_kop); + + if(is_expiry_datetime_valid) + furi_string_cat_printf( + parsed_data, + "\nExpires: %02u.%02u.%u", + expiry_datetime.day, + expiry_datetime.month, + expiry_datetime.year); + if(is_valid_to_datetime_valid) + furi_string_cat_printf( + parsed_data, + "\nValid to: %02u.%02u.%u", + valid_to_datetime.day, + valid_to_datetime.month, + valid_to_datetime.year); + if(is_last_refill_datetime_valid) + furi_string_cat_printf( + parsed_data, + "\nLast refill: %02u.%02u.%u", + last_refill_datetime.day, + last_refill_datetime.month, + last_refill_datetime.year); + + parsed = true; + } while(false); + + return parsed; +} + +/* Actual implementation of app<>plugin interface */ +static const NfcSupportedCardsPlugin umarsh_plugin = { + .protocol = NfcProtocolMfClassic, + .verify = NULL, + .read = NULL, + .parse = umarsh_parse, +}; + +/* Plugin descriptor to comply with basic plugin specification */ +static const FlipperAppPluginDescriptor umarsh_plugin_descriptor = { + .appid = NFC_SUPPORTED_CARD_PLUGIN_APP_ID, + .ep_api_version = NFC_SUPPORTED_CARD_PLUGIN_API_VERSION, + .entry_point = &umarsh_plugin, +}; + +/* Plugin entry point - must return a pointer to const descriptor */ +const FlipperAppPluginDescriptor* umarsh_plugin_ep() { + return &umarsh_plugin_descriptor; +} diff --git a/applications/main/nfc/resources/nfc/assets/mf_classic_dict.nfc b/applications/main/nfc/resources/nfc/assets/mf_classic_dict.nfc index 0925888f2..85f7193cd 100644 --- a/applications/main/nfc/resources/nfc/assets/mf_classic_dict.nfc +++ b/applications/main/nfc/resources/nfc/assets/mf_classic_dict.nfc @@ -1312,3 +1312,7 @@ CE99FBC8BD26 # PIK Comfort Moscow keys (ISBC Mifare Plus SE 1K) 009FB42D98ED 002E626E2820 + +# Volgograd (Russia) Volna transport cards keys +2B787A063D5D +D37C8F1793F7 \ No newline at end of file From 36aecfbec98bdb6c403c6eeb7e6f7eba884bc5d1 Mon Sep 17 00:00:00 2001 From: Leptopt1los <53914086+Leptopt1los@users.noreply.github.com> Date: Sat, 16 Dec 2023 02:05:16 +0900 Subject: [PATCH 12/44] nfc_util: little endian bytes2num functions added (#3287) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * nfc_util_bytes2num_little_endian function added * f18 target api version sync * Bump api version Co-authored-by: hedger Co-authored-by: あく --- lib/nfc/helpers/nfc_util.c | 13 +++++++++++++ lib/nfc/helpers/nfc_util.h | 2 ++ targets/f18/api_symbols.csv | 2 +- targets/f7/api_symbols.csv | 3 ++- 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/nfc/helpers/nfc_util.c b/lib/nfc/helpers/nfc_util.c index 8cb6d57f2..966f39ded 100644 --- a/lib/nfc/helpers/nfc_util.c +++ b/lib/nfc/helpers/nfc_util.c @@ -35,6 +35,19 @@ uint64_t nfc_util_bytes2num(const uint8_t* src, uint8_t len) { return res; } +uint64_t nfc_util_bytes2num_little_endian(const uint8_t* src, uint8_t len) { + furi_assert(src); + furi_assert(len <= 8); + + uint64_t res = 0; + uint8_t shift = 0; + while(len--) { + res |= *src << (8 * shift++); + src++; + } + return res; +} + uint8_t nfc_util_even_parity32(uint32_t data) { // data ^= data >> 16; // data ^= data >> 8; diff --git a/lib/nfc/helpers/nfc_util.h b/lib/nfc/helpers/nfc_util.h index a9d5a3f8a..39eb40171 100644 --- a/lib/nfc/helpers/nfc_util.h +++ b/lib/nfc/helpers/nfc_util.h @@ -10,6 +10,8 @@ void nfc_util_num2bytes(uint64_t src, uint8_t len, uint8_t* dest); uint64_t nfc_util_bytes2num(const uint8_t* src, uint8_t len); +uint64_t nfc_util_bytes2num_little_endian(const uint8_t* src, uint8_t len); + uint8_t nfc_util_even_parity32(uint32_t data); uint8_t nfc_util_odd_parity8(uint8_t data); diff --git a/targets/f18/api_symbols.csv b/targets/f18/api_symbols.csv index d684cc9e9..c166e78ee 100644 --- a/targets/f18/api_symbols.csv +++ b/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,49.2,, +Version,+,49.3,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index 61c1903de..d47908434 100644 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,49.2,, +Version,+,49.3,, Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, @@ -2488,6 +2488,7 @@ Function,+,nfc_set_mask_receive_time_fc,void,"Nfc*, uint32_t" Function,+,nfc_start,void,"Nfc*, NfcEventCallback, void*" Function,+,nfc_stop,void,Nfc* Function,+,nfc_util_bytes2num,uint64_t,"const uint8_t*, uint8_t" +Function,+,nfc_util_bytes2num_little_endian,uint64_t,"const uint8_t*, uint8_t" Function,+,nfc_util_even_parity32,uint8_t,uint32_t Function,+,nfc_util_num2bytes,void,"uint64_t, uint8_t, uint8_t*" Function,+,nfc_util_odd_parity,void,"const uint8_t*, uint8_t*, uint8_t" From 09540929c3d2c4f09af58511241b5ed9f4a2e845 Mon Sep 17 00:00:00 2001 From: gornekich Date: Fri, 15 Dec 2023 21:51:20 +0400 Subject: [PATCH 13/44] [FL-3717] MFC emulation fix (#3291) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * mf classic listener: reset state before sleep and after nack * Fix PVS warnings * Fix PVS and compiler disagree on builtins Co-authored-by: あく --- .../main/nfc/plugins/supported_cards/mykey.c | 6 +++--- lib/nfc/helpers/nfc_util.c | 2 +- lib/nfc/protocols/mf_classic/mf_classic_listener.c | 14 +++++++------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/applications/main/nfc/plugins/supported_cards/mykey.c b/applications/main/nfc/plugins/supported_cards/mykey.c index 69fd18ee3..a0e206f9c 100644 --- a/applications/main/nfc/plugins/supported_cards/mykey.c +++ b/applications/main/nfc/plugins/supported_cards/mykey.c @@ -52,7 +52,7 @@ static bool mykey_parse(const NfcDevice* device, FuriString* parsed_data) { } bool is_blank = mykey_is_blank(data); - furi_string_cat_printf(parsed_data, "Serial#: %08lX\n", __bswap32(data->blocks[7])); + furi_string_cat_printf(parsed_data, "Serial#: %08lX\n", (uint32_t)__bswap32(data->blocks[7])); furi_string_cat_printf(parsed_data, "Blank: %s\n", is_blank ? "yes" : "no"); furi_string_cat_printf(parsed_data, "LockID: %s\n", mykey_has_lockid(data) ? "maybe" : "no"); @@ -66,7 +66,7 @@ static bool mykey_parse(const NfcDevice* device, FuriString* parsed_data) { if(!is_blank) { furi_string_cat_printf( - parsed_data, "\nOp. count: %ld\n", __bswap32(data->blocks[0x12] & 0xFFFFFF00)); + parsed_data, "\nOp. count: %zu\n", (size_t)__bswap32(data->blocks[0x12] & 0xFFFFFF00)); uint32_t block3C = data->blocks[0x3C]; if(block3C == 0xFFFFFFFF) { @@ -75,7 +75,7 @@ static bool mykey_parse(const NfcDevice* device, FuriString* parsed_data) { block3C ^= data->blocks[0x07]; uint32_t startingOffset = ((block3C & 0x30000000) >> 28) | ((block3C & 0x00100000) >> 18); - furi_check(startingOffset < 8); + furi_check(startingOffset < 8); //-V547 for(int txnOffset = 8; txnOffset > 0; txnOffset--) { uint32_t txnBlock = __bswap32(data->blocks[0x34 + ((startingOffset + txnOffset) % 8)]); diff --git a/lib/nfc/helpers/nfc_util.c b/lib/nfc/helpers/nfc_util.c index 966f39ded..b7a9f5ec9 100644 --- a/lib/nfc/helpers/nfc_util.c +++ b/lib/nfc/helpers/nfc_util.c @@ -42,7 +42,7 @@ uint64_t nfc_util_bytes2num_little_endian(const uint8_t* src, uint8_t len) { uint64_t res = 0; uint8_t shift = 0; while(len--) { - res |= *src << (8 * shift++); + res |= ((uint64_t)*src) << (8 * shift++); src++; } return res; diff --git a/lib/nfc/protocols/mf_classic/mf_classic_listener.c b/lib/nfc/protocols/mf_classic/mf_classic_listener.c index 3423e89e4..bd25aba23 100644 --- a/lib/nfc/protocols/mf_classic/mf_classic_listener.c +++ b/lib/nfc/protocols/mf_classic/mf_classic_listener.c @@ -40,10 +40,11 @@ static void mf_classic_listener_reset_state(MfClassicListener* instance) { static MfClassicListenerCommand mf_classic_listener_halt_handler(MfClassicListener* instance, BitBuffer* buff) { + UNUSED(instance); + MfClassicListenerCommand command = MfClassicListenerCommandNack; if(bit_buffer_get_byte(buff, 1) == MF_CLASSIC_CMD_HALT_LSB) { - mf_classic_listener_reset_state(instance); command = MfClassicListenerCommandSleep; } @@ -59,10 +60,7 @@ static MfClassicListenerCommand mf_classic_listener_auth_first_part_handler( do { instance->state = MfClassicListenerStateIdle; - if(block_num >= instance->total_block_num) { - mf_classic_listener_reset_state(instance); - break; - } + if(block_num >= instance->total_block_num) break; uint8_t sector_num = mf_classic_get_sector_by_block(block_num); @@ -135,7 +133,7 @@ static MfClassicListenerCommand instance->cmd_in_progress = false; if(bit_buffer_get_size_bytes(buff) != (sizeof(MfClassicNr) + sizeof(MfClassicAr))) { - mf_classic_listener_reset_state(instance); + command = MfClassicListenerCommandSleep; break; } bit_buffer_write_bytes_mid(buff, instance->auth_context.nr.data, 0, sizeof(MfClassicNr)); @@ -157,7 +155,7 @@ static MfClassicListenerCommand if(secret_poller != prng_successor(nt_num, 64)) { FURI_LOG_T( TAG, "Wrong reader key: %08lX != %08lX", secret_poller, prng_successor(nt_num, 64)); - mf_classic_listener_reset_state(instance); + command = MfClassicListenerCommandSleep; break; } @@ -610,9 +608,11 @@ NfcCommand mf_classic_listener_run(NfcGenericEvent event, void* context) { } mf_classic_listener_send_short_frame(instance, nack); + mf_classic_listener_reset_state(instance); } else if(mfc_command == MfClassicListenerCommandSilent) { command = NfcCommandReset; } else if(mfc_command == MfClassicListenerCommandSleep) { + mf_classic_listener_reset_state(instance); command = NfcCommandSleep; } } else if(iso3_event->type == Iso14443_3aListenerEventTypeHalted) { From d6680d1f75970a81709e1febe1eb46d9a7bd2747 Mon Sep 17 00:00:00 2001 From: gornekich Date: Fri, 15 Dec 2023 22:09:52 +0400 Subject: [PATCH 14/44] [FL-3719] NFC Plugins loading rework (#3295) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * nfc app: rework supported cards * nfc app: supported cards optimization * nfc app: remove old nfc support implementation * nfc app: add documentation for supported cards * nfc app: format sources * nfc app: fix PVS warnings * nfc app: one more PVS fix * nfc app: PVS please stop * nfc app: add missing documentation Co-authored-by: あく --- .../main/nfc/helpers/nfc_supported_cards.c | 242 ++++++++++++++---- .../main/nfc/helpers/nfc_supported_cards.h | 37 ++- .../protocol_support/nfc_protocol_support.c | 10 +- applications/main/nfc/nfc_app.c | 5 +- applications/main/nfc/nfc_app_i.h | 2 + .../nfc/scenes/nfc_scene_supported_card.c | 3 +- 6 files changed, 236 insertions(+), 63 deletions(-) diff --git a/applications/main/nfc/helpers/nfc_supported_cards.c b/applications/main/nfc/helpers/nfc_supported_cards.c index a242ba3ae..6016ae178 100644 --- a/applications/main/nfc/helpers/nfc_supported_cards.c +++ b/applications/main/nfc/helpers/nfc_supported_cards.c @@ -1,4 +1,5 @@ #include "nfc_supported_cards.h" + #include "../plugins/supported_cards/nfc_supported_card_plugin.h" #include @@ -7,22 +8,72 @@ #include #include +#include #define TAG "NfcSupportedCards" #define NFC_SUPPORTED_CARDS_PLUGINS_PATH APP_DATA_PATH("plugins") #define NFC_SUPPORTED_CARDS_PLUGIN_SUFFIX "_parser.fal" +typedef enum { + NfcSupportedCardsPluginFeatureHasVerify = (1U << 0), + NfcSupportedCardsPluginFeatureHasRead = (1U << 1), + NfcSupportedCardsPluginFeatureHasParse = (1U << 2), +} NfcSupportedCardsPluginFeature; + +typedef struct { + FuriString* path; + NfcProtocol protocol; + NfcSupportedCardsPluginFeature feature; +} NfcSupportedCardsPluginCache; + +ARRAY_DEF(NfcSupportedCardsPluginCache, NfcSupportedCardsPluginCache, M_POD_OPLIST); + +typedef enum { + NfcSupportedCardsLoadStateIdle, + NfcSupportedCardsLoadStateInProgress, + NfcSupportedCardsLoadStateSuccess, + NfcSupportedCardsLoadStateFail, +} NfcSupportedCardsLoadState; + typedef struct { Storage* storage; File* directory; FuriString* file_path; char file_name[256]; FlipperApplication* app; -} NfcSupportedCards; +} NfcSupportedCardsLoadContext; -static NfcSupportedCards* nfc_supported_cards_alloc() { +struct NfcSupportedCards { + NfcSupportedCardsPluginCache_t plugins_cache_arr; + NfcSupportedCardsLoadState load_state; + NfcSupportedCardsLoadContext* load_context; +}; + +NfcSupportedCards* nfc_supported_cards_alloc() { NfcSupportedCards* instance = malloc(sizeof(NfcSupportedCards)); + NfcSupportedCardsPluginCache_init(instance->plugins_cache_arr); + + return instance; +} + +void nfc_supported_cards_free(NfcSupportedCards* instance) { + furi_assert(instance); + + NfcSupportedCardsPluginCache_it_t iter; + for(NfcSupportedCardsPluginCache_it(iter, instance->plugins_cache_arr); + !NfcSupportedCardsPluginCache_end_p(iter); + NfcSupportedCardsPluginCache_next(iter)) { + NfcSupportedCardsPluginCache* plugin_cache = NfcSupportedCardsPluginCache_ref(iter); + furi_string_free(plugin_cache->path); + } + + NfcSupportedCardsPluginCache_clear(instance->plugins_cache_arr); + free(instance); +} + +static NfcSupportedCardsLoadContext* nfc_supported_cards_load_context_alloc() { + NfcSupportedCardsLoadContext* instance = malloc(sizeof(NfcSupportedCardsLoadContext)); instance->storage = furi_record_open(RECORD_STORAGE); instance->directory = storage_file_alloc(instance->storage); @@ -35,7 +86,7 @@ static NfcSupportedCards* nfc_supported_cards_alloc() { return instance; } -static void nfc_supported_cards_free(NfcSupportedCards* instance) { +static void nfc_supported_cards_load_context_free(NfcSupportedCardsLoadContext* instance) { if(instance->app) { flipper_application_free(instance->app); } @@ -50,7 +101,36 @@ static void nfc_supported_cards_free(NfcSupportedCards* instance) { } static const NfcSupportedCardsPlugin* - nfc_supported_cards_get_next_plugin(NfcSupportedCards* instance) { + nfc_supported_cards_get_plugin(NfcSupportedCardsLoadContext* instance, FuriString* path) { + furi_assert(instance); + furi_assert(path); + + const NfcSupportedCardsPlugin* plugin = NULL; + do { + if(instance->app) flipper_application_free(instance->app); + instance->app = flipper_application_alloc(instance->storage, firmware_api_interface); + if(flipper_application_preload(instance->app, furi_string_get_cstr(path)) != + FlipperApplicationPreloadStatusSuccess) + break; + if(!flipper_application_is_plugin(instance->app)) break; + if(flipper_application_map_to_memory(instance->app) != FlipperApplicationLoadStatusSuccess) + break; + const FlipperAppPluginDescriptor* descriptor = + flipper_application_plugin_get_descriptor(instance->app); + + if(descriptor == NULL) break; + + if(strcmp(descriptor->appid, NFC_SUPPORTED_CARD_PLUGIN_APP_ID) != 0) break; + if(descriptor->ep_api_version != NFC_SUPPORTED_CARD_PLUGIN_API_VERSION) break; + + plugin = descriptor->entry_point; + } while(false); + + return plugin; +} + +static const NfcSupportedCardsPlugin* + nfc_supported_cards_get_next_plugin(NfcSupportedCardsLoadContext* instance) { const NfcSupportedCardsPlugin* plugin = NULL; do { @@ -65,83 +145,137 @@ static const NfcSupportedCardsPlugin* path_concat(NFC_SUPPORTED_CARDS_PLUGINS_PATH, instance->file_name, instance->file_path); - if(instance->app) flipper_application_free(instance->app); - instance->app = flipper_application_alloc(instance->storage, firmware_api_interface); - - if(flipper_application_preload(instance->app, furi_string_get_cstr(instance->file_path)) != - FlipperApplicationPreloadStatusSuccess) - continue; - if(!flipper_application_is_plugin(instance->app)) continue; - - if(flipper_application_map_to_memory(instance->app) != FlipperApplicationLoadStatusSuccess) - continue; - - const FlipperAppPluginDescriptor* descriptor = - flipper_application_plugin_get_descriptor(instance->app); - - if(descriptor == NULL) continue; - - if(strcmp(descriptor->appid, NFC_SUPPORTED_CARD_PLUGIN_APP_ID) != 0) continue; - if(descriptor->ep_api_version != NFC_SUPPORTED_CARD_PLUGIN_API_VERSION) continue; - - plugin = descriptor->entry_point; + plugin = nfc_supported_cards_get_plugin(instance, instance->file_path); } while(plugin == NULL); //-V654 return plugin; } -bool nfc_supported_cards_read(NfcDevice* device, Nfc* nfc) { +void nfc_supported_cards_load_cache(NfcSupportedCards* instance) { + furi_assert(instance); + + do { + if((instance->load_state == NfcSupportedCardsLoadStateSuccess) || + (instance->load_state == NfcSupportedCardsLoadStateFail)) + break; + + instance->load_context = nfc_supported_cards_load_context_alloc(); + + while(true) { + const NfcSupportedCardsPlugin* plugin = + nfc_supported_cards_get_next_plugin(instance->load_context); + if(plugin == NULL) break; //-V547 + + NfcSupportedCardsPluginCache plugin_cache = {}; //-V779 + plugin_cache.path = furi_string_alloc_set(instance->load_context->file_path); + plugin_cache.protocol = plugin->protocol; + if(plugin->verify) { + plugin_cache.feature |= NfcSupportedCardsPluginFeatureHasVerify; + } + if(plugin->read) { + plugin_cache.feature |= NfcSupportedCardsPluginFeatureHasRead; + } + if(plugin->parse) { + plugin_cache.feature |= NfcSupportedCardsPluginFeatureHasParse; + } + NfcSupportedCardsPluginCache_push_back(instance->plugins_cache_arr, plugin_cache); + } + + nfc_supported_cards_load_context_free(instance->load_context); + + size_t plugins_loaded = NfcSupportedCardsPluginCache_size(instance->plugins_cache_arr); + if(plugins_loaded == 0) { + FURI_LOG_D(TAG, "Plugins not found"); + instance->load_state = NfcSupportedCardsLoadStateFail; + } else { + FURI_LOG_D(TAG, "Loaded %zu plugins", plugins_loaded); + instance->load_state = NfcSupportedCardsLoadStateSuccess; + } + + } while(false); +} + +bool nfc_supported_cards_read(NfcSupportedCards* instance, NfcDevice* device, Nfc* nfc) { + furi_assert(instance); furi_assert(device); furi_assert(nfc); bool card_read = false; - - NfcSupportedCards* supported_cards = nfc_supported_cards_alloc(); + NfcProtocol protocol = nfc_device_get_protocol(device); do { - const NfcSupportedCardsPlugin* plugin = - nfc_supported_cards_get_next_plugin(supported_cards); - if(plugin == NULL) break; //-V547 + if(instance->load_state != NfcSupportedCardsLoadStateSuccess) break; - const NfcProtocol protocol = nfc_device_get_protocol(device); //-V779 - if(plugin->protocol != protocol) continue; + instance->load_context = nfc_supported_cards_load_context_alloc(); - if(plugin->verify) { - if(!plugin->verify(nfc)) continue; + NfcSupportedCardsPluginCache_it_t iter; + for(NfcSupportedCardsPluginCache_it(iter, instance->plugins_cache_arr); + !NfcSupportedCardsPluginCache_end_p(iter); + NfcSupportedCardsPluginCache_next(iter)) { + NfcSupportedCardsPluginCache* plugin_cache = NfcSupportedCardsPluginCache_ref(iter); + if(plugin_cache->protocol != protocol) continue; + if((plugin_cache->feature & NfcSupportedCardsPluginFeatureHasRead) == 0) continue; + + const NfcSupportedCardsPlugin* plugin = + nfc_supported_cards_get_plugin(instance->load_context, plugin_cache->path); + if(plugin == NULL) continue; + + if(plugin->verify) { + if(!plugin->verify(nfc)) continue; + } + + if(plugin->read) { + if(plugin->read(nfc, device)) { + card_read = true; + break; + } + } } - if(plugin->read) { - card_read = plugin->read(nfc, device); - } + nfc_supported_cards_load_context_free(instance->load_context); + } while(false); - } while(!card_read); - - nfc_supported_cards_free(supported_cards); return card_read; } -bool nfc_supported_cards_parse(const NfcDevice* device, FuriString* parsed_data) { +bool nfc_supported_cards_parse( + NfcSupportedCards* instance, + NfcDevice* device, + FuriString* parsed_data) { + furi_assert(instance); furi_assert(device); furi_assert(parsed_data); - bool parsed = false; - - NfcSupportedCards* supported_cards = nfc_supported_cards_alloc(); + bool card_parsed = false; + NfcProtocol protocol = nfc_device_get_protocol(device); do { - const NfcSupportedCardsPlugin* plugin = - nfc_supported_cards_get_next_plugin(supported_cards); - if(plugin == NULL) break; //-V547 + if(instance->load_state != NfcSupportedCardsLoadStateSuccess) break; - const NfcProtocol protocol = nfc_device_get_protocol(device); //-V779 - if(plugin->protocol != protocol) continue; + instance->load_context = nfc_supported_cards_load_context_alloc(); - if(plugin->parse) { - parsed = plugin->parse(device, parsed_data); + NfcSupportedCardsPluginCache_it_t iter; + for(NfcSupportedCardsPluginCache_it(iter, instance->plugins_cache_arr); + !NfcSupportedCardsPluginCache_end_p(iter); + NfcSupportedCardsPluginCache_next(iter)) { + NfcSupportedCardsPluginCache* plugin_cache = NfcSupportedCardsPluginCache_ref(iter); + if(plugin_cache->protocol != protocol) continue; + if((plugin_cache->feature & NfcSupportedCardsPluginFeatureHasParse) == 0) continue; + + const NfcSupportedCardsPlugin* plugin = + nfc_supported_cards_get_plugin(instance->load_context, plugin_cache->path); + if(plugin == NULL) continue; + + if(plugin->parse) { + if(plugin->parse(device, parsed_data)) { + card_parsed = true; + break; + } + } } - } while(!parsed); + nfc_supported_cards_load_context_free(instance->load_context); + } while(false); - nfc_supported_cards_free(supported_cards); - return parsed; + return card_parsed; } diff --git a/applications/main/nfc/helpers/nfc_supported_cards.h b/applications/main/nfc/helpers/nfc_supported_cards.h index 0c25a5b11..7778c6f22 100644 --- a/applications/main/nfc/helpers/nfc_supported_cards.h +++ b/applications/main/nfc/helpers/nfc_supported_cards.h @@ -15,6 +15,34 @@ extern "C" { #endif +/** + * @brief NfcSupportedCards opaque type definition. + */ +typedef struct NfcSupportedCards NfcSupportedCards; + +/** + * @brief Allocate NfcSupportedCards instance. + * + * @return pointer to allocated NfcSupportedCards instance. + */ +NfcSupportedCards* nfc_supported_cards_alloc(); + +/** + * @brief Delete an NfcSupportedCards instance + * + * @param[in] instance pointer to instance to be deleted. + */ +void nfc_supported_cards_free(NfcSupportedCards* instance); + +/** + * @brief Load plugins information to cache. + * + * @note This function must be called before calling read and parse fanctions. + * + * @param[in, out] instance pointer to NfcSupportedCards instance. + */ +void nfc_supported_cards_load_cache(NfcSupportedCards* instance); + /** * @brief Read the card using a custom procedure. * @@ -22,13 +50,14 @@ extern "C" { * try to execute the custom read procedure specified in each. Upon first success, * no further attempts will be made and the function will return. * + * @param[in, out] instance pointer to NfcSupportedCards instance. * @param[in,out] device pointer to a device instance to hold the read data. * @param[in,out] nfc pointer to an Nfc instance. * @returns true if the card was successfully read, false otherwise. * * @see NfcSupportedCardPluginRead for detailed description. */ -bool nfc_supported_cards_read(NfcDevice* device, Nfc* nfc); +bool nfc_supported_cards_read(NfcSupportedCards* instance, NfcDevice* device, Nfc* nfc); /** * @brief Parse raw data into human-readable representation. @@ -37,13 +66,17 @@ bool nfc_supported_cards_read(NfcDevice* device, Nfc* nfc); * try to parse the data according to each implementation. Upon first success, * no further attempts will be made and the function will return. * + * @param[in, out] instance pointer to NfcSupportedCards instance. * @param[in] device pointer to a device instance holding the data is to be parsed. * @param[out] parsed_data pointer to the string to contain the formatted result. * @returns true if the card was successfully parsed, false otherwise. * * @see NfcSupportedCardPluginParse for detailed description. */ -bool nfc_supported_cards_parse(const NfcDevice* device, FuriString* parsed_data); +bool nfc_supported_cards_parse( + NfcSupportedCards* instance, + NfcDevice* device, + FuriString* parsed_data); #ifdef __cplusplus } diff --git a/applications/main/nfc/helpers/protocol_support/nfc_protocol_support.c b/applications/main/nfc/helpers/protocol_support/nfc_protocol_support.c index 87fbe9f08..38ead0ac3 100644 --- a/applications/main/nfc/helpers/protocol_support/nfc_protocol_support.c +++ b/applications/main/nfc/helpers/protocol_support/nfc_protocol_support.c @@ -8,7 +8,6 @@ #include "nfc_protocol_support.h" #include "nfc/nfc_app_i.h" -#include "nfc/helpers/nfc_supported_cards.h" #include "nfc_protocol_support_defs.h" #include "nfc_protocol_support_gui_common.h" @@ -157,9 +156,11 @@ static void nfc_protocol_support_scene_read_on_enter(NfcApp* instance) { instance->protocols_detected[instance->protocols_detected_selected_idx]; instance->poller = nfc_poller_alloc(instance->nfc, protocol); + view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewPopup); + nfc_supported_cards_load_cache(instance->nfc_supported_cards); + // Start poller with the appropriate callback nfc_protocol_support[protocol]->scene_read.on_enter(instance); - view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewPopup); nfc_blink_detect_start(instance); } @@ -178,7 +179,8 @@ static bool nfc_protocol_support_scene_read_on_event(NfcApp* instance, SceneMana } else if(event.event == NfcCustomEventPollerIncomplete) { nfc_poller_stop(instance->poller); nfc_poller_free(instance->poller); - bool card_read = nfc_supported_cards_read(instance->nfc_device, instance->nfc); + bool card_read = nfc_supported_cards_read( + instance->nfc_supported_cards, instance->nfc_device, instance->nfc); if(card_read) { notification_message(instance->notifications, &sequence_success); scene_manager_next_scene(instance->scene_manager, NfcSceneReadSuccess); @@ -303,7 +305,7 @@ static void nfc_protocol_support_scene_read_success_on_enter(NfcApp* instance) { Widget* widget = instance->widget; FuriString* temp_str = furi_string_alloc(); - if(nfc_supported_cards_parse(instance->nfc_device, temp_str)) { + if(nfc_supported_cards_parse(instance->nfc_supported_cards, instance->nfc_device, temp_str)) { widget_add_text_scroll_element( instance->widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str)); } else { diff --git a/applications/main/nfc/nfc_app.c b/applications/main/nfc/nfc_app.c index 5ae0ca5f5..ec528ad9c 100644 --- a/applications/main/nfc/nfc_app.c +++ b/applications/main/nfc/nfc_app.c @@ -51,6 +51,7 @@ NfcApp* nfc_app_alloc() { instance->mf_ul_auth = mf_ultralight_auth_alloc(); instance->mfc_key_cache = mf_classic_key_cache_alloc(); + instance->nfc_supported_cards = nfc_supported_cards_alloc(); // Nfc device instance->nfc_device = nfc_device_alloc(); @@ -110,7 +111,6 @@ NfcApp* nfc_app_alloc() { instance->view_dispatcher, NfcViewWidget, widget_get_view(instance->widget)); // Dict attack - instance->dict_attack = dict_attack_alloc(); view_dispatcher_add_view( instance->view_dispatcher, NfcViewDictAttack, dict_attack_get_view(instance->dict_attack)); @@ -141,6 +141,7 @@ void nfc_app_free(NfcApp* instance) { mf_ultralight_auth_free(instance->mf_ul_auth); mf_classic_key_cache_free(instance->mfc_key_cache); + nfc_supported_cards_free(instance->nfc_supported_cards); // Nfc device nfc_device_free(instance->nfc_device); @@ -339,6 +340,8 @@ bool nfc_load_file(NfcApp* instance, FuriString* path, bool show_dialog) { furi_assert(path); bool result = false; + nfc_supported_cards_load_cache(instance->nfc_supported_cards); + FuriString* load_path = furi_string_alloc(); if(nfc_has_shadow_file_internal(instance, path)) { nfc_set_shadow_file_path(path, load_path); diff --git a/applications/main/nfc/nfc_app_i.h b/applications/main/nfc/nfc_app_i.h index 3c0092007..bde87b12b 100644 --- a/applications/main/nfc/nfc_app_i.h +++ b/applications/main/nfc/nfc_app_i.h @@ -31,6 +31,7 @@ #include "helpers/mf_user_dict.h" #include "helpers/mfkey32_logger.h" #include "helpers/mf_classic_key_cache.h" +#include "helpers/nfc_supported_cards.h" #include #include @@ -132,6 +133,7 @@ struct NfcApp { Mfkey32Logger* mfkey32_logger; MfUserDict* mf_user_dict; MfClassicKeyCache* mfc_key_cache; + NfcSupportedCards* nfc_supported_cards; NfcDevice* nfc_device; Iso14443_3aData* iso14443_3a_edit_data; diff --git a/applications/main/nfc/scenes/nfc_scene_supported_card.c b/applications/main/nfc/scenes/nfc_scene_supported_card.c index cea55b783..e32571bf3 100644 --- a/applications/main/nfc/scenes/nfc_scene_supported_card.c +++ b/applications/main/nfc/scenes/nfc_scene_supported_card.c @@ -1,6 +1,5 @@ #include "nfc/nfc_app_i.h" -#include "nfc/helpers/nfc_supported_cards.h" #include "nfc/helpers/protocol_support/nfc_protocol_support_gui_common.h" void nfc_scene_supported_card_on_enter(void* context) { @@ -8,7 +7,7 @@ void nfc_scene_supported_card_on_enter(void* context) { FuriString* temp_str = furi_string_alloc(); - if(nfc_supported_cards_parse(instance->nfc_device, temp_str)) { + if(nfc_supported_cards_parse(instance->nfc_supported_cards, instance->nfc_device, temp_str)) { widget_add_text_scroll_element( instance->widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str)); widget_add_button_element( From 11ac6240d280816123829c104ada3d7e8d10d8b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20de=20Le=C3=B3n?= Date: Fri, 15 Dec 2023 12:57:08 -0600 Subject: [PATCH 15/44] Add AC's Carrier 42QG5A580SC and AUX YKR-H/006E (#3284) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add Carrier 42QG5A580SC * Add AC Model: AUX YKR-H/006E * Cleanup ac.ir * Infrared: Move Carrier 42QHB12D8S to the back of universal remote * Infreared: more universal ac cleanup Co-authored-by: あく --- .../infrared/resources/infrared/assets/ac.ir | 260 ++++++++++++------ 1 file changed, 177 insertions(+), 83 deletions(-) diff --git a/applications/main/infrared/resources/infrared/assets/ac.ir b/applications/main/infrared/resources/infrared/assets/ac.ir index ac7628e17..201a29305 100644 --- a/applications/main/infrared/resources/infrared/assets/ac.ir +++ b/applications/main/infrared/resources/infrared/assets/ac.ir @@ -2,6 +2,7 @@ Filetype: IR library file Version: 1 # # Model: Electrolux EACM-16 HP/N3 +# name: Off type: raw frequency: 38000 @@ -39,6 +40,7 @@ duty_cycle: 0.33 data: 506 3430 506 478 506 479 505 480 504 481 503 482 502 484 500 1463 505 1465 503 482 502 483 501 484 500 485 509 476 508 477 507 478 506 486 508 477 507 478 506 479 505 480 504 481 503 482 502 483 500 523 502 482 502 483 501 484 500 485 509 476 508 478 506 1455 502 498 507 478 506 479 505 481 503 482 501 483 500 484 500 485 509 500 505 481 502 482 502 1461 507 1455 502 1459 509 476 508 477 507 563 504 1453 504 1454 503 1454 503 1453 504 3426 499 # # Model: Hisense Generic +# name: Off type: raw frequency: 38000 @@ -76,36 +78,37 @@ duty_cycle: 0.330000 data: 8972 4491 592 1651 592 1655 598 532 599 535 597 542 600 541 601 544 598 1656 597 526 595 1652 591 1658 595 539 593 545 597 545 597 546 596 537 594 529 592 535 596 1653 600 534 597 541 601 539 592 552 600 533 598 525 596 530 591 538 593 539 592 1665 598 1662 591 1673 601 533 598 526 595 533 598 532 600 534 597 540 591 548 594 550 592 542 600 523 598 528 593 536 595 537 594 543 599 542 600 543 599 517 594 7937 593 531 601 526 595 535 597 537 594 542 600 541 601 543 599 1654 599 523 598 528 593 536 596 538 594 542 600 541 590 552 600 532 599 524 597 528 593 536 595 537 595 541 601 539 593 551 591 542 600 522 599 527 594 536 595 537 594 543 599 540 591 552 600 532 600 523 598 527 594 535 596 537 595 542 600 540 591 552 600 532 600 523 598 528 593 536 595 538 593 543 599 541 601 543 599 535 596 527 594 532 600 531 601 534 597 540 592 549 593 552 600 534 597 525 596 529 592 1655 598 534 597 1656 597 1661 592 1671 592 1644 599 7934 596 529 592 535 597 535 597 538 593 544 598 543 599 545 597 538 593 1650 593 535 596 534 597 536 595 540 591 547 595 547 595 536 595 526 595 529 592 536 595 535 596 539 593 546 596 547 595 538 593 528 593 531 601 529 592 541 601 536 596 545 597 548 594 540 592 532 600 526 595 535 596 1656 597 541 601 540 592 553 599 534 597 526 595 532 599 531 600 533 598 539 593 548 594 552 600 535 596 1647 596 531 590 538 593 1656 597 538 594 545 597 545 597 518 593 # # Model: Daichi DA25AVQS1-W +# name: Dh type: raw frequency: 38000 duty_cycle: 0.330000 data: 9131 4318 815 389 817 1523 784 391 815 1523 784 1494 813 422 784 391 816 421 785 1524 784 392 814 422 783 1525 782 424 782 422 784 422 784 422 784 396 809 423 783 422 782 423 783 423 783 1496 812 1525 782 424 783 423 783 422 783 423 783 394 811 1526 782 424 782 1524 782 423 783 423 782 1525 782 423 675 19938 810 425 781 424 674 502 811 423 675 531 675 531 675 531 676 530 675 531 675 531 675 502 704 530 675 530 676 530 676 502 704 530 676 530 676 530 675 530 675 530 676 530 675 530 676 530 676 529 677 529 677 529 677 530 677 529 677 1631 676 529 677 1630 678 1631 677 -# +# name: Cool_hi type: raw frequency: 38000 duty_cycle: 0.330000 data: 9076 4455 677 1629 678 528 677 528 677 1630 677 529 677 530 676 530 676 531 675 531 675 531 675 531 675 531 674 531 675 532 674 531 674 532 674 531 675 532 674 531 674 531 674 532 674 1633 674 1633 674 532 674 532 674 532 674 532 674 532 674 1634 673 533 673 1634 673 533 674 532 674 1633 674 533 673 19965 674 531 674 532 675 531 675 531 675 531 675 531 675 531 675 531 675 532 674 531 675 531 676 531 674 531 675 531 675 531 674 531 675 531 675 532 674 532 674 531 675 532 674 532 674 531 675 531 675 532 674 532 674 532 674 532 674 1633 674 1633 674 532 674 532 674 -# +# name: Cool_lo type: raw frequency: 38000 duty_cycle: 0.330000 data: 9076 4453 679 1628 703 503 703 503 702 1607 700 506 699 507 699 507 699 507 699 1609 698 1610 698 1609 699 507 699 508 698 508 698 508 698 508 698 508 698 507 699 508 698 508 698 508 697 1609 698 1610 698 508 698 508 698 508 698 508 698 509 697 1610 697 508 698 1610 698 508 698 508 698 1610 697 509 697 19941 699 507 699 507 699 507 699 508 698 508 698 508 698 508 698 508 697 508 698 508 698 507 699 508 698 508 698 508 698 508 698 508 698 508 698 508 697 509 697 509 697 508 698 508 698 508 698 508 698 509 697 508 697 509 697 509 696 509 697 1635 673 533 673 1611 696 -# +# name: Heat_hi type: raw frequency: 38000 duty_cycle: 0.330000 data: 148 110377 9082 4422 707 499 706 500 704 1603 703 1606 701 505 700 507 699 506 700 507 699 506 700 1607 700 1608 700 1609 699 506 699 507 699 506 699 507 699 507 699 506 700 507 699 507 699 507 699 1608 699 1607 699 507 699 507 699 507 699 507 699 507 699 1609 699 507 699 1608 699 507 699 507 699 1609 699 507 699 19940 700 506 700 506 699 507 699 507 699 506 700 506 700 507 699 507 699 507 700 507 699 506 699 507 699 507 699 507 699 507 699 507 699 507 699 507 699 507 698 507 700 507 699 507 699 507 699 507 699 507 699 508 698 508 698 507 699 507 699 508 698 1610 699 508 698 -# +# name: Heat_lo type: raw frequency: 38000 duty_cycle: 0.330000 data: 9081 4423 707 499 706 500 704 1604 702 1606 701 505 701 506 700 506 700 506 700 1608 700 1607 700 1609 699 506 700 506 700 506 700 506 700 506 700 507 699 506 700 506 700 507 699 507 699 1608 700 1608 699 507 699 507 699 507 699 507 699 507 699 1608 699 507 698 1609 698 507 699 507 699 1609 699 507 699 19938 699 506 700 506 700 507 699 506 699 506 700 506 699 506 700 507 699 507 699 507 700 506 699 507 699 507 699 507 699 507 699 507 698 507 699 507 699 507 699 507 699 507 699 507 699 507 699 507 700 507 699 507 698 507 699 507 699 1609 699 507 698 1609 699 1609 699 -# +# name: Off type: raw frequency: 38000 @@ -113,36 +116,37 @@ duty_cycle: 0.330000 data: 9106 4398 731 499 706 500 705 502 702 504 701 505 701 505 701 1606 701 505 701 1607 701 505 701 506 700 1607 700 506 700 506 700 505 700 505 701 506 700 506 700 506 699 506 700 506 700 1607 700 506 700 506 700 506 700 505 701 506 700 506 700 1608 699 506 700 1608 699 506 700 506 700 1608 700 506 700 19941 701 1606 700 505 701 505 701 506 700 505 700 506 700 506 700 506 700 506 700 506 700 506 700 506 700 506 701 506 700 506 700 506 700 506 700 506 700 506 700 506 700 506 700 506 700 506 700 506 700 506 700 506 699 506 700 506 700 1608 700 1607 700 506 700 506 700 # # Model: Saturn CS-TL09CHR +# name: Dh type: raw frequency: 38000 duty_cycle: 0.330000 data: 3014 1708 488 1059 464 1085 461 362 461 363 460 387 436 1085 462 362 461 402 436 1084 463 1083 463 364 459 1083 463 363 460 386 437 1082 518 1044 464 386 437 1108 439 1108 438 386 464 360 463 1082 464 360 490 352 459 1084 462 362 460 363 460 363 460 364 459 364 459 364 459 380 459 364 459 364 459 364 460 364 459 364 459 364 459 364 459 380 459 364 459 365 458 1088 459 364 459 365 458 1088 458 365 458 380 459 365 458 1088 459 365 458 364 459 365 459 365 458 365 458 380 458 1088 459 1088 459 1088 458 365 458 365 458 365 458 365 458 381 458 365 458 365 458 365 458 365 458 365 459 365 458 365 458 381 458 366 457 366 457 366 457 366 457 366 458 365 458 366 458 381 457 366 457 366 457 366 457 366 457 366 457 366 457 366 458 382 457 366 457 366 457 367 456 367 457 367 456 367 456 390 433 406 433 367 456 367 456 390 433 391 433 390 433 390 433 390 433 406 433 391 432 1114 432 391 432 391 432 391 432 391 432 1114 433 396 433 -# +# name: Cool_hi type: raw frequency: 38000 duty_cycle: 0.330000 data: 3011 1710 462 1084 462 1085 486 356 467 356 444 364 484 1060 462 364 483 357 458 1085 461 1085 461 388 435 1085 461 388 435 388 435 1084 462 1099 463 387 436 1084 462 1085 461 388 461 362 461 1084 462 362 461 378 460 1087 459 365 458 365 458 366 457 366 457 366 457 366 457 382 457 366 457 366 457 366 457 367 456 367 456 367 456 367 456 382 457 367 456 367 456 1090 457 367 456 367 456 1090 457 367 456 382 457 1090 456 1090 457 367 456 367 456 367 456 367 456 367 456 382 457 1091 456 1091 456 1091 456 1090 456 367 456 367 456 367 457 382 457 367 456 367 456 367 456 367 456 368 456 367 456 368 455 383 456 367 456 367 456 368 455 368 455 368 455 368 456 368 455 383 456 368 455 368 455 368 455 368 455 368 455 368 455 368 455 383 456 368 455 368 455 368 455 368 455 368 455 368 455 368 455 384 455 368 455 368 455 368 455 368 455 368 455 368 455 368 455 383 456 1091 456 1091 456 368 456 1091 455 368 455 368 455 1091 456 373 456 -# +# name: Cool_lo type: raw frequency: 38000 duty_cycle: 0.330000 data: 3012 1709 462 1083 463 1084 463 361 462 362 484 355 469 1059 463 387 436 402 437 1083 464 1083 464 362 462 1080 520 354 469 354 469 1026 521 1068 518 354 390 1108 439 1108 438 386 463 360 464 1081 465 359 464 375 463 1083 463 361 462 362 461 363 460 363 460 364 459 364 459 380 459 364 459 364 459 365 458 365 458 365 458 365 458 365 458 380 459 365 458 365 458 1089 458 365 459 365 458 1089 458 366 457 382 456 1090 457 1113 433 390 433 390 433 390 433 390 433 390 433 405 434 390 433 390 433 390 433 1113 434 390 433 390 433 390 433 405 434 390 433 390 433 390 434 390 433 390 433 390 433 390 433 405 434 390 433 390 433 390 433 390 433 390 433 390 433 390 434 405 433 390 433 390 433 390 433 390 433 390 433 390 433 390 433 406 433 390 433 390 433 390 433 390 433 390 433 391 432 391 432 406 433 390 433 391 432 391 432 391 433 390 433 390 433 391 432 406 433 391 432 391 432 1114 433 391 432 391 432 391 432 1114 433 396 433 -# +# name: Heat_hi type: raw frequency: 38000 duty_cycle: 0.330000 data: 3011 1712 461 1087 459 1088 459 364 459 389 434 366 458 1086 461 388 435 404 435 1086 460 1085 461 388 435 1085 461 365 458 388 435 1084 462 1098 464 387 436 1084 462 1084 462 388 461 362 461 1084 462 362 461 378 460 1086 460 364 459 365 458 365 458 365 458 366 457 365 458 381 458 366 457 366 458 366 457 366 457 366 457 366 457 365 458 381 458 366 458 366 457 1089 458 366 457 366 457 1089 458 366 457 381 458 1089 458 366 457 366 457 366 457 366 458 366 457 366 457 381 458 366 457 366 457 366 457 366 457 366 457 366 457 366 457 381 458 366 457 366 457 366 458 366 457 366 457 366 457 366 457 382 457 366 457 366 457 366 457 366 457 366 457 366 457 366 457 382 457 366 457 366 457 367 456 367 456 367 457 366 457 366 457 382 457 367 457 366 457 367 457 366 457 367 457 366 457 366 457 382 457 367 456 367 456 367 456 367 456 367 456 367 456 367 456 382 457 367 456 1090 457 367 456 1091 456 1090 457 1090 456 367 456 373 456 -# +# name: Heat_lo type: raw frequency: 38000 duty_cycle: 0.330000 data: 3045 1677 493 1023 524 1024 522 354 469 354 469 354 469 1026 576 353 470 350 487 1001 492 1054 492 354 469 1054 492 355 468 354 469 1054 492 1070 491 354 468 1056 438 1109 438 386 437 385 438 1107 439 385 438 400 464 1081 465 359 464 360 463 361 462 362 461 388 435 388 435 404 434 389 434 389 434 389 434 389 434 389 434 389 434 389 434 405 434 389 434 389 434 1112 434 389 434 389 434 1113 434 389 434 405 434 1112 435 389 434 366 458 365 458 365 458 365 458 365 458 381 458 365 458 366 457 365 458 1089 457 366 457 366 457 366 457 382 456 367 433 390 433 391 432 391 432 391 432 391 432 391 432 406 433 391 432 391 432 390 433 391 432 391 432 391 432 391 432 406 433 391 432 391 433 391 432 391 432 391 432 391 432 391 432 407 432 391 432 391 432 391 432 392 431 391 433 391 432 391 432 430 409 393 430 392 431 392 431 392 432 391 457 367 432 392 431 408 431 392 431 1138 433 391 408 392 431 392 456 367 456 1113 408 421 433 -# +# name: Off type: raw frequency: 38000 @@ -150,111 +154,115 @@ duty_cycle: 0.330000 data: 3013 1709 463 1085 462 1084 463 387 461 355 469 355 444 1084 463 387 461 378 436 1084 462 1084 487 355 469 1059 463 387 460 355 444 1083 463 1098 464 386 437 1083 463 1083 489 361 463 360 463 1082 464 361 462 376 462 1085 461 363 460 364 459 364 459 365 458 365 459 364 459 380 459 365 458 365 458 365 458 365 458 365 458 365 458 365 459 380 458 365 459 365 458 365 459 365 458 365 458 1089 458 365 458 380 459 1088 459 365 458 365 458 365 458 365 459 365 458 365 458 381 458 365 458 365 458 365 458 1089 458 365 458 365 458 365 458 381 458 365 458 365 458 365 458 365 458 365 458 365 458 365 458 381 457 366 457 366 457 366 457 366 457 366 458 365 458 366 457 381 458 366 458 366 457 366 457 366 457 366 457 366 457 366 457 381 458 366 457 366 457 366 457 366 457 366 457 366 457 366 457 382 457 366 457 366 457 366 457 366 457 366 457 367 457 366 457 382 457 367 456 1090 457 1090 456 1090 457 1090 457 1090 456 367 457 372 457 # # Model: Olimpia Splendid OS-SEAMH09EI +# name: Dh type: raw frequency: 38000 duty_cycle: 0.330000 data: 4402 4336 561 1641 538 554 535 1616 563 1640 539 554 535 557 532 1645 534 560 539 551 538 1639 540 553 536 556 533 1644 535 1642 537 556 533 1620 558 558 531 561 538 554 535 1641 538 1639 540 1638 530 1620 559 1647 532 1643 536 1641 538 1613 566 553 536 557 532 560 539 553 536 558 531 560 529 1647 532 535 564 1613 555 537 563 1614 565 554 535 559 530 1645 534 559 530 1647 532 560 539 1612 557 562 537 1640 539 1611 557 5189 4398 4344 564 1638 530 563 537 1640 539 1639 529 563 537 530 559 1644 535 560 529 535 564 1639 529 537 563 556 533 1644 535 1643 536 557 532 1647 532 559 530 536 564 555 534 1643 536 1616 563 1640 539 1613 555 1624 565 1610 558 1619 560 1617 562 557 532 560 539 554 535 557 532 562 537 553 536 1641 538 555 534 1643 536 530 559 1644 535 558 531 564 536 1639 539 553 536 1641 537 555 534 1617 562 557 532 1645 534 1645 534 -# +# name: Cool_hi type: raw frequency: 38000 duty_cycle: 0.330000 data: 4404 4345 563 1613 566 553 536 1641 538 1614 565 528 561 557 532 1645 534 560 539 551 538 1639 529 563 536 556 533 1618 561 1642 537 556 533 1645 534 557 532 561 538 1638 530 1646 533 1645 554 1623 556 1621 558 1596 562 1613 586 1591 588 531 537 555 534 559 530 562 537 555 534 561 538 552 537 555 534 559 530 562 537 555 534 559 530 562 537 557 532 1643 536 1615 564 1639 560 1591 588 1616 563 1588 580 1623 556 1621 537 5183 4404 4339 579 1597 581 538 530 1646 533 1619 580 539 529 563 536 1615 564 557 532 532 557 1646 533 560 539 553 536 1641 538 1639 539 554 535 1643 536 555 534 559 530 1647 532 1646 533 1644 535 1617 582 1620 559 1621 537 1612 587 1590 589 530 538 554 535 558 531 561 538 554 535 560 539 551 538 554 535 558 531 561 538 554 535 557 532 561 538 556 533 1642 537 1640 538 1613 565 1638 561 1590 589 1588 580 1623 556 1598 560 -# +# name: Cool_lo type: raw frequency: 38000 duty_cycle: 0.330000 data: 4400 4357 561 1616 563 530 559 1619 559 1644 535 557 532 535 564 1613 555 565 534 556 533 1645 534 533 556 536 563 1614 565 1639 529 537 563 1643 536 529 560 558 531 1647 532 1645 533 1618 561 1643 536 1642 537 1642 537 1613 565 1638 530 537 563 556 533 559 530 563 536 556 533 562 538 527 562 1615 563 555 534 1643 536 531 558 561 538 554 535 560 539 1610 558 560 539 1612 556 563 537 1640 538 1639 539 1612 556 1620 558 5189 4398 4345 562 1614 564 529 560 1643 536 1616 563 531 558 534 565 1639 529 565 534 556 533 1619 559 559 530 563 537 1641 538 1640 538 554 535 1645 534 531 558 560 539 1639 529 1622 556 1621 558 1646 532 1619 559 1646 533 1617 562 1642 537 557 532 560 539 554 535 557 532 561 538 556 533 558 531 1620 559 560 539 1638 530 563 536 556 533 560 539 555 534 1642 537 556 533 1619 559 559 530 1622 557 1621 558 1620 558 1647 532 -# +# name: Heat_hi type: raw frequency: 38000 duty_cycle: 0.330000 data: 4402 4346 561 1615 564 555 534 1644 535 1643 536 531 558 561 538 1639 539 555 534 531 558 1645 533 560 529 563 536 1641 537 1640 538 528 561 1645 533 531 558 561 538 1639 539 1638 530 1622 557 1647 532 1646 564 1590 557 1619 559 1618 561 558 531 562 537 555 534 559 530 563 536 558 531 1645 533 559 530 1648 530 1647 531 1646 532 1646 532 560 539 556 533 558 531 1621 557 561 538 555 534 558 531 562 537 1641 537 1639 539 5183 4405 4339 558 1645 533 559 530 1648 530 1647 532 561 538 555 534 1644 535 560 539 551 538 1614 564 555 534 559 530 1647 532 1620 558 561 538 1615 563 553 536 531 558 1620 558 1644 534 1643 536 1642 537 1641 537 1642 536 1613 565 1638 530 563 536 557 532 534 565 554 535 557 532 563 536 1613 565 554 535 1642 537 1641 537 1640 538 1640 538 554 535 560 539 551 538 1614 564 528 561 558 531 562 537 555 534 1644 534 1645 533 -# +# name: Heat_lo type: raw frequency: 38000 duty_cycle: 0.330000 data: 4404 4354 564 1614 564 528 561 1617 562 1642 537 530 559 534 565 1613 555 539 560 556 533 1619 559 534 555 563 536 1642 537 1641 537 555 534 1646 533 532 557 562 537 1640 538 1613 565 1613 555 1648 531 1647 532 1622 557 1619 559 1618 560 559 530 563 536 556 533 560 539 554 535 559 530 561 538 1639 539 554 535 1616 563 1615 564 1615 563 555 534 561 538 1612 556 563 536 1641 538 529 560 533 556 563 537 1641 538 1614 564 5183 4404 4342 555 1622 557 562 537 1641 537 1640 538 529 560 533 556 1648 531 538 562 555 534 1618 560 559 530 562 537 1615 563 1640 538 529 560 1646 532 532 557 562 537 1640 538 1639 539 1639 539 1638 530 1648 530 1649 540 1611 557 1646 532 561 538 554 535 558 531 562 537 555 534 561 538 552 537 1641 537 555 534 1644 534 1643 536 1617 562 557 532 563 536 1639 539 553 536 1642 537 556 533 560 539 554 535 1642 537 1643 535 -# +# name: Off type: raw frequency: 38000 duty_cycle: 0.330000 data: 4403 4333 563 1615 563 528 561 1618 560 1618 560 531 558 561 538 1614 564 556 533 558 541 1611 557 562 537 555 534 1619 559 1618 560 558 541 1613 565 551 538 1614 564 1614 564 1614 564 1613 565 528 561 1617 561 1619 559 1617 561 557 532 535 564 528 561 533 566 1611 557 562 537 558 531 1619 559 1619 559 1619 559 559 540 553 536 557 532 561 538 557 532 559 540 553 536 557 532 1620 558 1620 558 1620 558 1620 558 1618 560 5188 4398 4346 561 1618 560 558 531 1621 557 1621 557 561 538 555 534 1619 559 561 538 553 536 1616 562 556 533 560 539 1614 564 1613 565 554 535 1619 559 557 532 1621 557 1620 558 1620 558 1620 558 560 539 1613 565 1615 563 1613 565 553 536 557 532 535 564 554 535 1618 560 558 531 564 535 1615 563 1615 563 1614 564 555 534 559 540 552 537 530 559 536 563 528 561 532 557 562 537 1615 563 1615 563 1614 564 1614 564 1616 562 # -# Model: Sharp AH-X9VEW. Doesn't have heat function. +# Model: Sharp AH-X9VEW. Doesn't have heat function +# name: Dh type: raw frequency: 38000 duty_cycle: 0.330000 data: 307 125509 3831 1867 489 482 491 1392 461 468 485 1397 456 489 464 1411 463 466 487 1397 456 488 465 1390 463 482 481 1402 462 1402 483 471 461 1412 462 468 485 1400 464 1401 484 1397 488 1395 458 471 461 485 457 1408 487 1393 460 485 457 473 459 486 456 474 489 1394 459 471 461 485 457 473 459 488 465 466 455 490 463 467 465 480 462 468 464 482 460 470 483 1399 465 464 457 488 465 465 488 1393 460 484 458 471 461 485 457 1415 459 1405 511 408 482 489 464 466 487 1377 456 489 464 481 461 469 463 482 460 470 462 483 459 470 462 484 458 472 460 485 457 473 459 487 455 474 489 1395 458 471 461 485 457 472 460 486 456 473 459 486 456 474 458 487 455 474 458 488 465 466 487 1396 457 487 434 496 457 488 433 496 457 489 432 497 466 479 432 498 465 480 431 499 464 482 439 490 463 482 460 1394 491 1389 485 1395 490 1392 461 468 464 482 460 469 484 1399 465 1399 465 480 462 483 491 77962 300 -# +# name: Cool_hi type: raw frequency: 38000 duty_cycle: 0.330000 data: 345 2685 478 1170 176 29680 3832 1891 465 481 482 1400 464 465 488 1395 458 470 483 1396 457 487 466 1406 458 471 492 1389 464 481 461 1411 463 1408 456 489 464 1407 457 473 490 1392 482 1383 481 1399 486 1396 458 462 459 497 456 1409 486 1394 459 459 483 473 459 487 455 474 489 1392 461 468 464 481 461 469 463 483 459 471 482 1398 487 1379 464 481 461 485 457 1416 458 487 466 1407 457 472 460 460 482 474 489 1393 460 469 463 483 459 471 461 485 457 1408 456 488 465 481 461 469 484 1381 462 483 459 486 456 473 459 487 455 474 458 487 455 475 457 489 464 467 465 481 461 1410 485 1380 484 1397 488 1392 461 483 459 471 461 485 457 473 459 486 456 474 458 488 454 476 456 490 463 467 465 481 461 1411 464 481 440 491 462 484 437 492 461 485 436 494 459 487 434 495 458 488 433 497 456 489 432 498 486 450 482 1408 467 1389 485 1394 480 1384 459 486 456 489 464 466 487 1393 460 485 457 1415 459 1406 510 -# +# name: Cool_lo type: raw frequency: 38000 duty_cycle: 0.330000 data: 181 11813 3819 1899 457 488 486 1421 433 472 491 1416 438 481 461 1417 437 482 492 1416 437 467 486 1419 435 485 457 1439 435 1403 461 483 480 1408 435 484 490 1416 438 1401 484 1395 490 1392 461 467 465 480 462 1427 458 1396 457 486 456 473 459 486 456 472 481 1426 438 466 466 480 462 467 465 480 462 467 465 479 463 1426 438 481 461 484 458 1438 436 1409 486 1378 465 480 462 483 459 471 482 1425 428 475 457 487 455 474 458 487 455 1434 430 489 464 481 461 468 485 1404 439 480 462 483 459 470 462 483 459 469 463 482 460 470 462 483 459 470 462 483 459 1437 458 1381 483 1395 490 1390 463 481 461 469 463 482 460 468 464 481 461 468 464 481 461 469 463 482 460 469 463 481 461 1434 430 474 458 486 456 473 459 486 456 473 459 486 456 473 459 486 456 473 459 485 457 472 460 485 489 449 462 1434 461 1378 486 1393 481 1397 519 400 479 476 456 489 464 1431 433 486 435 495 458 487 487 -# +# name: Off type: raw frequency: 38000 duty_cycle: 0.330000 data: 3826 1866 490 481 482 1382 461 484 490 1392 461 467 486 1396 457 471 482 1400 464 479 463 1390 463 481 482 1399 465 1398 518 401 510 1379 464 480 483 1398 456 1408 487 1392 482 1399 517 386 483 487 466 1399 486 1392 461 483 459 470 462 482 460 469 484 1397 456 473 459 459 483 472 460 484 458 471 461 483 459 1411 463 480 462 467 486 1377 487 1392 482 1396 457 486 456 472 460 486 456 473 480 1400 464 465 456 488 454 475 488 1393 460 468 464 480 462 467 486 1395 458 470 462 483 459 485 436 493 460 469 463 481 461 486 435 500 463 463 458 486 456 1397 488 1390 484 1394 480 1400 464 465 456 488 465 464 457 487 455 474 458 487 455 473 459 485 457 472 460 485 457 472 481 1399 517 401 458 497 456 473 459 485 457 487 434 495 458 471 461 484 458 488 433 502 430 507 435 500 432 498 455 1409 486 1392 482 1399 454 1409 455 488 465 480 462 467 465 480 462 1408 456 473 459 486 488 # -# Model: Electrolux ESV09CRO-B21. Doesn't have heat function. +# Model: Electrolux ESV09CRO-B21. Doesn't have heat function +# name: Dh type: raw frequency: 38000 duty_cycle: 0.330000 data: 3092 3057 3092 4438 579 1675 545 534 576 1650 571 535 575 531 569 1656 575 1652 579 527 573 533 577 1648 572 1655 576 1651 580 526 573 532 578 1647 573 532 578 1647 573 1654 577 529 571 535 575 530 570 535 575 529 571 534 576 529 571 534 576 528 571 534 576 528 572 533 577 528 572 533 577 527 573 1651 580 526 573 532 578 527 572 532 568 537 573 531 568 536 574 1650 571 535 575 531 569 536 574 530 569 535 575 529 571 534 576 529 571 533 577 528 572 533 577 527 572 532 568 536 574 531 569 1655 576 530 570 535 575 530 570 535 575 529 571 534 576 528 572 533 577 527 573 532 578 527 572 531 569 536 574 531 569 535 575 530 570 534 576 529 571 534 576 528 571 533 577 527 573 532 567 537 573 531 569 536 574 530 570 535 575 529 571 534 576 528 571 533 577 527 572 532 578 526 573 531 569 536 574 530 570 535 575 529 571 534 576 528 572 533 577 1646 574 532 578 1646 574 1652 579 527 572 533 577 1647 573 1653 578 1675 545 534 576 1649 571 -# +# name: Cool_hi type: raw frequency: 38000 duty_cycle: 0.330000 data: 315 101050 3094 3056 3093 4437 580 1648 572 534 576 1649 582 525 574 530 580 1646 574 1653 578 529 570 534 576 529 571 534 576 529 570 1655 576 1651 580 527 572 532 578 1647 573 1654 577 1651 580 526 573 531 579 526 573 531 579 526 573 531 579 526 573 531 579 526 573 531 579 525 574 531 579 525 574 531 579 1646 574 532 578 526 573 531 579 526 573 531 579 526 573 1652 579 527 572 1653 578 528 571 534 576 528 571 533 577 528 571 533 577 528 572 533 577 528 572 532 578 527 572 532 578 527 572 532 578 526 573 1652 579 527 572 532 578 527 572 532 578 527 572 532 578 526 573 531 579 526 573 531 579 526 573 531 579 525 574 530 580 525 574 530 580 525 574 530 580 524 575 529 581 524 575 529 571 534 576 528 571 533 577 528 571 533 577 528 571 533 577 527 572 532 578 527 572 532 578 526 573 531 579 526 573 531 579 525 574 531 579 525 574 530 580 525 574 1650 581 525 574 1651 580 1647 573 533 577 527 572 1653 578 528 572 1654 577 1650 581 1646 574 71637 254 -# +# name: Cool_lo type: raw frequency: 38000 duty_cycle: 0.330000 data: 284 19161 3098 3053 3096 4435 572 1656 575 532 578 1648 572 534 576 530 570 1682 549 1652 579 527 572 534 576 1649 571 1656 575 1652 579 1649 571 1656 575 531 579 527 572 1653 578 1649 571 1656 575 531 579 527 572 532 578 527 572 533 577 527 572 533 577 527 573 532 578 527 572 532 578 527 573 532 578 527 572 1652 579 527 572 533 577 528 571 533 577 528 571 533 577 1648 572 533 577 1649 571 535 575 530 569 536 574 531 569 536 574 530 569 536 574 530 570 535 575 530 570 535 575 530 569 535 575 530 569 535 575 1649 571 535 575 531 568 536 574 531 568 536 574 531 568 536 574 531 569 536 574 530 569 536 574 530 569 535 575 530 569 535 575 530 569 535 575 530 570 535 575 529 570 534 576 529 570 534 576 529 570 534 576 528 571 534 576 528 571 534 576 528 571 534 576 528 571 534 576 528 571 533 577 528 571 533 577 528 572 533 577 528 571 533 577 528 572 1652 579 527 572 1653 578 529 570 534 576 529 570 535 575 529 570 1654 577 1677 554 1673 547 -# +# name: Off type: raw frequency: 38000 duty_cycle: 0.330000 data: 3093 3058 3090 4441 576 1652 579 528 571 1654 577 531 579 526 573 1652 579 1649 582 525 574 1652 579 528 571 1654 577 1651 580 527 572 533 577 528 571 533 577 1649 582 1646 574 1653 578 529 581 525 574 530 580 525 574 530 580 525 574 531 579 526 573 531 579 526 573 531 579 526 573 531 579 526 573 531 579 526 573 531 579 526 573 531 579 526 573 532 578 1647 573 533 577 1648 572 535 575 530 569 535 575 530 580 525 574 531 579 525 574 531 579 526 573 531 579 526 573 531 579 526 573 531 579 526 573 1651 580 527 572 533 577 528 571 533 577 528 571 533 577 528 571 533 577 528 571 534 576 528 571 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 529 570 534 576 1649 582 525 574 1650 581 1647 573 1654 577 1651 580 1647 573 1654 577 531 579 1646 574 1653 578 # -# Model: Daikin FTE35KV1. Doesn't have heat function. +# Model: Daikin FTE35KV1. Doesn't have heat function +# name: Dh type: raw frequency: 38000 duty_cycle: 0.330000 data: 5045 2158 335 1768 358 690 357 723 335 716 331 1771 355 694 364 686 361 720 327 723 335 1767 359 690 357 1775 362 1770 356 692 366 1767 359 1772 354 1777 360 1771 355 1776 361 687 360 690 357 1776 361 687 360 690 357 693 365 716 331 719 328 692 366 1767 359 1772 354 1777 360 1771 355 1776 361 687 360 1773 364 1767 360 689 358 692 366 685 362 688 359 721 326 724 334 717 330 720 327 723 335 715 332 718 329 721 326 1777 360 1771 355 1776 361 1770 356 692 366 715 332 718 329 721 326 29460 5042 2161 332 1770 356 692 366 685 362 688 359 1774 363 685 362 688 359 721 326 694 364 1769 357 691 367 1767 360 1771 355 693 365 1769 358 1773 364 1768 359 1772 365 1766 361 688 359 691 367 1767 360 689 358 692 366 684 363 717 330 720 327 693 365 686 361 689 358 722 336 684 363 1770 357 1774 363 686 361 689 358 1774 363 686 361 1771 356 1776 361 1770 357 692 366 685 362 688 359 690 357 1776 361 687 360 690 357 1776 361 688 359 691 356 694 364 716 331 689 358 1775 362 686 361 689 358 692 366 685 362 688 359 691 356 724 334 716 331 689 358 722 336 685 362 688 359 721 326 693 365 716 331 689 358 692 366 684 363 718 329 690 357 693 365 716 331 689 358 722 336 1767 360 689 358 1774 363 686 361 1771 356 693 365 686 361 689 358 722 336 684 363 717 330 720 327 1776 361 687 360 690 357 693 365 716 331 1771 355 693 365 686 361 1772 355 1776 361 688 359 1773 364 1768 359 -# +# name: Cool_hi type: raw frequency: 38000 duty_cycle: 0.330000 data: 5038 2165 328 1772 365 686 361 689 358 692 366 1765 362 719 328 692 366 684 363 717 330 1771 366 684 363 1768 359 1774 363 686 361 1771 355 1776 361 1770 357 1775 362 1769 358 691 356 694 364 1767 360 691 356 694 364 686 361 689 358 692 366 685 362 1769 358 1775 362 1769 358 1774 363 1768 359 690 357 1776 361 1770 357 692 366 684 363 687 360 690 357 693 365 686 361 689 358 692 366 684 363 687 360 690 357 693 365 1766 361 1773 364 1767 360 1772 355 694 364 686 361 689 358 692 366 25151 319 3980 5041 2131 362 1769 358 693 365 686 361 689 358 1772 365 686 361 689 358 692 366 684 363 1768 359 692 366 1765 361 1772 354 694 364 1769 358 1774 363 1768 359 1773 364 1767 359 719 328 692 366 1796 331 719 328 692 366 685 362 688 359 691 356 694 364 686 361 689 358 692 366 685 362 1768 359 1775 362 686 361 689 358 1773 364 686 361 1770 357 1777 360 1771 355 693 365 686 361 689 358 1772 365 1769 358 690 357 694 364 1767 360 691 356 694 364 686 361 689 358 723 335 1766 361 690 357 693 365 685 362 688 359 691 356 694 364 687 360 690 357 693 365 685 362 688 359 691 356 694 364 687 360 690 357 693 365 685 362 688 359 691 367 684 363 687 360 1771 366 684 363 687 360 690 357 693 365 1767 360 690 357 1804 333 687 360 690 357 693 365 686 361 689 358 692 366 685 362 1768 359 692 366 685 362 688 359 690 357 1774 363 688 359 691 356 1774 363 1770 356 1775 362 1769 358 691 356 -# +# name: Cool_lo type: raw frequency: 38000 duty_cycle: 0.330000 data: 301 132136 5036 2167 337 1766 361 689 358 692 366 684 363 1770 357 692 366 684 363 718 329 690 357 1776 361 687 360 1773 364 1767 360 689 358 1775 362 1769 357 1774 363 1768 359 1773 364 684 363 718 329 1773 364 684 363 718 329 691 356 694 364 716 331 719 328 1775 362 1769 358 1774 363 1768 359 1772 365 714 333 1770 357 1774 363 716 331 719 328 722 336 715 332 718 329 721 326 724 334 716 331 719 328 722 336 715 332 718 329 1773 364 1767 360 1772 354 1777 360 719 328 721 326 725 333 717 330 29455 5036 2139 354 1777 360 688 359 691 367 714 333 1770 356 692 366 684 363 687 360 690 357 1776 361 688 359 1773 364 1768 359 689 358 1775 362 1769 357 1774 363 1768 359 1773 364 684 363 687 360 1773 364 685 362 688 359 691 356 694 364 686 361 689 358 692 366 685 362 688 359 691 356 1777 360 1771 355 693 365 685 362 1771 355 693 365 1768 359 1773 364 1767 360 689 358 692 366 685 362 1771 355 1775 362 687 360 690 357 1775 362 687 360 690 357 693 365 716 331 689 358 1774 363 686 361 689 358 692 366 685 362 688 359 691 356 694 364 686 361 689 358 692 366 685 362 688 359 691 356 694 364 686 361 689 358 692 366 685 362 1771 355 693 365 1768 358 1773 364 684 363 687 360 690 357 693 365 1768 359 690 357 1776 361 688 359 691 356 694 364 686 361 689 358 692 366 685 362 1770 356 693 365 685 362 688 359 691 356 1777 360 1771 355 693 365 686 361 689 358 692 366 685 362 1770 356 -# +# name: Off type: raw frequency: 38000 @@ -262,110 +270,113 @@ duty_cycle: 0.330000 data: 5043 2132 361 1770 356 723 335 715 332 718 329 1774 363 715 332 719 328 722 336 714 333 1770 356 722 336 1767 360 1772 354 724 334 1769 357 1774 363 1768 358 1773 364 1767 359 720 327 723 335 1768 359 720 327 723 335 716 331 719 328 722 336 714 333 1770 356 1774 363 1769 357 1773 364 1767 360 720 327 1775 362 1769 357 721 326 725 333 717 330 720 327 723 335 716 331 719 328 722 336 714 333 717 330 720 327 723 335 1768 359 1773 364 1767 360 1772 354 724 334 717 330 720 327 723 335 29451 5041 2134 359 1772 354 724 334 717 330 720 327 1775 362 717 330 720 327 723 335 715 332 1771 355 723 335 1768 358 1773 364 715 332 1770 357 1775 362 1769 357 1774 363 1768 359 720 327 723 335 1768 359 720 327 724 334 716 331 719 328 722 336 715 332 718 329 720 327 723 335 716 331 1771 355 1776 361 718 329 721 326 1776 361 718 329 1773 364 1767 360 720 327 723 335 715 332 718 329 1774 363 1768 359 720 327 723 335 1768 358 721 326 724 334 716 331 719 328 722 336 1767 360 719 328 722 336 715 332 718 329 721 326 724 334 717 330 720 327 723 335 715 332 719 328 722 325 725 333 717 330 720 327 723 335 716 331 719 328 1774 363 716 331 1771 355 1776 361 718 329 721 326 724 334 717 330 1772 365 714 333 1770 356 722 336 715 332 718 329 721 326 724 334 717 330 719 328 1775 362 717 330 720 327 723 335 715 332 718 329 1774 363 715 332 718 329 721 326 725 333 717 330 1772 365 # # Model: Dyson Purifier Hot+Cool +# name: Off type: raw frequency: 38000 duty_cycle: 0.330000 data: 2309 665 781 672 803 672 803 695 832 643 833 1355 804 694 836 640 781 695 804 1409 778 697 777 702 797 678 798 677 799 678 799 701 803 674 802 1412 801 674 801 674 801 674 802 674 801 51317 2284 670 775 1413 802 51252 2283 670 801 1412 775 51275 2258 673 798 1414 802 51248 2284 670 802 1412 774 51246 2259 695 775 1413 801 -# +# name: Heat_hi type: raw frequency: 38000 duty_cycle: 0.330000 data: 2316 610 806 671 781 695 806 695 781 695 782 1405 782 694 808 694 780 693 808 1381 779 697 802 1412 776 1438 800 1437 776 1438 775 700 775 1412 776 700 801 701 775 700 776 1438 776 700 776 51695 2258 695 776 1437 776 51248 2258 672 798 1439 776 51240 2258 670 801 1436 776 -# +# name: Heat_lo type: raw frequency: 38000 duty_cycle: 0.330000 data: 2342 612 781 695 805 668 810 666 810 665 811 1402 811 666 811 692 781 670 781 1432 781 696 778 1436 802 1412 802 1412 802 1413 801 1412 802 1412 801 1412 777 1411 776 1463 776 1412 800 1414 801 51041 2257 697 802 1411 777 51240 2283 671 776 1437 801 51209 2255 672 799 1412 801 -# +# name: Cool_hi type: raw frequency: 38000 duty_cycle: 0.330000 data: 2317 637 832 644 830 669 805 670 805 672 803 1411 803 673 802 674 802 673 803 1411 803 674 801 1411 802 675 775 1415 800 701 774 1440 801 1412 775 702 799 1414 774 1413 801 701 801 675 800 51681 2257 695 803 1411 801 51226 2283 671 799 1412 803 51246 2257 696 803 1411 775 51255 2282 668 803 1410 802 51243 2258 695 802 1387 798 -# +# name: Cool_lo type: raw frequency: 38000 duty_cycle: 0.330000 data: 2315 618 853 643 832 644 834 641 833 643 833 1356 805 695 835 640 808 667 809 1404 808 668 806 1409 803 674 801 1412 802 1388 799 677 799 701 775 701 801 1389 799 677 799 676 800 1439 802 51426 2283 671 800 1412 802 51251 2258 697 801 1387 800 51248 2283 669 802 1411 802 51230 2258 696 799 1387 801 51225 2283 670 801 1411 801 51200 2280 695 775 1411 802 51227 2258 696 802 1411 775 51204 2281 669 801 1411 800 -# +# name: Dh type: raw frequency: 38000 duty_cycle: 0.330000 data: 2320 634 837 637 838 637 838 640 835 642 832 1378 836 645 826 670 809 667 808 1406 806 672 803 674 802 1412 802 1412 800 676 801 675 802 1412 802 674 802 1413 801 1412 801 1413 802 1412 802 50937 2285 671 801 1411 802 51225 2280 696 775 1412 801 51212 2283 671 775 1412 802 -# -# Model: Daikin FTXM20M. +# +# Model: Daikin FTXM20M +# name: Off type: raw frequency: 38000 duty_cycle: 0.330000 data: 500 393 473 392 473 368 498 368 497 367 499 25050 3533 1662 502 1230 501 392 472 393 471 395 469 1263 467 400 465 401 465 401 465 401 465 1267 465 401 465 1268 464 1268 464 402 464 1268 464 1269 463 1269 463 1292 440 1269 463 404 462 426 439 1293 439 426 440 426 440 426 440 426 440 426 440 427 439 426 440 427 439 427 438 427 439 1294 438 427 439 1294 438 427 439 427 439 428 438 1294 438 1294 438 428 438 428 437 428 438 428 438 1294 438 428 438 428 438 429 437 429 437 429 436 429 437 429 437 429 437 429 436 429 437 430 436 1296 436 1296 436 1296 436 430 436 430 435 1297 435 1297 435 1298 434 35482 3500 1699 464 1268 464 402 463 402 463 403 463 1269 463 426 440 426 439 426 440 426 439 1293 439 426 440 1293 439 1293 439 427 439 1293 439 1293 439 1293 439 1293 439 1294 438 427 438 427 439 1294 438 427 439 428 438 428 438 428 438 427 438 428 438 428 437 428 438 428 437 428 438 428 438 1295 437 429 437 429 437 429 436 429 437 1296 436 429 437 429 436 429 437 430 436 430 436 430 435 430 436 430 435 431 435 431 435 431 435 455 410 456 409 1322 410 456 409 456 410 456 410 456 410 456 410 1323 409 457 409 457 409 1323 409 1323 409 457 409 35483 3500 1699 464 1268 464 402 464 402 463 403 463 1269 463 426 440 426 440 426 440 426 439 1293 439 426 439 1293 439 1293 439 427 439 1293 439 1293 439 1293 439 1294 438 1293 438 427 439 427 438 1294 438 428 438 427 438 428 438 428 438 428 438 428 437 428 438 428 438 428 438 428 438 428 438 428 438 429 437 429 437 429 437 429 437 429 437 429 437 429 437 429 437 430 436 1296 436 430 436 1297 435 430 436 430 436 431 435 431 435 456 410 456 410 456 410 456 409 1323 409 1322 410 456 410 456 409 457 409 457 409 457 409 457 409 457 408 457 409 1324 408 1324 408 1324 408 1324 408 458 408 1325 406 459 407 1351 356 1376 356 1376 356 1376 356 1377 355 510 355 510 356 511 355 511 354 511 355 537 328 537 329 538 328 538 327 538 328 539 327 565 300 566 300 1432 300 1433 298 593 272 594 271 621 245 621 244 622 243 -# +# name: Dh type: raw frequency: 38000 duty_cycle: 0.330000 data: 500 368 498 369 497 367 499 366 499 367 499 25050 3533 1662 502 1230 501 392 472 393 471 395 469 1264 467 400 465 401 465 401 465 401 465 1267 465 401 465 1268 464 1268 464 402 464 1269 463 1269 463 1269 463 1292 440 1292 440 426 440 426 440 1293 439 426 440 426 439 426 440 426 440 427 439 427 438 427 439 427 439 427 439 427 439 1293 439 427 439 1294 438 427 439 427 439 428 437 1294 438 1294 438 428 437 428 438 428 437 429 437 1295 437 428 437 429 437 429 437 429 436 429 437 429 437 429 437 429 437 429 437 429 437 430 436 1296 436 1297 435 1297 435 431 435 455 410 1298 434 1322 410 1322 410 35482 3500 1700 464 1269 463 403 463 403 463 403 462 1292 440 426 440 426 440 426 440 426 439 1293 439 426 440 1293 439 1293 439 427 439 1293 439 1293 439 1293 439 1293 439 1293 439 427 439 427 439 1294 438 427 439 427 439 427 439 428 438 427 438 428 438 428 438 428 437 428 438 428 438 428 438 1295 437 429 437 429 436 429 437 429 437 1296 436 429 437 429 437 429 437 430 436 430 436 430 436 431 435 431 435 431 435 455 410 456 410 456 410 456 410 1322 410 456 410 456 410 456 409 457 409 456 409 1323 409 457 409 457 409 1323 409 1324 408 458 408 35483 3500 1700 464 1268 464 402 464 403 463 402 464 1292 440 426 440 426 440 426 439 426 440 1293 439 426 440 1293 439 1293 439 427 439 1293 439 1293 439 1293 438 1293 439 1293 439 427 439 427 438 1294 438 428 438 428 438 427 438 428 438 428 438 428 438 428 438 428 438 428 438 428 437 428 438 429 436 429 437 429 437 429 437 429 437 429 437 429 437 1296 436 430 435 430 436 1297 435 431 435 1297 435 431 435 456 409 456 410 456 409 456 410 456 410 456 410 456 410 1323 409 1323 409 457 409 457 409 457 408 457 409 457 409 458 408 458 407 458 408 1325 407 1326 405 1327 406 1351 381 485 356 1376 356 510 355 1377 355 1377 355 1377 355 1378 354 1378 354 512 354 512 354 538 327 538 328 538 328 539 326 565 300 566 300 566 299 567 299 593 272 621 244 596 270 1488 244 -# +# name: Cool_hi type: raw frequency: 38000 duty_cycle: 0.330000 data: 504 389 477 364 501 364 502 364 501 364 502 25048 3511 1684 505 1228 504 389 475 390 474 392 472 1260 470 396 469 396 470 396 469 397 469 1263 469 397 469 1263 469 1263 469 397 468 1263 469 1263 469 1264 468 1263 469 1264 468 397 468 398 468 1264 468 398 468 398 468 398 468 398 468 398 468 399 467 398 468 399 467 423 443 400 466 1289 443 423 443 1289 443 423 443 423 443 423 443 1289 443 1290 442 424 442 423 442 423 443 424 442 1290 442 424 442 423 443 424 442 424 441 424 442 424 441 424 442 424 442 424 441 424 442 424 442 1291 441 1291 441 1291 441 425 441 425 441 1291 441 1291 441 1291 441 35478 3505 1695 468 1264 468 398 467 398 468 398 468 1265 467 398 467 398 468 398 468 399 467 1265 467 399 467 1266 466 1266 466 423 443 1289 443 1290 442 1290 442 1290 442 1290 442 424 442 423 442 1290 442 423 443 424 442 424 442 424 442 424 441 424 442 424 442 424 441 424 442 424 442 424 442 1291 441 425 441 425 441 424 442 424 441 1291 441 425 441 425 440 425 441 425 441 425 441 425 441 425 441 425 440 425 441 425 441 425 440 426 440 426 440 1292 440 426 440 426 440 426 440 426 439 427 439 1293 439 427 439 427 438 1294 438 1294 438 428 437 35479 3504 1695 468 1264 468 398 468 398 468 398 467 1265 467 399 467 399 467 399 466 399 467 1265 467 399 467 1289 443 1290 442 423 443 1290 442 1290 442 1290 442 1290 442 1290 442 423 443 424 442 1290 442 424 442 424 442 424 441 424 442 424 442 424 442 424 442 424 442 424 442 424 442 424 442 424 442 425 441 425 440 425 441 425 441 425 441 425 441 1291 441 425 441 425 441 1292 440 1292 440 1292 440 426 440 425 441 426 440 426 440 1292 440 426 440 426 440 1292 440 426 440 426 440 426 440 427 439 426 440 426 440 427 438 427 439 427 439 427 439 1294 438 1295 437 1294 438 1319 413 453 413 1319 413 453 412 1320 412 1319 413 1319 413 1319 413 1320 412 453 412 453 413 453 412 454 412 454 411 454 412 454 412 454 412 454 412 454 412 455 411 454 412 455 411 1321 411 1321 411 456 409 456 410 481 384 482 384 482 383 482 359 506 360 507 359 507 359 507 358 1374 358 1374 358 508 357 508 358 509 357 534 332 534 332 534 332 534 332 535 331 535 331 535 331 535 330 536 330 536 330 562 303 563 303 563 302 564 302 1430 302 565 301 564 302 591 274 619 247 619 247 1512 219 1539 190 -# +# name: Cool_lo type: raw frequency: 38000 duty_cycle: 0.330000 data: 502 390 476 365 501 365 500 365 500 365 501 25049 3535 1660 504 1229 502 390 474 391 473 393 471 1261 469 397 468 398 468 398 468 398 468 1264 468 398 468 1265 467 1265 467 399 467 1265 467 1265 467 1265 467 1266 466 1265 467 400 466 401 465 1266 466 401 465 401 465 401 465 424 442 424 441 424 442 424 441 424 442 424 442 424 442 1291 441 424 442 1291 441 424 442 425 440 425 441 1291 441 1291 441 425 441 425 441 425 440 425 441 1292 440 425 441 425 441 425 441 425 441 425 441 425 441 425 441 425 440 426 440 426 440 426 440 1292 440 1293 439 1293 439 426 439 427 439 1293 439 1293 439 1293 439 35480 3503 1696 467 1265 467 399 467 398 468 399 466 1266 466 399 467 399 467 399 467 399 467 1266 466 400 466 1267 465 1290 442 424 442 1290 442 1290 442 1290 442 1290 441 1291 441 424 442 424 442 1291 441 424 442 424 442 425 441 424 442 424 442 425 441 425 440 425 441 425 441 425 441 425 441 1292 440 425 441 425 441 425 440 426 440 1292 440 426 440 426 439 426 440 426 439 426 440 426 440 426 440 426 440 426 440 427 438 427 439 427 439 427 439 1293 439 427 438 427 439 428 438 428 438 428 438 1294 438 428 438 428 438 1295 437 1320 412 453 413 35480 3503 1696 467 1265 467 399 467 399 467 399 467 1266 466 399 467 399 467 400 466 400 466 1290 442 424 442 1289 443 1290 442 424 442 1291 441 1290 442 1290 442 1291 441 1291 441 424 442 424 442 1291 441 425 441 425 441 425 441 425 441 425 441 425 441 425 441 425 441 425 440 425 441 425 441 425 441 425 441 425 441 425 440 426 440 426 440 426 440 1292 440 426 440 426 440 1292 440 1293 439 1293 439 427 439 426 439 427 439 1293 439 1293 439 1293 439 427 438 1294 438 427 439 427 438 428 438 427 438 453 413 429 437 429 437 429 437 453 412 454 412 1320 412 1320 412 1320 412 1320 412 454 412 1321 411 454 412 1320 412 1321 411 1321 411 1321 411 1321 411 455 410 455 411 455 411 455 411 455 411 456 410 456 410 457 409 481 384 457 409 482 383 483 383 483 358 1374 358 1374 358 508 357 508 358 509 357 509 357 509 357 509 357 510 356 535 330 536 330 536 330 1402 330 1403 329 537 329 536 329 563 302 564 302 564 302 565 300 565 300 592 273 619 246 620 246 619 246 620 245 674 188 -# +# name: Heat_hi type: raw frequency: 38000 duty_cycle: 0.330000 data: 504 365 500 365 500 365 500 365 501 365 501 25049 3535 1660 504 1229 502 390 474 391 473 393 471 1261 470 397 468 397 469 398 468 398 468 1264 468 398 467 1265 467 1265 467 398 468 1265 467 1265 467 1265 467 1266 466 1266 466 399 466 399 467 1266 466 400 466 400 466 400 465 400 466 424 442 424 442 424 442 424 441 424 442 424 442 1291 441 424 442 1291 441 424 442 424 442 425 441 1291 441 1291 441 425 440 425 441 425 441 425 440 1292 440 425 441 425 440 425 441 425 441 425 441 425 441 425 441 426 440 426 440 426 440 426 439 1293 439 1293 439 1293 439 426 440 427 439 1293 439 1293 439 1293 439 35480 3503 1696 468 1264 468 398 468 398 468 398 467 1265 467 399 467 399 467 399 467 399 467 1267 465 400 466 1266 466 1267 465 424 441 1290 442 1290 442 1290 442 1290 442 1291 441 424 442 424 442 1291 441 424 442 424 442 424 442 424 442 424 441 425 441 425 441 425 441 425 441 425 441 425 441 1292 440 425 441 425 441 425 441 425 441 1292 440 426 440 426 439 426 440 426 440 426 439 426 440 426 440 426 439 427 439 426 440 427 439 427 439 427 438 1293 439 427 439 427 439 427 439 428 438 428 438 1295 437 428 438 429 436 1296 436 1296 436 453 412 35481 3502 1696 467 1265 467 399 466 399 467 399 467 1265 467 399 467 399 467 399 466 400 466 1266 466 400 466 1290 442 1267 465 424 442 1290 442 1290 442 1290 442 1290 442 1291 441 424 442 424 441 1291 441 424 442 424 442 424 442 424 441 425 441 425 441 425 441 425 441 425 441 425 441 425 441 425 441 425 440 426 440 425 441 425 441 425 441 426 440 1292 440 426 440 426 440 1292 440 426 440 426 439 1293 439 427 439 427 439 427 439 1293 439 1294 438 1294 438 1293 439 427 439 428 438 428 438 428 438 429 436 429 437 429 437 453 412 453 413 453 412 1320 412 1320 412 1320 412 1320 412 454 412 1320 412 454 412 1321 411 1321 411 1321 411 1321 411 1322 410 455 411 455 411 456 410 456 410 455 410 456 410 456 409 481 384 458 408 482 383 482 384 483 358 508 358 1374 358 1374 358 508 357 509 357 509 357 510 355 535 330 536 330 536 330 536 329 536 330 536 330 1403 329 1430 301 564 302 564 302 564 301 591 274 566 301 592 273 619 247 619 247 620 245 647 219 -# +# name: Heat_lo type: raw frequency: 38000 duty_cycle: 0.330000 data: 503 365 500 364 501 366 499 365 500 364 502 25049 3535 1660 504 1228 503 390 474 391 473 393 471 1261 469 397 468 397 469 397 469 397 469 1264 468 398 468 1264 468 1264 468 398 468 1265 467 1265 467 1265 467 1265 467 1265 467 399 467 399 467 1266 466 399 467 400 466 400 466 400 466 423 443 423 443 401 465 423 442 424 442 424 442 1290 442 424 442 1290 442 424 442 424 441 424 442 1290 442 1291 441 425 441 424 442 425 441 425 441 1291 441 425 440 425 441 425 441 425 441 425 441 425 440 425 441 425 441 425 441 425 441 426 440 1292 440 1292 440 1292 440 426 440 426 440 1292 440 1293 439 1293 439 35480 3503 1696 467 1264 468 398 468 398 467 398 468 1265 467 398 467 399 467 399 466 399 467 1265 467 399 467 1266 466 1267 465 400 466 1290 442 1290 442 1290 442 1290 442 1290 442 424 442 424 442 1290 442 424 441 424 442 424 442 424 442 424 442 424 441 424 442 425 441 424 442 425 441 425 441 1291 441 425 441 425 441 425 441 425 440 1292 440 425 441 425 440 426 440 426 440 426 440 426 440 426 440 426 440 426 440 426 439 427 439 426 440 426 440 1293 439 427 439 427 439 427 438 427 439 428 438 1294 438 428 437 428 438 1295 437 1319 413 453 413 35480 3503 1696 468 1265 467 398 468 398 468 398 468 1265 467 398 468 399 466 399 467 399 467 1266 466 399 466 1267 465 1290 442 401 465 1290 442 1290 442 1290 442 1290 442 1290 442 424 442 424 441 1291 441 424 442 424 442 424 442 424 442 424 441 424 442 425 441 424 442 424 441 425 441 425 441 425 440 425 441 425 441 425 441 425 441 425 441 425 441 1292 440 426 440 426 440 1292 440 426 440 426 440 1293 439 426 440 426 440 1293 439 1293 439 1293 439 427 439 1294 438 427 438 427 439 427 438 428 438 428 438 428 438 428 438 453 413 429 437 453 413 1319 413 1320 412 1320 412 1320 412 454 412 1320 412 454 412 1321 411 1321 411 1321 411 1321 411 1321 411 455 410 455 411 455 411 455 410 456 410 456 410 456 410 481 384 481 385 482 383 482 383 483 358 507 359 1374 358 1374 358 508 358 508 358 508 358 509 357 509 357 535 331 535 331 535 330 535 330 536 330 1403 329 1403 329 563 302 564 301 564 302 564 301 565 301 591 274 619 246 593 273 620 245 620 245 621 245 673 189 -# -# Model: Mitsubishi SRK63HE. +# +# Model: Mitsubishi SRK63HE +# name: Off type: raw frequency: 38000 duty_cycle: 0.330000 data: 3232 1526 463 334 462 1127 464 334 460 334 461 1128 463 336 459 1128 464 359 436 359 436 1133 458 1156 434 1157 434 362 433 1159 432 363 432 1159 432 1159 432 1159 432 363 433 363 432 363 432 363 432 1160 431 1160 432 363 432 1160 431 1160 431 363 432 364 432 1160 431 363 432 363 432 1160 432 363 432 364 431 1160 431 1160 431 364 431 1160 431 1160 431 1160 431 1160 431 1160 431 1160 431 364 431 1160 431 1160 431 1160 431 364 432 364 432 364 431 364 431 1160 432 364 432 364 431 364 431 1160 431 1160 431 1160 431 364 431 1161 430 1161 430 1160 431 1161 430 364 432 364 431 365 431 1161 430 364 431 365 431 364 431 365 430 365 431 1161 430 1161 430 1161 430 365 430 1161 430 365 430 365 430 1161 430 365 430 365 431 365 430 1161 430 365 430 1161 430 1161 430 -# +# name: Dh type: raw frequency: 38000 duty_cycle: 0.330000 data: 3229 1528 461 335 461 1128 463 334 461 335 460 1129 463 337 458 1129 463 359 436 360 434 1156 434 1157 433 1159 432 364 431 1161 430 364 431 1161 430 1161 430 1160 431 364 431 364 431 365 430 365 430 1161 430 1161 430 365 430 1161 430 1161 431 365 430 365 431 1161 430 365 430 365 430 1161 430 365 430 365 431 1161 430 1161 430 365 431 1161 430 1161 430 1161 430 1161 430 1161 431 1161 430 365 430 1161 430 1161 430 1161 431 365 430 365 430 365 430 365 430 1162 430 365 430 365 430 365 431 1162 429 1162 429 1162 430 365 430 1162 429 1162 429 1162 429 1162 429 366 430 366 429 366 430 1162 429 366 429 366 430 366 429 366 429 1162 429 366 429 1163 428 366 429 1162 429 366 429 366 429 1162 429 366 430 1162 429 366 429 1163 429 366 430 1163 428 1163 428 367 428 -# +# name: Cool_hi type: raw frequency: 38000 duty_cycle: 0.330000 data: 3230 1526 463 335 460 1128 464 333 461 335 460 1128 463 337 458 1128 463 359 436 359 436 1155 435 1157 433 1158 432 363 432 1160 431 364 431 1161 430 1160 431 1160 431 364 431 364 431 364 431 364 431 1161 430 1161 430 364 431 1161 430 1160 431 365 430 364 431 1161 431 364 431 364 431 1161 430 365 430 365 431 1161 430 1161 431 364 431 1161 430 1161 430 1161 430 1161 431 1161 430 1161 431 365 430 1161 431 1161 430 1162 430 365 430 365 430 365 431 365 430 1161 430 365 430 365 430 365 431 1161 430 1162 430 1162 429 365 430 1162 429 1162 429 1162 429 1162 429 366 429 366 430 366 430 1162 429 366 430 366 429 366 429 366 430 366 429 1162 429 1163 429 366 429 366 429 1163 428 1163 428 1163 429 1163 428 366 429 366 430 1163 428 1163 428 367 428 367 429 366 429 -# +# name: Cool_lo type: raw frequency: 38000 duty_cycle: 0.330000 data: 3231 1526 463 334 461 1127 465 333 461 334 460 1128 463 336 459 1129 463 359 436 359 436 1133 458 1156 434 1157 433 362 433 1159 432 363 432 1159 432 1160 431 1159 433 363 432 363 432 363 432 363 432 1159 433 1159 432 363 432 1159 432 1160 432 363 432 363 432 1159 432 363 432 363 433 1159 432 364 432 363 432 1160 431 1160 432 363 432 1160 431 1160 431 1160 431 1160 432 1160 431 1160 431 364 432 1160 431 1160 431 1160 431 364 431 364 431 364 432 364 431 1160 432 364 431 364 431 364 432 1160 431 1161 430 1161 430 364 431 1161 431 1161 430 1161 430 1161 430 364 432 364 431 364 431 1161 430 365 430 365 430 365 430 365 431 365 430 1161 430 1161 431 365 430 1161 430 365 430 365 431 1161 430 1161 430 365 431 365 430 1162 430 365 431 1161 430 1162 429 365 430 -# +# name: Heat_hi type: raw frequency: 38000 duty_cycle: 0.330000 data: 3230 1526 463 334 461 1128 464 333 461 334 461 1128 463 336 459 1129 463 359 436 359 436 1155 435 1156 434 1158 433 363 432 1159 432 363 432 1159 432 1160 431 1160 431 363 433 363 432 363 432 363 432 1160 432 1160 431 364 431 1160 431 1160 432 364 431 364 431 1160 431 364 431 364 432 1160 431 364 431 364 431 1160 431 1160 431 364 432 1160 431 1160 431 1160 431 1160 431 1160 431 1160 431 364 431 1160 432 1160 431 1160 431 364 432 364 431 364 431 364 431 1161 430 364 431 364 432 364 431 1161 430 1161 430 1161 430 365 430 1161 431 1161 430 1161 430 1161 430 365 430 365 430 365 430 1161 430 365 431 365 431 365 430 365 431 1161 430 1161 430 365 430 365 430 365 430 1162 430 365 430 365 430 365 431 365 430 1162 429 1162 430 1162 429 366 429 1162 429 1162 429 -# +# name: Heat_lo type: raw frequency: 38000 @@ -373,172 +384,177 @@ duty_cycle: 0.330000 data: 3234 1525 463 333 462 1127 465 332 462 333 436 1153 518 307 488 1073 518 307 488 308 434 1131 459 1155 435 1156 434 362 433 1159 432 363 432 1159 432 1159 432 1159 433 363 432 363 432 363 433 363 432 1159 433 1159 432 363 432 1159 433 1159 432 363 432 363 432 1159 432 363 433 363 432 1159 432 363 432 363 432 1159 432 1159 432 363 432 1160 432 1160 431 1160 432 1160 431 1160 431 1160 431 364 431 1160 431 1160 431 1160 431 364 431 364 431 364 431 364 431 1160 431 364 431 364 431 364 431 1160 432 1160 431 1160 432 364 431 1160 431 1160 431 1161 431 1161 430 364 431 364 431 364 431 1160 432 364 431 364 431 364 432 364 431 1161 431 1161 431 364 431 364 431 1161 430 364 432 364 431 1161 430 365 431 365 431 1161 430 1161 430 365 431 1161 430 1161 430 365 430 # # Model: Airwell Prime DCI Series +# name: Off type: raw frequency: 38000 duty_cycle: 0.330000 data: 3078 3852 2004 888 1054 1824 1045 894 1051 865 2062 861 1078 860 1080 865 1046 894 1015 1883 1945 899 1013 901 1013 901 1012 902 1012 900 1042 927 986 902 1012 927 987 901 1012 902 1012 927 986 903 1011 902 1012 931 1011 931 1011 904 1010 933 1009 928 985 928 986 1885 1944 927 3017 3943 1943 927 985 1915 984 929 985 929 1943 957 984 929 985 928 985 929 985 1886 1943 899 984 930 983 930 984 957 986 929 985 929 985 930 984 930 983 930 984 930 1013 930 984 959 983 931 982 931 983 930 984 930 984 930 984 960 1011 931 984 1918 1939 929 3016 3917 1940 930 982 1916 954 959 954 959 1913 957 955 933 981 959 928 1015 954 1916 1913 959 953 960 957 986 927 1015 928 1015 953 961 927 987 927 986 927 987 927 986 927 1016 927 987 927 1016 926 1044 928 987 926 1015 928 988 926 987 926 988 926 1946 1883 987 3974 -# +# name: Dh type: raw frequency: 38000 duty_cycle: 0.330000 data: 3060 3870 1026 888 1984 886 1026 888 1053 888 1026 887 1055 858 1055 858 1052 860 1024 891 1044 1854 1016 897 1975 1853 1975 925 1015 898 1015 898 1016 897 1016 898 1015 898 1016 898 1015 898 1015 898 1015 899 1015 899 1014 899 1014 899 1016 927 1014 900 1014 899 1014 1856 1974 926 3048 3883 1015 898 1975 897 1014 899 1015 899 1014 900 1014 899 1015 900 1013 900 1014 899 1014 1857 1014 900 1973 1855 1973 899 1012 901 1013 902 1011 926 987 927 987 926 987 927 987 955 987 926 988 926 987 927 1015 927 987 927 987 926 988 926 1016 927 1015 1884 1945 925 3020 3911 986 928 1946 925 986 927 986 928 986 928 986 927 987 927 987 928 986 928 986 1884 987 956 1946 1882 1946 925 986 928 986 927 986 928 985 928 986 928 986 928 986 928 985 928 985 929 959 954 984 930 984 987 931 955 959 956 958 955 959 1968 1891 980 3982 -# +# name: Cool_hi type: raw frequency: 38000 duty_cycle: 0.330000 data: 3054 3879 1977 892 1020 1846 1083 838 1073 840 2031 859 1051 864 1047 864 1077 896 1014 927 986 928 986 928 986 1885 1943 927 985 929 1013 928 986 929 985 928 985 928 985 928 985 929 985 929 985 957 985 928 1015 928 1015 928 985 929 984 929 985 929 985 1886 1943 927 3017 3914 1943 928 984 1886 985 958 984 929 1972 957 984 958 984 929 984 930 984 929 984 930 984 930 983 1887 1942 929 983 930 984 930 984 930 983 959 984 930 984 930 983 930 984 930 984 930 984 930 983 931 983 931 983 959 984 931 983 931 983 1888 1941 930 3014 3943 1914 931 981 1915 955 959 955 959 1913 958 955 959 954 959 955 959 955 959 955 988 955 960 953 1917 1941 959 953 960 953 961 953 961 953 961 927 987 927 987 927 987 926 987 927 1017 926 988 926 988 925 988 925 988 926 988 925 1018 925 1972 1857 1014 3946 -# +# name: Cool_lo type: raw frequency: 38000 duty_cycle: 0.330000 data: 3080 3850 2007 863 1049 1851 1048 888 1054 887 2012 886 1026 887 1025 888 1050 865 1045 1854 2029 871 1041 872 1040 873 1042 899 1043 899 1043 872 1015 898 1016 899 1041 872 1042 872 1015 926 1017 898 1016 927 1016 926 1016 899 1014 898 1015 926 1016 899 1015 898 1015 1856 1973 897 3048 3910 1947 898 1015 1884 1015 925 988 899 2003 953 988 900 1014 954 988 926 987 1857 1972 896 988 899 1014 900 1014 900 1013 927 987 929 1014 929 1013 926 987 927 986 927 987 927 987 927 987 927 986 927 987 927 986 985 958 928 986 927 986 927 1012 1860 1943 927 3018 3914 1943 955 986 1914 986 929 984 928 1944 955 957 930 984 957 985 956 958 1913 1915 956 957 957 956 957 931 1012 957 930 983 958 955 931 982 958 956 960 983 958 956 958 955 958 930 984 930 984 930 984 930 984 930 1013 930 984 930 985 928 1942 1887 983 3977 -# +# name: Heat_hi type: raw frequency: 38000 duty_cycle: 0.330000 data: 3083 3873 2012 1843 2013 1873 1054 888 2011 887 1025 887 1025 887 1052 890 1048 1852 1017 896 1018 895 1018 896 1976 895 1017 898 1016 898 1015 898 1016 897 1016 897 1016 897 1017 897 1016 897 1017 900 1043 899 1014 897 1016 897 1016 898 1016 898 1015 898 1015 1857 1972 896 3048 3911 1947 1853 1975 1854 1015 898 1973 897 1016 927 1015 926 987 926 1016 1857 1014 926 987 899 1015 901 1970 926 987 927 987 926 988 955 988 1013 958 900 1014 926 987 900 1014 900 1014 900 1013 927 986 927 987 927 1016 955 987 927 987 955 987 1884 1946 928 3045 3912 1974 1883 1974 1883 987 927 1974 926 986 927 987 928 987 956 987 1942 986 956 986 928 986 928 1944 926 986 928 985 929 984 929 985 928 986 956 987 928 986 958 984 929 984 930 984 930 983 929 985 958 984 930 984 957 957 956 957 1887 1971 956 4003 -# +# name: Heat_lo type: raw frequency: 38000 duty_cycle: 0.330000 data: 3108 3851 2062 1793 2006 1821 1103 839 2031 859 1085 829 1081 833 1079 836 1045 1911 1973 897 1015 898 1016 899 1041 871 1016 899 1014 898 1015 899 1015 899 1014 899 1041 872 1015 899 1041 872 1041 872 1015 899 1015 899 1041 873 1014 899 1041 873 1014 899 1014 1883 1975 900 3045 3886 1997 1856 1945 1857 1012 927 1945 900 1013 901 1012 901 1013 901 1012 1859 1999 901 1012 930 1012 903 1011 903 1010 903 1011 902 1012 960 1011 928 986 932 1010 903 1011 928 1015 928 985 929 985 928 1014 928 985 929 985 929 984 929 985 928 986 1915 1971 928 3017 3915 1942 1885 1943 1885 985 930 1971 929 984 930 983 930 984 930 984 1887 1942 929 983 960 983 931 982 931 983 932 981 958 985 958 956 958 984 959 954 931 983 932 981 959 955 932 982 959 954 960 982 961 983 933 955 988 955 985 929 1943 1915 958 4003 -# +# # Model: Danby DAC060EB7WDB +# name: Off type: raw frequency: 38000 duty_cycle: 0.330000 data: 4402 4442 527 1629 529 549 529 1628 530 550 529 548 531 549 530 550 529 1630 528 549 530 549 529 549 530 1630 527 1629 529 1630 528 548 530 550 529 547 531 1628 530 1629 529 1628 530 1628 529 1628 530 1628 530 549 530 1628 530 1628 530 1627 531 1628 530 1627 531 1631 527 1629 529 1628 530 1627 531 1628 530 1628 530 1629 529 1627 531 1627 531 1628 529 1627 531 1627 531 1629 529 1627 530 549 529 549 530 549 530 1628 529 1627 530 5234 4401 4440 530 550 528 1628 529 549 530 1628 529 1629 528 1626 531 1628 529 550 529 1628 530 1627 531 1629 529 549 529 548 530 549 530 1628 529 1628 530 1627 530 547 532 547 532 547 531 548 531 548 530 548 531 1626 531 549 530 547 531 547 531 548 530 548 530 549 530 548 531 546 532 578 500 547 532 548 531 548 531 548 530 548 531 548 530 548 531 547 531 547 532 547 531 1627 531 1627 530 1626 532 547 531 547 532 -# +# name: Dh type: raw frequency: 38000 duty_cycle: 0.330000 data: 4454 4387 586 1573 585 494 584 1571 586 494 584 493 585 524 554 493 531 1626 586 1573 585 494 585 492 586 492 586 494 585 493 585 493 586 1571 586 493 585 1572 531 1627 530 549 584 494 586 1571 587 1572 529 1628 529 1628 530 1627 530 1626 532 1627 531 1626 532 1628 529 1627 531 1626 531 1627 531 1627 587 1569 532 1625 533 1626 532 1626 532 1627 531 1627 530 548 531 1626 532 1627 531 548 531 1627 531 548 531 546 532 547 531 5233 4401 4443 530 548 530 1627 530 547 531 1627 531 1626 531 1626 531 1627 530 549 530 548 530 1627 531 1627 531 1627 530 1627 531 1627 531 1626 531 548 530 1627 530 547 532 547 532 1627 531 1627 532 546 531 547 531 548 530 548 530 548 531 548 531 548 530 548 530 549 530 548 531 548 531 548 530 547 532 549 529 548 530 548 531 547 532 548 530 548 531 1627 530 548 530 548 531 1626 533 546 531 1627 530 1627 532 1626 530 -# +# name: Cool_hi type: raw frequency: 38000 duty_cycle: 0.330000 data: 4492 4354 619 1537 619 459 621 1537 622 455 623 456 623 457 622 456 623 1535 622 1536 622 458 621 456 623 1536 621 1535 623 456 622 456 623 457 621 456 531 1627 621 1536 622 456 622 457 622 455 623 458 621 458 621 1537 621 1536 620 1539 618 1538 531 1628 531 1627 530 1628 530 1628 530 1627 531 1628 530 1628 530 1628 531 1627 530 1629 529 1628 529 1628 530 549 530 1627 531 1628 530 1628 530 1627 586 494 530 1627 530 549 530 5232 4400 4443 586 492 587 1571 587 493 585 1572 530 1628 586 1572 586 1572 586 492 587 493 586 1572 586 1571 586 492 587 493 585 1572 531 1627 585 1573 585 1572 585 492 586 494 585 1572 586 1571 531 1627 531 1628 530 1627 587 491 531 548 587 492 530 548 530 547 532 548 531 547 532 547 531 548 531 547 532 547 531 548 588 491 530 547 589 490 531 547 532 1626 532 548 531 548 531 547 532 547 532 1627 531 548 531 1626 532 -# +# name: Cool_lo type: raw frequency: 38000 duty_cycle: 0.330000 data: 4401 4441 528 1629 529 550 528 1628 529 551 528 550 528 551 527 551 528 1629 529 1629 529 550 529 1630 528 551 528 549 530 550 529 551 528 549 529 550 529 1629 529 1628 530 549 530 1629 529 550 529 1628 529 1629 529 1631 527 1628 530 1628 529 1629 528 1628 530 1629 529 1629 529 1629 529 1629 528 1629 529 1629 529 1630 528 1629 529 1629 529 1628 529 1629 528 551 528 1629 529 550 529 550 530 548 529 1631 527 551 528 1629 529 5235 4402 4439 530 550 528 1629 529 549 530 1628 529 1629 529 1628 530 1629 529 549 530 550 529 1628 530 552 526 1628 529 1628 530 1628 530 1627 531 1628 529 1629 528 551 528 550 529 1628 530 550 528 1628 529 549 529 550 528 550 529 549 530 548 530 551 528 550 528 578 500 550 529 550 529 551 527 549 530 549 529 549 529 550 528 548 530 550 528 549 529 1629 528 550 529 1630 528 1628 530 1628 530 549 530 1628 529 549 529 -# +# # Model: Carrier 42QHB12D8S +# name: Off type: raw frequency: 38000 duty_cycle: 0.330000 data: 4467 4363 599 1556 599 478 599 1556 599 1558 597 505 572 505 572 1583 571 505 572 506 624 1531 653 423 651 426 624 1530 622 1532 572 505 572 1583 571 506 571 1584 571 1583 571 1584 571 1584 571 507 570 1585 570 1585 570 1585 570 508 569 508 569 508 592 485 570 1585 593 484 570 508 569 1586 569 1586 592 1563 593 485 569 508 592 485 592 485 570 508 569 508 570 508 569 508 569 1586 569 1586 569 1586 569 1586 569 1586 569 5187 4461 4371 568 1586 569 508 593 1562 593 1563 569 509 591 486 591 1563 569 508 592 486 592 1563 592 485 592 486 591 1563 592 1563 591 486 592 1564 591 486 592 1563 593 1563 591 1563 592 1564 592 485 592 1563 592 1563 592 1564 591 486 591 486 592 485 592 485 592 1563 592 486 591 486 592 1564 591 1563 592 1563 592 486 592 485 592 486 591 486 592 485 592 486 591 486 591 486 591 1563 592 1563 593 1563 591 1564 591 1563 591 -# +# name: Dh type: raw frequency: 38000 duty_cycle: 0.330000 data: 4440 4390 571 1583 572 505 572 1583 596 1559 571 505 572 505 572 1583 596 481 596 481 597 1559 625 451 654 423 625 1529 595 1560 596 480 572 1583 572 505 596 482 594 483 571 1583 571 1584 571 1584 571 1584 571 1585 569 1585 593 1562 594 1561 593 485 569 508 593 484 592 485 593 484 592 485 592 1563 569 508 592 1562 592 485 570 1586 592 485 592 486 569 1586 592 485 569 1585 570 508 569 1586 569 508 569 1585 570 1586 569 5186 4438 4393 569 1585 593 485 592 1562 569 1585 569 508 569 508 569 1585 591 486 593 484 591 1563 591 486 591 486 590 1564 569 1585 569 508 593 1562 592 486 592 485 569 508 591 1563 592 1562 569 1586 569 1586 591 1563 592 1563 590 1564 591 1563 592 486 569 508 569 508 569 508 569 508 592 486 592 1563 568 508 593 1563 591 486 592 1563 569 508 592 486 592 1563 591 486 592 1563 592 485 592 1563 592 486 592 1563 591 1563 592 -# +# name: Cool_hi type: raw frequency: 38000 duty_cycle: 0.330000 data: 4465 4365 598 1557 598 479 598 1557 598 1557 598 479 598 479 598 1556 599 479 598 507 593 1562 652 424 624 452 595 1559 595 1560 594 483 571 1584 594 1561 593 484 593 1562 593 1562 593 1562 593 1562 593 1562 593 1563 592 485 592 1562 593 484 593 485 592 485 592 485 592 485 592 485 592 485 592 485 592 485 592 485 592 485 592 485 592 485 592 485 592 1562 592 1563 592 1562 593 1562 592 1563 592 1563 592 1562 592 1563 592 5165 4439 4394 569 1586 592 485 569 1586 569 1586 569 508 569 508 593 1562 592 485 570 508 592 1563 592 485 594 484 569 1586 569 1586 569 508 569 1586 592 1563 569 508 592 1563 569 1586 592 1563 592 1563 569 1586 569 1585 569 508 569 1586 569 508 569 508 569 508 569 508 592 485 569 508 592 485 569 508 593 485 569 508 569 508 569 508 593 484 570 508 569 1586 593 1562 570 1586 569 1586 592 1563 569 1586 592 1563 592 1563 592 -# +# name: Cool_lo type: raw frequency: 38000 duty_cycle: 0.330000 data: 4465 4364 599 1556 599 479 598 1556 599 1556 599 478 599 479 598 1559 596 505 572 506 571 1584 653 424 624 452 571 1583 572 1583 571 506 571 1583 571 1584 571 506 571 1584 571 1585 570 1585 570 1585 592 1563 592 1562 593 485 592 1563 592 485 593 485 592 485 592 485 592 485 592 485 593 485 592 1563 592 485 592 1563 592 485 592 485 592 485 592 485 592 1563 592 485 592 1563 592 485 592 1563 592 1563 592 1563 592 1563 592 5164 4460 4372 592 1563 592 485 593 1563 592 1563 592 486 591 486 591 1563 592 485 592 485 592 1563 592 485 592 485 592 1563 592 1563 592 485 592 1563 592 1563 592 485 592 1563 592 1563 592 1563 592 1563 592 1563 592 1564 591 486 591 1563 591 485 592 485 592 485 592 485 592 485 592 485 592 485 592 1563 592 485 592 1563 591 486 591 485 592 486 591 485 592 1563 592 485 592 1563 592 485 592 1564 591 1563 592 1563 592 1563 592 -# +# name: Heat_hi type: raw frequency: 38000 duty_cycle: 0.330000 data: 4440 4391 572 1583 572 505 572 1584 571 1583 572 505 572 505 572 1583 596 481 573 505 596 1559 626 451 655 422 625 1529 596 1559 572 505 572 1583 572 1582 572 505 572 1583 572 1583 571 1584 571 1584 571 1585 570 1584 594 484 593 1562 592 485 592 485 592 485 593 485 593 484 593 484 593 1562 593 484 593 1562 593 1563 592 1562 592 1563 592 485 593 484 592 485 593 1562 593 484 593 485 592 485 592 485 592 1562 593 1563 592 5163 4462 4370 592 1563 592 485 592 1563 592 1563 592 485 592 485 592 1563 592 485 592 485 593 1562 593 485 593 485 592 1563 592 1563 592 485 592 1562 593 1563 592 484 593 1563 592 1563 592 1563 592 1563 592 1563 592 1563 592 485 592 1563 592 485 592 485 592 485 592 485 592 485 593 485 592 1563 592 485 592 1563 592 1563 592 1563 592 1563 592 485 592 485 592 485 592 1563 591 485 592 486 591 485 592 485 593 1563 591 1563 593 -# +# name: Heat_lo type: raw frequency: 38000 duty_cycle: 0.330000 data: 4467 4390 571 1583 572 505 595 1560 572 1583 572 505 572 505 596 1559 596 482 596 481 597 1559 626 451 655 422 625 1529 596 1559 596 481 572 1582 573 1583 571 505 572 1583 595 1560 594 1561 592 1562 594 1561 593 1562 593 484 593 1563 592 485 592 485 592 485 592 485 593 484 593 485 592 485 592 1562 593 485 592 1563 592 1562 593 1562 594 483 593 485 593 1562 592 485 593 1561 593 484 593 484 593 484 593 1562 593 1562 592 5163 4462 4370 592 1563 593 484 592 1563 592 1563 592 485 592 485 593 1562 593 484 593 485 592 1562 593 484 593 485 592 1562 593 1562 593 485 592 1563 592 1563 592 485 592 1563 592 1562 593 1562 593 1563 592 1563 592 1562 592 485 593 1562 592 485 592 485 592 485 592 485 592 485 592 485 592 485 592 1563 592 485 592 1563 591 1563 592 1563 593 485 592 485 592 1563 592 485 592 1563 591 485 593 485 592 485 592 1563 592 1563 591 -# +# # Model: Mitsubishi MSZ-AP25VGK +# name: Off type: raw frequency: 38000 duty_cycle: 0.330000 data: 3531 1667 500 1225 499 1225 499 376 499 377 498 377 498 1224 500 377 498 377 498 1224 500 1225 499 377 527 1195 557 318 556 318 555 1167 530 1194 529 374 499 1224 499 1225 497 377 497 378 497 1228 496 379 496 380 495 1229 495 380 495 380 495 380 495 380 495 380 495 380 495 380 495 380 495 380 495 380 495 380 496 380 495 380 495 380 495 380 495 9028 3526 1672 495 1229 495 1229 495 380 495 380 495 380 495 1230 494 380 495 380 495 1229 495 1229 495 380 495 1229 495 380 495 380 495 1229 495 1229 495 380 495 1229 495 1229 495 380 495 380 495 1229 495 380 495 380 495 1229 495 380 495 381 494 381 494 380 495 380 495 380 495 380 495 381 494 380 495 381 494 381 494 381 494 381 494 381 494 380 495 381 494 381 494 381 494 381 494 381 494 381 494 381 494 381 494 381 494 381 494 381 494 1230 494 1230 494 381 494 381 494 381 494 381 494 381 494 381 494 1230 494 381 494 381 494 381 494 381 494 381 494 1230 494 1230 494 381 494 1230 494 1230 494 381 494 381 494 381 494 381 494 381 494 381 494 381 494 381 494 1230 494 381 494 1230 494 381 494 381 494 1230 494 381 494 1230 494 1230 494 381 494 381 494 381 494 381 494 381 494 381 494 381 494 381 494 381 494 381 494 381 494 381 494 382 493 382 493 382 493 382 493 382 493 382 493 382 493 382 493 382 493 382 493 382 493 382 493 382 493 1231 493 382 493 382 493 382 493 382 493 382 493 382 493 382 493 382 493 382 493 382 493 382 493 382 493 382 493 382 493 382 493 382 493 382 493 382 493 382 493 382 493 382 493 382 493 382 493 1231 493 382 493 1231 493 382 493 1231 493 382 493 383 492 382 493 -# +# name: Dh type: raw frequency: 38000 duty_cycle: 0.330000 data: 3561 1666 500 1195 529 1193 531 374 501 375 500 375 500 1196 529 374 501 375 500 1223 501 1223 501 375 529 1194 558 318 557 318 555 1168 530 1193 530 345 529 1194 529 1196 527 348 526 350 525 1200 524 352 522 353 522 1228 496 379 496 379 496 379 496 379 496 379 496 379 497 379 496 379 496 379 496 379 496 379 496 379 496 379 496 379 496 379 496 9028 3529 1670 496 1228 496 1228 496 379 496 379 496 379 496 1228 496 379 496 379 496 1228 496 1228 496 379 496 1228 496 379 496 379 496 1228 496 1228 496 379 496 1228 496 1228 496 379 496 379 496 1228 496 379 496 379 496 1228 496 379 496 379 496 379 496 379 496 379 496 379 496 379 496 379 496 379 496 379 496 379 496 380 495 379 496 379 496 379 496 379 496 380 495 379 496 380 495 379 496 1229 495 380 495 380 495 379 496 380 495 380 495 380 495 1229 495 380 495 380 495 380 495 380 495 380 495 380 495 1229 495 380 495 380 495 380 495 380 495 380 495 1229 495 380 495 380 495 1229 495 1229 495 380 495 380 495 380 495 380 495 380 496 380 495 380 495 380 495 1229 495 380 495 1229 495 380 495 380 495 1229 495 380 495 1229 495 1229 495 380 495 380 495 380 495 380 495 380 495 380 495 380 495 380 495 380 495 380 495 380 495 380 495 380 495 380 495 380 495 380 495 380 495 380 495 380 495 380 495 381 494 380 495 380 495 380 495 380 495 1230 494 380 495 381 494 381 494 380 495 380 495 380 495 380 495 381 494 381 495 380 495 381 494 381 495 380 495 381 494 381 495 380 495 381 494 381 494 381 494 381 494 381 494 381 494 381 494 1230 494 381 494 381 494 1230 494 381 494 1230 494 381 494 381 494 -# +# name: Cool_hi type: raw frequency: 38000 duty_cycle: 0.330000 data: 3534 1637 530 1192 533 1195 529 375 500 375 500 375 500 1195 530 375 501 375 500 1224 500 1224 501 376 528 1195 557 319 556 318 555 1168 530 1193 530 345 530 1194 529 1196 527 348 526 350 525 1201 523 353 522 378 497 1228 496 379 497 379 496 379 497 379 496 379 497 379 497 379 497 379 496 379 496 379 496 379 496 379 497 379 497 379 496 379 496 9030 3530 1671 496 1229 496 1229 495 379 496 379 496 379 497 1229 496 379 496 379 497 1229 496 1229 495 380 496 1229 495 379 497 379 496 1229 496 1229 495 379 497 1229 495 1228 497 379 496 380 496 1229 496 379 497 379 496 1229 496 379 496 380 496 380 495 380 496 379 496 380 496 380 495 380 496 380 496 380 496 379 496 380 496 380 495 380 496 380 495 380 496 380 495 380 496 380 495 380 495 1229 496 380 495 380 495 380 495 380 496 380 495 1229 496 1229 496 380 495 380 496 380 495 380 496 380 496 380 495 380 495 380 496 380 496 380 495 380 496 380 495 1229 495 1230 495 380 495 1229 496 1229 496 380 495 381 495 380 495 380 495 380 496 380 496 380 495 380 496 1229 496 380 495 1230 495 380 495 380 495 1230 495 380 495 1230 495 1230 495 380 495 380 496 380 495 380 495 380 495 380 496 380 496 380 495 380 496 380 495 380 495 380 496 380 495 381 495 380 495 380 495 380 495 381 495 380 495 381 495 380 495 381 494 381 495 381 495 380 495 1230 495 381 495 380 495 381 494 381 495 381 494 381 495 381 494 381 495 381 495 381 494 381 495 381 494 381 495 381 495 381 494 381 495 381 494 381 494 381 495 381 494 381 494 381 494 381 495 1230 495 381 495 1230 495 1230 495 381 494 1230 494 381 495 381 494 -# +# name: Cool_lo type: raw frequency: 38000 duty_cycle: 0.330000 data: 3534 1667 500 1224 501 1224 501 376 500 375 500 376 500 1224 501 376 500 376 499 1224 501 1225 500 376 500 1225 556 320 556 318 555 1167 530 1194 530 345 530 1195 529 1196 528 348 527 377 498 1227 498 378 497 379 496 1229 496 379 496 379 497 379 497 379 497 379 497 380 496 379 497 379 496 379 497 380 496 380 496 380 496 380 496 379 497 379 497 9033 3530 1672 496 1229 496 1229 496 380 496 380 496 380 496 1229 496 380 496 380 496 1229 496 1229 496 380 496 1229 496 380 496 380 496 1229 496 1229 496 380 496 1230 495 1229 496 380 495 380 496 1229 496 380 496 380 496 1229 496 380 496 380 496 380 496 380 496 380 496 380 496 380 496 380 496 380 496 380 496 380 496 380 496 380 495 380 496 380 496 380 496 380 496 380 496 380 496 380 496 1230 495 380 496 380 495 380 496 381 495 380 495 1230 495 1230 495 380 496 380 496 380 496 1230 495 1230 495 1230 495 380 496 380 496 380 496 380 496 380 496 381 495 1230 495 1230 495 381 495 1230 495 1230 495 380 495 381 495 381 495 381 495 381 495 381 495 380 496 381 495 1230 495 381 495 1230 495 381 495 380 496 1230 495 381 495 1230 495 1230 495 381 495 381 495 381 495 381 495 381 495 381 495 381 495 380 496 381 495 381 495 381 495 381 495 381 495 381 495 381 495 381 495 381 495 381 495 381 495 381 495 381 495 381 495 381 495 381 495 381 495 1231 494 381 495 381 495 381 495 381 495 381 495 381 494 381 495 381 495 381 495 381 495 381 495 381 495 381 495 381 495 381 495 381 495 381 495 381 495 381 495 381 495 381 495 381 495 381 495 382 494 382 494 1231 494 381 495 1231 494 1231 494 381 495 382 494 -# +# name: Heat_hi type: raw frequency: 38000 duty_cycle: 0.330000 data: 3539 1670 501 1226 502 1226 501 376 501 377 500 376 501 1226 501 376 499 378 500 1226 501 1226 501 377 528 1199 557 320 557 318 529 1197 531 1195 531 346 530 1196 530 1198 528 349 527 352 524 1229 498 379 498 379 498 1230 497 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 497 9045 3536 1674 496 1231 497 1231 497 380 497 380 497 380 497 1231 496 380 497 380 497 1231 497 1231 496 380 497 1231 496 380 497 380 497 1231 496 1231 497 380 497 1231 496 1231 496 380 497 380 497 1231 496 381 496 380 497 1231 497 381 496 380 497 380 497 380 497 380 497 381 496 381 496 381 496 380 497 380 497 381 496 381 496 381 496 381 496 380 497 381 496 381 496 381 496 381 496 380 497 1231 496 381 496 381 496 380 497 381 496 381 496 1232 495 381 496 381 496 381 496 381 496 1232 495 1232 495 1232 496 1232 495 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 1232 496 1232 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 1232 496 381 496 1232 495 381 496 1232 495 381 496 1232 495 1232 495 381 496 381 496 382 495 381 496 381 496 381 496 381 496 382 495 381 496 381 496 381 496 381 496 381 496 382 495 381 496 381 496 381 496 381 496 382 495 382 495 382 495 382 495 382 495 382 495 382 495 1232 495 382 495 382 495 382 495 382 495 382 495 382 495 382 495 382 495 382 495 382 495 382 495 382 495 382 495 382 495 382 495 382 495 382 495 382 495 382 495 382 495 382 495 382 495 382 495 1233 495 1233 494 1233 495 382 495 382 495 1233 495 1233 494 382 495 -# +# name: Heat_lo type: raw frequency: 38000 duty_cycle: 0.330000 data: 3539 1637 533 1225 502 1193 534 375 501 376 501 376 500 1226 501 376 501 376 500 1226 500 1227 501 376 529 1197 558 320 557 319 555 1169 531 1195 531 346 529 1196 530 1198 528 349 526 352 524 1229 497 379 497 379 497 1230 497 380 497 380 497 379 498 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 497 9042 3535 1674 496 1230 497 1230 497 380 497 380 497 380 497 1230 497 380 497 380 496 1230 497 1230 497 380 497 1230 497 380 497 380 497 1231 496 1230 497 380 497 1231 496 1231 496 380 496 380 497 1231 496 380 497 380 496 1231 496 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 497 380 496 380 497 380 497 380 497 380 497 380 496 381 496 380 497 380 497 380 497 381 496 1231 496 381 496 380 497 380 497 381 496 381 496 1231 496 381 496 381 496 380 497 381 495 1231 496 1231 496 1231 496 380 497 381 496 381 496 380 496 381 496 381 496 381 496 381 496 381 496 1231 496 1231 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 1231 496 381 496 381 496 1232 495 381 495 1232 495 381 496 1231 496 1231 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 496 381 495 381 496 381 496 381 496 381 496 1232 495 381 496 381 496 381 496 381 496 381 495 381 496 381 495 382 495 381 496 382 495 381 495 382 495 381 495 382 495 382 495 382 495 382 495 382 495 382 495 382 495 382 495 382 495 381 495 1232 495 1232 495 1232 495 1232 495 1232 495 382 495 382 495 382 495 -# +# # Model: Hitachi RAK-50PEB +# name: Off type: raw frequency: 38000 duty_cycle: 0.330000 data: 30683 50966 3411 1600 493 1186 493 347 492 348 491 348 491 349 490 349 490 350 489 351 488 351 488 352 487 352 488 351 488 1192 487 352 487 351 488 352 487 352 487 352 488 352 488 351 488 1192 487 1191 488 352 487 352 487 352 487 352 487 352 487 352 487 352 487 352 487 1192 487 352 487 1192 487 1192 487 1192 487 1192 488 1192 487 1192 488 352 487 1192 487 1192 487 352 487 352 487 352 487 352 488 352 487 352 488 352 487 352 487 1192 487 1192 487 1192 487 1192 487 1192 487 1192 487 1192 487 1192 487 352 487 352 488 352 487 1192 487 352 487 352 487 352 487 352 487 1192 487 352 487 353 486 1192 487 353 486 353 486 353 486 353 486 1193 486 353 487 353 486 353 486 353 486 353 486 353 486 1193 486 1193 486 353 487 353 486 353 486 353 486 353 487 353 486 353 486 353 486 1193 486 353 486 353 486 1193 486 353 487 353 486 353 487 353 486 353 486 353 486 353 486 353 487 353 486 353 486 1193 486 1193 486 353 487 353 486 353 486 353 486 354 485 353 486 354 485 353 486 354 486 353 486 353 486 354 486 353 486 353 487 1193 486 1194 485 353 487 353 486 354 485 354 485 354 486 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 486 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 486 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 485 354 485 355 484 355 484 355 484 354 485 354 485 355 484 355 484 355 484 355 484 354 486 355 484 378 461 356 484 378 461 355 485 355 484 355 484 355 485 355 484 378 461 378 461 355 484 356 483 355 484 378 461 378 462 355 485 378 461 378 462 378 461 379 461 356 483 378 461 1195 484 378 461 379 461 356 484 378 461 379 460 379 461 378 461 378 462 378 461 379 461 378 461 378 461 379 460 379 460 379 461 378 461 378 461 378 461 378 461 378 461 379 460 379 460 379 460 379 461 379 460 1219 460 1219 460 379 461 1219 460 379 461 1219 460 -# +# name: Dh type: raw frequency: 38000 duty_cycle: 0.330000 data: 30684 50965 3412 1599 494 1185 494 346 493 346 493 347 492 348 491 349 490 349 490 350 489 351 489 350 489 350 489 351 489 1191 488 351 488 351 488 351 489 351 488 351 488 351 488 351 488 1191 488 1191 488 351 488 351 488 351 488 351 488 351 488 351 489 351 488 351 488 1191 488 351 489 1191 488 1191 488 1191 488 1191 488 1191 488 1191 488 351 488 1191 488 1192 487 351 488 352 487 351 488 351 488 352 487 352 487 352 487 352 488 1192 487 1192 487 1216 463 1192 487 1192 488 1192 487 1193 486 1192 488 352 487 352 487 352 487 1193 486 376 463 376 463 376 464 352 487 1216 463 376 463 376 463 1216 464 376 463 376 463 376 463 1216 463 376 463 376 463 353 486 353 487 376 463 376 463 376 463 1216 463 376 463 1216 463 376 464 376 463 376 463 376 464 376 463 376 463 376 463 376 463 1216 463 376 463 1216 463 376 463 376 463 376 463 376 463 376 463 376 463 376 463 376 463 376 464 376 463 1216 463 1217 463 376 463 377 462 377 462 377 463 376 463 376 463 377 462 376 463 377 462 377 462 377 463 376 463 377 462 377 462 1217 462 1216 463 377 463 377 462 377 462 377 462 377 463 376 463 377 462 377 463 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 463 377 462 377 463 377 462 377 462 1217 462 377 462 377 462 377 463 377 462 377 463 377 462 377 462 377 462 377 462 377 463 377 462 377 462 377 462 377 462 377 462 377 463 377 462 377 462 377 462 377 462 377 462 377 462 377 463 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 463 377 462 377 463 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 462 377 462 1217 462 377 462 377 462 377 462 377 462 378 461 377 462 377 462 378 462 377 462 377 462 377 463 377 462 378 461 378 462 377 462 378 461 377 462 378 461 378 461 378 461 378 462 377 462 378 462 1217 462 1218 461 1218 461 378 461 378 461 1218 462 377 462 378 462 -# +# name: Cool_hi type: raw frequency: 38000 duty_cycle: 0.330000 data: 30747 50897 3484 1554 543 1137 542 310 529 309 530 309 530 309 530 310 529 309 530 310 529 309 530 309 530 309 530 309 530 1138 541 309 531 309 530 309 530 309 530 309 530 309 530 309 530 1138 541 1138 541 310 529 309 530 309 531 309 530 309 530 309 530 309 530 310 529 1139 541 309 530 1138 541 1138 541 1138 541 1138 542 1138 541 1138 541 310 529 1138 541 1138 541 309 530 309 530 309 531 310 529 309 530 309 530 309 530 309 530 1139 541 1139 540 1139 541 1138 541 1139 540 1139 540 1138 541 1139 540 310 529 310 529 309 530 1139 541 310 529 309 530 309 530 309 530 1139 540 309 530 309 530 1139 541 309 530 309 530 309 530 1139 540 309 531 309 530 1139 541 309 530 309 530 309 530 309 530 309 530 309 530 1139 540 309 531 309 530 309 530 309 530 309 530 309 530 309 531 309 530 309 531 309 530 1139 540 310 529 309 530 309 530 309 530 309 530 309 531 310 529 310 529 309 531 310 529 1140 540 309 530 309 531 309 530 309 530 309 530 309 531 309 530 309 530 309 530 309 530 309 531 309 530 309 531 309 530 310 529 1140 539 1140 539 309 530 309 530 309 530 309 530 310 529 309 530 309 530 309 530 309 530 309 531 309 530 309 530 309 530 309 530 309 530 309 531 309 530 309 530 309 530 309 530 309 530 1140 540 309 530 309 530 309 530 309 530 309 531 309 530 309 531 309 530 309 530 310 530 309 530 309 531 309 530 309 530 309 530 309 530 309 530 309 531 309 530 309 530 309 531 309 530 309 530 309 531 309 531 309 530 309 530 309 530 309 530 309 531 309 531 309 530 309 530 309 530 309 530 309 530 309 531 309 530 309 531 309 530 309 531 309 530 309 530 309 531 309 530 309 530 309 530 309 530 1141 538 309 531 309 530 309 530 309 530 309 531 309 530 309 530 309 530 309 531 309 530 309 530 309 530 309 530 309 530 309 530 309 530 310 530 309 531 309 530 309 530 309 530 309 530 309 530 309 531 1142 537 309 530 1142 538 309 530 1141 538 309 530 309 530 -# +# name: Cool_lo type: raw frequency: 38000 duty_cycle: 0.330000 data: 30694 50951 3483 1555 542 1137 542 308 531 309 530 308 531 308 531 308 531 308 531 308 531 308 531 308 532 308 531 308 532 1139 541 308 531 308 531 308 531 308 531 308 531 309 531 308 531 1139 541 1139 540 308 531 308 531 308 531 308 531 309 530 308 531 308 531 308 532 1139 541 308 532 1139 540 1139 541 1139 540 1139 540 1139 540 1139 541 309 530 1139 540 1139 540 308 531 308 531 308 531 308 532 308 531 308 531 308 531 308 531 1140 540 1139 541 1139 540 1139 540 1139 540 1139 541 1139 540 1139 540 308 531 308 531 308 531 1140 540 309 530 308 531 308 532 308 531 1140 540 308 531 308 532 1140 539 308 531 308 531 308 531 308 532 308 531 308 531 1140 540 308 531 308 531 308 531 308 531 308 532 308 531 1140 540 308 531 308 531 308 531 308 531 308 531 308 531 1140 540 1140 540 1140 539 308 531 1140 539 308 531 308 531 308 532 308 531 306 533 308 531 306 533 308 531 307 533 308 531 1141 539 308 532 308 531 308 531 306 534 306 533 306 534 306 533 306 533 306 533 306 533 306 534 307 532 307 533 306 533 308 532 1141 539 1141 539 308 531 308 532 308 531 307 533 307 481 352 538 307 533 307 532 307 533 307 481 352 539 307 532 307 533 306 482 352 487 352 537 306 534 307 482 352 538 307 482 352 487 1192 539 309 530 307 531 306 483 352 487 352 538 307 482 352 538 306 483 352 487 352 487 352 487 353 486 352 488 353 486 352 487 352 487 353 487 353 486 353 486 353 487 352 487 353 486 353 486 353 486 353 486 353 487 353 487 353 486 353 486 353 487 353 486 353 486 353 486 353 487 353 486 353 487 352 487 353 486 353 486 353 487 353 486 353 486 353 487 353 486 353 487 353 486 353 487 353 486 1193 537 306 483 353 486 353 487 353 486 353 487 353 486 353 486 353 487 353 486 353 486 353 487 353 486 353 486 353 486 353 486 353 487 353 486 353 486 353 486 353 486 353 486 353 486 353 486 1194 485 353 487 1193 538 1142 486 1193 486 353 486 353 486 353 568 -# +# name: Heat_hi type: raw frequency: 38000 duty_cycle: 0.330000 data: 30703 50953 3432 1606 490 1189 490 349 490 349 490 349 490 350 489 350 489 350 489 350 490 350 489 350 489 350 490 350 489 1190 490 350 489 350 489 350 489 350 489 350 490 350 489 350 490 1190 490 1190 489 350 489 350 489 350 489 350 490 350 490 350 489 350 490 350 490 1190 489 350 490 1190 489 1190 490 1190 489 1190 490 1190 489 1190 489 350 490 1190 489 1190 489 350 490 350 489 350 490 350 489 350 489 350 490 350 489 350 490 1190 489 1190 489 1190 490 1190 489 1190 490 1190 489 1190 489 1191 489 350 489 350 489 350 490 1190 490 350 489 350 490 350 489 350 490 1190 489 350 490 350 489 1190 490 350 489 350 490 350 490 350 489 350 489 350 489 1191 489 350 489 350 490 350 489 350 489 1191 489 1190 489 350 489 350 490 350 489 350 490 350 489 351 489 350 489 350 489 350 489 350 490 350 489 350 489 1191 489 350 489 351 489 351 488 351 489 351 488 351 489 350 489 351 489 351 489 1191 488 351 488 351 488 351 489 350 489 351 488 350 490 350 489 351 488 351 488 351 489 350 489 350 489 351 489 351 489 350 489 1191 488 1191 489 350 489 351 488 351 489 351 488 351 489 351 488 351 488 351 489 351 489 351 489 350 489 351 489 351 488 351 488 351 488 351 489 351 488 351 488 351 488 351 489 351 489 1191 488 351 489 351 488 351 489 351 488 351 489 351 489 351 488 351 488 351 489 351 489 351 488 351 488 351 488 351 489 351 488 351 488 351 489 351 488 351 488 351 489 351 489 351 488 351 488 351 489 351 489 351 488 351 489 351 488 351 489 351 488 351 489 351 488 351 489 351 488 351 489 351 488 351 488 351 489 351 488 351 489 351 489 351 489 351 488 351 489 351 488 351 488 351 489 351 488 1192 488 351 488 351 488 351 489 351 488 351 488 351 489 351 489 351 489 351 488 351 488 351 489 351 488 351 489 351 488 351 489 351 488 351 488 351 489 351 488 351 489 351 488 351 489 351 488 351 489 351 489 1191 488 1191 488 352 488 351 488 352 488 351 489 -# +# name: Heat_lo type: raw frequency: 38000 @@ -546,36 +562,37 @@ duty_cycle: 0.330000 data: 30675 50953 3432 1606 490 1190 489 350 489 350 489 350 489 350 489 351 488 350 489 351 489 351 488 351 489 351 488 351 489 1191 488 351 488 351 489 351 488 351 488 351 488 351 489 351 488 1191 489 1191 489 351 488 351 488 351 488 351 488 351 489 351 489 351 488 351 489 1191 488 351 488 1191 489 1191 488 1191 488 1191 488 1191 488 1191 488 351 489 1191 488 1191 489 351 488 351 489 351 488 351 489 351 488 351 488 351 488 351 488 1191 488 1191 488 1191 488 1191 489 1191 488 1191 488 1191 489 1191 488 351 488 351 489 351 488 1191 488 351 489 351 488 351 488 351 489 1191 488 351 489 351 488 1191 488 351 488 351 488 351 489 351 489 351 488 351 489 1191 488 351 488 351 489 351 488 351 488 1191 488 1191 488 351 488 351 489 351 488 351 489 351 488 351 489 351 489 1191 488 1192 488 1191 488 351 489 1191 489 351 488 351 488 351 489 351 489 351 488 351 488 351 489 351 488 351 488 351 488 1192 488 351 489 351 488 351 488 351 489 351 489 351 488 351 488 351 488 352 487 352 488 351 488 352 488 351 488 351 488 351 488 1192 488 1192 487 352 488 352 487 352 487 352 488 352 487 352 488 351 488 352 488 352 488 352 487 352 488 351 488 351 488 352 488 352 487 352 488 352 487 352 488 352 488 352 488 352 487 1192 487 352 487 352 488 352 488 352 488 352 487 352 487 352 488 352 487 352 487 352 487 352 488 352 488 352 487 352 487 352 488 352 487 352 488 352 487 352 487 352 487 352 487 352 487 352 488 352 487 352 487 352 487 352 488 352 487 352 488 352 487 352 488 352 487 352 487 352 488 352 487 352 488 352 487 352 488 352 488 352 487 352 487 352 487 352 487 352 487 352 488 352 487 352 487 352 487 1193 486 352 487 352 488 352 487 352 487 352 488 352 487 352 488 352 488 352 487 352 488 352 487 353 486 353 487 352 487 352 488 352 488 352 487 352 487 352 487 352 487 353 487 352 488 352 488 352 487 1193 486 1193 486 1193 486 1193 487 353 487 352 487 353 486 # # Model: LG PC07SQR +# name: Off type: raw frequency: 38000 duty_cycle: 0.330000 data: 3169 9836 535 1553 511 551 491 543 491 544 490 1586 490 532 510 530 511 543 491 1579 489 1577 490 543 490 543 491 543 491 544 490 544 489 544 490 543 491 544 490 550 492 544 490 543 491 1586 489 542 492 1583 492 552 490 532 510 537 512 1585 491 -# +# name: Dh type: raw frequency: 38000 duty_cycle: 0.330000 data: 3385 9888 512 1544 512 544 489 544 489 544 490 1586 489 545 489 544 489 545 489 531 511 541 508 533 508 542 507 544 489 546 487 544 490 1587 489 1573 510 543 490 543 491 1578 490 545 489 1574 509 545 488 1587 489 1573 510 1586 490 1579 489 1568 507 -# +# name: Cool_hi type: raw frequency: 38000 duty_cycle: 0.330000 data: 3288 9816 598 1504 574 472 569 463 571 463 571 1515 568 472 569 461 573 471 571 459 590 462 571 463 571 447 594 462 572 462 571 464 570 459 590 463 570 464 570 1496 571 1497 570 463 571 1514 569 464 570 1504 572 1514 569 471 571 473 568 462 572 -# +# name: Cool_lo type: raw frequency: 38000 duty_cycle: 0.330000 data: 3205 9865 616 1473 536 518 516 517 517 517 517 1575 517 527 568 464 515 517 571 463 570 462 572 462 572 469 573 461 573 463 570 462 572 469 573 1504 572 451 590 451 591 472 569 463 571 1494 573 461 573 1497 570 1505 570 1503 572 471 571 1491 592 -# +# name: Heat_hi type: raw frequency: 38000 duty_cycle: 0.330000 data: 3363 9846 596 1495 514 518 515 517 517 515 518 1552 516 502 539 517 517 516 518 516 518 517 517 517 571 462 517 518 516 1554 568 461 589 462 572 1505 571 1507 568 1514 514 1568 570 461 573 1504 572 472 570 1507 592 1490 593 460 574 462 572 447 594 -# +# name: Heat_lo type: raw frequency: 38000 @@ -583,38 +600,115 @@ duty_cycle: 0.330000 data: 3204 9889 537 1587 491 529 512 544 489 545 489 1573 510 530 511 543 491 552 490 538 511 543 491 543 491 532 509 543 491 1587 489 537 512 543 491 1577 490 543 491 543 491 544 489 543 491 1586 489 544 490 1587 489 539 510 543 491 543 491 1586 490 # # Model: Daikin FTXC35DV1B +# name: Off type: raw frequency: 38000 duty_cycle: 0.330000 data: 530 315 532 314 532 314 532 314 532 314 506 340 561 24780 3568 1647 507 1213 535 313 534 340 506 340 506 1212 507 339 507 339 506 339 506 339 506 1214 505 341 504 1215 505 1216 504 343 503 1217 503 1218 502 1218 502 1218 502 1218 502 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 1218 502 344 502 1219 501 345 501 344 502 345 501 1219 501 1219 501 345 501 344 502 344 502 345 501 344 502 345 501 344 502 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 1219 501 1219 501 1219 501 345 501 1219 501 345 501 1219 501 1219 501 34807 3563 1652 502 1218 502 344 502 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 1219 501 344 502 1218 502 1219 501 344 502 1219 501 1218 502 1219 501 1219 501 1219 501 345 501 344 502 1219 501 345 501 344 502 345 501 344 502 344 502 345 501 345 501 345 501 344 502 345 501 345 501 1219 501 345 501 345 501 345 501 345 501 1219 501 345 501 345 501 1219 501 345 501 345 501 1219 501 1219 501 345 501 1219 501 1219 501 1219 501 345 501 345 501 345 501 345 501 345 501 345 501 1219 501 345 501 345 501 1220 500 346 500 345 501 346 500 346 500 34806 3564 1652 502 1218 502 344 502 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 1218 502 344 502 1218 502 1218 502 344 502 1218 502 1218 502 1218 502 1219 501 1218 502 344 502 345 501 1219 501 345 501 344 502 345 501 344 502 344 502 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 1219 501 345 501 1219 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 1219 501 1219 501 345 501 345 501 345 501 346 500 345 501 345 501 345 501 345 501 346 500 346 500 346 500 346 500 346 500 1220 499 346 500 1220 499 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 347 499 346 500 1221 499 1221 499 1221 499 347 499 347 499 347 499 347 499 347 499 347 499 347 499 347 499 347 499 1245 475 1222 498 1245 475 371 475 348 498 348 498 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 372 474 372 474 372 474 371 475 371 475 1246 474 371 475 1246 474 372 474 372 474 372 474 1246 474 1246 474 372 474 371 475 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 1246 474 372 474 1246 474 1246 473 372 474 372 474 1246 474 372 474 -# +# name: Dh type: raw frequency: 38000 duty_cycle: 0.330000 data: 536 339 507 311 535 312 534 312 534 312 534 339 507 24807 3710 1507 594 1156 563 305 543 304 542 304 570 1126 592 304 515 304 542 304 542 304 542 1155 564 304 541 1158 505 1215 505 342 504 1217 503 1217 503 1218 502 1218 502 1218 502 344 502 343 503 1218 502 343 503 343 503 344 502 344 502 344 502 344 502 344 502 343 503 343 503 344 502 1218 502 344 502 1218 502 344 502 344 502 344 502 1218 502 1218 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 1218 502 1218 502 1218 501 344 502 1218 502 344 502 1218 502 1218 502 34800 3564 1651 503 1217 503 343 503 344 502 343 503 1217 503 343 503 343 503 344 502 344 502 1218 502 344 502 1217 503 1218 502 344 502 1218 502 1218 502 1218 502 1218 502 1218 502 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 1218 502 344 502 1218 502 1218 502 344 502 344 502 1218 502 1218 502 344 502 1218 502 1219 501 1219 501 345 501 344 502 344 502 344 502 344 502 345 501 345 501 1219 501 345 501 1219 501 345 501 345 501 345 501 345 501 34805 3565 1650 503 1216 503 343 503 343 503 344 502 1217 503 343 503 344 502 343 503 343 503 1217 503 344 502 1218 502 1218 502 344 502 1218 502 1218 502 1218 502 1218 502 1218 502 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 1218 502 344 502 344 502 1218 502 344 502 1218 501 344 502 344 502 344 502 345 501 344 502 345 501 344 502 345 501 1219 501 1219 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 1219 501 345 501 1219 501 345 501 345 501 345 501 345 501 346 500 345 501 345 501 346 500 370 476 346 500 346 500 346 500 370 476 346 500 346 500 346 500 346 500 1221 499 1244 476 1244 476 370 476 346 500 370 476 370 476 370 476 370 476 370 476 370 476 370 476 1244 476 1244 476 1244 476 370 476 370 476 370 476 370 476 370 476 370 476 370 476 370 476 370 476 370 476 370 476 370 476 370 476 370 476 370 476 370 476 1244 476 370 476 1245 475 370 476 371 475 370 476 1245 475 1245 475 371 475 371 475 370 476 370 476 370 476 370 476 370 476 371 475 370 476 371 475 371 475 371 475 371 475 370 476 371 475 371 475 371 475 1245 475 1245 475 1245 475 371 475 371 475 1245 475 371 475 -# +# name: Cool_hi type: raw frequency: 38000 duty_cycle: 0.330000 data: 507 340 559 306 487 341 530 315 531 313 561 305 541 24776 3569 1646 508 1212 537 340 506 340 506 340 506 1213 507 339 507 339 506 339 506 340 505 1214 505 341 504 1215 504 1216 503 343 503 1217 502 1218 502 1218 502 1218 502 1218 501 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 1218 502 344 502 1218 502 344 502 344 502 344 502 1219 501 1218 502 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 1219 501 1219 501 1219 501 345 501 1219 501 345 501 1219 501 1219 501 34800 3563 1652 502 1217 502 344 502 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 1218 502 344 502 1218 502 1218 501 344 502 1218 502 1218 502 1218 502 1218 502 1218 502 344 502 344 502 1218 502 345 501 345 501 344 502 345 501 344 502 345 501 345 501 345 501 344 502 345 501 345 501 1219 501 345 501 345 501 345 501 345 501 1219 501 345 501 1219 501 1219 501 345 501 345 501 1219 501 1219 501 345 501 1219 500 1219 500 1219 500 345 501 345 501 345 501 345 501 345 501 345 501 345 501 1219 501 345 501 1220 500 346 500 346 500 346 500 346 500 34808 3564 1652 503 1218 502 344 502 344 502 344 502 1218 502 344 502 344 502 345 501 344 502 1218 502 345 501 1218 502 1219 501 344 502 1219 501 1219 501 1219 501 1219 501 1219 501 345 501 345 501 1219 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 1219 500 345 501 345 501 1219 500 1219 501 1219 501 345 501 345 501 345 501 345 501 1219 501 345 501 345 501 1219 501 346 500 346 500 345 501 345 501 346 500 346 500 346 500 345 501 346 500 346 500 346 500 346 500 346 500 346 500 346 500 1220 500 346 500 1220 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 347 499 347 499 346 500 1221 499 1245 475 1221 499 347 499 347 499 347 499 348 498 347 499 348 498 348 498 371 475 348 498 1222 498 1245 475 1245 475 348 498 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 372 474 372 474 372 474 371 475 1245 474 372 474 1246 474 372 474 372 474 372 474 1246 474 1246 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 1246 474 372 474 372 474 372 474 372 474 1247 473 1247 473 -# +# name: Cool_lo type: raw frequency: 38000 duty_cycle: 0.330000 data: 533 311 535 312 534 312 534 313 533 310 536 312 534 24804 3705 1509 593 1129 590 305 542 305 542 305 569 1127 590 304 514 305 541 304 542 305 541 1155 564 305 540 1157 561 1159 504 341 504 1217 503 1217 503 1217 503 1218 502 1218 502 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 1218 502 344 502 1218 502 344 502 344 502 344 502 1218 502 1218 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 345 501 1218 502 1218 502 1218 502 344 502 1219 501 345 501 1219 501 1219 501 34806 3565 1650 503 1217 502 343 503 343 503 343 503 1217 503 344 502 344 502 344 502 344 502 1218 502 344 502 1218 502 1218 502 344 502 1218 502 1218 502 1218 502 1218 502 1218 502 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 1218 502 344 502 1219 501 344 502 1218 502 344 502 1219 501 1218 501 345 501 1218 501 1219 501 1218 502 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 1219 501 1219 501 345 501 345 501 345 501 345 501 34805 3565 1651 503 1217 502 343 503 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 1218 502 344 502 1218 502 1218 502 344 502 1218 502 1218 502 1218 502 1218 502 1218 502 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 1218 502 344 502 344 502 1218 502 1219 501 1218 502 345 501 344 502 345 501 1219 501 1219 501 1219 501 345 501 1219 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 1219 501 345 501 1219 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 346 500 346 500 345 501 345 501 346 500 346 500 346 500 346 500 346 500 346 500 1220 500 1221 499 1221 498 346 500 346 500 370 476 346 500 347 499 347 499 370 476 370 476 370 476 1244 476 1244 476 1244 476 370 476 370 476 370 476 370 476 370 476 370 476 370 476 371 475 370 476 370 476 370 476 371 475 370 476 370 476 370 476 370 476 1244 476 371 475 1245 475 370 476 371 475 371 475 1245 475 1245 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 476 371 475 1245 475 1245 475 371 475 371 475 1246 474 1245 475 -# +# name: Heat_lo type: raw frequency: 38000 duty_cycle: 0.330000 data: 535 313 533 311 535 311 535 312 534 312 534 313 533 24805 3711 1506 592 1129 592 305 543 305 540 305 569 1126 592 304 514 304 542 304 541 304 485 1213 507 340 506 1214 506 1215 505 342 504 1217 503 1218 502 1218 502 1218 502 1218 502 344 502 344 502 1218 503 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 1218 502 344 502 1218 502 344 502 344 502 344 502 1218 502 1218 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 503 344 502 1219 501 1219 501 1219 501 345 501 1219 501 345 501 1219 502 1219 502 34818 3566 1651 503 1217 503 343 503 344 502 344 502 1218 502 344 502 344 502 344 502 344 503 1218 502 344 502 1218 503 1218 502 344 502 1218 502 1218 503 1218 503 1218 502 1218 502 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 1218 502 344 502 345 501 344 502 344 502 1219 501 345 501 345 502 1219 501 345 501 1219 502 1219 502 1219 502 344 502 1219 501 1219 502 1219 501 345 501 345 501 345 501 345 501 345 501 345 501 1219 501 345 501 345 501 345 501 1219 501 345 501 345 501 345 501 34812 3566 1651 503 1217 503 344 502 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 1218 503 344 502 1218 502 1218 502 344 502 1218 502 1218 502 1218 502 1219 501 1218 502 344 502 344 502 1218 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 344 502 345 501 344 502 345 501 345 501 1219 502 345 501 345 501 1219 502 345 501 345 501 1219 501 345 501 345 501 1219 501 1219 501 1219 501 345 501 1219 501 345 501 345 501 345 501 345 501 345 501 345 502 345 501 345 501 345 501 346 500 345 501 345 501 345 501 345 501 345 501 1220 500 346 500 1220 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 347 499 346 500 347 499 347 499 370 476 1244 476 1221 499 1244 476 370 476 370 476 370 476 370 476 370 476 370 476 370 476 370 476 370 476 1245 475 1245 476 1245 475 371 475 370 476 370 476 371 475 371 475 370 476 370 476 371 475 371 476 370 476 370 476 371 475 371 475 371 475 371 475 371 475 1245 475 371 475 1245 475 371 475 371 475 371 475 1245 475 1245 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 476 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 371 475 1245 475 1245 475 1245 475 371 475 1245 475 1246 474 -# +# name: Heat_hi type: raw frequency: 38000 duty_cycle: 0.330000 data: 535 314 532 314 533 313 533 312 534 313 533 312 508 24840 3569 1647 508 1213 536 342 505 342 504 341 505 1214 506 340 506 340 506 340 505 340 506 1214 506 341 504 1216 504 1217 503 343 503 1218 502 1219 501 1219 502 1219 502 1219 502 345 502 344 502 1219 502 345 501 345 502 345 502 345 501 345 501 345 501 345 501 345 501 345 502 345 501 1219 502 345 501 1219 501 345 502 345 501 345 501 1219 501 1219 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 1220 500 1219 501 1220 500 345 501 1220 500 345 501 1220 501 1220 500 34815 3564 1653 502 1218 502 344 502 345 501 344 502 1219 501 345 501 345 501 345 501 345 501 1219 502 345 501 1219 502 1220 501 345 502 1219 501 1219 502 1219 501 1219 502 1219 502 345 501 345 501 1220 501 345 502 345 501 345 501 345 501 345 501 345 501 345 502 345 501 345 502 345 501 345 501 1220 501 345 501 345 501 345 501 345 501 1220 500 345 501 346 501 1220 500 1220 501 345 501 345 501 346 500 1220 500 1220 500 1220 500 1220 500 346 500 346 500 346 500 345 501 346 500 345 501 1220 500 346 500 1220 500 1220 500 1220 500 346 500 346 500 346 500 34816 3565 1653 502 1219 501 344 502 345 501 345 501 1219 502 345 501 345 502 345 501 345 501 1219 501 345 501 1219 502 1219 501 345 501 1219 502 1219 501 1219 501 1219 501 1219 501 345 501 345 501 1219 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 345 501 1220 501 346 501 345 501 1220 501 346 500 346 500 1220 500 346 500 345 501 346 500 1220 500 1220 500 1220 501 1220 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 346 500 1220 500 346 500 1220 500 347 499 346 500 346 500 346 500 347 499 347 499 346 500 346 500 347 499 347 499 347 499 347 499 347 499 347 499 347 499 347 499 347 499 1222 498 1222 499 1222 498 347 499 348 498 348 498 347 499 371 475 348 498 348 498 348 498 371 475 1222 498 1246 474 1246 474 372 475 371 475 372 474 372 474 348 498 371 475 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 1246 474 372 474 1246 474 372 474 372 474 372 474 1246 474 1246 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 372 474 1246 474 372 474 1247 473 372 474 1246 474 1246 474 1246 474 +# +# Model: AUX YKR-H/006E +# +name: Off +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8957 4502 539 1683 538 1681 540 559 538 559 538 556 541 557 540 1683 538 1682 539 1684 537 1682 539 1681 540 1684 537 1684 537 1682 539 1684 537 558 539 558 539 558 539 558 539 559 538 558 539 1682 539 1681 540 1683 538 557 540 558 539 558 539 557 540 559 538 557 540 557 540 561 536 559 538 558 539 557 540 558 539 558 539 1683 538 558 539 1682 540 557 540 559 538 557 540 557 540 561 536 558 539 559 538 558 539 560 537 557 540 558 539 558 539 558 539 559 538 558 539 1682 539 557 540 558 539 557 540 557 540 558 539 560 537 557 540 557 540 558 539 559 538 557 540 559 538 556 541 558 539 558 539 558 539 556 541 559 538 557 540 558 539 558 539 558 539 557 540 558 539 557 541 557 540 557 540 559 538 558 539 558 539 558 539 558 539 1681 540 557 540 1683 538 558 539 559 538 557 540 559 538 559 538 1683 538 1683 538 1683 538 557 540 558 539 558 540 1683 538 560 563 +# +name: Dh +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8956 4504 536 1684 537 1687 534 559 538 559 538 559 538 560 537 1683 538 1685 536 1682 539 1684 537 1683 538 1684 537 1683 538 1684 537 1683 538 558 539 562 535 559 538 558 539 562 535 560 537 1683 538 1684 537 1683 538 561 536 561 536 561 537 560 537 561 536 558 539 560 537 559 538 560 537 561 536 561 536 563 534 559 538 1684 537 559 538 1684 537 561 536 560 537 560 537 560 537 560 537 560 537 559 538 559 538 559 538 588 509 558 539 559 538 559 538 564 533 1684 537 559 538 560 537 559 538 588 509 563 534 559 538 559 538 558 539 562 535 558 539 561 536 560 537 560 537 559 538 588 509 561 536 560 537 561 536 563 534 561 536 560 537 561 536 1684 537 559 538 559 538 559 538 561 536 560 537 560 537 559 538 561 536 558 539 560 537 1684 537 559 538 1683 538 561 536 561 536 563 534 559 538 558 539 1683 538 1684 537 1684 537 560 537 560 537 1683 538 560 537 560 563 +# +name: Cool_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8957 4502 538 1683 538 1684 537 562 535 560 537 559 538 559 539 1683 538 1682 539 1711 510 1685 536 1683 538 558 539 588 509 557 540 1682 539 557 540 558 539 559 538 559 538 558 539 561 536 1681 540 1682 539 1683 538 559 538 559 538 559 538 561 536 560 537 559 538 558 539 559 538 559 538 559 538 559 538 560 537 560 537 1685 536 560 537 1685 536 560 537 559 538 560 537 560 537 559 538 558 539 559 538 560 537 587 510 562 535 559 538 560 537 557 540 1685 536 559 538 560 537 587 510 588 509 559 538 562 535 560 537 557 540 559 538 557 540 560 537 587 510 560 538 558 539 559 538 559 538 561 536 560 537 560 537 558 540 560 537 559 538 560 537 1683 538 562 535 560 537 559 538 560 537 558 539 559 538 558 539 560 537 560 537 559 538 1683 538 558 539 1684 537 559 538 558 539 559 538 558 539 558 539 1682 539 1684 537 1684 537 1683 538 560 537 558 539 1683 538 1684 564 +# +name: Cool_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8956 4501 539 1682 539 1682 539 559 538 557 540 587 510 558 539 1684 537 1682 539 1682 539 1682 539 1680 541 1682 539 1682 539 1682 539 1681 540 558 539 558 539 558 539 557 540 558 539 557 540 1683 538 1683 538 1683 538 558 539 558 539 558 539 557 540 560 537 560 537 557 540 558 539 557 540 558 539 557 540 560 537 558 539 1681 540 556 541 1684 537 558 539 557 540 559 538 558 539 557 540 558 539 558 539 560 537 559 538 558 539 558 539 557 540 559 538 1685 536 559 538 558 539 587 510 557 540 559 538 559 538 560 537 560 537 558 539 559 538 558 539 559 538 562 535 558 539 557 540 557 540 559 538 559 538 558 539 559 538 558 539 558 539 557 540 1682 539 557 540 558 539 559 538 557 540 558 539 560 537 559 538 557 540 561 536 558 539 1682 539 558 539 1682 539 559 538 557 540 558 539 559 538 559 538 1682 539 1684 537 1683 538 557 540 558 539 558 539 560 537 559 564 +# +name: Heat_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8959 4502 539 1682 539 1682 539 556 541 559 538 558 539 559 538 1680 541 1681 540 1684 537 1683 538 1684 537 557 540 560 537 558 539 1683 538 1682 539 558 539 559 538 559 538 558 539 558 539 1683 538 1681 540 1683 538 559 538 560 537 560 537 559 538 561 536 560 537 559 538 559 538 559 538 559 538 559 538 560 537 557 540 1682 539 557 540 1682 539 559 538 558 539 560 538 558 539 558 539 558 539 558 539 558 539 559 538 559 538 557 540 558 539 558 539 559 538 560 537 1684 537 561 536 557 540 559 538 559 538 557 540 558 539 559 538 560 537 558 539 558 539 559 538 558 539 559 539 559 538 557 540 559 538 557 540 558 540 561 536 558 539 558 539 1683 538 558 539 559 538 557 540 559 538 557 540 558 539 559 538 559 538 558 539 559 538 1681 540 558 539 1684 537 562 535 560 537 559 538 559 538 560 537 1682 539 1682 539 1682 539 1686 535 559 538 1682 539 559 538 1682 565 +# +name: Heat_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8961 4501 539 1681 540 1681 540 559 538 558 539 558 539 557 540 1682 539 1682 539 1681 540 1682 539 1682 539 1683 538 1682 539 1683 538 1682 539 557 540 560 537 558 539 560 537 560 537 558 539 1681 540 1681 540 1682 539 557 540 558 539 561 536 558 539 560 537 558 539 556 541 558 539 558 539 557 540 559 538 558 539 559 538 1684 537 559 538 1682 539 558 539 556 541 559 538 562 535 556 541 558 539 558 539 557 540 558 539 557 540 558 539 559 538 560 537 557 540 557 540 1682 539 558 539 557 540 558 539 559 538 559 538 557 540 558 539 558 539 558 539 558 539 557 540 561 536 558 539 586 511 558 539 557 540 586 511 559 539 556 541 557 540 557 540 1682 539 559 538 558 539 558 539 559 538 558 539 560 537 558 539 559 538 558 539 557 540 1681 540 558 539 1680 541 557 540 557 540 559 538 558 539 559 538 1682 539 1682 539 1682 539 558 539 558 539 1682 539 1682 539 558 565 +# +# Model: Carrier 42QG5A580SC +# +name: Off +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8403 4308 519 1425 518 625 520 1461 485 1427 518 559 517 564 567 1386 518 1429 517 562 597 524 519 1431 517 1430 518 567 516 1426 518 565 517 1429 518 1431 518 1425 519 565 517 1457 485 562 518 1429 519 1424 520 565 516 1426 517 561 519 1430 515 1427 518 563 595 525 518 1428 517 528 489 21085 8424 4296 642 467 568 1400 569 533 569 536 647 1402 569 1395 569 535 568 534 569 1405 566 1397 567 549 568 535 569 1401 567 533 570 1399 571 537 570 534 568 537 567 1397 570 535 571 1401 568 534 567 533 567 1399 567 539 568 1402 569 565 569 532 571 1399 571 1397 569 535 566 1358 489 21085 8401 4318 512 1438 517 573 515 1476 532 1389 516 573 518 609 535 1393 568 1392 516 574 567 528 566 1393 565 1390 516 576 516 1437 517 574 517 1441 516 1445 567 1389 517 578 566 1390 516 578 568 1398 566 1392 515 575 516 1437 516 574 517 1442 567 1425 483 597 515 575 516 1446 514 539 490 +# +name: Dh +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8391 4318 536 1417 518 564 516 1432 517 1428 518 563 518 562 517 1433 516 1428 518 564 519 565 513 1433 517 1430 517 562 518 1463 483 561 517 1430 516 1428 518 563 595 1393 516 559 519 565 514 1425 519 1429 517 569 514 1426 518 566 514 1466 485 562 518 559 518 561 518 1425 519 531 488 21116 8369 4318 569 534 641 1326 640 462 641 465 641 1330 641 1325 639 464 568 534 595 1403 641 1328 641 462 639 467 640 1328 568 536 642 1367 568 531 567 536 569 1398 568 537 542 1432 640 1327 567 532 568 535 567 1400 567 539 567 1399 568 536 568 1402 569 1402 568 1401 567 537 565 1359 487 21117 8392 4294 565 1388 517 575 566 1393 516 1443 514 574 516 573 517 1443 567 1391 515 574 516 577 566 1393 565 1390 566 528 567 1392 516 575 567 1395 565 1390 515 576 568 1391 515 572 566 528 565 1395 565 1393 515 572 564 1391 515 581 563 1389 516 578 513 609 483 576 566 1391 514 538 487 +# +name: Cool_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8424 4292 514 1428 518 559 518 1431 514 1432 517 561 515 566 512 1433 516 1434 516 562 519 562 516 1432 517 1426 518 566 516 1429 517 566 516 1429 518 1428 517 562 516 1467 481 570 517 561 518 565 519 563 515 566 516 567 516 1433 516 1429 514 564 518 561 518 562 519 1428 519 536 562 21009 8478 4280 638 461 641 1328 641 456 642 467 637 1325 643 1326 568 597 568 537 639 1330 641 1327 568 535 640 468 639 1324 568 534 543 1432 566 535 641 494 637 1327 566 532 640 1329 567 1398 640 1327 641 1327 640 1326 642 1328 568 531 568 538 567 1402 567 1406 566 1402 568 532 569 1357 489 21085 8401 4319 565 1394 516 577 567 1396 565 1390 515 574 543 566 516 1441 568 1392 516 575 566 531 566 1393 567 1390 516 576 515 1456 515 579 562 1392 515 1440 515 575 566 1391 516 576 544 569 563 525 516 574 514 606 514 576 514 1439 567 1390 515 575 515 574 570 566 567 1390 515 540 488 +# +name: Cool_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8401 4306 518 1460 483 566 518 1432 517 1430 514 561 516 564 517 1429 518 1430 519 592 485 564 517 1427 517 1432 516 561 545 1430 516 566 518 1462 483 1430 515 568 517 1427 516 566 516 564 517 1430 518 1425 518 559 518 562 518 1426 518 1425 517 593 484 561 516 573 516 1427 517 530 564 21007 8401 4322 642 465 643 1324 643 457 643 458 643 1327 643 1327 641 463 642 461 644 1325 644 1324 643 462 642 483 643 1328 641 460 645 1321 643 458 643 464 641 1325 643 459 644 1327 642 1323 643 461 643 461 642 1347 644 1331 641 463 639 462 641 1327 571 1405 542 1428 670 462 645 1282 562 21007 8402 4317 515 1436 517 606 641 1321 516 1438 517 572 515 578 516 1441 515 1440 516 572 515 575 515 1474 610 1316 515 574 644 1314 516 574 567 1394 640 1316 517 578 639 1319 516 576 517 575 513 1447 641 1315 516 576 515 577 566 1396 514 1440 516 573 518 571 638 456 565 1393 515 538 564 +# +name: Heat_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8399 4307 519 1426 518 560 517 1432 517 1460 485 561 518 558 517 1436 518 1427 518 555 520 561 517 1430 519 1428 516 560 519 1425 518 566 517 1430 516 1432 519 563 519 1425 518 563 515 1429 517 1433 517 1430 516 1432 518 1429 518 568 516 1432 515 1429 519 561 516 567 517 1427 519 533 487 21083 8424 4339 567 536 568 1402 641 493 608 462 545 1431 640 1326 567 532 568 538 640 1331 640 1329 641 536 565 534 641 1329 567 537 639 1329 640 462 642 467 641 1325 568 532 642 1332 640 488 568 534 565 536 566 566 536 567 641 1329 570 535 638 464 569 1401 641 1326 568 534 639 1287 490 21083 8403 4313 567 1390 516 579 514 1441 515 1438 517 575 516 576 568 1393 568 1394 515 606 534 530 515 1441 567 1425 482 576 568 1392 514 578 566 1392 569 1432 515 576 568 1389 517 577 515 1444 515 1437 569 1393 516 1444 566 1389 566 528 567 1394 566 1419 517 575 513 578 515 1440 516 539 490 +# +name: Heat_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8425 4291 542 1401 544 538 542 1404 518 1427 544 534 570 540 516 1434 542 1399 544 539 544 539 541 1403 541 1402 516 570 517 1427 545 566 511 1406 517 1431 542 534 544 1406 543 536 517 567 543 1404 542 1400 595 525 544 1405 542 534 516 1433 516 1428 544 537 544 535 543 1403 542 505 488 21084 8424 4298 566 535 569 1402 567 533 568 537 570 1403 570 1403 565 534 566 537 566 1402 569 1398 569 533 569 538 592 1446 569 535 570 1400 569 567 535 535 568 1437 568 533 568 1398 569 1402 565 533 567 534 569 1403 568 536 569 1402 568 535 567 534 571 1403 568 1415 566 536 571 1362 489 21084 8403 4313 516 1439 517 574 515 1442 515 1441 518 573 516 574 567 1397 514 1440 515 573 516 575 516 1443 515 1439 518 574 516 1440 517 608 535 1396 517 1441 517 579 515 1438 515 576 517 578 568 1390 569 1391 516 575 518 1439 516 573 517 1445 566 1391 516 571 517 572 516 1441 514 543 487 From 8c4716f170db6c4d8e15265fc4fa68fec2296496 Mon Sep 17 00:00:00 2001 From: MarcelSchm Date: Fri, 15 Dec 2023 20:07:01 +0100 Subject: [PATCH 16/44] added new TV Philips OLED 934/12 (#3293) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- .../infrared/resources/infrared/assets/tv.ir | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/applications/main/infrared/resources/infrared/assets/tv.ir b/applications/main/infrared/resources/infrared/assets/tv.ir index 86b11e8a7..d10e14df2 100644 --- a/applications/main/infrared/resources/infrared/assets/tv.ir +++ b/applications/main/infrared/resources/infrared/assets/tv.ir @@ -1686,3 +1686,41 @@ type: parsed protocol: NEC address: 40 00 00 00 command: 10 00 00 00 +# +# Philips OLED 934/12 +# +name: Power +type: parsed +protocol: RC6 +address: 00 00 00 00 +command: 0C 00 00 00 +# +name: Mute +type: parsed +protocol: RC6 +address: 00 00 00 00 +command: 0D 00 00 00 +# +name: Vol_up +type: parsed +protocol: RC6 +address: 00 00 00 00 +command: 10 00 00 00 +# +name: Vol_dn +type: parsed +protocol: RC6 +address: 00 00 00 00 +command: 11 00 00 00 +# +name: Ch_next +type: parsed +protocol: RC6 +address: 00 00 00 00 +command: 20 00 00 00 +# +name: Ch_prev +type: parsed +protocol: RC6 +address: 00 00 00 00 +command: 21 00 00 00 From 364b33465416ea7f4bc1a71425fa5e4795c34083 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Sat, 16 Dec 2023 02:33:00 +0300 Subject: [PATCH 17/44] fix dict remove dupes --- .../main/nfc/resources/nfc/assets/mf_classic_dict.nfc | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/applications/main/nfc/resources/nfc/assets/mf_classic_dict.nfc b/applications/main/nfc/resources/nfc/assets/mf_classic_dict.nfc index ee436125d..02435c601 100644 --- a/applications/main/nfc/resources/nfc/assets/mf_classic_dict.nfc +++ b/applications/main/nfc/resources/nfc/assets/mf_classic_dict.nfc @@ -3828,11 +3828,6 @@ F72CD208FDF9 555D8BBC2D3E 78DF1176C8FD ADC169F922CB - -# PIK Comfort Moscow keys (ISBC Mifare Plus SE 1K) -009FB42D98ED -002E626E2820 - # Volgograd (Russia) Volna transport cards keys 2B787A063D5D -D37C8F1793F7 \ No newline at end of file +D37C8F1793F7 From ebe1a8f55f22368e7c0f5795d9045b24c300d363 Mon Sep 17 00:00:00 2001 From: Methodius Date: Sat, 16 Dec 2023 23:57:46 +0900 Subject: [PATCH 18/44] parsers cleanup for new api --- applications/main/nfc/plugins/supported_cards/kazan.c | 7 +++---- applications/main/nfc/plugins/supported_cards/metromoney.c | 5 ++--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/applications/main/nfc/plugins/supported_cards/kazan.c b/applications/main/nfc/plugins/supported_cards/kazan.c index 18e4da1ee..e0179be5b 100644 --- a/applications/main/nfc/plugins/supported_cards/kazan.c +++ b/applications/main/nfc/plugins/supported_cards/kazan.c @@ -250,19 +250,18 @@ static bool kazan_parse(const NfcDevice* device, FuriString* parsed_data) { last_trip.day = block_start_ptr[2]; last_trip.hour = block_start_ptr[3]; last_trip.minute = block_start_ptr[4]; - bool is_last_trip_valid = (block_start_ptr[0] | block_start_ptr[1] | block_start_ptr[0]) && + bool is_last_trip_valid = (block_start_ptr[0] | block_start_ptr[1] | block_start_ptr[2]) && (last_trip.day < 32 && last_trip.month < 12 && last_trip.hour < 24 && last_trip.minute < 60); start_block_num = mf_classic_get_first_block_num_of_sector(balance_sector_number); block_start_ptr = &data->block[start_block_num].data[0]; - const uint32_t trip_counter = (block_start_ptr[3] << 24) | (block_start_ptr[2] << 16) | - (block_start_ptr[1] << 8) | (block_start_ptr[0]); + const uint32_t trip_counter = nfc_util_bytes2num_little_endian(block_start_ptr, 4); size_t uid_len = 0; const uint8_t* uid = mf_classic_get_uid(data, &uid_len); - const uint32_t card_number = (uid[3] << 24) | (uid[2] << 16) | (uid[1] << 8) | (uid[0]); + const uint32_t card_number = nfc_util_bytes2num_little_endian(uid, 4); furi_string_cat_printf( parsed_data, "\e#Kazan transport card\nCard number: %lu\n", card_number); diff --git a/applications/main/nfc/plugins/supported_cards/metromoney.c b/applications/main/nfc/plugins/supported_cards/metromoney.c index 263bbc44e..b094d055a 100644 --- a/applications/main/nfc/plugins/supported_cards/metromoney.c +++ b/applications/main/nfc/plugins/supported_cards/metromoney.c @@ -148,15 +148,14 @@ static bool metromoney_parse(const NfcDevice* device, FuriString* parsed_data) { const uint8_t* block_start_ptr = &data->block[start_block_num + ticket_block_number].data[0]; - uint32_t balance = (block_start_ptr[3] << 24) | (block_start_ptr[2] << 16) | - (block_start_ptr[1] << 8) | (block_start_ptr[0]); + uint32_t balance = nfc_util_bytes2num_little_endian(block_start_ptr, 4); uint32_t balance_lari = balance / 100; uint8_t balance_tetri = balance % 100; size_t uid_len = 0; const uint8_t* uid = mf_classic_get_uid(data, &uid_len); - uint32_t card_number = (uid[3] << 24) | (uid[2] << 16) | (uid[1] << 8) | (uid[0]); + uint32_t card_number = nfc_util_bytes2num_little_endian(uid, 4); furi_string_printf( parsed_data, From c53f5aa5b551b518c6cac2f02a1d8c38782a42f2 Mon Sep 17 00:00:00 2001 From: Methodius Date: Sun, 17 Dec 2023 04:58:07 +0900 Subject: [PATCH 19/44] Zolotaya Korona transport card parser added --- applications/main/nfc/application.fam | 9 + .../plugins/supported_cards/zolotaya_korona.c | 254 ++++++++++++++++++ 2 files changed, 263 insertions(+) create mode 100644 applications/main/nfc/plugins/supported_cards/zolotaya_korona.c diff --git a/applications/main/nfc/application.fam b/applications/main/nfc/application.fam index 4a31458d8..1b999e37e 100644 --- a/applications/main/nfc/application.fam +++ b/applications/main/nfc/application.fam @@ -137,6 +137,15 @@ App( sources=["plugins/supported_cards/mykey.c"], ) +App( + appid="zolotaya_korona_parser", + apptype=FlipperAppType.PLUGIN, + entry_point="zolotaya_korona_plugin_ep", + targets=["f7"], + requires=["nfc"], + sources=["plugins/supported_cards/zolotaya_korona.c"], +) + App( appid="nfc_start", targets=["f7"], diff --git a/applications/main/nfc/plugins/supported_cards/zolotaya_korona.c b/applications/main/nfc/plugins/supported_cards/zolotaya_korona.c new file mode 100644 index 000000000..1c48f967a --- /dev/null +++ b/applications/main/nfc/plugins/supported_cards/zolotaya_korona.c @@ -0,0 +1,254 @@ +/* + * Parser for Zolotaya Korona card (Russia). + * + * Copyright 2023 Leptoptilos + * + * More info about Zolotaya Korona cards: https://github.com/metrodroid/metrodroid/wiki/Zolotaya-Korona + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "core/core_defines.h" +#include "core/string.h" +#include "furi_hal_rtc.h" +#include "nfc_supported_card_plugin.h" + +#include "protocols/mf_classic/mf_classic.h" +#include + +#include +#include +#include +#include +#include + +#define TAG "Zolotaya Korona" + +#define TRIP_SECTOR_NUM (4) +#define PURSE_SECTOR_NUM (6) +#define INFO_SECTOR_NUM (15) + +typedef struct { + uint64_t a; + uint64_t b; +} MfClassicKeyPair; + +// Sector 15 data. Byte [11] contains the mistake. If byte [11] was 0xEF, bytes [1-18] means "ЗАО Золотая Корона" +static const uint8_t info_sector_signature[] = {0xE2, 0x87, 0x80, 0x8E, 0x20, 0x87, 0xAE, + 0xAB, 0xAE, 0xF2, 0xA0, 0xEF, 0x20, 0x8A, + 0xAE, 0xE0, 0xAE, 0xAD, 0xA0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + +#define FURI_HAL_RTC_SECONDS_PER_MINUTE 60 +#define FURI_HAL_RTC_SECONDS_PER_HOUR (FURI_HAL_RTC_SECONDS_PER_MINUTE * 60) +#define FURI_HAL_RTC_SECONDS_PER_DAY (FURI_HAL_RTC_SECONDS_PER_HOUR * 24) +#define FURI_HAL_RTC_EPOCH_START_YEAR 1970 + +void timestamp_to_datetime(uint32_t timestamp, FuriHalRtcDateTime* datetime) { + uint32_t days = timestamp / FURI_HAL_RTC_SECONDS_PER_DAY; + uint32_t seconds_in_day = timestamp % FURI_HAL_RTC_SECONDS_PER_DAY; + + datetime->year = FURI_HAL_RTC_EPOCH_START_YEAR; + + while(days >= furi_hal_rtc_get_days_per_year(datetime->year)) { + days -= furi_hal_rtc_get_days_per_year(datetime->year); + (datetime->year)++; + } + + datetime->month = 1; + while(days >= furi_hal_rtc_get_days_per_month( + furi_hal_rtc_is_leap_year(datetime->year), datetime->month)) { + days -= furi_hal_rtc_get_days_per_month( + furi_hal_rtc_is_leap_year(datetime->year), datetime->month); + (datetime->month)++; + } + + datetime->day = days + 1; + datetime->hour = seconds_in_day / FURI_HAL_RTC_SECONDS_PER_HOUR; + datetime->minute = + (seconds_in_day % FURI_HAL_RTC_SECONDS_PER_HOUR) / FURI_HAL_RTC_SECONDS_PER_MINUTE; + datetime->second = seconds_in_day % FURI_HAL_RTC_SECONDS_PER_MINUTE; +} + +uint64_t bytes2num_bcd(const uint8_t* src, uint8_t len_bytes) { + furi_assert(src); + + uint64_t res = 0; + + for(uint8_t i = 0; i < len_bytes; i++) { + res *= 10; + res += src[i] / 16; + res *= 10; + res += src[i] % 16; + } + + return res; +} + +static bool zolotaya_korona_parse(const NfcDevice* device, FuriString* parsed_data) { + furi_assert(device); + + const MfClassicData* data = nfc_device_get_data(device, NfcProtocolMfClassic); + + bool parsed = false; + + do { + // Verify info sector data + const uint8_t start_info_block_number = + mf_classic_get_first_block_num_of_sector(INFO_SECTOR_NUM); + const uint8_t* block_start_ptr = &data->block[start_info_block_number].data[0]; + + bool verified = true; + for(uint8_t i = 0; i < sizeof(info_sector_signature); i++) { + if(i == 16) { + block_start_ptr = &data->block[start_info_block_number + 1].data[0]; + } + if(block_start_ptr[i % 16] != info_sector_signature[i]) { + verified = false; + break; + } + } + + if(!verified) break; + + // Parse data + + // INFO SECTOR + // block 1 + const uint8_t region_number = bytes2num_bcd(block_start_ptr + 10, 1); + + // block 2 + block_start_ptr = &data->block[start_info_block_number + 2].data[4]; + const uint64_t card_number = + bytes2num_bcd(block_start_ptr, 9) * 10 + bytes2num_bcd(block_start_ptr + 9, 1) / 10; + + // TRIP SECTOR + const uint8_t start_trip_block_number = + mf_classic_get_first_block_num_of_sector(TRIP_SECTOR_NUM); + // block 0 + block_start_ptr = &data->block[start_trip_block_number].data[7]; + + const uint8_t status = block_start_ptr[0] % 16; + const uint16_t sequence_number = nfc_util_bytes2num(block_start_ptr + 1, 2); + const uint8_t discount_code = nfc_util_bytes2num(block_start_ptr + 3, 1); + + // block 1: refill block + block_start_ptr = &data->block[start_trip_block_number + 1].data[1]; + + const uint16_t refill_machine_id = nfc_util_bytes2num_little_endian(block_start_ptr, 2); + const uint32_t last_refill_timestamp = + nfc_util_bytes2num_little_endian(block_start_ptr + 2, 4); + const uint32_t last_refill_amount = + nfc_util_bytes2num_little_endian(block_start_ptr + 6, 4); + const uint32_t last_refill_amount_rub = last_refill_amount / 100; + const uint8_t last_refill_amount_kop = last_refill_amount % 100; + const uint16_t refill_counter = nfc_util_bytes2num_little_endian(block_start_ptr + 10, 2); + + FuriHalRtcDateTime last_refill_datetime = {0}; + timestamp_to_datetime(last_refill_timestamp, &last_refill_datetime); + + // block 2: trip block + block_start_ptr = &data->block[start_trip_block_number + 2].data[0]; + const char validator_first_letter = + nfc_util_bytes2num_little_endian(block_start_ptr + 1, 1); + const uint32_t validator_id = bytes2num_bcd(block_start_ptr + 2, 3); + const uint32_t last_trip_timestamp = + nfc_util_bytes2num_little_endian(block_start_ptr + 6, 4); + const uint8_t track_number = nfc_util_bytes2num_little_endian(block_start_ptr + 10, 1); + const uint32_t prev_balance = nfc_util_bytes2num_little_endian(block_start_ptr + 11, 4); + const uint32_t prev_balance_rub = prev_balance / 100; + const uint8_t prev_balance_kop = prev_balance % 100; + + FuriHalRtcDateTime last_trip_datetime = {0}; + timestamp_to_datetime(last_trip_timestamp, &last_trip_datetime); + + // PARSE DATA FROM PURSE SECTOR + const uint8_t start_purse_block_number = + mf_classic_get_first_block_num_of_sector(PURSE_SECTOR_NUM); + block_start_ptr = &data->block[start_purse_block_number].data[0]; + + // block 0 + uint32_t balance = nfc_util_bytes2num_little_endian(block_start_ptr, 4); + + uint32_t balance_rub = balance / 100; + uint8_t balance_kop = balance % 100; + + furi_string_cat_printf( + parsed_data, + "\e#Zolotaya korona\nCard number: %llu\nRegion: %u\nBalance: %lu.%02u RUR\nPrev. balance: %lu.%02u RUR", + card_number, + region_number, + balance_rub, + balance_kop, + prev_balance_rub, + prev_balance_kop); + + furi_string_cat_printf( + parsed_data, + "\nLast refill amount: %lu.%02u RUR\nRefill counter: %u\nLast refill: %u.%02u.%02u %02u:%02u\nRefill machine id: %u", + last_refill_amount_rub, + last_refill_amount_kop, + refill_counter, + last_refill_datetime.day, + last_refill_datetime.month, + last_refill_datetime.year, + last_refill_datetime.hour, + last_refill_datetime.minute, + refill_machine_id); + + furi_string_cat_printf( + parsed_data, + "\nLast trip: %u.%02u.%02u %02u:%02u\nTrack number: %u\nValidator: %c%06lu", + last_trip_datetime.day, + last_trip_datetime.month, + last_trip_datetime.year, + last_trip_datetime.hour, + last_trip_datetime.minute, + track_number, + validator_first_letter, + validator_id); + + if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { + furi_string_cat_printf( + parsed_data, + "\nStatus: %u\nSequence num: %u\nDiscount code: %u", + status, + sequence_number, + discount_code); + } + + parsed = true; + } while(false); + + return parsed; +} + +/* Actual implementation of app<>plugin interface */ +static const NfcSupportedCardsPlugin zolotaya_korona_plugin = { + .protocol = NfcProtocolMfClassic, + .verify = NULL, + .read = NULL, + .parse = zolotaya_korona_parse, +}; + +/* Plugin descriptor to comply with basic plugin specification */ +static const FlipperAppPluginDescriptor zolotaya_korona_plugin_descriptor = { + .appid = NFC_SUPPORTED_CARD_PLUGIN_APP_ID, + .ep_api_version = NFC_SUPPORTED_CARD_PLUGIN_API_VERSION, + .entry_point = &zolotaya_korona_plugin, +}; + +/* Plugin entry point - must return a pointer to const descriptor */ +const FlipperAppPluginDescriptor* zolotaya_korona_plugin_ep() { + return &zolotaya_korona_plugin_descriptor; +} \ No newline at end of file From 238187730c56b1dc59fd653d7984997e69508278 Mon Sep 17 00:00:00 2001 From: ushastoe Date: Mon, 18 Dec 2023 11:41:54 +0300 Subject: [PATCH 20/44] [IR] change percent on number change percent on number in ir brute --- applications/main/infrared/views/infrared_progress_view.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/applications/main/infrared/views/infrared_progress_view.c b/applications/main/infrared/views/infrared_progress_view.c index 432da7ff1..1f491e4ab 100644 --- a/applications/main/infrared/views/infrared_progress_view.c +++ b/applications/main/infrared/views/infrared_progress_view.c @@ -54,11 +54,11 @@ static void infrared_progress_view_draw_callback(Canvas* canvas, void* _model) { float progress_value = (float)model->progress / model->progress_total; elements_progress_bar(canvas, x + 4, y + 19, width - 7, progress_value); - uint8_t percent_value = 100 * model->progress / model->progress_total; - char percents_string[10] = {0}; - snprintf(percents_string, sizeof(percents_string), "%d%%", percent_value); + char number_string[10] = {0}; + snprintf( + number_string, sizeof(number_string), "%d/%d", model->progress, model->progress_total); elements_multiline_text_aligned( - canvas, x + 33, y + 37, AlignCenter, AlignCenter, percents_string); + canvas, x + 33, y + 37, AlignCenter, AlignCenter, number_string); canvas_draw_icon(canvas, x + 14, y + height - 14, &I_Pin_back_arrow_10x8); canvas_draw_str(canvas, x + 30, y + height - 6, "= stop"); From 7642d67cae89d4f9eed908ea01f514c7e52704c4 Mon Sep 17 00:00:00 2001 From: Andrea Maugeri Date: Mon, 18 Dec 2023 15:30:56 +0100 Subject: [PATCH 21/44] NfcDict Refactoring (#3271) * toolbox(keys_dict): generalize nfc_dict * nfc: rework nfc app and tests * toolbox(keys_dict): improve code readability --- applications/debug/unit_tests/nfc/nfc_test.c | 46 +-- applications/main/nfc/helpers/mf_user_dict.c | 20 +- applications/main/nfc/nfc_app_i.h | 4 +- .../scenes/nfc_scene_mf_classic_dict_attack.c | 29 +- .../nfc/scenes/nfc_scene_mf_classic_keys.c | 16 +- .../scenes/nfc_scene_mf_classic_keys_add.c | 10 +- lib/nfc/SConscript | 1 - lib/nfc/helpers/nfc_dict.c | 270 -------------- lib/nfc/helpers/nfc_dict.h | 103 ------ lib/toolbox/SConscript | 1 + lib/toolbox/keys_dict.c | 335 ++++++++++++++++++ lib/toolbox/keys_dict.h | 103 ++++++ targets/f18/api_symbols.csv | 12 +- targets/f7/api_symbols.csv | 22 +- 14 files changed, 524 insertions(+), 448 deletions(-) delete mode 100644 lib/nfc/helpers/nfc_dict.c delete mode 100644 lib/nfc/helpers/nfc_dict.h create mode 100644 lib/toolbox/keys_dict.c create mode 100644 lib/toolbox/keys_dict.h diff --git a/applications/debug/unit_tests/nfc/nfc_test.c b/applications/debug/unit_tests/nfc/nfc_test.c index 0dcd09046..29b9e80d9 100644 --- a/applications/debug/unit_tests/nfc/nfc_test.c +++ b/applications/debug/unit_tests/nfc/nfc_test.c @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include "../minunit.h" @@ -443,36 +443,36 @@ MU_TEST(mf_classic_dict_test) { "Remove test dict failed"); } - NfcDict* dict = nfc_dict_alloc( - NFC_APP_MF_CLASSIC_DICT_UNIT_TEST_PATH, NfcDictModeOpenAlways, sizeof(MfClassicKey)); - mu_assert(dict != NULL, "nfc_dict_alloc() failed"); + KeysDict* dict = keys_dict_alloc( + NFC_APP_MF_CLASSIC_DICT_UNIT_TEST_PATH, KeysDictModeOpenAlways, sizeof(MfClassicKey)); + mu_assert(dict != NULL, "keys_dict_alloc() failed"); - size_t dict_keys_total = nfc_dict_get_total_keys(dict); - mu_assert(dict_keys_total == 0, "nfc_dict_keys_total() failed"); + size_t dict_keys_total = keys_dict_get_total_keys(dict); + mu_assert(dict_keys_total == 0, "keys_dict_keys_total() failed"); const uint32_t test_key_num = 30; MfClassicKey* key_arr_ref = malloc(test_key_num * sizeof(MfClassicKey)); for(size_t i = 0; i < test_key_num; i++) { furi_hal_random_fill_buf(key_arr_ref[i].data, sizeof(MfClassicKey)); mu_assert( - nfc_dict_add_key(dict, key_arr_ref[i].data, sizeof(MfClassicKey)), "add key failed"); + keys_dict_add_key(dict, key_arr_ref[i].data, sizeof(MfClassicKey)), "add key failed"); - size_t dict_keys_total = nfc_dict_get_total_keys(dict); - mu_assert(dict_keys_total == (i + 1), "nfc_dict_keys_total() failed"); + size_t dict_keys_total = keys_dict_get_total_keys(dict); + mu_assert(dict_keys_total == (i + 1), "keys_dict_keys_total() failed"); } - nfc_dict_free(dict); + keys_dict_free(dict); - dict = nfc_dict_alloc( - NFC_APP_MF_CLASSIC_DICT_UNIT_TEST_PATH, NfcDictModeOpenAlways, sizeof(MfClassicKey)); - mu_assert(dict != NULL, "nfc_dict_alloc() failed"); + dict = keys_dict_alloc( + NFC_APP_MF_CLASSIC_DICT_UNIT_TEST_PATH, KeysDictModeOpenAlways, sizeof(MfClassicKey)); + mu_assert(dict != NULL, "keys_dict_alloc() failed"); - dict_keys_total = nfc_dict_get_total_keys(dict); - mu_assert(dict_keys_total == test_key_num, "nfc_dict_keys_total() failed"); + dict_keys_total = keys_dict_get_total_keys(dict); + mu_assert(dict_keys_total == test_key_num, "keys_dict_keys_total() failed"); MfClassicKey key_dut = {}; size_t key_idx = 0; - while(nfc_dict_get_next_key(dict, key_dut.data, sizeof(MfClassicKey))) { + while(keys_dict_get_next_key(dict, key_dut.data, sizeof(MfClassicKey))) { mu_assert( memcmp(key_arr_ref[key_idx].data, key_dut.data, sizeof(MfClassicKey)) == 0, "Loaded key data mismatch"); @@ -484,19 +484,19 @@ MU_TEST(mf_classic_dict_test) { for(size_t i = 0; i < COUNT_OF(delete_keys_idx); i++) { MfClassicKey* key = &key_arr_ref[delete_keys_idx[i]]; mu_assert( - nfc_dict_is_key_present(dict, key->data, sizeof(MfClassicKey)), - "nfc_dict_is_key_present() failed"); + keys_dict_is_key_present(dict, key->data, sizeof(MfClassicKey)), + "keys_dict_is_key_present() failed"); mu_assert( - nfc_dict_delete_key(dict, key->data, sizeof(MfClassicKey)), - "nfc_dict_delete_key() failed"); + keys_dict_delete_key(dict, key->data, sizeof(MfClassicKey)), + "keys_dict_delete_key() failed"); } - dict_keys_total = nfc_dict_get_total_keys(dict); + dict_keys_total = keys_dict_get_total_keys(dict); mu_assert( dict_keys_total == test_key_num - COUNT_OF(delete_keys_idx), - "nfc_dict_keys_total() failed"); + "keys_dict_keys_total() failed"); - nfc_dict_free(dict); + keys_dict_free(dict); free(key_arr_ref); mu_assert( diff --git a/applications/main/nfc/helpers/mf_user_dict.c b/applications/main/nfc/helpers/mf_user_dict.c index 09f0c1506..1a019cf59 100644 --- a/applications/main/nfc/helpers/mf_user_dict.c +++ b/applications/main/nfc/helpers/mf_user_dict.c @@ -1,6 +1,6 @@ #include "mf_user_dict.h" -#include +#include #include #include @@ -15,22 +15,22 @@ struct MfUserDict { MfUserDict* mf_user_dict_alloc(size_t max_keys_to_load) { MfUserDict* instance = malloc(sizeof(MfUserDict)); - NfcDict* dict = nfc_dict_alloc( - NFC_APP_MF_CLASSIC_DICT_USER_PATH, NfcDictModeOpenAlways, sizeof(MfClassicKey)); + KeysDict* dict = keys_dict_alloc( + NFC_APP_MF_CLASSIC_DICT_USER_PATH, KeysDictModeOpenAlways, sizeof(MfClassicKey)); furi_assert(dict); - size_t dict_keys_num = nfc_dict_get_total_keys(dict); + size_t dict_keys_num = keys_dict_get_total_keys(dict); instance->keys_num = MIN(max_keys_to_load, dict_keys_num); if(instance->keys_num > 0) { instance->keys_arr = malloc(instance->keys_num * sizeof(MfClassicKey)); for(size_t i = 0; i < instance->keys_num; i++) { bool key_loaded = - nfc_dict_get_next_key(dict, instance->keys_arr[i].data, sizeof(MfClassicKey)); + keys_dict_get_next_key(dict, instance->keys_arr[i].data, sizeof(MfClassicKey)); furi_assert(key_loaded); } } - nfc_dict_free(dict); + keys_dict_free(dict); return instance; } @@ -67,13 +67,13 @@ bool mf_user_dict_delete_key(MfUserDict* instance, uint32_t index) { furi_assert(index < instance->keys_num); furi_assert(instance->keys_arr); - NfcDict* dict = nfc_dict_alloc( - NFC_APP_MF_CLASSIC_DICT_USER_PATH, NfcDictModeOpenAlways, sizeof(MfClassicKey)); + KeysDict* dict = keys_dict_alloc( + NFC_APP_MF_CLASSIC_DICT_USER_PATH, KeysDictModeOpenAlways, sizeof(MfClassicKey)); furi_assert(dict); bool key_delete_success = - nfc_dict_delete_key(dict, instance->keys_arr[index].data, sizeof(MfClassicKey)); - nfc_dict_free(dict); + keys_dict_delete_key(dict, instance->keys_arr[index].data, sizeof(MfClassicKey)); + keys_dict_free(dict); if(key_delete_success) { instance->keys_num--; diff --git a/applications/main/nfc/nfc_app_i.h b/applications/main/nfc/nfc_app_i.h index bde87b12b..943d722f8 100644 --- a/applications/main/nfc/nfc_app_i.h +++ b/applications/main/nfc/nfc_app_i.h @@ -52,7 +52,7 @@ #include #include -#include +#include #include #include @@ -80,7 +80,7 @@ typedef enum { } NfcRpcState; typedef struct { - NfcDict* dict; + KeysDict* dict; uint8_t sectors_total; uint8_t sectors_read; uint8_t current_sector; diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c index ff7af9e1e..b6ba1c119 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c @@ -41,7 +41,8 @@ NfcCommand nfc_dict_attack_worker_callback(NfcGenericEvent event, void* context) instance->view_dispatcher, NfcCustomEventDictAttackDataUpdate); } else if(mfc_event->type == MfClassicPollerEventTypeRequestKey) { MfClassicKey key = {}; - if(nfc_dict_get_next_key(instance->nfc_dict_context.dict, key.data, sizeof(MfClassicKey))) { + if(keys_dict_get_next_key( + instance->nfc_dict_context.dict, key.data, sizeof(MfClassicKey))) { mfc_event->data->key_request_data.key = key; mfc_event->data->key_request_data.key_provided = true; instance->nfc_dict_context.dict_keys_current++; @@ -60,7 +61,7 @@ NfcCommand nfc_dict_attack_worker_callback(NfcGenericEvent event, void* context) view_dispatcher_send_custom_event( instance->view_dispatcher, NfcCustomEventDictAttackDataUpdate); } else if(mfc_event->type == MfClassicPollerEventTypeNextSector) { - nfc_dict_rewind(instance->nfc_dict_context.dict); + keys_dict_rewind(instance->nfc_dict_context.dict); instance->nfc_dict_context.dict_keys_current = 0; instance->nfc_dict_context.current_sector = mfc_event->data->next_sector_data.current_sector; @@ -79,7 +80,7 @@ NfcCommand nfc_dict_attack_worker_callback(NfcGenericEvent event, void* context) view_dispatcher_send_custom_event( instance->view_dispatcher, NfcCustomEventDictAttackDataUpdate); } else if(mfc_event->type == MfClassicPollerEventTypeKeyAttackStop) { - nfc_dict_rewind(instance->nfc_dict_context.dict); + keys_dict_rewind(instance->nfc_dict_context.dict); instance->nfc_dict_context.is_key_attack = false; instance->nfc_dict_context.dict_keys_current = 0; view_dispatcher_send_custom_event( @@ -124,15 +125,15 @@ static void nfc_scene_mf_classic_dict_attack_prepare_view(NfcApp* instance) { scene_manager_get_scene_state(instance->scene_manager, NfcSceneMfClassicDictAttack); if(state == DictAttackStateUserDictInProgress) { do { - if(!nfc_dict_check_presence(NFC_APP_MF_CLASSIC_DICT_USER_PATH)) { + if(!keys_dict_check_presence(NFC_APP_MF_CLASSIC_DICT_USER_PATH)) { state = DictAttackStateSystemDictInProgress; break; } - instance->nfc_dict_context.dict = nfc_dict_alloc( - NFC_APP_MF_CLASSIC_DICT_USER_PATH, NfcDictModeOpenAlways, sizeof(MfClassicKey)); - if(nfc_dict_get_total_keys(instance->nfc_dict_context.dict) == 0) { - nfc_dict_free(instance->nfc_dict_context.dict); + instance->nfc_dict_context.dict = keys_dict_alloc( + NFC_APP_MF_CLASSIC_DICT_USER_PATH, KeysDictModeOpenAlways, sizeof(MfClassicKey)); + if(keys_dict_get_total_keys(instance->nfc_dict_context.dict) == 0) { + keys_dict_free(instance->nfc_dict_context.dict); state = DictAttackStateSystemDictInProgress; break; } @@ -141,13 +142,13 @@ static void nfc_scene_mf_classic_dict_attack_prepare_view(NfcApp* instance) { } while(false); } if(state == DictAttackStateSystemDictInProgress) { - instance->nfc_dict_context.dict = nfc_dict_alloc( - NFC_APP_MF_CLASSIC_DICT_SYSTEM_PATH, NfcDictModeOpenExisting, sizeof(MfClassicKey)); + instance->nfc_dict_context.dict = keys_dict_alloc( + NFC_APP_MF_CLASSIC_DICT_SYSTEM_PATH, KeysDictModeOpenExisting, sizeof(MfClassicKey)); dict_attack_set_header(instance->dict_attack, "MF Classic System Dictionary"); } instance->nfc_dict_context.dict_keys_total = - nfc_dict_get_total_keys(instance->nfc_dict_context.dict); + keys_dict_get_total_keys(instance->nfc_dict_context.dict); dict_attack_set_total_dict_keys( instance->dict_attack, instance->nfc_dict_context.dict_keys_total); instance->nfc_dict_context.dict_keys_current = 0; @@ -185,7 +186,7 @@ bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent if(state == DictAttackStateUserDictInProgress) { nfc_poller_stop(instance->poller); nfc_poller_free(instance->poller); - nfc_dict_free(instance->nfc_dict_context.dict); + keys_dict_free(instance->nfc_dict_context.dict); scene_manager_set_scene_state( instance->scene_manager, NfcSceneMfClassicDictAttack, @@ -215,7 +216,7 @@ bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent if(instance->nfc_dict_context.is_card_present) { nfc_poller_stop(instance->poller); nfc_poller_free(instance->poller); - nfc_dict_free(instance->nfc_dict_context.dict); + keys_dict_free(instance->nfc_dict_context.dict); scene_manager_set_scene_state( instance->scene_manager, NfcSceneMfClassicDictAttack, @@ -253,7 +254,7 @@ void nfc_scene_mf_classic_dict_attack_on_exit(void* context) { scene_manager_set_scene_state( instance->scene_manager, NfcSceneMfClassicDictAttack, DictAttackStateUserDictInProgress); - nfc_dict_free(instance->nfc_dict_context.dict); + keys_dict_free(instance->nfc_dict_context.dict); instance->nfc_dict_context.current_sector = 0; instance->nfc_dict_context.sectors_total = 0; diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_keys.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys.c index 3106c740a..44f9963af 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_keys.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys.c @@ -14,20 +14,20 @@ void nfc_scene_mf_classic_keys_on_enter(void* context) { // Load flipper dict keys total uint32_t flipper_dict_keys_total = 0; - NfcDict* dict = nfc_dict_alloc( - NFC_APP_MF_CLASSIC_DICT_SYSTEM_PATH, NfcDictModeOpenExisting, sizeof(MfClassicKey)); + KeysDict* dict = keys_dict_alloc( + NFC_APP_MF_CLASSIC_DICT_SYSTEM_PATH, KeysDictModeOpenExisting, sizeof(MfClassicKey)); if(dict) { - flipper_dict_keys_total = nfc_dict_get_total_keys(dict); - nfc_dict_free(dict); + flipper_dict_keys_total = keys_dict_get_total_keys(dict); + keys_dict_free(dict); } // Load user dict keys total uint32_t user_dict_keys_total = 0; - dict = nfc_dict_alloc( - NFC_APP_MF_CLASSIC_DICT_USER_PATH, NfcDictModeOpenAlways, sizeof(MfClassicKey)); + dict = keys_dict_alloc( + NFC_APP_MF_CLASSIC_DICT_USER_PATH, KeysDictModeOpenAlways, sizeof(MfClassicKey)); if(dict) { - user_dict_keys_total = nfc_dict_get_total_keys(dict); - nfc_dict_free(dict); + user_dict_keys_total = keys_dict_get_total_keys(dict); + keys_dict_free(dict); } FuriString* temp_str = furi_string_alloc(); diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_add.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_add.c index 824000343..4111cca81 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_add.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_add.c @@ -29,23 +29,23 @@ bool nfc_scene_mf_classic_keys_add_on_event(void* context, SceneManagerEvent eve if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcCustomEventByteInputDone) { // Add key to dict - NfcDict* dict = nfc_dict_alloc( - NFC_APP_MF_CLASSIC_DICT_USER_PATH, NfcDictModeOpenAlways, sizeof(MfClassicKey)); + KeysDict* dict = keys_dict_alloc( + NFC_APP_MF_CLASSIC_DICT_USER_PATH, KeysDictModeOpenAlways, sizeof(MfClassicKey)); furi_assert(dict); MfClassicKey key = {}; memcpy(key.data, instance->byte_input_store, sizeof(MfClassicKey)); - if(nfc_dict_is_key_present(dict, key.data, sizeof(MfClassicKey))) { + if(keys_dict_is_key_present(dict, key.data, sizeof(MfClassicKey))) { scene_manager_next_scene( instance->scene_manager, NfcSceneMfClassicKeysWarnDuplicate); - } else if(nfc_dict_add_key(dict, key.data, sizeof(MfClassicKey))) { + } else if(keys_dict_add_key(dict, key.data, sizeof(MfClassicKey))) { scene_manager_next_scene(instance->scene_manager, NfcSceneSaveSuccess); dolphin_deed(DolphinDeedNfcMfcAdd); } else { scene_manager_previous_scene(instance->scene_manager); } - nfc_dict_free(dict); + keys_dict_free(dict); consumed = true; } } diff --git a/lib/nfc/SConscript b/lib/nfc/SConscript index d2cfbe2fb..41332362c 100644 --- a/lib/nfc/SConscript +++ b/lib/nfc/SConscript @@ -48,7 +48,6 @@ env.Append( File("helpers/iso14443_crc.h"), File("helpers/iso13239_crc.h"), File("helpers/nfc_data_generator.h"), - File("helpers/nfc_dict.h"), ], ) diff --git a/lib/nfc/helpers/nfc_dict.c b/lib/nfc/helpers/nfc_dict.c deleted file mode 100644 index d4572a3d6..000000000 --- a/lib/nfc/helpers/nfc_dict.c +++ /dev/null @@ -1,270 +0,0 @@ -#include "nfc_dict.h" - -#include -#include -#include -#include -#include - -#include - -#define TAG "NfcDict" - -struct NfcDict { - Stream* stream; - size_t key_size; - size_t key_size_symbols; - uint32_t total_keys; -}; - -typedef struct { - const char* path; - FS_OpenMode open_mode; -} NfcDictFile; - -bool nfc_dict_check_presence(const char* path) { - furi_assert(path); - - Storage* storage = furi_record_open(RECORD_STORAGE); - - bool dict_present = storage_common_stat(storage, path, NULL) == FSE_OK; - - furi_record_close(RECORD_STORAGE); - - return dict_present; -} - -NfcDict* nfc_dict_alloc(const char* path, NfcDictMode mode, size_t key_size) { - furi_assert(path); - - NfcDict* instance = malloc(sizeof(NfcDict)); - Storage* storage = furi_record_open(RECORD_STORAGE); - instance->stream = buffered_file_stream_alloc(storage); - furi_record_close(RECORD_STORAGE); - - FS_OpenMode open_mode = FSOM_OPEN_EXISTING; - if(mode == NfcDictModeOpenAlways) { - open_mode = FSOM_OPEN_ALWAYS; - } - instance->key_size = key_size; - // Byte = 2 symbols + 1 end of line - instance->key_size_symbols = key_size * 2 + 1; - - bool dict_loaded = false; - do { - if(!buffered_file_stream_open(instance->stream, path, FSAM_READ_WRITE, open_mode)) { - buffered_file_stream_close(instance->stream); - break; - } - - // Check for new line ending - if(!stream_eof(instance->stream)) { - if(!stream_seek(instance->stream, -1, StreamOffsetFromEnd)) break; - uint8_t last_char = 0; - if(stream_read(instance->stream, &last_char, 1) != 1) break; - if(last_char != '\n') { - FURI_LOG_D(TAG, "Adding new line ending"); - if(stream_write_char(instance->stream, '\n') != 1) break; - } - if(!stream_rewind(instance->stream)) break; - } - - // Read total amount of keys - FuriString* next_line; - next_line = furi_string_alloc(); - while(true) { - if(!stream_read_line(instance->stream, next_line)) { - FURI_LOG_T(TAG, "No keys left in dict"); - break; - } - FURI_LOG_T( - TAG, - "Read line: %s, len: %zu", - furi_string_get_cstr(next_line), - furi_string_size(next_line)); - if(furi_string_get_char(next_line, 0) == '#') continue; - if(furi_string_size(next_line) != instance->key_size_symbols) continue; - instance->total_keys++; - } - furi_string_free(next_line); - stream_rewind(instance->stream); - - dict_loaded = true; - FURI_LOG_I(TAG, "Loaded dictionary with %lu keys", instance->total_keys); - } while(false); - - if(!dict_loaded) { - buffered_file_stream_close(instance->stream); - free(instance); - instance = NULL; - } - - return instance; -} - -void nfc_dict_free(NfcDict* instance) { - furi_assert(instance); - furi_assert(instance->stream); - - buffered_file_stream_close(instance->stream); - stream_free(instance->stream); - free(instance); -} - -static void nfc_dict_int_to_str(NfcDict* instance, const uint8_t* key_int, FuriString* key_str) { - furi_string_reset(key_str); - for(size_t i = 0; i < instance->key_size; i++) { - furi_string_cat_printf(key_str, "%02X", key_int[i]); - } -} - -static void nfc_dict_str_to_int(NfcDict* instance, FuriString* key_str, uint64_t* key_int) { - uint8_t key_byte_tmp; - - *key_int = 0ULL; - for(uint8_t i = 0; i < instance->key_size * 2; i += 2) { - args_char_to_hex( - furi_string_get_char(key_str, i), furi_string_get_char(key_str, i + 1), &key_byte_tmp); - *key_int |= (uint64_t)key_byte_tmp << (8 * (instance->key_size - 1 - i / 2)); - } -} - -uint32_t nfc_dict_get_total_keys(NfcDict* instance) { - furi_assert(instance); - - return instance->total_keys; -} - -bool nfc_dict_rewind(NfcDict* instance) { - furi_assert(instance); - furi_assert(instance->stream); - - return stream_rewind(instance->stream); -} - -static bool nfc_dict_get_next_key_str(NfcDict* instance, FuriString* key) { - furi_assert(instance); - furi_assert(instance->stream); - - bool key_read = false; - furi_string_reset(key); - while(!key_read) { - if(!stream_read_line(instance->stream, key)) break; - if(furi_string_get_char(key, 0) == '#') continue; - if(furi_string_size(key) != instance->key_size_symbols) continue; - furi_string_left(key, instance->key_size_symbols - 1); - key_read = true; - } - - return key_read; -} - -bool nfc_dict_get_next_key(NfcDict* instance, uint8_t* key, size_t key_size) { - furi_assert(instance); - furi_assert(instance->stream); - furi_assert(instance->key_size == key_size); - - FuriString* temp_key = furi_string_alloc(); - uint64_t key_int = 0; - bool key_read = nfc_dict_get_next_key_str(instance, temp_key); - if(key_read) { - nfc_dict_str_to_int(instance, temp_key, &key_int); - nfc_util_num2bytes(key_int, key_size, key); - } - furi_string_free(temp_key); - return key_read; -} - -static bool nfc_dict_is_key_present_str(NfcDict* instance, FuriString* key) { - furi_assert(instance); - furi_assert(instance->stream); - - FuriString* next_line; - next_line = furi_string_alloc(); - - bool key_found = false; - stream_rewind(instance->stream); - while(!key_found) { //-V654 - if(!stream_read_line(instance->stream, next_line)) break; - if(furi_string_get_char(next_line, 0) == '#') continue; - if(furi_string_size(next_line) != instance->key_size_symbols) continue; - furi_string_left(next_line, instance->key_size_symbols - 1); - if(!furi_string_equal(key, next_line)) continue; - key_found = true; - } - - furi_string_free(next_line); - return key_found; -} - -bool nfc_dict_is_key_present(NfcDict* instance, const uint8_t* key, size_t key_size) { - furi_assert(instance); - furi_assert(key); - furi_assert(instance->stream); - furi_assert(instance->key_size == key_size); - - FuriString* temp_key = furi_string_alloc(); - nfc_dict_int_to_str(instance, key, temp_key); - bool key_found = nfc_dict_is_key_present_str(instance, temp_key); - furi_string_free(temp_key); - - return key_found; -} - -static bool nfc_dict_add_key_str(NfcDict* instance, FuriString* key) { - furi_assert(instance); - furi_assert(instance->stream); - - furi_string_cat_printf(key, "\n"); - - bool key_added = false; - do { - if(!stream_seek(instance->stream, 0, StreamOffsetFromEnd)) break; - if(!stream_insert_string(instance->stream, key)) break; - instance->total_keys++; - key_added = true; - } while(false); - - furi_string_left(key, instance->key_size_symbols - 1); - return key_added; -} - -bool nfc_dict_add_key(NfcDict* instance, const uint8_t* key, size_t key_size) { - furi_assert(instance); - furi_assert(key); - furi_assert(instance->stream); - furi_assert(instance->key_size == key_size); - - FuriString* temp_key = furi_string_alloc(); - nfc_dict_int_to_str(instance, key, temp_key); - bool key_added = nfc_dict_add_key_str(instance, temp_key); - furi_string_free(temp_key); - - return key_added; -} - -bool nfc_dict_delete_key(NfcDict* instance, const uint8_t* key, size_t key_size) { - furi_assert(instance); - furi_assert(instance->stream); - furi_assert(key); - furi_assert(instance->key_size == key_size); - - bool key_removed = false; - uint8_t* temp_key = malloc(key_size); - - nfc_dict_rewind(instance); - while(!key_removed) { - if(!nfc_dict_get_next_key(instance, temp_key, key_size)) break; - if(memcmp(temp_key, key, key_size) == 0) { - int32_t offset = (-1) * (instance->key_size_symbols); - stream_seek(instance->stream, offset, StreamOffsetFromCurrent); - if(!stream_delete(instance->stream, instance->key_size_symbols)) break; - instance->total_keys--; - key_removed = true; - } - } - nfc_dict_rewind(instance); - free(temp_key); - - return key_removed; -} diff --git a/lib/nfc/helpers/nfc_dict.h b/lib/nfc/helpers/nfc_dict.h deleted file mode 100644 index 80f3ff680..000000000 --- a/lib/nfc/helpers/nfc_dict.h +++ /dev/null @@ -1,103 +0,0 @@ -#pragma once - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - NfcDictModeOpenExisting, - NfcDictModeOpenAlways, -} NfcDictMode; - -typedef struct NfcDict NfcDict; - -/** Check dictionary presence - * - * @param path - dictionary path - * - * @return true if dictionary exists, false otherwise -*/ -bool nfc_dict_check_presence(const char* path); - -/** Open or create dictionary - * Depending on mode, dictionary will be opened or created. - * - * @param path - dictionary path - * @param mode - NfcDictMode value - * @param key_size - size of dictionary keys in bytes - * - * @return NfcDict dictionary instance -*/ -NfcDict* nfc_dict_alloc(const char* path, NfcDictMode mode, size_t key_size); - -/** Close dictionary - * - * @param instance - NfcDict dictionary instance -*/ -void nfc_dict_free(NfcDict* instance); - -/** Get total number of keys in dictionary - * - * @param instance - NfcDict dictionary instance - * - * @return total number of keys in dictionary -*/ -uint32_t nfc_dict_get_total_keys(NfcDict* instance); - -/** Rewind dictionary - * - * @param instance - NfcDict dictionary instance - * - * @return true if rewind was successful, false otherwise -*/ -bool nfc_dict_rewind(NfcDict* instance); - -/** Check if key is present in dictionary - * - * @param instance - NfcDict dictionary instance - * @param key - key to check - * @param key_size - size of key in bytes - * - * @return true if key is present, false otherwise -*/ -bool nfc_dict_is_key_present(NfcDict* instance, const uint8_t* key, size_t key_size); - -/** Get next key from dictionary - * This function will return next key from dictionary. If there are no more - * keys, it will return false, and nfc_dict_rewind() should be called. - * - * @param instance - NfcDict dictionary instance - * @param key - buffer to store key - * @param key_size - size of key in bytes - * - * @return true if key was successfully retrieved, false otherwise -*/ -bool nfc_dict_get_next_key(NfcDict* instance, uint8_t* key, size_t key_size); - -/** Add key to dictionary - * - * @param instance - NfcDict dictionary instance - * @param key - key to add - * @param key_size - size of key in bytes - * - * @return true if key was successfully added, false otherwise -*/ -bool nfc_dict_add_key(NfcDict* instance, const uint8_t* key, size_t key_size); - -/** Delete key from dictionary - * - * @param instance - NfcDict dictionary instance - * @param key - key to delete - * @param key_size - size of key in bytes - * - * @return true if key was successfully deleted, false otherwise -*/ -bool nfc_dict_delete_key(NfcDict* instance, const uint8_t* key, size_t key_size); - -#ifdef __cplusplus -} -#endif diff --git a/lib/toolbox/SConscript b/lib/toolbox/SConscript index 14f8de064..121362424 100644 --- a/lib/toolbox/SConscript +++ b/lib/toolbox/SConscript @@ -34,6 +34,7 @@ env.Append( File("hex.h"), File("simple_array.h"), File("bit_buffer.h"), + File("keys_dict.h"), ], ) diff --git a/lib/toolbox/keys_dict.c b/lib/toolbox/keys_dict.c new file mode 100644 index 000000000..30580bf5e --- /dev/null +++ b/lib/toolbox/keys_dict.c @@ -0,0 +1,335 @@ +#include "keys_dict.h" + +#include +#include +#include +#include +#include + +#define TAG "KeysDict" + +struct KeysDict { + Stream* stream; + size_t key_size; + size_t key_size_symbols; + size_t total_keys; +}; + +static inline void keys_dict_add_ending_new_line(KeysDict* instance) { + if(stream_seek(instance->stream, -1, StreamOffsetFromEnd)) { + uint8_t last_char = 0; + + // Check if the last char is new line or add a new line + if(stream_read(instance->stream, &last_char, 1) == 1 && last_char != '\n') { + FURI_LOG_D(TAG, "Adding new line ending"); + stream_write_char(instance->stream, '\n'); + } + + stream_rewind(instance->stream); + } +} + +static bool keys_dict_read_key_line(KeysDict* instance, FuriString* line, bool* is_endfile) { + if(stream_read_line(instance->stream, line) == false) { + *is_endfile = true; + } + + else { + FURI_LOG_T( + TAG, "Read line: %s, len: %zu", furi_string_get_cstr(line), furi_string_size(line)); + + bool is_comment = furi_string_get_char(line, 0) == '#'; + + if(!is_comment) { + furi_string_left(line, instance->key_size_symbols - 1); + } + + bool is_correct_size = furi_string_size(line) == instance->key_size_symbols - 1; + + return !is_comment && is_correct_size; + } + + return false; +} + +bool keys_dict_check_presence(const char* path) { + furi_assert(path); + + Storage* storage = furi_record_open(RECORD_STORAGE); + + bool dict_present = storage_common_stat(storage, path, NULL) == FSE_OK; + + furi_record_close(RECORD_STORAGE); + + return dict_present; +} + +KeysDict* keys_dict_alloc(const char* path, KeysDictMode mode, size_t key_size) { + furi_assert(path); + furi_assert(key_size > 0); + + KeysDict* instance = malloc(sizeof(KeysDict)); + + Storage* storage = furi_record_open(RECORD_STORAGE); + furi_assert(storage); + + instance->stream = buffered_file_stream_alloc(storage); + furi_assert(instance->stream); + + FS_OpenMode open_mode = (mode == KeysDictModeOpenAlways) ? FSOM_OPEN_ALWAYS : + FSOM_OPEN_EXISTING; + + // Byte = 2 symbols + 1 end of line + instance->key_size = key_size; + instance->key_size_symbols = key_size * 2 + 1; + + instance->total_keys = 0; + + bool file_exists = + buffered_file_stream_open(instance->stream, path, FSAM_READ_WRITE, open_mode); + + if(!file_exists) { + buffered_file_stream_close(instance->stream); + } else { + // Eventually add new line character in the last line to avoid skipping keys + keys_dict_add_ending_new_line(instance); + } + + FuriString* line = furi_string_alloc(); + + bool is_endfile = false; + + // In this loop we only count the entries in the file + // We prefer not to load the whole file in memory for space reasons + while(file_exists && !is_endfile) { + bool read_key = keys_dict_read_key_line(instance, line, &is_endfile); + if(read_key) { + instance->total_keys++; + } + } + stream_rewind(instance->stream); + FURI_LOG_I(TAG, "Loaded dictionary with %u keys", instance->total_keys); + + furi_string_free(line); + + return instance; +} + +void keys_dict_free(KeysDict* instance) { + furi_assert(instance); + furi_assert(instance->stream); + + buffered_file_stream_close(instance->stream); + stream_free(instance->stream); + free(instance); + + furi_record_close(RECORD_STORAGE); +} + +static void keys_dict_int_to_str(KeysDict* instance, const uint8_t* key_int, FuriString* key_str) { + furi_assert(instance); + furi_assert(key_str); + furi_assert(key_int); + + furi_string_reset(key_str); + + for(size_t i = 0; i < instance->key_size; i++) + furi_string_cat_printf(key_str, "%02X", key_int[i]); +} + +static void keys_dict_str_to_int(KeysDict* instance, FuriString* key_str, uint64_t* key_int) { + furi_assert(instance); + furi_assert(key_str); + furi_assert(key_int); + + uint8_t key_byte_tmp; + char h, l; + + *key_int = 0ULL; + + for(size_t i = 0; i < instance->key_size_symbols - 1; i += 2) { + h = furi_string_get_char(key_str, i); + l = furi_string_get_char(key_str, i + 1); + + args_char_to_hex(h, l, &key_byte_tmp); + *key_int |= (uint64_t)key_byte_tmp << (8 * (instance->key_size - 1 - i / 2)); + } +} + +size_t keys_dict_get_total_keys(KeysDict* instance) { + furi_assert(instance); + + return instance->total_keys; +} + +bool keys_dict_rewind(KeysDict* instance) { + furi_assert(instance); + furi_assert(instance->stream); + + return stream_rewind(instance->stream); +} + +static bool keys_dict_get_next_key_str(KeysDict* instance, FuriString* key) { + furi_assert(instance); + furi_assert(instance->stream); + furi_assert(key); + + bool key_read = false; + bool is_endfile = false; + + furi_string_reset(key); + + while(!key_read && !is_endfile) key_read = keys_dict_read_key_line(instance, key, &is_endfile); + + return key_read; +} + +bool keys_dict_get_next_key(KeysDict* instance, uint8_t* key, size_t key_size) { + furi_assert(instance); + furi_assert(instance->stream); + furi_assert(instance->key_size == key_size); + furi_assert(key); + + FuriString* temp_key = furi_string_alloc(); + + bool key_read = keys_dict_get_next_key_str(instance, temp_key); + + if(key_read) { + size_t tmp_len = key_size; + uint64_t key_int = 0; + + keys_dict_str_to_int(instance, temp_key, &key_int); + + while(tmp_len--) { + key[tmp_len] = (uint8_t)key_int; + key_int >>= 8; + } + } + + furi_string_free(temp_key); + return key_read; +} + +static bool keys_dict_is_key_present_str(KeysDict* instance, FuriString* key) { + furi_assert(instance); + furi_assert(instance->stream); + furi_assert(key); + + FuriString* line = furi_string_alloc(); + + bool is_endfile = false; + bool line_found = false; + + uint32_t actual_pos = stream_tell(instance->stream); + stream_rewind(instance->stream); + + while(!line_found && !is_endfile) + line_found = // The line is found if the line was read and the key is equal to the line + (keys_dict_read_key_line(instance, line, &is_endfile)) && + (furi_string_equal(key, line)); + + furi_string_free(line); + + // Restore the position of the stream + stream_seek(instance->stream, actual_pos, StreamOffsetFromStart); + + return line_found; +} + +bool keys_dict_is_key_present(KeysDict* instance, const uint8_t* key, size_t key_size) { + furi_assert(instance); + furi_assert(instance->stream); + furi_assert(instance->key_size == key_size); + furi_assert(key); + + FuriString* temp_key = furi_string_alloc(); + + keys_dict_int_to_str(instance, key, temp_key); + bool key_found = keys_dict_is_key_present_str(instance, temp_key); + furi_string_free(temp_key); + + return key_found; +} + +static bool keys_dict_add_key_str(KeysDict* instance, FuriString* key) { + furi_assert(instance); + furi_assert(instance->stream); + furi_assert(key); + + furi_string_cat_str(key, "\n"); + + bool key_added = false; + + uint32_t actual_pos = stream_tell(instance->stream); + + if(stream_seek(instance->stream, 0, StreamOffsetFromEnd) && + stream_insert_string(instance->stream, key)) { + instance->total_keys++; + key_added = true; + } + + stream_seek(instance->stream, actual_pos, StreamOffsetFromStart); + + return key_added; +} + +bool keys_dict_add_key(KeysDict* instance, const uint8_t* key, size_t key_size) { + furi_assert(instance); + furi_assert(instance->stream); + furi_assert(instance->key_size == key_size); + furi_assert(key); + + FuriString* temp_key = furi_string_alloc(); + furi_assert(temp_key); + + keys_dict_int_to_str(instance, key, temp_key); + bool key_added = keys_dict_add_key_str(instance, temp_key); + + FURI_LOG_I(TAG, "Added key %s", furi_string_get_cstr(temp_key)); + + furi_string_free(temp_key); + + return key_added; +} + +bool keys_dict_delete_key(KeysDict* instance, const uint8_t* key, size_t key_size) { + furi_assert(instance); + furi_assert(instance->stream); + furi_assert(instance->key_size == key_size); + furi_assert(key); + + bool key_removed = false; + bool is_endfile = false; + + uint8_t* temp_key = malloc(key_size); + + stream_rewind(instance->stream); + + while(!key_removed && !is_endfile) { + if(!keys_dict_get_next_key(instance, temp_key, key_size)) { + break; + } + + if(memcmp(temp_key, key, key_size) == 0) { + stream_seek(instance->stream, -instance->key_size_symbols, StreamOffsetFromCurrent); + if(stream_delete(instance->stream, instance->key_size_symbols) == false) { + break; + } + instance->total_keys--; + key_removed = true; + } + } + + FuriString* tmp = furi_string_alloc(); + + keys_dict_int_to_str(instance, key, tmp); + + FURI_LOG_I(TAG, "Removed key %s", furi_string_get_cstr(tmp)); + + furi_string_free(tmp); + + stream_rewind(instance->stream); + free(temp_key); + + return key_removed; +} \ No newline at end of file diff --git a/lib/toolbox/keys_dict.h b/lib/toolbox/keys_dict.h new file mode 100644 index 000000000..df6f49344 --- /dev/null +++ b/lib/toolbox/keys_dict.h @@ -0,0 +1,103 @@ +#pragma once + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + KeysDictModeOpenExisting, + KeysDictModeOpenAlways, +} KeysDictMode; + +typedef struct KeysDict KeysDict; + +/** Check if the file list exists + * + * @param path - list path + * + * @return true if list exists, false otherwise +*/ +bool keys_dict_check_presence(const char* path); + +/** Open or create list + * Depending on mode, list will be opened or created. + * + * @param path - Path of the file that contain the list + * @param mode - ListKeysMode value + * @param key_size - Size of each key in bytes + * + * @return Returns KeysDict list instance +*/ +KeysDict* keys_dict_alloc(const char* path, KeysDictMode mode, size_t key_size); + +/** Close list + * + * @param instance - KeysDict list instance +*/ +void keys_dict_free(KeysDict* instance); + +/** Get total number of keys in list + * + * @param instance - KeysDict list instance + * + * @return Returns total number of keys in list +*/ +size_t keys_dict_get_total_keys(KeysDict* instance); + +/** Rewind list + * + * @param instance - KeysDict list instance + * + * @return Returns true if rewind was successful, false otherwise +*/ +bool keys_dict_rewind(KeysDict* instance); + +/** Check if key is present in list + * + * @param instance - KeysDict list instance + * @param key - key to check + * @param key_size - Size of the key in bytes + * + * @return Returns true if key is present, false otherwise +*/ +bool keys_dict_is_key_present(KeysDict* instance, const uint8_t* key, size_t key_size); + +/** Get next key from the list + * This function will return next key from list. If there are no more + * keys, it will return false, and keys_dict_rewind() should be called. + * + * @param instance - KeysDict list instance + * @param key - Array where to store key + * @param key_size - Size of key in bytes + * + * @return Returns true if key was successfully retrieved, false otherwise +*/ +bool keys_dict_get_next_key(KeysDict* instance, uint8_t* key, size_t key_size); + +/** Add key to list + * + * @param instance - KeysDict list instance + * @param key - Key to add + * @param key_size - Size of the key in bytes + * + * @return Returns true if key was successfully added, false otherwise +*/ +bool keys_dict_add_key(KeysDict* instance, const uint8_t* key, size_t key_size); + +/** Delete key from list + * + * @param instance - KeysDict list instance + * @param key - Key to delete + * @param key_size - Size of the key in bytes + * + * @return Returns true if key was successfully deleted, false otherwise +*/ +bool keys_dict_delete_key(KeysDict* instance, const uint8_t* key, size_t key_size); + +#ifdef __cplusplus +} +#endif diff --git a/targets/f18/api_symbols.csv b/targets/f18/api_symbols.csv index c166e78ee..8a5e44c97 100644 --- a/targets/f18/api_symbols.csv +++ b/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,49.3,, +Version,+,50.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -139,6 +139,7 @@ Header,+,lib/toolbox/crc32_calc.h,, Header,+,lib/toolbox/dir_walk.h,, Header,+,lib/toolbox/float_tools.h,, Header,+,lib/toolbox/hex.h,, +Header,+,lib/toolbox/keys_dict.h,, Header,+,lib/toolbox/manchester_decoder.h,, Header,+,lib/toolbox/manchester_encoder.h,, Header,+,lib/toolbox/name_generator.h,, @@ -1592,6 +1593,15 @@ Function,-,j1f,float,float Function,-,jn,double,"int, double" Function,-,jnf,float,"int, float" Function,-,jrand48,long,unsigned short[3] +Function,+,keys_dict_add_key,_Bool,"KeysDict*, const uint8_t*, size_t" +Function,+,keys_dict_alloc,KeysDict*,"const char*, KeysDictMode, size_t" +Function,+,keys_dict_check_presence,_Bool,const char* +Function,+,keys_dict_delete_key,_Bool,"KeysDict*, const uint8_t*, size_t" +Function,+,keys_dict_free,void,KeysDict* +Function,+,keys_dict_get_next_key,_Bool,"KeysDict*, uint8_t*, size_t" +Function,+,keys_dict_get_total_keys,size_t,KeysDict* +Function,+,keys_dict_is_key_present,_Bool,"KeysDict*, const uint8_t*, size_t" +Function,+,keys_dict_rewind,_Bool,KeysDict* Function,-,l64a,char*,long Function,-,labs,long,long Function,-,lcong48,void,unsigned short[7] diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index d47908434..353d511ec 100644 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,49.3,, +Version,+,50.0,, Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, @@ -114,7 +114,6 @@ Header,+,lib/nanopb/pb_encode.h,, Header,+,lib/nfc/helpers/iso13239_crc.h,, Header,+,lib/nfc/helpers/iso14443_crc.h,, Header,+,lib/nfc/helpers/nfc_data_generator.h,, -Header,+,lib/nfc/helpers/nfc_dict.h,, Header,+,lib/nfc/helpers/nfc_util.h,, Header,+,lib/nfc/nfc.h,, Header,+,lib/nfc/nfc_device.h,, @@ -204,6 +203,7 @@ Header,+,lib/toolbox/crc32_calc.h,, Header,+,lib/toolbox/dir_walk.h,, Header,+,lib/toolbox/float_tools.h,, Header,+,lib/toolbox/hex.h,, +Header,+,lib/toolbox/keys_dict.h,, Header,+,lib/toolbox/manchester_decoder.h,, Header,+,lib/toolbox/manchester_encoder.h,, Header,+,lib/toolbox/name_generator.h,, @@ -1967,6 +1967,15 @@ Function,-,j1f,float,float Function,-,jn,double,"int, double" Function,-,jnf,float,"int, float" Function,-,jrand48,long,unsigned short[3] +Function,+,keys_dict_add_key,_Bool,"KeysDict*, const uint8_t*, size_t" +Function,+,keys_dict_alloc,KeysDict*,"const char*, KeysDictMode, size_t" +Function,+,keys_dict_check_presence,_Bool,const char* +Function,+,keys_dict_delete_key,_Bool,"KeysDict*, const uint8_t*, size_t" +Function,+,keys_dict_free,void,KeysDict* +Function,+,keys_dict_get_next_key,_Bool,"KeysDict*, uint8_t*, size_t" +Function,+,keys_dict_get_total_keys,size_t,KeysDict* +Function,+,keys_dict_is_key_present,_Bool,"KeysDict*, const uint8_t*, size_t" +Function,+,keys_dict_rewind,_Bool,KeysDict* Function,-,l64a,char*,long Function,-,labs,long,long Function,-,lcong48,void,unsigned short[7] @@ -2441,15 +2450,6 @@ Function,+,nfc_device_save,_Bool,"NfcDevice*, const char*" Function,+,nfc_device_set_data,void,"NfcDevice*, NfcProtocol, const NfcDeviceData*" Function,+,nfc_device_set_loading_callback,void,"NfcDevice*, NfcLoadingCallback, void*" Function,+,nfc_device_set_uid,_Bool,"NfcDevice*, const uint8_t*, size_t" -Function,+,nfc_dict_add_key,_Bool,"NfcDict*, const uint8_t*, size_t" -Function,+,nfc_dict_alloc,NfcDict*,"const char*, NfcDictMode, size_t" -Function,+,nfc_dict_check_presence,_Bool,const char* -Function,+,nfc_dict_delete_key,_Bool,"NfcDict*, const uint8_t*, size_t" -Function,+,nfc_dict_free,void,NfcDict* -Function,+,nfc_dict_get_next_key,_Bool,"NfcDict*, uint8_t*, size_t" -Function,+,nfc_dict_get_total_keys,uint32_t,NfcDict* -Function,+,nfc_dict_is_key_present,_Bool,"NfcDict*, const uint8_t*, size_t" -Function,+,nfc_dict_rewind,_Bool,NfcDict* Function,+,nfc_felica_listener_set_sensf_res_data,NfcError,"Nfc*, const uint8_t*, const uint8_t, const uint8_t*, const uint8_t" Function,+,nfc_free,void,Nfc* Function,+,nfc_iso14443a_listener_set_col_res_data,NfcError,"Nfc*, uint8_t*, uint8_t, uint8_t*, uint8_t" From 25d24f1e4c8bdcbb618a554707c06855b094d414 Mon Sep 17 00:00:00 2001 From: Evgeny Stepanischev Date: Mon, 18 Dec 2023 21:36:50 +0300 Subject: [PATCH 22/44] Added UTF-8 support to Flipper Zero canvas API (#3297) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added UTF-8 support to Flipper Zero canvas API * Add unicode example Co-authored-by: あく --- .../example_custom_font/example_custom_font.c | 86 ++++++++++++------- applications/services/gui/canvas.c | 10 +-- 2 files changed, 62 insertions(+), 34 deletions(-) diff --git a/applications/debug/example_custom_font/example_custom_font.c b/applications/debug/example_custom_font/example_custom_font.c index 15eeb5f02..8d85f23c6 100644 --- a/applications/debug/example_custom_font/example_custom_font.c +++ b/applications/debug/example_custom_font/example_custom_font.c @@ -7,35 +7,62 @@ //This arrays contains the font itself. You can use any u8g2 font you want /* -Fontname: -Raccoon-Fixed4x6-Medium-R-Normal--6-60-75-75-P-40-ISO10646-1 -Copyright: -Glyphs: 95/203 -BBX Build Mode: 0 + Fontname: -Misc-Fixed-Medium-R-Normal--6-60-75-75-C-40-ISO10646-1 + Copyright: Public domain font. Share and enjoy. + Glyphs: 191/919 + BBX Build Mode: 0 */ -const uint8_t u8g2_font_tom_thumb_4x6_tr[725] = - "_\0\2\2\2\3\3\4\4\3\6\0\377\5\377\5\0\0\352\1\330\2\270 \5\340\315\0!\6\265\310" - "\254\0\42\6\213\313$\25#\10\227\310\244\241\206\12$\10\227\310\215\70b\2%\10\227\310d\324F\1" - "&\10\227\310(\65R\22'\5\251\313\10(\6\266\310\251\62)\10\226\310\304\224\24\0*\6\217\312\244" - "\16+\7\217\311\245\225\0,\6\212\310)\0-\5\207\312\14.\5\245\310\4/\7\227\310Ve\4\60" - "\7\227\310-k\1\61\6\226\310\255\6\62\10\227\310h\220\312\1\63\11\227\310h\220\62X\0\64\10\227" - "\310$\65b\1\65\10\227\310\214\250\301\2\66\10\227\310\315\221F\0\67\10\227\310\314TF\0\70\10\227" - "\310\214\64\324\10\71\10\227\310\214\64\342\2:\6\255\311\244\0;\7\222\310e\240\0<\10\227\310\246\32" - "d\20=\6\217\311l\60>\11\227\310d\220A*\1\77\10\227\310\314\224a\2@\10\227\310UC\3" - "\1A\10\227\310UC\251\0B\10\227\310\250\264\322\2C\7\227\310\315\32\10D\10\227\310\250d-\0" - "E\10\227\310\214\70\342\0F\10\227\310\214\70b\4G\10\227\310\315\221\222\0H\10\227\310$\65\224\12" - "I\7\227\310\254X\15J\7\227\310\226\252\2K\10\227\310$\265\222\12L\7\227\310\304\346\0M\10\227" - "\310\244\61\224\12N\10\227\310\244q\250\0O\7\227\310UV\5P\10\227\310\250\264b\4Q\10\227\310" - "Uj$\1R\10\227\310\250\64V\1S\10\227\310m\220\301\2T\7\227\310\254\330\2U\7\227\310$" - "W\22V\10\227\310$\253L\0W\10\227\310$\65\206\12X\10\227\310$\325R\1Y\10\227\310$U" - "V\0Z\7\227\310\314T\16[\7\227\310\214X\16\134\10\217\311d\220A\0]\7\227\310\314r\4^" - "\5\213\313\65_\5\207\310\14`\6\212\313\304\0a\7\223\310\310\65\2b\10\227\310D\225\324\2c\7" - "\223\310\315\14\4d\10\227\310\246\245\222\0e\6\223\310\235\2f\10\227\310\246\264b\2g\10\227\307\35" - "\61%\0h\10\227\310D\225\254\0i\6\265\310\244\1j\10\233\307f\30U\5k\10\227\310\304\264T" - "\1l\7\227\310\310\326\0m\7\223\310\11\253\310d\220A*\1\77\11\253\310h\220\62L\0@\7" + "\253\310-\33\10A\10\253\310UC\251\0B\10\253\310\250\264\322\2C\10\253\310U\62U\0D\10\253" + "\310\250d-\0E\10\253\310\214\250\342\0F\10\253\310\214\250b\4G\10\253\310\315\244\222\0H\10\253" + "\310$\65\224\12I\7\253\310\254X\15J\7\253\310\226\252\2K\10\253\310$\265\222\12L\7\253\310\304" + "\346\0M\10\253\310\244\61\224\12N\10\253\310\252\241$\0O\7\253\310UV\5P\10\253\310\250\264b" + "\4Q\10\263\307UV\15\2R\10\253\310\250\264\222\12S\10\253\310m\220\301\2T\7\253\310\254\330\2" + "U\7\253\310$\327\10V\10\253\310$k\244\4W\10\253\310$\65\206\12X\10\253\310$\325R\1Y" + "\10\253\310$UV\0Z\7\253\310\314T\16[\6\352\310\254J\134\11\253\310\304\14\62\210\1]\6\252" + "\310\250j^\5\223\313\65_\5\213\307\14`\6\322\313\304\0a\7\243\310-\225\4b\10\253\310D\225" + "\324\2c\7\243\310\315\14\4d\10\253\310\246\245\222\0e\6\243\310USf\10\253\310\246\264b\2g" + "\10\253\307\255$\27\0h\10\253\310D\225\254\0i\10\253\310e$\323\0j\10\263\307fX.\0k" + "\10\253\310\304\264\222\12l\7\253\310\310\326\0m\10\243\310\244\241T\0n\7\243\310\250d\5o\7\243" + "\310U\252\2p\10\253\307\250\264b\4q\10\253\307-\225d\0r\10\243\310\244\25#\0s\10\243\310" + "\215\14\26\0t\10\253\310\245\25\63\10u\7\243\310$+\11v\7\243\310$\253\2w\10\243\310$\65" + "T\0x\7\243\310\244\62\25y\10\253\307$\225\344\2z\7\243\310\314\224\6{\10\263\307\246$k\20" + "|\6\351\310\14\1}\11\263\307d\20UL\21~\7\224\313%\225\0\0\0\0\4\377\377\4\1\11\253" + "\310\244\261\342\0\4\2\11\253\310\214\250\222\12\4\3\10\253\310\16Y\2\4\4\11\253\310M\225\201\0\4" + "\5\11\253\310m\220\301\2\4\6\10\253\310\254X\15\4\7\11\253\310\244\221b\32\4\10\10\253\310\226\252" + "\2\4\11\11\254\310L\325Z\2\4\12\11\254\310\244\326JK\4\13\11\253\310\250\250\222\12\4\14\10\253" + "\310\312\264\12\4\16\11\263\307\244\32u\2\4\17\11\263\307$\327H\11\4\20\11\253\310UC\251\0\4" + "\21\11\253\310\214\250\322\2\4\22\11\253\310\250\264\322\2\4\23\10\253\310\214\330\4\4\24\11\263\307\254\245" + "\206\12\4\25\11\253\310\214\250\342\0\4\26\12\253\310\244\221\322H\1\4\27\12\253\310h\220\62X\0\4" + "\30\11\253\310\304\64T\14\4\31\11\263\307\315\64T\14\4\32\11\253\310$\265\222\12\4\33\10\253\310-" + "W\0\4\34\11\253\310\244\241\254\0\4\35\11\253\310$\65\224\12\4\36\10\253\310UV\5\4\37\10\253" + "\310\214\344\12\4 \11\253\310\250\264b\4\4!\11\253\310U\62U\0\4\42\10\253\310\254\330\2\4#" + "\11\263\307$\253L\21\4$\12\253\310\245\221FJ\0\4%\11\253\310$\325R\1\4&\10\253\310$" + "\327\10\4'\11\253\310$\225d\1\4(\11\253\310$\65\216\0\4)\12\264\307\244\326#\203\0\4*" + "\13\254\310h\220\201LI\1\4+\12\254\310D\271\324H\1\4,\11\253\310\304\250\322\2\4-\11\253" + "\310h\220\344\2\4.\12\254\310\244\244.\225\0\4/\11\253\310\255\264T\0\4\60\10\243\310-\225\4" + "\4\61\11\253\310\315\221*\0\4\62\11\243\310\14\225\26\0\4\63\10\243\310\214X\2\4\64\11\253\307-" + "\65T\0\4\65\7\243\310US\4\66\11\244\310$S%\1\4\67\11\243\310\254\14\26\0\4\70\11\243" + "\310\244\61T\0\4\71\11\253\310\244\326P\1\4:\10\243\310$\265\12\4;\7\243\310-+\4<\11" + "\243\310\244\241T\0\4=\11\243\310\244\241T\0\4>\10\243\310U\252\2\4\77\10\243\310\214d\5\4" + "@\11\253\307\250\264b\4\4A\10\243\310\315\14\4\4B\10\243\310\254X\1\4C\11\253\307$\225\344" + "\2\4D\12\263\307\305\224T\231\0\4E\10\243\310\244\62\25\4F\11\253\307$k\304\0\4G\11\243" + "\310$\225d\0\4H\10\243\310\244q\4\4I\11\254\307\244\364\310 \4J\12\244\310h SR\0" + "\4K\11\244\310\304\245F\12\4L\11\243\310D\225\26\0\4M\10\243\310H\271\0\4N\12\244\310\244" + "\244\226J\0\4O\10\243\310\255\264\2\4Q\10\253\310\244\326\24\4R\11\263\307D\25U\31\4S\11" + "\253\310\246\64b\4\4T\11\243\310\215\224\201\0\4U\11\243\310\215\14\26\0\4V\11\253\310e$\323" + "\0\4W\11\253\310\244\14d\32\4X\11\263\307fX.\0\4Y\10\244\310\251\326\22\4Z\11\244\310" + "\244\264\322\22\4[\11\253\310D\25U\1\4\134\10\253\310\312\264\12\4^\11\263\307\244\32u\2\4_" + "\11\253\307$k\244\4\4\220\10\253\310\16Y\2\4\221\10\243\310\16\31\1\4\222\11\253\310\251\264b\2" + "\4\223\11\243\310\251\264\22\0\0"; // Screen is 128x64 px static void app_draw_callback(Canvas* canvas, void* ctx) { @@ -43,10 +70,11 @@ static void app_draw_callback(Canvas* canvas, void* ctx) { canvas_clear(canvas); - canvas_set_custom_u8g2_font(canvas, u8g2_font_tom_thumb_4x6_tr); + canvas_set_custom_u8g2_font(canvas, u8g2_font_4x6_t_cyrillic); canvas_draw_str(canvas, 0, 6, "This is a tiny custom font"); canvas_draw_str(canvas, 0, 12, "012345.?! ,:;\"\'@#$%"); + canvas_draw_str(canvas, 0, 18, "И немного юникода"); } static void app_input_callback(InputEvent* input_event, void* ctx) { diff --git a/applications/services/gui/canvas.c b/applications/services/gui/canvas.c index 44adcd939..209c82a82 100644 --- a/applications/services/gui/canvas.c +++ b/applications/services/gui/canvas.c @@ -150,7 +150,7 @@ void canvas_draw_str(Canvas* canvas, uint8_t x, uint8_t y, const char* str) { if(!str) return; x += canvas->offset_x; y += canvas->offset_y; - u8g2_DrawStr(&canvas->fb, x, y, str); + u8g2_DrawUTF8(&canvas->fb, x, y, str); } void canvas_draw_str_aligned( @@ -169,10 +169,10 @@ void canvas_draw_str_aligned( case AlignLeft: break; case AlignRight: - x -= u8g2_GetStrWidth(&canvas->fb, str); + x -= u8g2_GetUTF8Width(&canvas->fb, str); break; case AlignCenter: - x -= (u8g2_GetStrWidth(&canvas->fb, str) / 2); + x -= (u8g2_GetUTF8Width(&canvas->fb, str) / 2); break; default: furi_crash(); @@ -193,13 +193,13 @@ void canvas_draw_str_aligned( break; } - u8g2_DrawStr(&canvas->fb, x, y, str); + u8g2_DrawUTF8(&canvas->fb, x, y, str); } uint16_t canvas_string_width(Canvas* canvas, const char* str) { furi_assert(canvas); if(!str) return 0; - return u8g2_GetStrWidth(&canvas->fb, str); + return u8g2_GetUTF8Width(&canvas->fb, str); } uint8_t canvas_glyph_width(Canvas* canvas, uint16_t symbol) { From 6f6074dc01e1370a64e953c956f6d3cfe41f0d4f Mon Sep 17 00:00:00 2001 From: gornekich Date: Tue, 19 Dec 2023 16:11:35 +0400 Subject: [PATCH 23/44] Keys Dict: fix PVS warnings (#3299) * keys dict: fix PVS warnings * nfc app: suppress PVS warning --- applications/main/nfc/nfc_app.c | 2 +- lib/toolbox/keys_dict.c | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/applications/main/nfc/nfc_app.c b/applications/main/nfc/nfc_app.c index ec528ad9c..bf15161aa 100644 --- a/applications/main/nfc/nfc_app.c +++ b/applications/main/nfc/nfc_app.c @@ -343,7 +343,7 @@ bool nfc_load_file(NfcApp* instance, FuriString* path, bool show_dialog) { nfc_supported_cards_load_cache(instance->nfc_supported_cards); FuriString* load_path = furi_string_alloc(); - if(nfc_has_shadow_file_internal(instance, path)) { + if(nfc_has_shadow_file_internal(instance, path)) { //-V1051 nfc_set_shadow_file_path(path, load_path); } else if(furi_string_end_with(path, NFC_APP_SHADOW_EXTENSION)) { size_t path_len = furi_string_size(path); diff --git a/lib/toolbox/keys_dict.c b/lib/toolbox/keys_dict.c index 30580bf5e..8d6f8c846 100644 --- a/lib/toolbox/keys_dict.c +++ b/lib/toolbox/keys_dict.c @@ -108,7 +108,7 @@ KeysDict* keys_dict_alloc(const char* path, KeysDictMode mode, size_t key_size) } } stream_rewind(instance->stream); - FURI_LOG_I(TAG, "Loaded dictionary with %u keys", instance->total_keys); + FURI_LOG_I(TAG, "Loaded dictionary with %zu keys", instance->total_keys); furi_string_free(line); @@ -299,13 +299,12 @@ bool keys_dict_delete_key(KeysDict* instance, const uint8_t* key, size_t key_siz furi_assert(key); bool key_removed = false; - bool is_endfile = false; uint8_t* temp_key = malloc(key_size); stream_rewind(instance->stream); - while(!key_removed && !is_endfile) { + while(!key_removed) { if(!keys_dict_get_next_key(instance, temp_key, key_size)) { break; } @@ -332,4 +331,4 @@ bool keys_dict_delete_key(KeysDict* instance, const uint8_t* key, size_t key_siz free(temp_key); return key_removed; -} \ No newline at end of file +} From 1e1d9fcb69358c291e65b02e89026966aead3cca Mon Sep 17 00:00:00 2001 From: hedger Date: Tue, 19 Dec 2023 16:43:06 +0400 Subject: [PATCH 24/44] ufbt: changed toolchain environment invocation; updated .gitignore for app template (#3300) --- scripts/fbt/util.py | 21 +++++++++++++ scripts/ufbt/SConstruct | 40 ++++++++++-------------- scripts/ufbt/project_template/.gitignore | 4 ++- scripts/ufbt/site_tools/ufbt_help.py | 6 +++- scripts/ufbt/site_tools/ufbt_state.py | 1 - site_scons/environ.scons | 39 ++++++++--------------- 6 files changed, 58 insertions(+), 53 deletions(-) diff --git a/scripts/fbt/util.py b/scripts/fbt/util.py index fb36ef55a..629467568 100644 --- a/scripts/fbt/util.py +++ b/scripts/fbt/util.py @@ -11,6 +11,27 @@ WINPATHSEP_RE = re.compile(r"\\([^\"'\\]|$)") # Excludes all files ending with ~, usually created by editors as backup files GLOB_FILE_EXCLUSION = ["*~"] +# List of environment variables to proxy to child processes +FORWARDED_ENV_VARIABLES = [ + # CI/CD variables + "WORKFLOW_BRANCH_OR_TAG", + "DIST_SUFFIX", + # Python & other tools + "HOME", + "APPDATA", + "PYTHONHOME", + "PYTHONNOUSERSITE", + "TMP", + "TEMP", + # ccache + "CCACHE_DISABLE", + # Colors for tools + "TERM", + # Toolchain + "FBT_TOOLCHAIN_PATH", + "UFBT_HOME", +] + def tempfile_arg_esc_func(arg): arg = quote_spaces(arg) diff --git a/scripts/ufbt/SConstruct b/scripts/ufbt/SConstruct index 46d663578..2fc170ad9 100644 --- a/scripts/ufbt/SConstruct +++ b/scripts/ufbt/SConstruct @@ -25,33 +25,10 @@ forward_os_env = { "PATH": os.environ["PATH"], } -# Proxying environment to child processes & scripts -variables_to_forward = [ - # CI/CD variables - "WORKFLOW_BRANCH_OR_TAG", - "DIST_SUFFIX", - # Python & other tools - "HOME", - "APPDATA", - "PYTHONHOME", - "PYTHONNOUSERSITE", - "TMP", - "TEMP", - # Colors for tools - "TERM", -] - -if proxy_env := GetOption("proxy_env"): - variables_to_forward.extend(proxy_env.split(",")) - -for env_value_name in variables_to_forward: - if environ_value := os.environ.get(env_value_name, None): - forward_os_env[env_value_name] = environ_value # Core environment init - loads SDK state, sets up paths, etc. core_env = Environment( variables=ufbt_variables, - ENV=forward_os_env, UFBT_STATE_DIR=ufbt_state_dir, UFBT_CURRENT_SDK_DIR=ufbt_current_sdk_dir, UFBT_SCRIPT_DIR=ufbt_script_dir, @@ -69,6 +46,7 @@ core_env.Append(CPPDEFINES=GetOption("extra_defines")) from fbt.appmanifest import FlipperApplication, FlipperAppType from fbt.sdk.cache import SdkCache from fbt.util import ( + FORWARDED_ENV_VARIABLES, path_as_posix, resolve_real_dir_node, single_quote, @@ -76,8 +54,19 @@ from fbt.util import ( wrap_tempfile, ) +variables_to_forward = list(FORWARDED_ENV_VARIABLES) + +if proxy_env := GetOption("proxy_env"): + variables_to_forward.extend(proxy_env.split(",")) + +for env_value_name in variables_to_forward: + if environ_value := os.environ.get(env_value_name, None): + forward_os_env[env_value_name] = environ_value + + # Base environment with all tools loaded from SDK env = core_env.Clone( + ENV=forward_os_env, toolpath=[core_env["FBT_SCRIPT_DIR"].Dir("fbt_tools")], tools=[ "fbt_tweaks", @@ -477,9 +466,12 @@ else: dist_env.PhonyTarget("dolphin_ext", Action(missing_dolphin_folder, None)) +# print(env.Dump()) dist_env.PhonyTarget( "env", - "@echo $( ${FBT_SCRIPT_DIR.abspath}/toolchain/fbtenv.sh $)", + '@echo "FBT_TOOLCHAIN_PATH=' + + forward_os_env["FBT_TOOLCHAIN_PATH"] + + '" source $( "${FBT_SCRIPT_DIR.abspath}/toolchain/fbtenv.sh" $)', ) dist_env.PostConfigureUfbtEnvionment() diff --git a/scripts/ufbt/project_template/.gitignore b/scripts/ufbt/project_template/.gitignore index e2a15a10a..81a8981f7 100644 --- a/scripts/ufbt/project_template/.gitignore +++ b/scripts/ufbt/project_template/.gitignore @@ -1,4 +1,6 @@ dist/* .vscode .clang-format -.editorconfig \ No newline at end of file +.editorconfig +.env +.ufbt diff --git a/scripts/ufbt/site_tools/ufbt_help.py b/scripts/ufbt/site_tools/ufbt_help.py index 1df6a0591..ab20e2f7d 100644 --- a/scripts/ufbt/site_tools/ufbt_help.py +++ b/scripts/ufbt/site_tools/ufbt_help.py @@ -44,7 +44,11 @@ How to create a new application: 4. Run `ufbt launch` to build and upload your application. How to open a shell with toolchain environment and other build tools: - In your shell, type "source `ufbt -s env`". You can also use "." instead of "source". + In your shell, type "eval `ufbt -s env`". + +How to update uFBT SDK: + Run "ufbt update" to fetch latest SDK. + You can also specify branch, target and/or channel options. See "ufbt update -h" for details. """ diff --git a/scripts/ufbt/site_tools/ufbt_state.py b/scripts/ufbt/site_tools/ufbt_state.py index 0038b66a3..d9aa0fd6b 100644 --- a/scripts/ufbt/site_tools/ufbt_state.py +++ b/scripts/ufbt/site_tools/ufbt_state.py @@ -1,6 +1,5 @@ import json import os -import pathlib import sys from functools import reduce diff --git a/site_scons/environ.scons b/site_scons/environ.scons index 74762cb15..ece8de212 100644 --- a/site_scons/environ.scons +++ b/site_scons/environ.scons @@ -1,13 +1,14 @@ -from SCons.Platform import TempFileMunge -from fbt.util import ( - tempfile_arg_esc_func, - single_quote, - wrap_tempfile, - resolve_real_dir_node, -) - -import os import multiprocessing +import os + +from fbt.util import ( + FORWARDED_ENV_VARIABLES, + resolve_real_dir_node, + single_quote, + tempfile_arg_esc_func, + wrap_tempfile, +) +from SCons.Platform import TempFileMunge Import("VAR_ENV") @@ -15,23 +16,9 @@ forward_os_env = { # Import PATH from OS env - scons doesn't do that by default "PATH": os.environ["PATH"], } -# Proxying CI environment to child processes & scripts -variables_to_forward = [ - # CI/CD variables - "WORKFLOW_BRANCH_OR_TAG", - "DIST_SUFFIX", - # Python & other tools - "HOME", - "APPDATA", - "PYTHONHOME", - "PYTHONNOUSERSITE", - "TMP", - "TEMP", - # ccache - "CCACHE_DISABLE", - # Colors for tools - "TERM", -] + +variables_to_forward = list(FORWARDED_ENV_VARIABLES) + if proxy_env := GetOption("proxy_env"): variables_to_forward.extend(proxy_env.split(",")) From 17b122990f35998d412bf2769467e5cd4b192311 Mon Sep 17 00:00:00 2001 From: Skorpionm <85568270+Skorpionm@users.noreply.github.com> Date: Tue, 19 Dec 2023 18:13:37 +0400 Subject: [PATCH 25/44] USART Bridge: added support for software control of DE/RE pins (#3280) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * USART Bridge: added support for software control of DE/RE pins * USART Bridge: fix syntax * UsbUsartBridge: add TODO ticket * UsbUsartBridge: add second TODO ticket * GpioUartBridge: human readable configuration * GpioUartBridge: rename `Soft DE/RE` to `DE/RE Pin` * GpioUartBridge: push pull for DE/RE pin Co-authored-by: あく --- .../gpio/scenes/gpio_scene_usb_uart_config.c | 17 +++++++++ applications/main/gpio/usb_uart_bridge.c | 35 +++++++++++++++++++ applications/main/gpio/usb_uart_bridge.h | 1 + 3 files changed, 53 insertions(+) diff --git a/applications/main/gpio/scenes/gpio_scene_usb_uart_config.c b/applications/main/gpio/scenes/gpio_scene_usb_uart_config.c index e2ab66264..8fcacd403 100644 --- a/applications/main/gpio/scenes/gpio_scene_usb_uart_config.c +++ b/applications/main/gpio/scenes/gpio_scene_usb_uart_config.c @@ -27,6 +27,7 @@ static const uint32_t baudrate_list[] = { 460800, 921600, }; +static const char* software_de_re[] = {"None", "4"}; bool gpio_scene_usb_uart_cfg_on_event(void* context, SceneManagerEvent event) { GpioApp* app = context; @@ -84,6 +85,17 @@ static void line_port_cb(VariableItem* item) { view_dispatcher_send_custom_event(app->view_dispatcher, GpioUsbUartEventConfigSet); } +static void line_software_de_re_cb(VariableItem* item) { + GpioApp* app = variable_item_get_context(item); + furi_assert(app); + uint8_t index = variable_item_get_current_value_index(item); + + variable_item_set_current_value_text(item, software_de_re[index]); + + app->usb_uart_cfg->software_de_re = index; + view_dispatcher_send_custom_event(app->view_dispatcher, GpioUsbUartEventConfigSet); +} + static void line_flow_cb(VariableItem* item) { GpioApp* app = variable_item_get_context(item); furi_assert(app); @@ -155,6 +167,11 @@ void gpio_scene_usb_uart_cfg_on_enter(void* context) { app->var_item_flow = item; line_ensure_flow_invariant(app); + item = variable_item_list_add( + var_item_list, "DE/RE Pin", COUNT_OF(software_de_re), line_software_de_re_cb, app); + variable_item_set_current_value_index(item, app->usb_uart_cfg->software_de_re); + variable_item_set_current_value_text(item, software_de_re[app->usb_uart_cfg->software_de_re]); + variable_item_list_set_selected_item( var_item_list, scene_manager_get_scene_state(app->scene_manager, GpioAppViewUsbUartCfg)); diff --git a/applications/main/gpio/usb_uart_bridge.c b/applications/main/gpio/usb_uart_bridge.c index 9bc759dc8..366c5cdc4 100644 --- a/applications/main/gpio/usb_uart_bridge.c +++ b/applications/main/gpio/usb_uart_bridge.c @@ -6,11 +6,16 @@ #include #include +//TODO: FL-3276 port to new USART API +#include +#include + #define USB_CDC_PKT_LEN CDC_DATA_SZ #define USB_UART_RX_BUF_SIZE (USB_CDC_PKT_LEN * 5) #define USB_CDC_BIT_DTR (1 << 0) #define USB_CDC_BIT_RTS (1 << 1) +#define USB_USART_DE_RE_PIN &gpio_ext_pa4 static const GpioPin* flow_pins[][2] = { {&gpio_ext_pa7, &gpio_ext_pa6}, // 2, 3 @@ -247,6 +252,17 @@ static int32_t usb_uart_worker(void* context) { usb_uart->cfg.flow_pins = usb_uart->cfg_new.flow_pins; events |= WorkerEvtCtrlLineSet; } + if(usb_uart->cfg.software_de_re != usb_uart->cfg_new.software_de_re) { + usb_uart->cfg.software_de_re = usb_uart->cfg_new.software_de_re; + if(usb_uart->cfg.software_de_re != 0) { + furi_hal_gpio_write(USB_USART_DE_RE_PIN, true); + furi_hal_gpio_init( + USB_USART_DE_RE_PIN, GpioModeOutputPushPull, GpioPullNo, GpioSpeedMedium); + } else { + furi_hal_gpio_init( + USB_USART_DE_RE_PIN, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + } + } api_lock_unlock(usb_uart->cfg_lock); } if(events & WorkerEvtLineCfgSet) { @@ -260,6 +276,8 @@ static int32_t usb_uart_worker(void* context) { usb_uart_vcp_deinit(usb_uart, usb_uart->cfg.vcp_ch); usb_uart_serial_deinit(usb_uart, usb_uart->cfg.uart_ch); + furi_hal_gpio_init(USB_USART_DE_RE_PIN, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + if(usb_uart->cfg.flow_pins != 0) { furi_hal_gpio_init_simple(flow_pins[usb_uart->cfg.flow_pins - 1][0], GpioModeAnalog); furi_hal_gpio_init_simple(flow_pins[usb_uart->cfg.flow_pins - 1][1], GpioModeAnalog); @@ -298,7 +316,24 @@ static int32_t usb_uart_tx_thread(void* context) { if(len > 0) { usb_uart->st.tx_cnt += len; + + if(usb_uart->cfg.software_de_re != 0) + furi_hal_gpio_write(USB_USART_DE_RE_PIN, false); + furi_hal_uart_tx(usb_uart->cfg.uart_ch, data, len); + + if(usb_uart->cfg.software_de_re != 0) { + //TODO: FL-3276 port to new USART API + if(usb_uart->cfg.uart_ch == FuriHalUartIdUSART1) { + while(!LL_USART_IsActiveFlag_TC(USART1)) + ; + } else if(usb_uart->cfg.uart_ch == FuriHalUartIdLPUART1) { + while(!LL_LPUART_IsActiveFlag_TC(LPUART1)) + ; + } + + furi_hal_gpio_write(USB_USART_DE_RE_PIN, true); + } } } } diff --git a/applications/main/gpio/usb_uart_bridge.h b/applications/main/gpio/usb_uart_bridge.h index b456c3cc4..ebb103f54 100644 --- a/applications/main/gpio/usb_uart_bridge.h +++ b/applications/main/gpio/usb_uart_bridge.h @@ -11,6 +11,7 @@ typedef struct { uint8_t flow_pins; uint8_t baudrate_mode; uint32_t baudrate; + uint8_t software_de_re; } UsbUartConfig; typedef struct { From bc1fdabce4965ae3ec77eb3fdbcbd5d119800e07 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Wed, 20 Dec 2023 01:25:35 +0300 Subject: [PATCH 26/44] its time to enable this one --- assets/dolphin/external/manifest.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/assets/dolphin/external/manifest.txt b/assets/dolphin/external/manifest.txt index 9aaff3c6f..c2583ae5a 100644 --- a/assets/dolphin/external/manifest.txt +++ b/assets/dolphin/external/manifest.txt @@ -203,3 +203,10 @@ Max butthurt: 10 Min level: 3 Max level: 3 Weight: 2 + +Name: L1_New_year_128x64 +Min butthurt: 0 +Max butthurt: 10 +Min level: 1 +Max level: 3 +Weight: 7 From 49b2a4da8a17f0d63a7bc8d6b1c011bea964398f Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Thu, 21 Dec 2023 03:14:23 +0300 Subject: [PATCH 27/44] fix broken texts due to usage of utf8, add proper api --- .../example_custom_font/example_custom_font.c | 6 +- applications/services/gui/canvas.c | 57 +++++++++++++++++++ applications/services/gui/canvas.h | 38 +++++++++++++ targets/f7/api_symbols.csv | 3 + 4 files changed, 101 insertions(+), 3 deletions(-) diff --git a/applications/debug/example_custom_font/example_custom_font.c b/applications/debug/example_custom_font/example_custom_font.c index 8d85f23c6..334aa8aa8 100644 --- a/applications/debug/example_custom_font/example_custom_font.c +++ b/applications/debug/example_custom_font/example_custom_font.c @@ -72,9 +72,9 @@ static void app_draw_callback(Canvas* canvas, void* ctx) { canvas_set_custom_u8g2_font(canvas, u8g2_font_4x6_t_cyrillic); - canvas_draw_str(canvas, 0, 6, "This is a tiny custom font"); - canvas_draw_str(canvas, 0, 12, "012345.?! ,:;\"\'@#$%"); - canvas_draw_str(canvas, 0, 18, "И немного юникода"); + canvas_draw_utf8_str(canvas, 0, 6, "This is a tiny custom font"); + canvas_draw_utf8_str(canvas, 0, 12, "012345.?! ,:;\"\'@#$%"); + canvas_draw_utf8_str(canvas, 0, 18, "И немного юникода"); } static void app_input_callback(InputEvent* input_event, void* ctx) { diff --git a/applications/services/gui/canvas.c b/applications/services/gui/canvas.c index f8f33da9b..3cd35e402 100644 --- a/applications/services/gui/canvas.c +++ b/applications/services/gui/canvas.c @@ -154,6 +154,14 @@ void canvas_set_custom_u8g2_font(Canvas* canvas, const uint8_t* font) { } void canvas_draw_str(Canvas* canvas, uint8_t x, uint8_t y, const char* str) { + furi_assert(canvas); + if(!str) return; + x += canvas->offset_x; + y += canvas->offset_y; + u8g2_DrawStr(&canvas->fb, x, y, str); +} + +void canvas_draw_utf8_str(Canvas* canvas, uint8_t x, uint8_t y, const char* str) { furi_assert(canvas); if(!str) return; x += canvas->offset_x; @@ -173,6 +181,49 @@ void canvas_draw_str_aligned( x += canvas->offset_x; y += canvas->offset_y; + switch(horizontal) { + case AlignLeft: + break; + case AlignRight: + x -= u8g2_GetStrWidth(&canvas->fb, str); + break; + case AlignCenter: + x -= (u8g2_GetStrWidth(&canvas->fb, str) / 2); + break; + default: + furi_crash(); + break; + } + + switch(vertical) { + case AlignTop: + y += u8g2_GetAscent(&canvas->fb); + break; + case AlignBottom: + break; + case AlignCenter: + y += (u8g2_GetAscent(&canvas->fb) / 2); + break; + default: + furi_crash(); + break; + } + + u8g2_DrawStr(&canvas->fb, x, y, str); +} + +void canvas_draw_utf8_str_aligned( + Canvas* canvas, + uint8_t x, + uint8_t y, + Align horizontal, + Align vertical, + const char* str) { + furi_assert(canvas); + if(!str) return; + x += canvas->offset_x; + y += canvas->offset_y; + switch(horizontal) { case AlignLeft: break; @@ -205,6 +256,12 @@ void canvas_draw_str_aligned( } uint16_t canvas_string_width(Canvas* canvas, const char* str) { + furi_assert(canvas); + if(!str) return 0; + return u8g2_GetStrWidth(&canvas->fb, str); +} + +uint16_t canvas_utf8_string_width(Canvas* canvas, const char* str) { furi_assert(canvas); if(!str) return 0; return u8g2_GetUTF8Width(&canvas->fb, str); diff --git a/applications/services/gui/canvas.h b/applications/services/gui/canvas.h index bda730ff2..afed58548 100644 --- a/applications/services/gui/canvas.h +++ b/applications/services/gui/canvas.h @@ -187,6 +187,15 @@ void canvas_set_custom_u8g2_font(Canvas* canvas, const uint8_t* font); */ void canvas_draw_str(Canvas* canvas, uint8_t x, uint8_t y, const char* str); +/** Draw UTF8 string at position of baseline defined by x, y. + * + * @param canvas Canvas instance + * @param x anchor point x coordinate + * @param y anchor point y coordinate + * @param str C-string + */ +void canvas_draw_utf8_str(Canvas* canvas, uint8_t x, uint8_t y, const char* str); + /** Draw aligned string defined by x, y. * * Align calculated from position of baseline, string width and ascent (height @@ -207,6 +216,26 @@ void canvas_draw_str_aligned( Align vertical, const char* str); +/** Draw aligned UTF8 string defined by x, y. + * + * Align calculated from position of baseline, string width and ascent (height + * of the glyphs above the baseline) + * + * @param canvas Canvas instance + * @param x anchor point x coordinate + * @param y anchor point y coordinate + * @param horizontal horizontal alignment + * @param vertical vertical alignment + * @param str C-string + */ +void canvas_draw_utf8_str_aligned( + Canvas* canvas, + uint8_t x, + uint8_t y, + Align horizontal, + Align vertical, + const char* str); + /** Get string width * * @param canvas Canvas instance @@ -216,6 +245,15 @@ void canvas_draw_str_aligned( */ uint16_t canvas_string_width(Canvas* canvas, const char* str); +/** Get UTF8 string width + * + * @param canvas Canvas instance + * @param str C-string + * + * @return width in pixels. + */ +uint16_t canvas_utf8_string_width(Canvas* canvas, const char* str); + /** Get glyph width * * @param canvas Canvas instance diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index 3ab58f58d..afce83fe5 100644 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -735,6 +735,8 @@ Function,+,canvas_draw_rframe,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, Function,+,canvas_draw_str,void,"Canvas*, uint8_t, uint8_t, const char*" Function,+,canvas_draw_str_aligned,void,"Canvas*, uint8_t, uint8_t, Align, Align, const char*" Function,+,canvas_draw_triangle,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, CanvasDirection" +Function,+,canvas_draw_utf8_str,void,"Canvas*, uint8_t, uint8_t, const char*" +Function,+,canvas_draw_utf8_str_aligned,void,"Canvas*, uint8_t, uint8_t, Align, Align, const char*" Function,+,canvas_draw_xbm,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, const uint8_t*" Function,+,canvas_get_font_params,const CanvasFontParameters*,"const Canvas*, Font" Function,+,canvas_glyph_width,uint8_t,"Canvas*, uint16_t" @@ -747,6 +749,7 @@ Function,+,canvas_set_custom_u8g2_font,void,"Canvas*, const uint8_t*" Function,+,canvas_set_font,void,"Canvas*, Font" Function,+,canvas_set_font_direction,void,"Canvas*, CanvasDirection" Function,+,canvas_string_width,uint16_t,"Canvas*, const char*" +Function,+,canvas_utf8_string_width,uint16_t,"Canvas*, const char*" Function,+,canvas_width,uint8_t,const Canvas* Function,-,cbrt,double,double Function,-,cbrtf,float,float From 8fa21c49b2ee49aadd28d713f586880469e3bff1 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Thu, 21 Dec 2023 03:16:16 +0300 Subject: [PATCH 28/44] better subghz history element removal by Willy-JL https://github.com/Flipper-XFW/Xtreme-Firmware/commit/c40755f700a89af2b6519e7cd9a5d64f11c95165 --- .../subghz/scenes/subghz_scene_receiver.c | 4 +- applications/main/subghz/subghz_history.c | 27 +++++-------- applications/main/subghz/subghz_history.h | 2 +- applications/main/subghz/views/receiver.c | 38 ++++++++----------- applications/main/subghz/views/receiver.h | 2 +- 5 files changed, 30 insertions(+), 43 deletions(-) diff --git a/applications/main/subghz/scenes/subghz_scene_receiver.c b/applications/main/subghz/scenes/subghz_scene_receiver.c index 9dc48965d..bffff9988 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver.c @@ -249,7 +249,9 @@ bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event) { subghz_view_receiver_disable_draw_callback(subghz->subghz_receiver); subghz_history_delete_item(subghz->history, subghz->idx_menu_chosen); - subghz_view_receiver_delete_element_callback(subghz->subghz_receiver); + subghz_view_receiver_delete_item( + subghz->subghz_receiver, + subghz_view_receiver_get_idx_menu(subghz->subghz_receiver)); subghz_view_receiver_enable_draw_callback(subghz->subghz_receiver); subghz_scene_receiver_update_statusbar(subghz); diff --git a/applications/main/subghz/subghz_history.c b/applications/main/subghz/subghz_history.c index 396e28421..048104f35 100644 --- a/applications/main/subghz/subghz_history.c +++ b/applications/main/subghz/subghz_history.c @@ -89,26 +89,19 @@ void subghz_history_reset(SubGhzHistory* instance) { instance->code_last_hash_data = 0; } -void subghz_history_delete_item(SubGhzHistory* instance, uint16_t item_id) { +void subghz_history_delete_item(SubGhzHistory* instance, uint16_t idx) { furi_assert(instance); - SubGhzHistoryItemArray_it_t it; - //SubGhzHistoryItem* target_item = SubGhzHistoryItemArray_get(instance->history->data, item_id); - SubGhzHistoryItemArray_it_last(it, instance->history->data); - while(!SubGhzHistoryItemArray_end_p(it)) { - SubGhzHistoryItem* item = SubGhzHistoryItemArray_ref(it); - - if(it->index == (size_t)(item_id)) { - furi_string_free(item->item_str); - furi_string_free(item->preset->name); - free(item->preset); - flipper_format_free(item->flipper_string); - item->type = 0; - SubGhzHistoryItemArray_remove(instance->history->data, it); - } - SubGhzHistoryItemArray_previous(it); + if(idx < SubGhzHistoryItemArray_size(instance->history->data)) { + SubGhzHistoryItem* item = SubGhzHistoryItemArray_get(instance->history->data, idx); + furi_string_free(item->item_str); + furi_string_free(item->preset->name); + free(item->preset); + flipper_format_free(item->flipper_string); + item->type = 0; + SubGhzHistoryItemArray_remove_v(instance->history->data, idx, idx + 1); + instance->last_index_write--; } - instance->last_index_write--; } uint16_t subghz_history_get_item(SubGhzHistory* instance) { diff --git a/applications/main/subghz/subghz_history.h b/applications/main/subghz/subghz_history.h index 1b27d52ad..cc63c0259 100644 --- a/applications/main/subghz/subghz_history.h +++ b/applications/main/subghz/subghz_history.h @@ -27,7 +27,7 @@ void subghz_history_free(SubGhzHistory* instance); */ void subghz_history_reset(SubGhzHistory* instance); -void subghz_history_delete_item(SubGhzHistory* instance, uint16_t item_id); +void subghz_history_delete_item(SubGhzHistory* instance, uint16_t idx); /** Get frequency to history[idx] * diff --git a/applications/main/subghz/views/receiver.c b/applications/main/subghz/views/receiver.c index f1d0324fc..98c15dbff 100644 --- a/applications/main/subghz/views/receiver.c +++ b/applications/main/subghz/views/receiver.c @@ -655,40 +655,32 @@ uint16_t subghz_view_receiver_get_idx_menu(SubGhzViewReceiver* subghz_receiver) return idx; } -void subghz_view_receiver_delete_element_callback(SubGhzViewReceiver* subghz_receiver) { +void subghz_view_receiver_delete_item(SubGhzViewReceiver* subghz_receiver, uint16_t idx) { furi_assert(subghz_receiver); with_view_model( subghz_receiver->view, SubGhzViewReceiverModel * model, { - SubGhzReceiverMenuItemArray_it_t it; - // SubGhzReceiverMenuItem* target_item = - // SubGhzReceiverMenuItemArray_get(model->history->data, model->idx); - SubGhzReceiverMenuItemArray_it_last(it, model->history->data); - while(!SubGhzReceiverMenuItemArray_end_p(it)) { - SubGhzReceiverMenuItem* item = SubGhzReceiverMenuItemArray_ref(it); + if(idx < SubGhzReceiverMenuItemArray_size(model->history->data)) { + SubGhzReceiverMenuItem* item = + SubGhzReceiverMenuItemArray_get(model->history->data, idx); + furi_string_free(item->item_str); + furi_string_free(item->time); + item->type = 0; + SubGhzReceiverMenuItemArray_remove_v(model->history->data, idx, idx + 1); - if(it->index == (size_t)(model->idx)) { - furi_string_free(item->item_str); - furi_string_free(item->time); - item->type = 0; - SubGhzReceiverMenuItemArray_remove(model->history->data, it); + if(model->history_item == 5) { + if(model->idx >= 2) { + model->idx = model->history_item - 1; + } } + model->history_item--; - SubGhzReceiverMenuItemArray_previous(it); - } - - if(model->history_item == 5) { - if(model->idx >= 2) { - model->idx = model->history_item - 1; + if(model->idx && (model->idx > idx || model->idx == model->history_item)) { + model->idx--; } } - model->history_item--; - - if(model->idx != 0) { - model->idx--; - } }, true); } diff --git a/applications/main/subghz/views/receiver.h b/applications/main/subghz/views/receiver.h index c280e1de6..f28ed1304 100644 --- a/applications/main/subghz/views/receiver.h +++ b/applications/main/subghz/views/receiver.h @@ -53,7 +53,7 @@ uint16_t subghz_view_receiver_get_idx_menu(SubGhzViewReceiver* subghz_receiver); void subghz_view_receiver_set_idx_menu(SubGhzViewReceiver* subghz_receiver, uint16_t idx); -void subghz_view_receiver_delete_element_callback(SubGhzViewReceiver* subghz_receiver); +void subghz_view_receiver_delete_item(SubGhzViewReceiver* subghz_receiver, uint16_t idx); void subghz_view_receiver_enable_draw_callback(SubGhzViewReceiver* subghz_receiver); From 77f458fb6ea27057962f3767bd54a5bc5253276e Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Thu, 21 Dec 2023 03:17:21 +0300 Subject: [PATCH 29/44] testing subghz dynamic limit based on freeheap + RPC by Willy-JL https://github.com/Flipper-XFW/Xtreme-Firmware/commit/5cd2d3eabe10e303b94e1960f8fa78a7ce45ce40 https://github.com/Flipper-XFW/Xtreme-Firmware/commit/e8d9325bec454603b79b33cef2337110af4e2c99 --- applications/main/subghz/subghz_history.c | 15 +++++++++------ applications/main/subghz/views/receiver.c | 22 ++++++++++++++++++++-- applications/services/rpc/rpc.c | 9 +++++++++ applications/services/rpc/rpc.h | 7 +++++++ targets/f7/api_symbols.csv | 1 + 5 files changed, 46 insertions(+), 8 deletions(-) diff --git a/applications/main/subghz/subghz_history.c b/applications/main/subghz/subghz_history.c index 048104f35..b18df0ee8 100644 --- a/applications/main/subghz/subghz_history.c +++ b/applications/main/subghz/subghz_history.c @@ -1,10 +1,11 @@ #include "subghz_history.h" #include +#include #include -#define SUBGHZ_HISTORY_MAX 55 -#define SUBGHZ_HISTORY_FREE_HEAP 20480 +#define SUBGHZ_HISTORY_MAX 65530 // uint16_t index max, ram limit below +#define SUBGHZ_HISTORY_FREE_HEAP (10240 * (3 - MIN(rpc_get_sessions_count(instance->rpc), 2U))) #define TAG "SubGhzHistory" typedef struct { @@ -29,6 +30,7 @@ struct SubGhzHistory { uint8_t code_last_hash_data; FuriString* tmp_string; SubGhzHistoryStruct* history; + Rpc* rpc; }; SubGhzHistory* subghz_history_alloc(void) { @@ -36,6 +38,7 @@ SubGhzHistory* subghz_history_alloc(void) { instance->tmp_string = furi_string_alloc(); instance->history = malloc(sizeof(SubGhzHistoryStruct)); SubGhzHistoryItemArray_init(instance->history->data); + instance->rpc = furi_record_open(RECORD_RPC); return instance; } @@ -52,6 +55,7 @@ void subghz_history_free(SubGhzHistory* instance) { } SubGhzHistoryItemArray_clear(instance->history->data); free(instance->history); + furi_record_close(RECORD_RPC); free(instance); } @@ -143,15 +147,14 @@ FlipperFormat* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx bool subghz_history_get_text_space_left(SubGhzHistory* instance, FuriString* output) { furi_assert(instance); if(memmgr_get_free_heap() < SUBGHZ_HISTORY_FREE_HEAP) { - if(output != NULL) furi_string_printf(output, " Free heap LOW"); + if(output != NULL) furi_string_printf(output, " Memory is FULL"); return true; } if(instance->last_index_write == SUBGHZ_HISTORY_MAX) { - if(output != NULL) furi_string_printf(output, " Memory is FULL"); + if(output != NULL) furi_string_printf(output, " History is FULL"); return true; } - if(output != NULL) - furi_string_printf(output, "%02u/%02u", instance->last_index_write, SUBGHZ_HISTORY_MAX); + if(output != NULL) furi_string_printf(output, "%02u", instance->last_index_write); return false; } diff --git a/applications/main/subghz/views/receiver.c b/applications/main/subghz/views/receiver.c index 98c15dbff..1d3967edb 100644 --- a/applications/main/subghz/views/receiver.c +++ b/applications/main/subghz/views/receiver.c @@ -383,7 +383,16 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) { #else canvas_draw_str(canvas, 79, 62, furi_string_get_cstr(model->preset_str)); #endif - canvas_draw_str(canvas, 96, 62, furi_string_get_cstr(model->history_stat_str)); + if(!furi_string_empty(model->history_stat_str)) { + canvas_draw_str_aligned( + canvas, + 114, + 62, + AlignRight, + AlignBottom, + furi_string_get_cstr(model->history_stat_str)); + canvas_draw_icon(canvas, 116, 53, &I_sub1_10px); + } canvas_set_font(canvas, FontSecondary); elements_bold_rounded_frame(canvas, 14, 8, 99, 48); elements_multiline_text(canvas, 65, 26, "To unlock\npress:"); @@ -419,7 +428,16 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) { #else canvas_draw_str(canvas, 79, 62, furi_string_get_cstr(model->preset_str)); #endif - canvas_draw_str(canvas, 96, 62, furi_string_get_cstr(model->history_stat_str)); + if(!furi_string_empty(model->history_stat_str)) { + canvas_draw_str_aligned( + canvas, + 114, + 62, + AlignRight, + AlignBottom, + furi_string_get_cstr(model->history_stat_str)); + canvas_draw_icon(canvas, 116, 53, &I_sub1_10px); + } } break; } } diff --git a/applications/services/rpc/rpc.c b/applications/services/rpc/rpc.c index 50c4b3608..6d9f31da0 100644 --- a/applications/services/rpc/rpc.c +++ b/applications/services/rpc/rpc.c @@ -87,6 +87,7 @@ struct RpcSession { struct Rpc { FuriMutex* busy_mutex; + size_t sessions_count; }; RpcOwner rpc_session_get_owner(RpcSession* session) { @@ -407,6 +408,8 @@ RpcSession* rpc_session_open(Rpc* rpc, RpcOwner owner) { furi_thread_start(session->thread); + rpc->sessions_count++; + return session; } @@ -414,6 +417,8 @@ void rpc_session_close(RpcSession* session) { furi_assert(session); furi_assert(session->rpc); + session->rpc->sessions_count--; + rpc_session_set_send_bytes_callback(session, NULL); rpc_session_set_close_callback(session, NULL); rpc_session_set_buffer_is_empty_callback(session, NULL); @@ -489,3 +494,7 @@ void rpc_send_and_release_empty(RpcSession* session, uint32_t command_id, PB_Com rpc_send_and_release(session, &message); pb_release(&PB_Main_msg, &message); } + +size_t rpc_get_sessions_count(Rpc* rpc) { + return rpc->sessions_count; +} diff --git a/applications/services/rpc/rpc.h b/applications/services/rpc/rpc.h index 863bca355..b1e7a4d47 100644 --- a/applications/services/rpc/rpc.h +++ b/applications/services/rpc/rpc.h @@ -134,6 +134,13 @@ size_t rpc_session_feed(RpcSession* session, uint8_t* buffer, size_t size, uint3 */ size_t rpc_session_get_available_size(RpcSession* session); +/** Get number of open RPC sessions + * + * @param rpc instance + * @return sessions count + */ +size_t rpc_get_sessions_count(Rpc* rpc); + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index afce83fe5..0f15dc761 100644 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -2709,6 +2709,7 @@ Function,-,rintl,long double,long double Function,-,round,double,double Function,+,roundf,float,float Function,-,roundl,long double,long double +Function,+,rpc_get_sessions_count,size_t,Rpc* Function,+,rpc_session_close,void,RpcSession* Function,+,rpc_session_feed,size_t,"RpcSession*, uint8_t*, size_t, uint32_t" Function,+,rpc_session_get_available_size,size_t,RpcSession* From eaae5da51914a5ac5132d3540dda81c8a79c158d Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Thu, 21 Dec 2023 03:28:53 +0300 Subject: [PATCH 30/44] faac rcxt add manually (not tested) --- .../main/subghz/helpers/subghz_custom_event.h | 2 + .../subghz/scenes/subghz_scene_set_type.c | 42 +++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/applications/main/subghz/helpers/subghz_custom_event.h b/applications/main/subghz/helpers/subghz_custom_event.h index fec4c66c5..6838b345d 100644 --- a/applications/main/subghz/helpers/subghz_custom_event.h +++ b/applications/main/subghz/helpers/subghz_custom_event.h @@ -27,6 +27,8 @@ typedef enum { SubmenuIndexGibidi433, SubmenuIndexNiceMHouse_433_92, SubmenuIndexJCM_433_92, + SubmenuIndexFAACRCXT_433_92, + SubmenuIndexFAACRCXT_868, SubmenuIndexNormstahl_433_92, SubmenuIndexGSN, SubmenuIndexAprimatic, diff --git a/applications/main/subghz/scenes/subghz_scene_set_type.c b/applications/main/subghz/scenes/subghz_scene_set_type.c index 28db55d75..2d6181851 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_type.c +++ b/applications/main/subghz/scenes/subghz_scene_set_type.c @@ -181,6 +181,18 @@ void subghz_scene_set_type_on_enter(void* context) { SubmenuIndexJCM_433_92, subghz_scene_set_type_submenu_callback, subghz); + submenu_add_item( + subghz->submenu, + "KL: FAAC RC,XT 433MHz", + SubmenuIndexFAACRCXT_433_92, + subghz_scene_set_type_submenu_callback, + subghz); + submenu_add_item( + subghz->submenu, + "KL: FAAC RC,XT 868MHz", + SubmenuIndexFAACRCXT_868, + subghz_scene_set_type_submenu_callback, + subghz); submenu_add_item( subghz->submenu, "KL: Nice Mhouse 433MHz", @@ -744,6 +756,36 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); } break; + case SubmenuIndexFAACRCXT_433_92: + generated_protocol = subghz_txrx_gen_keeloq_protocol( + subghz->txrx, + "AM650", + 433920000, + (key & 0x0000FFFF) | 0x00100000, + 0x2, + 0x0003, + "FAAC_RC,XT"); + if(!generated_protocol) { + furi_string_set( + subghz->error_str, "Function requires\nan SD card with\nfresh databases."); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); + } + break; + case SubmenuIndexFAACRCXT_868: + generated_protocol = subghz_txrx_gen_keeloq_protocol( + subghz->txrx, + "AM650", + 868350000, + (key & 0x0000FFFF) | 0x00100000, + 0x2, + 0x0003, + "FAAC_RC,XT"); + if(!generated_protocol) { + furi_string_set( + subghz->error_str, "Function requires\nan SD card with\nfresh databases."); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); + } + break; case SubmenuIndexNormstahl_433_92: generated_protocol = subghz_txrx_gen_keeloq_protocol( subghz->txrx, "AM650", 433920000, key & 0x00FFFFFF, 0x2, 0x0003, "Normstahl"); From 271ec6cf97077bf0721c1585c47510881048564e Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Thu, 21 Dec 2023 03:37:44 +0300 Subject: [PATCH 31/44] fix readme --- ReadMe.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ReadMe.md b/ReadMe.md index e5da572cc..18fcc7c06 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -100,7 +100,7 @@ Also check the [changelog in releases](https://github.com/DarkFlippers/unleashed ### Current modified and new Sub-GHz protocols list: Thanks to Official team (to their SubGHz Developer, Skorp) for implementing decoders for these protocols in OFW. -Keeloq [Not ALL systems supported for decode or emulation yet!] - [Supported manufacturers list](https://0bin.net/paste/VwR2lNJY#WH9vnPgvcp7w6zVKucFCuNREKAcOij8KsJ6vqLfMn3b) +Keeloq [Not ALL systems supported for decode or emulation!] - [Supported manufacturers list](https://pastes.io/raw/unuj9bhe4m) Encoders or sending made by @xMasterX: - Nero Radio 57bit (+ 56bit encoder improvements) From 1acbd84b7c389627a2b060dca80cf229820e7c4f Mon Sep 17 00:00:00 2001 From: amec0e <88857687+amec0e@users.noreply.github.com> Date: Thu, 21 Dec 2023 15:39:57 +0000 Subject: [PATCH 32/44] Update tv.ir New additions --- .../main/infrared/resources/infrared/assets/tv.ir | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/applications/main/infrared/resources/infrared/assets/tv.ir b/applications/main/infrared/resources/infrared/assets/tv.ir index d2164b16d..9e2f13b40 100755 --- a/applications/main/infrared/resources/infrared/assets/tv.ir +++ b/applications/main/infrared/resources/infrared/assets/tv.ir @@ -1,7 +1,7 @@ Filetype: IR library file Version: 1 -# Last Updated 29th Oct, 2023 -# Last Checked 29th Oct, 2023 +# Last Updated 21st Dec, 2023 +# Last Checked 21st Dec, 2023 # name: Power type: parsed @@ -2459,3 +2459,9 @@ type: parsed protocol: NEC address: 38 00 00 00 command: 1C 00 00 00 +# +name: Mute +type: parsed +protocol: NEC +address: 38 00 00 00 +command: 04 00 00 00 From c5a76af1dd316aea4f2d102b08f9d9c73fbbe9bb Mon Sep 17 00:00:00 2001 From: amec0e <88857687+amec0e@users.noreply.github.com> Date: Thu, 21 Dec 2023 15:40:44 +0000 Subject: [PATCH 33/44] Update projectors.ir Updated last checked, no new additions --- .../main/infrared/resources/infrared/assets/projectors.ir | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/main/infrared/resources/infrared/assets/projectors.ir b/applications/main/infrared/resources/infrared/assets/projectors.ir index 2fef79ee4..35c9485da 100644 --- a/applications/main/infrared/resources/infrared/assets/projectors.ir +++ b/applications/main/infrared/resources/infrared/assets/projectors.ir @@ -1,7 +1,7 @@ Filetype: IR library file Version: 1 # Last Updated 1st Oct, 2023 -# Last Checked 1st Oct, 2023 +# Last Checked 21st Dec, 2023 # # TEMP FIX FOR POWER # From cdede67f311586d83b0d87795d0e4af33fb81acf Mon Sep 17 00:00:00 2001 From: amec0e <88857687+amec0e@users.noreply.github.com> Date: Thu, 21 Dec 2023 15:41:08 +0000 Subject: [PATCH 34/44] Update fans.ir New additions --- .../resources/infrared/assets/fans.ir | 40 ++++++++++++++++++- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/applications/main/infrared/resources/infrared/assets/fans.ir b/applications/main/infrared/resources/infrared/assets/fans.ir index 938bc96a6..1c0360a1d 100644 --- a/applications/main/infrared/resources/infrared/assets/fans.ir +++ b/applications/main/infrared/resources/infrared/assets/fans.ir @@ -1,7 +1,7 @@ Filetype: IR library file Version: 1 -#Last Updated 1st Oct, 2023 -#Last Checked 1st Oct, 2023 +#Last Updated 21st Dec, 2023 +#Last Checked 21st Dec, 2023 # name: Power type: raw @@ -2103,3 +2103,39 @@ type: raw frequency: 38000 duty_cycle: 0.33 data: 1330 376 1303 376 460 1192 1331 376 1302 376 459 1191 463 1217 462 1218 1331 376 459 1195 484 1219 460 7907 1300 379 1300 380 456 1223 1300 380 1300 380 456 1224 456 1224 456 1224 1299 380 456 1224 456 1224 456 8166 1299 380 1299 380 456 1224 1299 380 1299 380 456 1224 456 1224 455 1224 1299 380 456 1224 455 1224 456 7909 1299 380 1299 380 455 1224 1299 380 1299 380 456 1224 455 1225 455 1225 1298 381 455 1225 454 1225 455 +# +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 9213 4493 613 530 612 529 613 528 614 526 616 1631 615 1631 615 529 613 528 614 1631 615 1631 615 1632 614 1632 614 529 613 528 614 1632 614 1630 616 527 615 1631 615 528 614 1634 611 527 614 527 615 527 615 1630 616 1635 611 528 614 1632 614 527 615 1634 612 1631 615 1632 614 527 615 39730 9215 2228 617 95835 9215 2231 614 +# +name: Speed_up +type: parsed +protocol: NEC +address: 30 00 00 00 +command: 89 00 00 00 +# +name: Timer +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 9279 4487 620 526 617 528 614 527 615 527 615 1633 612 1631 614 526 615 527 614 1634 611 1631 614 1633 612 1633 612 529 612 531 610 1633 612 1632 614 528 613 1630 615 1633 613 1632 613 526 615 529 613 527 615 1633 613 1632 614 526 615 526 616 527 615 1632 614 1631 614 1632 614 526 615 39731 9204 2230 614 +# +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 2227 839 757 1597 751 1599 749 829 757 815 750 817 748 814 751 806 749 866 751 836 750 832 754 823 753 819 757 811 754 807 758 799 756 103041 2229 837 749 1605 754 1597 751 826 750 823 753 815 750 812 753 804 751 864 753 834 752 830 756 821 755 818 758 809 756 806 749 808 757 64662 2229 774 749 1558 748 60749 2229 775 748 1559 758 +# +name: Speed_up +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 2222 843 753 1626 732 1590 758 820 756 817 759 808 757 804 751 806 749 893 724 1603 755 827 748 1595 753 820 756 1578 759 1570 757 827 728 99745 2231 834 752 1601 757 1592 756 821 755 817 759 808 757 805 750 807 758 856 751 1630 728 827 749 1622 726 820 756 1605 732 1570 757 800 755 +# +name: Speed_dn +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 2221 844 752 1600 758 1591 757 820 756 816 749 817 748 813 752 804 751 1632 758 1596 752 1597 751 1594 754 1585 752 1582 756 806 749 808 757 102464 2224 841 756 1597 751 1599 749 828 748 824 752 815 750 811 754 802 753 1629 750 1604 754 1595 753 1591 757 1583 755 1579 759 804 751 806 749 From 18194b6bb58107a227808389edc6edb95a09d33d Mon Sep 17 00:00:00 2001 From: amec0e <88857687+amec0e@users.noreply.github.com> Date: Thu, 21 Dec 2023 15:41:32 +0000 Subject: [PATCH 35/44] Update audio.ir New additions --- .../resources/infrared/assets/audio.ir | 160 +++++++++++++++++- 1 file changed, 158 insertions(+), 2 deletions(-) diff --git a/applications/main/infrared/resources/infrared/assets/audio.ir b/applications/main/infrared/resources/infrared/assets/audio.ir index 724c7c572..ffa108bc4 100644 --- a/applications/main/infrared/resources/infrared/assets/audio.ir +++ b/applications/main/infrared/resources/infrared/assets/audio.ir @@ -1,7 +1,7 @@ Filetype: IR library file Version: 1 -# Last Updated 1st Sept, 2023 -# Last Checked 1st Oct, 2023 +# Last Updated 21st Dec, 2023 +# Last Checked 21st Dec, 2023 # name: Power type: parsed @@ -3896,3 +3896,159 @@ type: parsed protocol: NECext address: 80 70 00 00 command: C1 3E 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 87 7C 00 00 +command: C8 37 00 00 +# +name: Pause +type: parsed +protocol: NECext +address: 87 7C 00 00 +command: 4A B5 00 00 +# +name: Play +type: parsed +protocol: NECext +address: 87 7C 00 00 +command: 01 FE 00 00 +# +name: Prev +type: parsed +protocol: NECext +address: 87 7C 00 00 +command: 05 FA 00 00 +# +name: Next +type: parsed +protocol: NECext +address: 87 7C 00 00 +command: 06 F9 00 00 +# +name: Power +type: parsed +protocol: NECext +address: 12 34 00 00 +command: 01 FE 00 00 +# +name: Vol_up +type: parsed +protocol: NECext +address: 12 34 00 00 +command: 0A F5 00 00 +# +name: Vol_dn +type: parsed +protocol: NECext +address: 12 34 00 00 +command: 0B F4 00 00 +# +name: Mute +type: parsed +protocol: NECext +address: 12 34 00 00 +command: 09 F6 00 00 +# +name: Power +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 67 00 00 00 +# +name: Next +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 38 00 00 00 +# +name: Vol_up +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 3C 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 3D 00 00 00 +# +name: Mute +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 8C 00 00 00 +# +name: Prev +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 44 00 00 00 +# +name: Vol_dn +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 07 00 00 00 +# +name: Vol_up +type: parsed +protocol: NEC +address: 00 00 00 00 +command: 1C 00 00 00 +# +name: Power +type: raw +frequency: 38000 +duty_cycle: 0.33 +data: 9120 4354 714 1539 660 497 633 499 631 500 630 503 628 503 628 503 629 503 628 503 628 1627 628 1627 628 1627 628 1627 628 1626 628 1627 628 1627 628 1627 628 1627 628 503 628 503 628 503 628 503 628 504 627 503 628 504 627 503 628 1627 628 1628 627 1628 627 1627 628 1627 628 1628 627 40094 9038 2194 628 +# +name: Prev +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 5A 00 00 00 +# +name: Next +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 5B 00 00 00 +# +name: Pause +type: parsed +protocol: NEC +address: 01 00 00 00 +command: B2 00 00 00 +# +name: Pause +type: parsed +protocol: NECext +address: 00 EF 00 00 +command: 11 EE 00 00 +# +name: Pause +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 2C 00 00 00 +# +name: Play +type: parsed +protocol: NEC +address: 01 00 00 00 +command: B2 00 00 00 +# +name: Play +type: parsed +protocol: NECext +address: 00 EF 00 00 +command: 11 EE 00 00 +# +name: Play +type: parsed +protocol: NEC +address: 01 00 00 00 +command: 2C 00 00 00 From 1543170f4cfa4ef23616c7a3d83704107e703919 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=81=8F?= Date: Thu, 21 Dec 2023 16:43:11 +0000 Subject: [PATCH 36/44] [FL-3729, FL-3730] Gui: fix string width calculation (#3305) --- applications/services/gui/canvas.c | 8 ++++---- applications/services/gui/canvas_i.h | 2 +- lib/u8g2/u8g2.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/applications/services/gui/canvas.c b/applications/services/gui/canvas.c index 209c82a82..c7e7dc355 100644 --- a/applications/services/gui/canvas.c +++ b/applications/services/gui/canvas.c @@ -321,10 +321,10 @@ static void canvas_draw_u8g2_bitmap_int( void canvas_draw_u8g2_bitmap( u8g2_t* u8g2, - u8g2_uint_t x, - u8g2_uint_t y, - u8g2_uint_t w, - u8g2_uint_t h, + uint8_t x, + uint8_t y, + uint8_t w, + uint8_t h, const uint8_t* bitmap, IconRotation rotation) { u8g2_uint_t blen; diff --git a/applications/services/gui/canvas_i.h b/applications/services/gui/canvas_i.h index f3b8f17ad..5f7d69e72 100644 --- a/applications/services/gui/canvas_i.h +++ b/applications/services/gui/canvas_i.h @@ -96,4 +96,4 @@ void canvas_draw_u8g2_bitmap( uint8_t width, uint8_t height, const uint8_t* bitmap, - uint8_t rotation); + IconRotation rotation); diff --git a/lib/u8g2/u8g2.h b/lib/u8g2/u8g2.h index 68611d482..540b7a873 100644 --- a/lib/u8g2/u8g2.h +++ b/lib/u8g2/u8g2.h @@ -67,7 +67,7 @@ Use 16 Bit mode for any display with more than 240 pixel in one direction. */ -//#define U8G2_16BIT +#define U8G2_16BIT /* The following macro switches the library into dynamic display buffer allocation mode. From bcadbc6353961b4a7da8aaf6e8769ee0565ea2ad Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Thu, 21 Dec 2023 19:45:45 +0300 Subject: [PATCH 37/44] Revert "fix broken texts due to usage of utf8, add proper api" This reverts commit 49b2a4da8a17f0d63a7bc8d6b1c011bea964398f. --- .../example_custom_font/example_custom_font.c | 6 +- applications/services/gui/canvas.c | 57 ------------------- applications/services/gui/canvas.h | 38 ------------- targets/f7/api_symbols.csv | 3 - 4 files changed, 3 insertions(+), 101 deletions(-) diff --git a/applications/debug/example_custom_font/example_custom_font.c b/applications/debug/example_custom_font/example_custom_font.c index 334aa8aa8..8d85f23c6 100644 --- a/applications/debug/example_custom_font/example_custom_font.c +++ b/applications/debug/example_custom_font/example_custom_font.c @@ -72,9 +72,9 @@ static void app_draw_callback(Canvas* canvas, void* ctx) { canvas_set_custom_u8g2_font(canvas, u8g2_font_4x6_t_cyrillic); - canvas_draw_utf8_str(canvas, 0, 6, "This is a tiny custom font"); - canvas_draw_utf8_str(canvas, 0, 12, "012345.?! ,:;\"\'@#$%"); - canvas_draw_utf8_str(canvas, 0, 18, "И немного юникода"); + canvas_draw_str(canvas, 0, 6, "This is a tiny custom font"); + canvas_draw_str(canvas, 0, 12, "012345.?! ,:;\"\'@#$%"); + canvas_draw_str(canvas, 0, 18, "И немного юникода"); } static void app_input_callback(InputEvent* input_event, void* ctx) { diff --git a/applications/services/gui/canvas.c b/applications/services/gui/canvas.c index 3cd35e402..f8f33da9b 100644 --- a/applications/services/gui/canvas.c +++ b/applications/services/gui/canvas.c @@ -154,14 +154,6 @@ void canvas_set_custom_u8g2_font(Canvas* canvas, const uint8_t* font) { } void canvas_draw_str(Canvas* canvas, uint8_t x, uint8_t y, const char* str) { - furi_assert(canvas); - if(!str) return; - x += canvas->offset_x; - y += canvas->offset_y; - u8g2_DrawStr(&canvas->fb, x, y, str); -} - -void canvas_draw_utf8_str(Canvas* canvas, uint8_t x, uint8_t y, const char* str) { furi_assert(canvas); if(!str) return; x += canvas->offset_x; @@ -181,49 +173,6 @@ void canvas_draw_str_aligned( x += canvas->offset_x; y += canvas->offset_y; - switch(horizontal) { - case AlignLeft: - break; - case AlignRight: - x -= u8g2_GetStrWidth(&canvas->fb, str); - break; - case AlignCenter: - x -= (u8g2_GetStrWidth(&canvas->fb, str) / 2); - break; - default: - furi_crash(); - break; - } - - switch(vertical) { - case AlignTop: - y += u8g2_GetAscent(&canvas->fb); - break; - case AlignBottom: - break; - case AlignCenter: - y += (u8g2_GetAscent(&canvas->fb) / 2); - break; - default: - furi_crash(); - break; - } - - u8g2_DrawStr(&canvas->fb, x, y, str); -} - -void canvas_draw_utf8_str_aligned( - Canvas* canvas, - uint8_t x, - uint8_t y, - Align horizontal, - Align vertical, - const char* str) { - furi_assert(canvas); - if(!str) return; - x += canvas->offset_x; - y += canvas->offset_y; - switch(horizontal) { case AlignLeft: break; @@ -256,12 +205,6 @@ void canvas_draw_utf8_str_aligned( } uint16_t canvas_string_width(Canvas* canvas, const char* str) { - furi_assert(canvas); - if(!str) return 0; - return u8g2_GetStrWidth(&canvas->fb, str); -} - -uint16_t canvas_utf8_string_width(Canvas* canvas, const char* str) { furi_assert(canvas); if(!str) return 0; return u8g2_GetUTF8Width(&canvas->fb, str); diff --git a/applications/services/gui/canvas.h b/applications/services/gui/canvas.h index afed58548..bda730ff2 100644 --- a/applications/services/gui/canvas.h +++ b/applications/services/gui/canvas.h @@ -187,15 +187,6 @@ void canvas_set_custom_u8g2_font(Canvas* canvas, const uint8_t* font); */ void canvas_draw_str(Canvas* canvas, uint8_t x, uint8_t y, const char* str); -/** Draw UTF8 string at position of baseline defined by x, y. - * - * @param canvas Canvas instance - * @param x anchor point x coordinate - * @param y anchor point y coordinate - * @param str C-string - */ -void canvas_draw_utf8_str(Canvas* canvas, uint8_t x, uint8_t y, const char* str); - /** Draw aligned string defined by x, y. * * Align calculated from position of baseline, string width and ascent (height @@ -216,26 +207,6 @@ void canvas_draw_str_aligned( Align vertical, const char* str); -/** Draw aligned UTF8 string defined by x, y. - * - * Align calculated from position of baseline, string width and ascent (height - * of the glyphs above the baseline) - * - * @param canvas Canvas instance - * @param x anchor point x coordinate - * @param y anchor point y coordinate - * @param horizontal horizontal alignment - * @param vertical vertical alignment - * @param str C-string - */ -void canvas_draw_utf8_str_aligned( - Canvas* canvas, - uint8_t x, - uint8_t y, - Align horizontal, - Align vertical, - const char* str); - /** Get string width * * @param canvas Canvas instance @@ -245,15 +216,6 @@ void canvas_draw_utf8_str_aligned( */ uint16_t canvas_string_width(Canvas* canvas, const char* str); -/** Get UTF8 string width - * - * @param canvas Canvas instance - * @param str C-string - * - * @return width in pixels. - */ -uint16_t canvas_utf8_string_width(Canvas* canvas, const char* str); - /** Get glyph width * * @param canvas Canvas instance diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index 0f15dc761..769763f81 100644 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -735,8 +735,6 @@ Function,+,canvas_draw_rframe,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, Function,+,canvas_draw_str,void,"Canvas*, uint8_t, uint8_t, const char*" Function,+,canvas_draw_str_aligned,void,"Canvas*, uint8_t, uint8_t, Align, Align, const char*" Function,+,canvas_draw_triangle,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, CanvasDirection" -Function,+,canvas_draw_utf8_str,void,"Canvas*, uint8_t, uint8_t, const char*" -Function,+,canvas_draw_utf8_str_aligned,void,"Canvas*, uint8_t, uint8_t, Align, Align, const char*" Function,+,canvas_draw_xbm,void,"Canvas*, uint8_t, uint8_t, uint8_t, uint8_t, const uint8_t*" Function,+,canvas_get_font_params,const CanvasFontParameters*,"const Canvas*, Font" Function,+,canvas_glyph_width,uint8_t,"Canvas*, uint16_t" @@ -749,7 +747,6 @@ Function,+,canvas_set_custom_u8g2_font,void,"Canvas*, const uint8_t*" Function,+,canvas_set_font,void,"Canvas*, Font" Function,+,canvas_set_font_direction,void,"Canvas*, CanvasDirection" Function,+,canvas_string_width,uint16_t,"Canvas*, const char*" -Function,+,canvas_utf8_string_width,uint16_t,"Canvas*, const char*" Function,+,canvas_width,uint8_t,const Canvas* Function,-,cbrt,double,double Function,-,cbrtf,float,float From 4d56bb4e443146a8d460dbea541e553e5148503f Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Thu, 21 Dec 2023 21:42:17 +0300 Subject: [PATCH 38/44] Revert "testing subghz dynamic limit based on freeheap + RPC" This reverts commit 77f458fb6ea27057962f3767bd54a5bc5253276e. --- applications/main/subghz/subghz_history.c | 15 ++++++--------- applications/main/subghz/views/receiver.c | 22 ++-------------------- applications/services/rpc/rpc.c | 9 --------- applications/services/rpc/rpc.h | 7 ------- targets/f7/api_symbols.csv | 1 - 5 files changed, 8 insertions(+), 46 deletions(-) diff --git a/applications/main/subghz/subghz_history.c b/applications/main/subghz/subghz_history.c index b18df0ee8..048104f35 100644 --- a/applications/main/subghz/subghz_history.c +++ b/applications/main/subghz/subghz_history.c @@ -1,11 +1,10 @@ #include "subghz_history.h" #include -#include #include -#define SUBGHZ_HISTORY_MAX 65530 // uint16_t index max, ram limit below -#define SUBGHZ_HISTORY_FREE_HEAP (10240 * (3 - MIN(rpc_get_sessions_count(instance->rpc), 2U))) +#define SUBGHZ_HISTORY_MAX 55 +#define SUBGHZ_HISTORY_FREE_HEAP 20480 #define TAG "SubGhzHistory" typedef struct { @@ -30,7 +29,6 @@ struct SubGhzHistory { uint8_t code_last_hash_data; FuriString* tmp_string; SubGhzHistoryStruct* history; - Rpc* rpc; }; SubGhzHistory* subghz_history_alloc(void) { @@ -38,7 +36,6 @@ SubGhzHistory* subghz_history_alloc(void) { instance->tmp_string = furi_string_alloc(); instance->history = malloc(sizeof(SubGhzHistoryStruct)); SubGhzHistoryItemArray_init(instance->history->data); - instance->rpc = furi_record_open(RECORD_RPC); return instance; } @@ -55,7 +52,6 @@ void subghz_history_free(SubGhzHistory* instance) { } SubGhzHistoryItemArray_clear(instance->history->data); free(instance->history); - furi_record_close(RECORD_RPC); free(instance); } @@ -147,14 +143,15 @@ FlipperFormat* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx bool subghz_history_get_text_space_left(SubGhzHistory* instance, FuriString* output) { furi_assert(instance); if(memmgr_get_free_heap() < SUBGHZ_HISTORY_FREE_HEAP) { - if(output != NULL) furi_string_printf(output, " Memory is FULL"); + if(output != NULL) furi_string_printf(output, " Free heap LOW"); return true; } if(instance->last_index_write == SUBGHZ_HISTORY_MAX) { - if(output != NULL) furi_string_printf(output, " History is FULL"); + if(output != NULL) furi_string_printf(output, " Memory is FULL"); return true; } - if(output != NULL) furi_string_printf(output, "%02u", instance->last_index_write); + if(output != NULL) + furi_string_printf(output, "%02u/%02u", instance->last_index_write, SUBGHZ_HISTORY_MAX); return false; } diff --git a/applications/main/subghz/views/receiver.c b/applications/main/subghz/views/receiver.c index 1d3967edb..98c15dbff 100644 --- a/applications/main/subghz/views/receiver.c +++ b/applications/main/subghz/views/receiver.c @@ -383,16 +383,7 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) { #else canvas_draw_str(canvas, 79, 62, furi_string_get_cstr(model->preset_str)); #endif - if(!furi_string_empty(model->history_stat_str)) { - canvas_draw_str_aligned( - canvas, - 114, - 62, - AlignRight, - AlignBottom, - furi_string_get_cstr(model->history_stat_str)); - canvas_draw_icon(canvas, 116, 53, &I_sub1_10px); - } + canvas_draw_str(canvas, 96, 62, furi_string_get_cstr(model->history_stat_str)); canvas_set_font(canvas, FontSecondary); elements_bold_rounded_frame(canvas, 14, 8, 99, 48); elements_multiline_text(canvas, 65, 26, "To unlock\npress:"); @@ -428,16 +419,7 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) { #else canvas_draw_str(canvas, 79, 62, furi_string_get_cstr(model->preset_str)); #endif - if(!furi_string_empty(model->history_stat_str)) { - canvas_draw_str_aligned( - canvas, - 114, - 62, - AlignRight, - AlignBottom, - furi_string_get_cstr(model->history_stat_str)); - canvas_draw_icon(canvas, 116, 53, &I_sub1_10px); - } + canvas_draw_str(canvas, 96, 62, furi_string_get_cstr(model->history_stat_str)); } break; } } diff --git a/applications/services/rpc/rpc.c b/applications/services/rpc/rpc.c index 6d9f31da0..50c4b3608 100644 --- a/applications/services/rpc/rpc.c +++ b/applications/services/rpc/rpc.c @@ -87,7 +87,6 @@ struct RpcSession { struct Rpc { FuriMutex* busy_mutex; - size_t sessions_count; }; RpcOwner rpc_session_get_owner(RpcSession* session) { @@ -408,8 +407,6 @@ RpcSession* rpc_session_open(Rpc* rpc, RpcOwner owner) { furi_thread_start(session->thread); - rpc->sessions_count++; - return session; } @@ -417,8 +414,6 @@ void rpc_session_close(RpcSession* session) { furi_assert(session); furi_assert(session->rpc); - session->rpc->sessions_count--; - rpc_session_set_send_bytes_callback(session, NULL); rpc_session_set_close_callback(session, NULL); rpc_session_set_buffer_is_empty_callback(session, NULL); @@ -494,7 +489,3 @@ void rpc_send_and_release_empty(RpcSession* session, uint32_t command_id, PB_Com rpc_send_and_release(session, &message); pb_release(&PB_Main_msg, &message); } - -size_t rpc_get_sessions_count(Rpc* rpc) { - return rpc->sessions_count; -} diff --git a/applications/services/rpc/rpc.h b/applications/services/rpc/rpc.h index b1e7a4d47..863bca355 100644 --- a/applications/services/rpc/rpc.h +++ b/applications/services/rpc/rpc.h @@ -134,13 +134,6 @@ size_t rpc_session_feed(RpcSession* session, uint8_t* buffer, size_t size, uint3 */ size_t rpc_session_get_available_size(RpcSession* session); -/** Get number of open RPC sessions - * - * @param rpc instance - * @return sessions count - */ -size_t rpc_get_sessions_count(Rpc* rpc); - #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index 769763f81..3ab58f58d 100644 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -2706,7 +2706,6 @@ Function,-,rintl,long double,long double Function,-,round,double,double Function,+,roundf,float,float Function,-,roundl,long double,long double -Function,+,rpc_get_sessions_count,size_t,Rpc* Function,+,rpc_session_close,void,RpcSession* Function,+,rpc_session_feed,size_t,"RpcSession*, uint8_t*, size_t, uint32_t" Function,+,rpc_session_get_available_size,size_t,RpcSession* From 531ba24e9a1af8ff007e72dd976cb66259895bc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=81=8F?= Date: Fri, 22 Dec 2023 11:08:46 +0000 Subject: [PATCH 39/44] Rollback #3305 and #3297 fix various rendering issues (#3307) * Revert "[FL-3729, FL-3730] Gui: fix string width calculation (#3305)" * Revert "Added UTF-8 support to Flipper Zero canvas API (#3297)" --- .../example_custom_font/example_custom_font.c | 86 +++++++------------ applications/services/gui/canvas.c | 18 ++-- applications/services/gui/canvas_i.h | 2 +- lib/u8g2/u8g2.h | 2 +- 4 files changed, 40 insertions(+), 68 deletions(-) diff --git a/applications/debug/example_custom_font/example_custom_font.c b/applications/debug/example_custom_font/example_custom_font.c index 8d85f23c6..15eeb5f02 100644 --- a/applications/debug/example_custom_font/example_custom_font.c +++ b/applications/debug/example_custom_font/example_custom_font.c @@ -7,62 +7,35 @@ //This arrays contains the font itself. You can use any u8g2 font you want /* - Fontname: -Misc-Fixed-Medium-R-Normal--6-60-75-75-C-40-ISO10646-1 - Copyright: Public domain font. Share and enjoy. - Glyphs: 191/919 - BBX Build Mode: 0 +Fontname: -Raccoon-Fixed4x6-Medium-R-Normal--6-60-75-75-P-40-ISO10646-1 +Copyright: +Glyphs: 95/203 +BBX Build Mode: 0 */ -const uint8_t u8g2_font_4x6_t_cyrillic[] = - "\277\0\2\2\3\3\2\4\4\4\6\0\377\5\377\5\377\0\356\1\334\2\301 \5\200\315\0!\6\351\310" - "\254\0\42\6\223\313$\25#\12\254\310\244\64T\32*\1$\11\263\307\245\241\301H\11%\10\253\310d" - "\324F\1&\11\254\310\305\24\253\230\2'\5\321\313\10(\7\362\307\251f\0)\10\262\307\304T)\0" - "*\7\253\310\244j\65+\10\253\310\305\264b\2,\6\222\307)\0-\5\213\312\14.\5\311\310\4/" - "\7\253\310Ve\4\60\10\253\310UCU\0\61\7\253\310%Y\15\62\7\253\310\65S\32\63\10\253\310" - "\314\224\301\2\64\10\253\310$\65b\1\65\10\253\310\214\250\301\2\66\7\253\310M\325\2\67\10\253\310\314" - "TF\0\70\7\253\310\255\326\2\71\7\253\310\265\344\2:\6\341\310\304\0;\7\252\307e\250\0<\10" - "\253\310\246\32d\20=\6\233\311l\60>\11\253\310d\220A*\1\77\11\253\310h\220\62L\0@\7" - "\253\310-\33\10A\10\253\310UC\251\0B\10\253\310\250\264\322\2C\10\253\310U\62U\0D\10\253" - "\310\250d-\0E\10\253\310\214\250\342\0F\10\253\310\214\250b\4G\10\253\310\315\244\222\0H\10\253" - "\310$\65\224\12I\7\253\310\254X\15J\7\253\310\226\252\2K\10\253\310$\265\222\12L\7\253\310\304" - "\346\0M\10\253\310\244\61\224\12N\10\253\310\252\241$\0O\7\253\310UV\5P\10\253\310\250\264b" - "\4Q\10\263\307UV\15\2R\10\253\310\250\264\222\12S\10\253\310m\220\301\2T\7\253\310\254\330\2" - "U\7\253\310$\327\10V\10\253\310$k\244\4W\10\253\310$\65\206\12X\10\253\310$\325R\1Y" - "\10\253\310$UV\0Z\7\253\310\314T\16[\6\352\310\254J\134\11\253\310\304\14\62\210\1]\6\252" - "\310\250j^\5\223\313\65_\5\213\307\14`\6\322\313\304\0a\7\243\310-\225\4b\10\253\310D\225" - "\324\2c\7\243\310\315\14\4d\10\253\310\246\245\222\0e\6\243\310USf\10\253\310\246\264b\2g" - "\10\253\307\255$\27\0h\10\253\310D\225\254\0i\10\253\310e$\323\0j\10\263\307fX.\0k" - "\10\253\310\304\264\222\12l\7\253\310\310\326\0m\10\243\310\244\241T\0n\7\243\310\250d\5o\7\243" - "\310U\252\2p\10\253\307\250\264b\4q\10\253\307-\225d\0r\10\243\310\244\25#\0s\10\243\310" - "\215\14\26\0t\10\253\310\245\25\63\10u\7\243\310$+\11v\7\243\310$\253\2w\10\243\310$\65" - "T\0x\7\243\310\244\62\25y\10\253\307$\225\344\2z\7\243\310\314\224\6{\10\263\307\246$k\20" - "|\6\351\310\14\1}\11\263\307d\20UL\21~\7\224\313%\225\0\0\0\0\4\377\377\4\1\11\253" - "\310\244\261\342\0\4\2\11\253\310\214\250\222\12\4\3\10\253\310\16Y\2\4\4\11\253\310M\225\201\0\4" - "\5\11\253\310m\220\301\2\4\6\10\253\310\254X\15\4\7\11\253\310\244\221b\32\4\10\10\253\310\226\252" - "\2\4\11\11\254\310L\325Z\2\4\12\11\254\310\244\326JK\4\13\11\253\310\250\250\222\12\4\14\10\253" - "\310\312\264\12\4\16\11\263\307\244\32u\2\4\17\11\263\307$\327H\11\4\20\11\253\310UC\251\0\4" - "\21\11\253\310\214\250\322\2\4\22\11\253\310\250\264\322\2\4\23\10\253\310\214\330\4\4\24\11\263\307\254\245" - "\206\12\4\25\11\253\310\214\250\342\0\4\26\12\253\310\244\221\322H\1\4\27\12\253\310h\220\62X\0\4" - "\30\11\253\310\304\64T\14\4\31\11\263\307\315\64T\14\4\32\11\253\310$\265\222\12\4\33\10\253\310-" - "W\0\4\34\11\253\310\244\241\254\0\4\35\11\253\310$\65\224\12\4\36\10\253\310UV\5\4\37\10\253" - "\310\214\344\12\4 \11\253\310\250\264b\4\4!\11\253\310U\62U\0\4\42\10\253\310\254\330\2\4#" - "\11\263\307$\253L\21\4$\12\253\310\245\221FJ\0\4%\11\253\310$\325R\1\4&\10\253\310$" - "\327\10\4'\11\253\310$\225d\1\4(\11\253\310$\65\216\0\4)\12\264\307\244\326#\203\0\4*" - "\13\254\310h\220\201LI\1\4+\12\254\310D\271\324H\1\4,\11\253\310\304\250\322\2\4-\11\253" - "\310h\220\344\2\4.\12\254\310\244\244.\225\0\4/\11\253\310\255\264T\0\4\60\10\243\310-\225\4" - "\4\61\11\253\310\315\221*\0\4\62\11\243\310\14\225\26\0\4\63\10\243\310\214X\2\4\64\11\253\307-" - "\65T\0\4\65\7\243\310US\4\66\11\244\310$S%\1\4\67\11\243\310\254\14\26\0\4\70\11\243" - "\310\244\61T\0\4\71\11\253\310\244\326P\1\4:\10\243\310$\265\12\4;\7\243\310-+\4<\11" - "\243\310\244\241T\0\4=\11\243\310\244\241T\0\4>\10\243\310U\252\2\4\77\10\243\310\214d\5\4" - "@\11\253\307\250\264b\4\4A\10\243\310\315\14\4\4B\10\243\310\254X\1\4C\11\253\307$\225\344" - "\2\4D\12\263\307\305\224T\231\0\4E\10\243\310\244\62\25\4F\11\253\307$k\304\0\4G\11\243" - "\310$\225d\0\4H\10\243\310\244q\4\4I\11\254\307\244\364\310 \4J\12\244\310h SR\0" - "\4K\11\244\310\304\245F\12\4L\11\243\310D\225\26\0\4M\10\243\310H\271\0\4N\12\244\310\244" - "\244\226J\0\4O\10\243\310\255\264\2\4Q\10\253\310\244\326\24\4R\11\263\307D\25U\31\4S\11" - "\253\310\246\64b\4\4T\11\243\310\215\224\201\0\4U\11\243\310\215\14\26\0\4V\11\253\310e$\323" - "\0\4W\11\253\310\244\14d\32\4X\11\263\307fX.\0\4Y\10\244\310\251\326\22\4Z\11\244\310" - "\244\264\322\22\4[\11\253\310D\25U\1\4\134\10\253\310\312\264\12\4^\11\263\307\244\32u\2\4_" - "\11\253\307$k\244\4\4\220\10\253\310\16Y\2\4\221\10\243\310\16\31\1\4\222\11\253\310\251\264b\2" - "\4\223\11\243\310\251\264\22\0\0"; +const uint8_t u8g2_font_tom_thumb_4x6_tr[725] = + "_\0\2\2\2\3\3\4\4\3\6\0\377\5\377\5\0\0\352\1\330\2\270 \5\340\315\0!\6\265\310" + "\254\0\42\6\213\313$\25#\10\227\310\244\241\206\12$\10\227\310\215\70b\2%\10\227\310d\324F\1" + "&\10\227\310(\65R\22'\5\251\313\10(\6\266\310\251\62)\10\226\310\304\224\24\0*\6\217\312\244" + "\16+\7\217\311\245\225\0,\6\212\310)\0-\5\207\312\14.\5\245\310\4/\7\227\310Ve\4\60" + "\7\227\310-k\1\61\6\226\310\255\6\62\10\227\310h\220\312\1\63\11\227\310h\220\62X\0\64\10\227" + "\310$\65b\1\65\10\227\310\214\250\301\2\66\10\227\310\315\221F\0\67\10\227\310\314TF\0\70\10\227" + "\310\214\64\324\10\71\10\227\310\214\64\342\2:\6\255\311\244\0;\7\222\310e\240\0<\10\227\310\246\32" + "d\20=\6\217\311l\60>\11\227\310d\220A*\1\77\10\227\310\314\224a\2@\10\227\310UC\3" + "\1A\10\227\310UC\251\0B\10\227\310\250\264\322\2C\7\227\310\315\32\10D\10\227\310\250d-\0" + "E\10\227\310\214\70\342\0F\10\227\310\214\70b\4G\10\227\310\315\221\222\0H\10\227\310$\65\224\12" + "I\7\227\310\254X\15J\7\227\310\226\252\2K\10\227\310$\265\222\12L\7\227\310\304\346\0M\10\227" + "\310\244\61\224\12N\10\227\310\244q\250\0O\7\227\310UV\5P\10\227\310\250\264b\4Q\10\227\310" + "Uj$\1R\10\227\310\250\64V\1S\10\227\310m\220\301\2T\7\227\310\254\330\2U\7\227\310$" + "W\22V\10\227\310$\253L\0W\10\227\310$\65\206\12X\10\227\310$\325R\1Y\10\227\310$U" + "V\0Z\7\227\310\314T\16[\7\227\310\214X\16\134\10\217\311d\220A\0]\7\227\310\314r\4^" + "\5\213\313\65_\5\207\310\14`\6\212\313\304\0a\7\223\310\310\65\2b\10\227\310D\225\324\2c\7" + "\223\310\315\14\4d\10\227\310\246\245\222\0e\6\223\310\235\2f\10\227\310\246\264b\2g\10\227\307\35" + "\61%\0h\10\227\310D\225\254\0i\6\265\310\244\1j\10\233\307f\30U\5k\10\227\310\304\264T" + "\1l\7\227\310\310\326\0m\7\223\310offset_x; y += canvas->offset_y; - u8g2_DrawUTF8(&canvas->fb, x, y, str); + u8g2_DrawStr(&canvas->fb, x, y, str); } void canvas_draw_str_aligned( @@ -169,10 +169,10 @@ void canvas_draw_str_aligned( case AlignLeft: break; case AlignRight: - x -= u8g2_GetUTF8Width(&canvas->fb, str); + x -= u8g2_GetStrWidth(&canvas->fb, str); break; case AlignCenter: - x -= (u8g2_GetUTF8Width(&canvas->fb, str) / 2); + x -= (u8g2_GetStrWidth(&canvas->fb, str) / 2); break; default: furi_crash(); @@ -193,13 +193,13 @@ void canvas_draw_str_aligned( break; } - u8g2_DrawUTF8(&canvas->fb, x, y, str); + u8g2_DrawStr(&canvas->fb, x, y, str); } uint16_t canvas_string_width(Canvas* canvas, const char* str) { furi_assert(canvas); if(!str) return 0; - return u8g2_GetUTF8Width(&canvas->fb, str); + return u8g2_GetStrWidth(&canvas->fb, str); } uint8_t canvas_glyph_width(Canvas* canvas, uint16_t symbol) { @@ -321,10 +321,10 @@ static void canvas_draw_u8g2_bitmap_int( void canvas_draw_u8g2_bitmap( u8g2_t* u8g2, - uint8_t x, - uint8_t y, - uint8_t w, - uint8_t h, + u8g2_uint_t x, + u8g2_uint_t y, + u8g2_uint_t w, + u8g2_uint_t h, const uint8_t* bitmap, IconRotation rotation) { u8g2_uint_t blen; diff --git a/applications/services/gui/canvas_i.h b/applications/services/gui/canvas_i.h index 5f7d69e72..f3b8f17ad 100644 --- a/applications/services/gui/canvas_i.h +++ b/applications/services/gui/canvas_i.h @@ -96,4 +96,4 @@ void canvas_draw_u8g2_bitmap( uint8_t width, uint8_t height, const uint8_t* bitmap, - IconRotation rotation); + uint8_t rotation); diff --git a/lib/u8g2/u8g2.h b/lib/u8g2/u8g2.h index 540b7a873..68611d482 100644 --- a/lib/u8g2/u8g2.h +++ b/lib/u8g2/u8g2.h @@ -67,7 +67,7 @@ Use 16 Bit mode for any display with more than 240 pixel in one direction. */ -#define U8G2_16BIT +//#define U8G2_16BIT /* The following macro switches the library into dynamic display buffer allocation mode. From 283216089145316ae7c5b4fe0c1f42275360c099 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Fri, 22 Dec 2023 22:13:28 +0300 Subject: [PATCH 40/44] change log level --- applications/main/subghz/scenes/subghz_scene_receiver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/main/subghz/scenes/subghz_scene_receiver.c b/applications/main/subghz/scenes/subghz_scene_receiver.c index bffff9988..ae092907f 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver.c @@ -136,7 +136,7 @@ static void subghz_scene_add_to_history_callback( furi_string_free(item_time); subghz_rx_key_state_set(subghz, SubGhzRxKeyStateAddKey); } else { - FURI_LOG_I(TAG, "%s protocol ignored", decoder_base->protocol->name); + FURI_LOG_D(TAG, "%s protocol ignored", decoder_base->protocol->name); } } From b84f14386c9f2c111811b031a18a6914f71a3e74 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Sun, 24 Dec 2023 03:08:24 +0300 Subject: [PATCH 41/44] subghz option to delete old signals on full memory --- .../subghz/scenes/subghz_scene_receiver.c | 16 ++++++++++++++ .../scenes/subghz_scene_receiver_config.c | 22 +++++++++++++++++++ .../main/subghz/subghz_last_settings.c | 10 +++++++++ .../main/subghz/subghz_last_settings.h | 1 + 4 files changed, 49 insertions(+) diff --git a/applications/main/subghz/scenes/subghz_scene_receiver.c b/applications/main/subghz/scenes/subghz_scene_receiver.c index ae092907f..51063c999 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver.c @@ -112,6 +112,22 @@ static void subghz_scene_add_to_history_callback( uint16_t idx = subghz_history_get_item(history); SubGhzRadioPreset preset = subghz_txrx_get_preset(subghz->txrx); + if(subghz->last_settings->delete_old_signals) { + if(subghz_history_get_last_index(subghz->history) >= 54) { + subghz->state_notifications = SubGhzNotificationStateRx; + + subghz_view_receiver_disable_draw_callback(subghz->subghz_receiver); + + subghz_history_delete_item(subghz->history, 0); + subghz_view_receiver_delete_item(subghz->subghz_receiver, 0); + subghz_view_receiver_enable_draw_callback(subghz->subghz_receiver); + + subghz_scene_receiver_update_statusbar(subghz); + subghz->idx_menu_chosen = + subghz_view_receiver_get_idx_menu(subghz->subghz_receiver); + idx--; + } + } if(subghz_history_add_to_history(history, decoder_base, &preset)) { furi_string_reset(item_name); furi_string_reset(item_time); diff --git a/applications/main/subghz/scenes/subghz_scene_receiver_config.c b/applications/main/subghz/scenes/subghz_scene_receiver_config.c index 09c3976cc..f98b33b4f 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver_config.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver_config.c @@ -13,6 +13,7 @@ enum SubGhzSettingIndex { SubGhzSettingIndexIgnoreMagellan, SubGhzSettingIndexIgnorePrinceton, SubGhzSettingIndexIgnoreNiceFlorS, + SubGhzSettingIndexDeleteOldSignals, SubGhzSettingIndexSound, SubGhzSettingIndexResetToDefault, SubGhzSettingIndexLock, @@ -283,6 +284,15 @@ static void subghz_scene_receiver_config_set_niceflors(VariableItem* item) { subghz_scene_receiver_config_set_ignore_filter(item, SubGhzProtocolFlag_NiceFlorS); } +static void subghz_scene_receiver_config_set_delete_old_signals(VariableItem* item) { + SubGhz* subghz = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + + variable_item_set_current_value_text(item, combobox_text[index]); + + subghz->last_settings->delete_old_signals = index == 1; +} + static void subghz_scene_receiver_config_var_list_enter_callback(void* context, uint32_t index) { furi_assert(context); SubGhz* subghz = context; @@ -314,6 +324,7 @@ static void subghz_scene_receiver_config_var_list_enter_callback(void* context, subghz_txrx_receiver_set_filter(subghz->txrx, subghz->filter); subghz->last_settings->ignore_filter = subghz->ignore_filter; subghz->last_settings->filter = subghz->filter; + subghz->last_settings->delete_old_signals = false; subghz_txrx_speaker_set_state(subghz->txrx, speaker_value[default_index]); @@ -461,6 +472,17 @@ void subghz_scene_receiver_config_on_enter(void* context) { subghz->ignore_filter, SubGhzProtocolFlag_NiceFlorS); variable_item_set_current_value_index(item, value_index); variable_item_set_current_value_text(item, combobox_text[value_index]); + + item = variable_item_list_add( + subghz->variable_item_list, + "Delete old signals when memory is full", + COMBO_BOX_COUNT, + subghz_scene_receiver_config_set_delete_old_signals, + subghz); + + value_index = subghz->last_settings->delete_old_signals; + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, combobox_text[value_index]); } // Enable speaker, will send all incoming noises and signals to speaker so you can listen how your remote sounds like :) diff --git a/applications/main/subghz/subghz_last_settings.c b/applications/main/subghz/subghz_last_settings.c index fe072a1ef..07bad225d 100644 --- a/applications/main/subghz/subghz_last_settings.c +++ b/applications/main/subghz/subghz_last_settings.c @@ -19,6 +19,7 @@ #define SUBGHZ_LAST_SETTING_FIELD_IGNORE_FILTER "IgnoreFilter" #define SUBGHZ_LAST_SETTING_FIELD_FILTER "Filter" #define SUBGHZ_LAST_SETTING_FIELD_RSSI_THRESHOLD "RSSI" +#define SUBGHZ_LAST_SETTING_FIELD_DELETE_OLD "DelOldSignals" SubGhzLastSettings* subghz_last_settings_alloc(void) { SubGhzLastSettings* instance = malloc(sizeof(SubGhzLastSettings)); @@ -44,6 +45,7 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count bool temp_external_module_power_amp = false; bool temp_timestamp_file_names = false; bool temp_enable_hopping = false; + bool temp_delete_old_sig = false; uint32_t temp_ignore_filter = 0; uint32_t temp_filter = 0; float temp_rssi = 0; @@ -106,6 +108,8 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count 1); filter_was_read = flipper_format_read_uint32( fff_data_file, SUBGHZ_LAST_SETTING_FIELD_FILTER, (uint32_t*)&temp_filter, 1); + flipper_format_read_bool( + fff_data_file, SUBGHZ_LAST_SETTING_FIELD_DELETE_OLD, (bool*)&temp_delete_old_sig, 1); } else { FURI_LOG_E(TAG, "Error open file %s", SUBGHZ_LAST_SETTINGS_PATH); } @@ -156,6 +160,8 @@ void subghz_last_settings_load(SubGhzLastSettings* instance, size_t preset_count instance->timestamp_file_names = temp_timestamp_file_names; + instance->delete_old_signals = temp_delete_old_sig; + // External power amp CC1101 instance->external_module_power_amp = temp_external_module_power_amp; @@ -270,6 +276,10 @@ bool subghz_last_settings_save(SubGhzLastSettings* instance) { file, SUBGHZ_LAST_SETTING_FIELD_FILTER, &instance->filter, 1)) { break; } + if(!flipper_format_insert_or_update_bool( + file, SUBGHZ_LAST_SETTING_FIELD_DELETE_OLD, &instance->delete_old_signals, 1)) { + break; + } saved = true; } while(0); diff --git a/applications/main/subghz/subghz_last_settings.h b/applications/main/subghz/subghz_last_settings.h index b3742d4bf..74dded4b7 100644 --- a/applications/main/subghz/subghz_last_settings.h +++ b/applications/main/subghz/subghz_last_settings.h @@ -30,6 +30,7 @@ typedef struct { uint32_t ignore_filter; uint32_t filter; float rssi; + bool delete_old_signals; } SubGhzLastSettings; SubGhzLastSettings* subghz_last_settings_alloc(void); From 5c00a403f6477fc7f0b2c6f82689983bbc284410 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Tue, 26 Dec 2023 22:49:38 +0300 Subject: [PATCH 42/44] temp fix for subghz keyboard lock actually - furi timer is broken :((((( --- applications/main/subghz/views/receiver.c | 37 ++++++++++++----------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/applications/main/subghz/views/receiver.c b/applications/main/subghz/views/receiver.c index 98c15dbff..1eb4d0460 100644 --- a/applications/main/subghz/views/receiver.c +++ b/applications/main/subghz/views/receiver.c @@ -101,6 +101,24 @@ void subghz_receiver_rssi(SubGhzViewReceiver* instance, float rssi) { true); } +static void subghz_view_receiver_timer_callback(void* context) { + furi_assert(context); + SubGhzViewReceiver* subghz_receiver = context; + with_view_model( + subghz_receiver->view, + SubGhzViewReceiverModel * model, + { model->bar_show = SubGhzViewReceiverBarShowDefault; }, + true); + if(subghz_receiver->lock_count < UNLOCK_CNT) { + subghz_receiver->callback( + SubGhzCustomEventViewReceiverOffDisplay, subghz_receiver->context); + } else { + subghz_receiver->lock = false; + subghz_receiver->callback(SubGhzCustomEventViewReceiverUnlock, subghz_receiver->context); + } + subghz_receiver->lock_count = 0; +} + void subghz_view_receiver_set_lock(SubGhzViewReceiver* subghz_receiver, bool lock) { furi_assert(subghz_receiver); subghz_receiver->lock_count = 0; @@ -112,6 +130,7 @@ void subghz_view_receiver_set_lock(SubGhzViewReceiver* subghz_receiver, bool loc { model->bar_show = SubGhzViewReceiverBarShowLock; }, true); furi_timer_start(subghz_receiver->timer, 1000); + subghz_view_receiver_timer_callback(subghz_receiver); } else { with_view_model( subghz_receiver->view, @@ -424,24 +443,6 @@ void subghz_view_receiver_draw(Canvas* canvas, SubGhzViewReceiverModel* model) { } } -static void subghz_view_receiver_timer_callback(void* context) { - furi_assert(context); - SubGhzViewReceiver* subghz_receiver = context; - with_view_model( - subghz_receiver->view, - SubGhzViewReceiverModel * model, - { model->bar_show = SubGhzViewReceiverBarShowDefault; }, - true); - if(subghz_receiver->lock_count < UNLOCK_CNT) { - subghz_receiver->callback( - SubGhzCustomEventViewReceiverOffDisplay, subghz_receiver->context); - } else { - subghz_receiver->lock = false; - subghz_receiver->callback(SubGhzCustomEventViewReceiverUnlock, subghz_receiver->context); - } - subghz_receiver->lock_count = 0; -} - bool subghz_view_receiver_input(InputEvent* event, void* context) { furi_assert(context); SubGhzViewReceiver* subghz_receiver = context; From 528d29b82deb6e0e206952733330dd9e49a11bc7 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Tue, 26 Dec 2023 23:24:57 +0300 Subject: [PATCH 43/44] upd changelog and ac --- CHANGELOG.md | 83 +++++-------------- .../infrared/resources/infrared/assets/ac.ir | 76 +++++++++++++++++ 2 files changed, 99 insertions(+), 60 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e4f19092..62edba5a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,74 +6,37 @@ - Mifare Mini clones reading is broken (original mini working fine) (OFW) - Mifare Classic dict attack fast skip (multiple presses on OK button) causes glitches/incorrect reading (OFW) - EMV simple data parser was removed with protocol with refactoring (OFW) -- Mifare Classic Emulation slow response (unconfirmed) (OFW) - Option to unlock Slix-L (NFC V) with preset or custom password was removed with refactoring (OFW) - NFC CLI was removed with refactoring (OFW) ### Some apps that was made for old nfc stack is now not compatible with the new API and require complete remake: **If you want to help with making this apps work again please send PR to the repo at link below** - Current list of affected apps: https://github.com/xMasterX/all-the-plugins/tree/dev/apps_broken_by_last_refactors - Also in app **Enhanced Sub-GHz Chat** - NFC part was temporarily removed to make app usable, NFC part of the app requires remaking it with new nfc stack
-**API was updated to v49.x** +**API was updated to v50.x** ## New changes -* NFC: Added new parsers for transport cards - Umarsh, Kazan, Moscow, Metromoney(Tbilisi), and fixes for OFW parsers (by @assasinfil and @Leptopt1los) (special thanks for users who provided various dumps of those cards for research) -* NFC: Added simple key name display to UI to fix regression -* NFC: Add keys to mf_classic_dict (by @hnlcory | PR #660) -* NFC: Add Saflok and MyKey KDFs (by @noproto | PR #662) -* NFC: social_moscow parser verification collisions fix (by @Leptopt1los) -* iButton: Fix UI text - protocol name getting out of screen bounds when key name is too large, and other related issues (by @krolchonok | PR #649) -* SubGHz: Fixed feature naming in menu -* SubGHz: Added honeywell protocol [(by @htotoo)](https://github.com/Flipper-XFW/Xtreme-Firmware/commit/ceee551befa0cb8fd8514a4f8a1250fd9e0997ee) -* SubGHz: Add 303.9 Mhz to default frequency list -* SubGHz: Fix Keeloq decoding order bug (random switch to HCS101 or anmotors) -* SubGHz: Fix secplus v1 key display issue -* API: Add new get function for varitemlist (by @Willy-JL) -* Misc code cleanup -* Apps: **Bluetooth Remote / USB Keyboard & Mouse** - `Movie` and `PTT` modes by @hryamzik -* Apps: **BLE Spam app** updated to latest version (New devices support, + Menu by holding Start) (by @Willy-JL) -> (app can be found in builds ` `, `e`, `n`, `r`) -* Apps: **NFC Magic** - Gen4 Actions (option to fix card with broken config) (by @Leptopt1los and @xMasterX) +* NFC: Fix Saflok edge case 0.5% of UIDs got wrong result (by @noproto | PR #668) +* NFC: Zolotaya Korona transport card parser added (by @Leptopt1los) +* NFC: Parsers cleanup for new api (by @Leptopt1los) +* SubGHz: Temp fix for subghz keyboard lock display issue (furi_timer is not working properly) +* SubGHz: Added new option to delete old signals on full memory +* SubGHz: Faac rc/xt add manually (unverified) +* SubGHz: Better subghz history element removal (by @Willy-JL) +* SubGHz: Fix key display newline issue in came atomo * Apps: **Check out Apps updates by following** [this link](https://github.com/xMasterX/all-the-plugins/commits/dev) -* OFW: NFC fixes -* OFW: nfc: m1k-based Aime (non-AIC) card support -* OFW: SubGhz: fix count bit for detect gate_tx protocol -* OFW: Fixed a zero allocation error when reading an iso15693 nfc tag with no additional blocks. -* OFW: Ntag21x write -* OFW: Mifare Classic nested auth support -* OFW: ST25TB poller refining + write support -* OFW: Libraries cleanup; u2f crypto rework to use mbedtls -* OFW: Add the secret door animation -* OFW: Allows you to use UCS-2 in canvas_glyph_width -* OFW: Mifare Classic fixes -* OFW: NFC: Felica UID emulation -* OFW: 64k does not enough -* OFW: fbt: improvements -* OFW: Various Fixes for 0.95 -* OFW: Add Mastercode SubGHz Protocol -* OFW: Do not remove file when renaming to itself -* OFW: Fix iButton crash on missing file -* OFW: NFC API improvements -* OFW: MF Ultralight no pwd polling adjustment -* OFW: Fix limited_credit_value having wrong value in mf_desfire_file_settings_parse -* OFW: Infrared remote button index support -* OFW: Fix NFC unit tests -* OFW: fix: invariant format of log time data -* OFW: fbt: dist improvements -* OFW: Fix crash when exiting write mode -* OFW: Dolphin: Extreme butthurt loop fix -* OFW: **Furi, FuriHal: remove FreeRTOS headers leaks** -* OFW: fbt: source collection improvements -* OFW: Rename menu items related to dummy mode and sound -* OFW: fbt: SD card resource handling speedup -* OFW: **Furi: cleanup crash use** -* OFW: Allow for larger Infrared remotes -* OFW: **fbt: reworked assets & resources handling** -* OFW: Storage: speedup write_chunk cli command -* OFW: fix crash after st25tb save -* OFW: Fix crash when reading files > 64B -* OFW: NFC RC fixes -* OFW: Fix MF DESFire record file handling -* OFW: **NFC refactoring** (new NFC stack) -> some apps still require very big changes to make them work with new system - see apps that was temporarily removed from this release here: https://github.com/xMasterX/all-the-plugins/tree/dev/apps_broken_by_last_refactors -* OFW: fbt: glob & git improvements -* OFW: FastFAP: human readable error log +* OFW: USART Bridge: added support for software control of DE/RE pins +* OFW: ufbt: changed toolchain environment invocation; updated .gitignore for app template +* OFW: Keys Dict: fix PVS warnings +* OFW: NfcDict Refactoring +* OFW: Add AC's Carrier 42QG5A580SC and AUX YKR-H/006E +* OFW: NFC Plugins loading rework +* OFW: MFC emulation fix +* OFW: nfc_util: little endian bytes2num functions added +* OFW: Add MyKey parser +* OFW: Update CLI MOTD +* OFW: NFC NTAG and ISO14443-3b reading fix +* OFW: FuriHal: RTC register reset API. New factory reset routine that wipes all RTC backup registers content. +* OFW: FuriHal: various GPIO improvements +* OFW: SubGhz: changed the name of the button when sending RAW to SubGHz ---- diff --git a/applications/main/infrared/resources/infrared/assets/ac.ir b/applications/main/infrared/resources/infrared/assets/ac.ir index 22bd473a7..301df5e5e 100644 --- a/applications/main/infrared/resources/infrared/assets/ac.ir +++ b/applications/main/infrared/resources/infrared/assets/ac.ir @@ -807,3 +807,79 @@ type: raw frequency: 38000 duty_cycle: 0.330000 data: 6175 7369 602 1570 602 1570 601 1570 573 1598 574 1598 573 1597 574 1597 574 1598 574 525 574 526 573 526 573 527 572 528 571 529 570 529 570 530 568 1603 568 1627 544 1627 544 1627 544 1628 544 554 545 1627 544 1628 544 555 544 555 544 555 544 555 544 554 544 1627 545 555 544 554 545 1627 544 1627 544 1627 544 1627 544 1627 544 1603 568 1602 569 1603 569 530 569 529 570 529 570 529 570 529 570 529 570 529 570 528 570 1601 571 528 570 1602 570 529 570 528 570 1601 570 1600 571 1601 571 528 571 1601 570 528 570 1601 570 1602 570 529 570 529 570 528 570 1601 570 1601 570 1600 571 1601 571 528 570 1601 570 1601 571 528 571 528 571 529 570 528 571 528 570 1601 571 528 571 528 570 1603 570 529 571 1603 570 529 570 1603 570 529 570 1603 570 529 571 1602 571 1603 570 529 571 1603 570 529 571 1603 570 529 571 1603 570 530 570 7370 570 +# +# Model: AUX YKR-H/006E +# +name: Off +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8957 4502 539 1683 538 1681 540 559 538 559 538 556 541 557 540 1683 538 1682 539 1684 537 1682 539 1681 540 1684 537 1684 537 1682 539 1684 537 558 539 558 539 558 539 558 539 559 538 558 539 1682 539 1681 540 1683 538 557 540 558 539 558 539 557 540 559 538 557 540 557 540 561 536 559 538 558 539 557 540 558 539 558 539 1683 538 558 539 1682 540 557 540 559 538 557 540 557 540 561 536 558 539 559 538 558 539 560 537 557 540 558 539 558 539 558 539 559 538 558 539 1682 539 557 540 558 539 557 540 557 540 558 539 560 537 557 540 557 540 558 539 559 538 557 540 559 538 556 541 558 539 558 539 558 539 556 541 559 538 557 540 558 539 558 539 558 539 557 540 558 539 557 541 557 540 557 540 559 538 558 539 558 539 558 539 558 539 1681 540 557 540 1683 538 558 539 559 538 557 540 559 538 559 538 1683 538 1683 538 1683 538 557 540 558 539 558 540 1683 538 560 563 +# +name: Dh +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8956 4504 536 1684 537 1687 534 559 538 559 538 559 538 560 537 1683 538 1685 536 1682 539 1684 537 1683 538 1684 537 1683 538 1684 537 1683 538 558 539 562 535 559 538 558 539 562 535 560 537 1683 538 1684 537 1683 538 561 536 561 536 561 537 560 537 561 536 558 539 560 537 559 538 560 537 561 536 561 536 563 534 559 538 1684 537 559 538 1684 537 561 536 560 537 560 537 560 537 560 537 560 537 559 538 559 538 559 538 588 509 558 539 559 538 559 538 564 533 1684 537 559 538 560 537 559 538 588 509 563 534 559 538 559 538 558 539 562 535 558 539 561 536 560 537 560 537 559 538 588 509 561 536 560 537 561 536 563 534 561 536 560 537 561 536 1684 537 559 538 559 538 559 538 561 536 560 537 560 537 559 538 561 536 558 539 560 537 1684 537 559 538 1683 538 561 536 561 536 563 534 559 538 558 539 1683 538 1684 537 1684 537 560 537 560 537 1683 538 560 537 560 563 +# +name: Cool_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8957 4502 538 1683 538 1684 537 562 535 560 537 559 538 559 539 1683 538 1682 539 1711 510 1685 536 1683 538 558 539 588 509 557 540 1682 539 557 540 558 539 559 538 559 538 558 539 561 536 1681 540 1682 539 1683 538 559 538 559 538 559 538 561 536 560 537 559 538 558 539 559 538 559 538 559 538 559 538 560 537 560 537 1685 536 560 537 1685 536 560 537 559 538 560 537 560 537 559 538 558 539 559 538 560 537 587 510 562 535 559 538 560 537 557 540 1685 536 559 538 560 537 587 510 588 509 559 538 562 535 560 537 557 540 559 538 557 540 560 537 587 510 560 538 558 539 559 538 559 538 561 536 560 537 560 537 558 540 560 537 559 538 560 537 1683 538 562 535 560 537 559 538 560 537 558 539 559 538 558 539 560 537 560 537 559 538 1683 538 558 539 1684 537 559 538 558 539 559 538 558 539 558 539 1682 539 1684 537 1684 537 1683 538 560 537 558 539 1683 538 1684 564 +# +name: Cool_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8956 4501 539 1682 539 1682 539 559 538 557 540 587 510 558 539 1684 537 1682 539 1682 539 1682 539 1680 541 1682 539 1682 539 1682 539 1681 540 558 539 558 539 558 539 557 540 558 539 557 540 1683 538 1683 538 1683 538 558 539 558 539 558 539 557 540 560 537 560 537 557 540 558 539 557 540 558 539 557 540 560 537 558 539 1681 540 556 541 1684 537 558 539 557 540 559 538 558 539 557 540 558 539 558 539 560 537 559 538 558 539 558 539 557 540 559 538 1685 536 559 538 558 539 587 510 557 540 559 538 559 538 560 537 560 537 558 539 559 538 558 539 559 538 562 535 558 539 557 540 557 540 559 538 559 538 558 539 559 538 558 539 558 539 557 540 1682 539 557 540 558 539 559 538 557 540 558 539 560 537 559 538 557 540 561 536 558 539 1682 539 558 539 1682 539 559 538 557 540 558 539 559 538 559 538 1682 539 1684 537 1683 538 557 540 558 539 558 539 560 537 559 564 +# +name: Heat_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8959 4502 539 1682 539 1682 539 556 541 559 538 558 539 559 538 1680 541 1681 540 1684 537 1683 538 1684 537 557 540 560 537 558 539 1683 538 1682 539 558 539 559 538 559 538 558 539 558 539 1683 538 1681 540 1683 538 559 538 560 537 560 537 559 538 561 536 560 537 559 538 559 538 559 538 559 538 559 538 560 537 557 540 1682 539 557 540 1682 539 559 538 558 539 560 538 558 539 558 539 558 539 558 539 558 539 559 538 559 538 557 540 558 539 558 539 559 538 560 537 1684 537 561 536 557 540 559 538 559 538 557 540 558 539 559 538 560 537 558 539 558 539 559 538 558 539 559 539 559 538 557 540 559 538 557 540 558 540 561 536 558 539 558 539 1683 538 558 539 559 538 557 540 559 538 557 540 558 539 559 538 559 538 558 539 559 538 1681 540 558 539 1684 537 562 535 560 537 559 538 559 538 560 537 1682 539 1682 539 1682 539 1686 535 559 538 1682 539 559 538 1682 565 +# +name: Heat_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8961 4501 539 1681 540 1681 540 559 538 558 539 558 539 557 540 1682 539 1682 539 1681 540 1682 539 1682 539 1683 538 1682 539 1683 538 1682 539 557 540 560 537 558 539 560 537 560 537 558 539 1681 540 1681 540 1682 539 557 540 558 539 561 536 558 539 560 537 558 539 556 541 558 539 558 539 557 540 559 538 558 539 559 538 1684 537 559 538 1682 539 558 539 556 541 559 538 562 535 556 541 558 539 558 539 557 540 558 539 557 540 558 539 559 538 560 537 557 540 557 540 1682 539 558 539 557 540 558 539 559 538 559 538 557 540 558 539 558 539 558 539 558 539 557 540 561 536 558 539 586 511 558 539 557 540 586 511 559 539 556 541 557 540 557 540 1682 539 559 538 558 539 558 539 559 538 558 539 560 537 558 539 559 538 558 539 557 540 1681 540 558 539 1680 541 557 540 557 540 559 538 558 539 559 538 1682 539 1682 539 1682 539 558 539 558 539 1682 539 1682 539 558 565 +# +# Model: Carrier 42QG5A580SC +# +name: Off +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8403 4308 519 1425 518 625 520 1461 485 1427 518 559 517 564 567 1386 518 1429 517 562 597 524 519 1431 517 1430 518 567 516 1426 518 565 517 1429 518 1431 518 1425 519 565 517 1457 485 562 518 1429 519 1424 520 565 516 1426 517 561 519 1430 515 1427 518 563 595 525 518 1428 517 528 489 21085 8424 4296 642 467 568 1400 569 533 569 536 647 1402 569 1395 569 535 568 534 569 1405 566 1397 567 549 568 535 569 1401 567 533 570 1399 571 537 570 534 568 537 567 1397 570 535 571 1401 568 534 567 533 567 1399 567 539 568 1402 569 565 569 532 571 1399 571 1397 569 535 566 1358 489 21085 8401 4318 512 1438 517 573 515 1476 532 1389 516 573 518 609 535 1393 568 1392 516 574 567 528 566 1393 565 1390 516 576 516 1437 517 574 517 1441 516 1445 567 1389 517 578 566 1390 516 578 568 1398 566 1392 515 575 516 1437 516 574 517 1442 567 1425 483 597 515 575 516 1446 514 539 490 +# +name: Dh +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8391 4318 536 1417 518 564 516 1432 517 1428 518 563 518 562 517 1433 516 1428 518 564 519 565 513 1433 517 1430 517 562 518 1463 483 561 517 1430 516 1428 518 563 595 1393 516 559 519 565 514 1425 519 1429 517 569 514 1426 518 566 514 1466 485 562 518 559 518 561 518 1425 519 531 488 21116 8369 4318 569 534 641 1326 640 462 641 465 641 1330 641 1325 639 464 568 534 595 1403 641 1328 641 462 639 467 640 1328 568 536 642 1367 568 531 567 536 569 1398 568 537 542 1432 640 1327 567 532 568 535 567 1400 567 539 567 1399 568 536 568 1402 569 1402 568 1401 567 537 565 1359 487 21117 8392 4294 565 1388 517 575 566 1393 516 1443 514 574 516 573 517 1443 567 1391 515 574 516 577 566 1393 565 1390 566 528 567 1392 516 575 567 1395 565 1390 515 576 568 1391 515 572 566 528 565 1395 565 1393 515 572 564 1391 515 581 563 1389 516 578 513 609 483 576 566 1391 514 538 487 +# +name: Cool_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8424 4292 514 1428 518 559 518 1431 514 1432 517 561 515 566 512 1433 516 1434 516 562 519 562 516 1432 517 1426 518 566 516 1429 517 566 516 1429 518 1428 517 562 516 1467 481 570 517 561 518 565 519 563 515 566 516 567 516 1433 516 1429 514 564 518 561 518 562 519 1428 519 536 562 21009 8478 4280 638 461 641 1328 641 456 642 467 637 1325 643 1326 568 597 568 537 639 1330 641 1327 568 535 640 468 639 1324 568 534 543 1432 566 535 641 494 637 1327 566 532 640 1329 567 1398 640 1327 641 1327 640 1326 642 1328 568 531 568 538 567 1402 567 1406 566 1402 568 532 569 1357 489 21085 8401 4319 565 1394 516 577 567 1396 565 1390 515 574 543 566 516 1441 568 1392 516 575 566 531 566 1393 567 1390 516 576 515 1456 515 579 562 1392 515 1440 515 575 566 1391 516 576 544 569 563 525 516 574 514 606 514 576 514 1439 567 1390 515 575 515 574 570 566 567 1390 515 540 488 +# +name: Cool_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8401 4306 518 1460 483 566 518 1432 517 1430 514 561 516 564 517 1429 518 1430 519 592 485 564 517 1427 517 1432 516 561 545 1430 516 566 518 1462 483 1430 515 568 517 1427 516 566 516 564 517 1430 518 1425 518 559 518 562 518 1426 518 1425 517 593 484 561 516 573 516 1427 517 530 564 21007 8401 4322 642 465 643 1324 643 457 643 458 643 1327 643 1327 641 463 642 461 644 1325 644 1324 643 462 642 483 643 1328 641 460 645 1321 643 458 643 464 641 1325 643 459 644 1327 642 1323 643 461 643 461 642 1347 644 1331 641 463 639 462 641 1327 571 1405 542 1428 670 462 645 1282 562 21007 8402 4317 515 1436 517 606 641 1321 516 1438 517 572 515 578 516 1441 515 1440 516 572 515 575 515 1474 610 1316 515 574 644 1314 516 574 567 1394 640 1316 517 578 639 1319 516 576 517 575 513 1447 641 1315 516 576 515 577 566 1396 514 1440 516 573 518 571 638 456 565 1393 515 538 564 +# +name: Heat_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8399 4307 519 1426 518 560 517 1432 517 1460 485 561 518 558 517 1436 518 1427 518 555 520 561 517 1430 519 1428 516 560 519 1425 518 566 517 1430 516 1432 519 563 519 1425 518 563 515 1429 517 1433 517 1430 516 1432 518 1429 518 568 516 1432 515 1429 519 561 516 567 517 1427 519 533 487 21083 8424 4339 567 536 568 1402 641 493 608 462 545 1431 640 1326 567 532 568 538 640 1331 640 1329 641 536 565 534 641 1329 567 537 639 1329 640 462 642 467 641 1325 568 532 642 1332 640 488 568 534 565 536 566 566 536 567 641 1329 570 535 638 464 569 1401 641 1326 568 534 639 1287 490 21083 8403 4313 567 1390 516 579 514 1441 515 1438 517 575 516 576 568 1393 568 1394 515 606 534 530 515 1441 567 1425 482 576 568 1392 514 578 566 1392 569 1432 515 576 568 1389 517 577 515 1444 515 1437 569 1393 516 1444 566 1389 566 528 567 1394 566 1419 517 575 513 578 515 1440 516 539 490 +# +name: Heat_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 8425 4291 542 1401 544 538 542 1404 518 1427 544 534 570 540 516 1434 542 1399 544 539 544 539 541 1403 541 1402 516 570 517 1427 545 566 511 1406 517 1431 542 534 544 1406 543 536 517 567 543 1404 542 1400 595 525 544 1405 542 534 516 1433 516 1428 544 537 544 535 543 1403 542 505 488 21084 8424 4298 566 535 569 1402 567 533 568 537 570 1403 570 1403 565 534 566 537 566 1402 569 1398 569 533 569 538 592 1446 569 535 570 1400 569 567 535 535 568 1437 568 533 568 1398 569 1402 565 533 567 534 569 1403 568 536 569 1402 568 535 567 534 571 1403 568 1415 566 536 571 1362 489 21084 8403 4313 516 1439 517 574 515 1442 515 1441 518 573 516 574 567 1397 514 1440 515 573 516 575 516 1443 515 1439 518 574 516 1440 517 608 535 1396 517 1441 517 579 515 1438 515 576 517 578 568 1390 569 1391 516 575 518 1439 516 573 517 1445 566 1391 516 571 517 572 516 1441 514 543 487 From 5ef6adb9eaffb72632516d82abe5dac1cf781dd7 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Tue, 26 Dec 2023 23:29:24 +0300 Subject: [PATCH 44/44] upd changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62edba5a2..a3b54a4be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ - Also in app **Enhanced Sub-GHz Chat** - NFC part was temporarily removed to make app usable, NFC part of the app requires remaking it with new nfc stack
**API was updated to v50.x** ## New changes +* IR: Updated infrared assets (by @amec0e | PR #677) * NFC: Fix Saflok edge case 0.5% of UIDs got wrong result (by @noproto | PR #668) * NFC: Zolotaya Korona transport card parser added (by @Leptopt1los) * NFC: Parsers cleanup for new api (by @Leptopt1los)