From 787df44c7992d8718fe634f13f4b64118486e89c Mon Sep 17 00:00:00 2001 From: Astra <93453568+Astrrra@users.noreply.github.com> Date: Mon, 19 Sep 2022 15:30:18 +0300 Subject: [PATCH 1/6] [FL-2800] Fix Mifare Classic 4K reading of the last 8 sectors (#1712) * Fix FURI_BIT_SET Co-authored-by: gornekich Co-authored-by: SG --- furi/core/core_defines.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/furi/core/core_defines.h b/furi/core/core_defines.h index 801810f6a..487fe2ca3 100644 --- a/furi/core/core_defines.h +++ b/furi/core/core_defines.h @@ -85,7 +85,11 @@ extern "C" { #endif #ifndef FURI_BIT_SET -#define FURI_BIT_SET(x, n) ((x) |= (1 << (n))) +#define FURI_BIT_SET(x, n) \ + ({ \ + __typeof__(x) _x = (1); \ + (x) |= (_x << (n)); \ + }) #endif #ifndef FURI_BIT_CLEAR From ed385594a35983c21a285af7e783d753cf014283 Mon Sep 17 00:00:00 2001 From: hedger Date: Mon, 19 Sep 2022 16:39:00 +0400 Subject: [PATCH 2/6] faploader: more subsystem headers in API table (#1742) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * faploader: more subsystem headers in API table; not counting header entries for SDK version change * subghz: removed dead function * Adjusted API version * hal: removed furi_hal_power_get_system_voltage * lib: mbedtls: additional flags for .fap linkage * fbt: rebuilding assets when git commit id changes * fbt: removed assets rebuild on git commit id change; added explicit dependency for SDK source on compiled assets parts; removed unneeded sdk regeneration runs * fbt: changed stock plugins to EXTERNAL apps; restored building app as a PLUGIN as a part of main fw as well as a .fap; readme fixes * fbt: restored certain apps to PLUGIN type * fbt: app manifests: renamed version->fap_version, added extra fields * fbt: fixed version processing after rename Co-authored-by: あく --- applications/plugins/picopass/application.fam | 2 +- assets/SConscript | 9 +- documentation/AppManifests.md | 29 ++--- fbt_options.py | 3 +- firmware.scons | 2 +- firmware/targets/f7/api_symbols.csv | 103 +++++++++++++++++- .../targets/furi_hal_include/furi_hal_power.h | 6 - lib/lfrfid/SConscript | 8 ++ lib/mbedtls.scons | 8 ++ lib/subghz/SConscript | 1 + lib/subghz/protocols/raw.h | 14 ++- lib/toolbox/SConscript | 2 + site_scons/extapps.scons | 5 +- site_scons/fbt/appmanifest.py | 7 +- site_scons/fbt/elfmanifest.py | 4 +- site_scons/fbt/sdk.py | 51 +++++---- site_scons/fbt/version.py | 2 + site_scons/site_tools/fbt_sdk.py | 1 + 18 files changed, 192 insertions(+), 65 deletions(-) diff --git a/applications/plugins/picopass/application.fam b/applications/plugins/picopass/application.fam index 887d0324c..7a81e0804 100644 --- a/applications/plugins/picopass/application.fam +++ b/applications/plugins/picopass/application.fam @@ -1,7 +1,7 @@ App( appid="picopass", name="PicoPass Reader", - apptype=FlipperAppType.PLUGIN, + apptype=FlipperAppType.EXTERNAL, entry_point="picopass_app", requires=[ "storage", diff --git a/assets/SConscript b/assets/SConscript index 6328035fa..47713d1a6 100644 --- a/assets/SConscript +++ b/assets/SConscript @@ -1,13 +1,5 @@ Import("env") -# HACHHACK -# Currently injected to CPPPATH by libs - since they are built earlier and depend on assets -# env.Append( -# CPPPATH=[ -# Dir("./compiled"), -# ] -# ) - assetsenv = env.Clone( tools=["fbt_assets"], FW_LIB_NAME="assets", @@ -109,6 +101,7 @@ if assetsenv["IS_BASE_FIRMWARE"]: ) # Exporting resources node to external environment + env["FW_ASSETS_HEADERS"] = assets_parts env["FW_RESOURCES"] = resources assetsenv.Alias("resources", resources) diff --git a/documentation/AppManifests.md b/documentation/AppManifests.md index 5e7ceb939..7bc8d0a47 100644 --- a/documentation/AppManifests.md +++ b/documentation/AppManifests.md @@ -1,16 +1,16 @@ # Flipper Application Manifests (.fam) -All components of Flipper Zero firmware — services, user applications, system settings — are developed independently. Each component has a build system manifest file, named `application.fam`, defining basic properties of a components and its relations to other parts of the system. +All components of Flipper Zero firmware — services, user applications, system settings — are developed independently. Each component has a build system manifest file, named `application.fam`, which defines basic properties of that component and its relations to other parts of the system. -When building firmware, **`fbt`** collects all application manifests, processes their dependencies and builds only those components that are utilized in current build configuration. See [fbt docs](./fbt.md#firmware-application-set) for details on build configurations. +When building firmware, **`fbt`** collects all application manifests and processes their dependencies. Then it builds only those components that are referenced in the current build configuration. See [fbt docs](./fbt.md#firmware-application-set) for details on build configurations. ## Application definition Properties of a firmware component are declared in a form of a Python code snippet, forming a call to App() function with various parameters. -Only 2 parameters are mandatoty: ***appid*** and ***apptype***, others are optional and may be meaningful only for certain application types. +Only 2 parameters are mandatory: ***appid*** and ***apptype***, others are optional and may only be meaningful for certain application types. -### Keys +### Parameters * **appid**: string, application id within the build system. Used for specifying which applications to include in build configuration and to resolve dependencies and conflicts. @@ -21,7 +21,7 @@ Only 2 parameters are mandatoty: ***appid*** and ***apptype***, others are optio | SERVICE | System service, created at early startup | | SYSTEM | Application not being shown in any menus. Can be started by other apps or from CLI | | APP | Regular application for main menu | -| PLUGIN | Application to be built as .fap plugin | +| PLUGIN | Application to be built as a part of firmware an to be placed in Plugins menu | | DEBUG | Application only visible in Debug menu with debug mode enabled | | ARCHIVE | One and only Archive app | | SETTINGS | Application to be placed in System settings menu | @@ -29,25 +29,28 @@ Only 2 parameters are mandatoty: ***appid*** and ***apptype***, others are optio | EXTERNAL | Application to be built as .fap plugin | | METAPACKAGE | Does not define any code to be run, used for declaring dependencies and application bundles | -* **name**: Name to show in menus. -* **entry_point**: C function to be used as applicaiton's entry point. +* **name**: Name that is displayed in menus. +* **entry_point**: C function to be used as application's entry point. * **flags**: Internal flags for system apps. Do not use. * **cdefines**: C preprocessor definitions to declare globally for other apps when current application is included in active build configuration. * **requires**: List of application IDs to also include in build configuration, when current application is referenced in list of applications to build. * **conflicts**: List of application IDs that current application conflicts with. If any of them is found in constructed application list, **`fbt`** will abort firmware build process. * **provides**: Functionally identical to ***requires*** field. -* **stack_size**: Stack size, in bytes, to allocate for application on its startup. Note that allocating a stack too small for app to run will cause system crash due to stack overflow, and allocating too much stack will reduce usable heap memory size for app to process data. *Note: you can use `ps` and `free` CLI commands to profile you app's memory usage.* +* **stack_size**: Stack size, in bytes, to allocate for application on its startup. Note that allocating a stack that is too small for an app to run will cause system crash due to stack overflow, and allocating too much stack space will reduce usable heap memory size for apps to process data. *Note: you can use `ps` and `free` CLI commands to profile your app's memory usage.* * **icon**: Animated icon name from built-in assets to be used when building app as a part of firmware. -* **order**: Order of an application within its group when sorting entries in it. The lower the order is, the closer to the start of the list the items is located. Used for ordering startup hooks and menu entries. -* **sdk_headers**: List of C header files from this app's code to include in API definitions for external applicaions. +* **order**: Order of an application within its group when sorting entries in it. The lower the order is, the closer to the start of the list the item is placed. *Used for ordering startup hooks and menu entries.* +* **sdk_headers**: List of C header files from this app's code to include in API definitions for external applications. The following parameters are used only for [FAPs](./AppsOnSDCard.md): * **sources**: list of file name masks, used for gathering sources within app folder. Default value of ["\*.c\*"] includes C and CPP source files. -* **version**: string, 2 numbers in form of "x.y": application version to be embedded within .fap file. -* **fap_icon**: name of .png file, 1-bit color depth, 10x10px, to be embedded within .fap file. +* **fap_version**: string, 2 numbers in form of "x.y": application version to be embedded within .fap file. +* **fap_icon**: name of a .png file, 1-bit color depth, 10x10px, to be embedded within .fap file. * **fap_libs**: list of extra libraries to link application against. Provides access to extra functions that are not exported as a part of main firmware at expense of increased .fap file size and RAM consumption. * **fap_category**: string, may be empty. App subcategory, also works as path of FAP within apps folder in the file system. +* **fap_description**: string, may be empty. Short application descriotion. +* **fap_author**: string, may be empty. Application's author. +* **fap_weburl**: string, may be empty. Application's homepage. ## .fam file contents @@ -76,4 +79,4 @@ App( ) ``` -For more examples, see application.fam files for basic firmware components. \ No newline at end of file +For more examples, see .fam files from various firmware parts. diff --git a/fbt_options.py b/fbt_options.py index bdf8fc03b..716f99fdf 100644 --- a/fbt_options.py +++ b/fbt_options.py @@ -73,7 +73,8 @@ FIRMWARE_APPS = { "system_apps", # Settings "settings_apps", - # Plugins + # Stock plugins - no longer built into fw, now they're .faps + # Yet you can still build them as a part of fw # "basic_plugins", # Debug # "debug_apps", diff --git a/firmware.scons b/firmware.scons index 962c70725..530634ef2 100644 --- a/firmware.scons +++ b/firmware.scons @@ -302,7 +302,7 @@ if fwenv["IS_BASE_FIRMWARE"]: "-D__inline__=inline", ], ) - Depends(sdk_source, fwenv["SDK_HEADERS"]) + Depends(sdk_source, (fwenv["SDK_HEADERS"], fwenv["FW_ASSETS_HEADERS"])) sdk_tree = fwenv.SDKTree("sdk/sdk.opts", "sdk_origin") AlwaysBuild(sdk_tree) diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 545e1d644..3f2a86b24 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,1.0,, +Version,+,1.3,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -109,6 +109,12 @@ Header,+,lib/STM32CubeWB/Drivers/STM32WBxx_HAL_Driver/Inc/stm32wbxx_ll_wwdg.h,, Header,+,lib/flipper_application/flipper_application.h,, Header,+,lib/flipper_format/flipper_format.h,, Header,+,lib/flipper_format/flipper_format_i.h,, +Header,+,lib/lfrfid/lfrfid_dict_file.h,, +Header,+,lib/lfrfid/lfrfid_raw_file.h,, +Header,+,lib/lfrfid/lfrfid_raw_worker.h,, +Header,+,lib/lfrfid/lfrfid_worker.h,, +Header,+,lib/lfrfid/protocols/lfrfid_protocols.h,, +Header,+,lib/lfrfid/tools/bit_lib.h,, Header,+,lib/micro-ecc/uECC.h,, Header,+,lib/one_wire/ibutton/ibutton_worker.h,, Header,+,lib/one_wire/maxim_crc.h,, @@ -118,6 +124,7 @@ Header,+,lib/one_wire/one_wire_host_timing.h,, Header,+,lib/one_wire/one_wire_slave.h,, Header,+,lib/print/wrappers.h,, Header,+,lib/subghz/environment.h,, +Header,+,lib/subghz/protocols/raw.h,, Header,+,lib/subghz/receiver.h,, Header,+,lib/subghz/subghz_tx_rx_worker.h,, Header,+,lib/subghz/subghz_worker.h,, @@ -130,8 +137,10 @@ Header,+,lib/toolbox/manchester_decoder.h,, Header,+,lib/toolbox/manchester_encoder.h,, Header,+,lib/toolbox/md5.h,, Header,+,lib/toolbox/path.h,, +Header,+,lib/toolbox/protocols/protocol_dict.h,, Header,+,lib/toolbox/random_name.h,, Header,+,lib/toolbox/saved_struct.h,, +Header,+,lib/toolbox/stream/buffered_file_stream.h,, Header,+,lib/toolbox/stream/file_stream.h,, Header,+,lib/toolbox/stream/stream.h,, Header,+,lib/toolbox/stream/string_stream.h,, @@ -465,6 +474,26 @@ Function,-,atoll,long long,const char* Function,-,basename,char*,const char* Function,-,bcmp,int,"const void*, const void*, size_t" Function,-,bcopy,void,"const void*, void*, size_t" +Function,+,bit_lib_add_parity,size_t,"const uint8_t*, size_t, uint8_t*, size_t, uint8_t, uint8_t, BitLibParity" +Function,+,bit_lib_copy_bits,void,"uint8_t*, size_t, size_t, const uint8_t*, size_t" +Function,+,bit_lib_crc16,uint16_t,"const uint8_t*, size_t, uint16_t, uint16_t, _Bool, _Bool, uint16_t" +Function,+,bit_lib_crc8,uint16_t,"const uint8_t*, size_t, uint8_t, uint8_t, _Bool, _Bool, uint8_t" +Function,+,bit_lib_get_bit,_Bool,"const uint8_t*, size_t" +Function,+,bit_lib_get_bit_count,uint8_t,uint32_t +Function,+,bit_lib_get_bits,uint8_t,"const uint8_t*, size_t, uint8_t" +Function,+,bit_lib_get_bits_16,uint16_t,"const uint8_t*, size_t, uint8_t" +Function,+,bit_lib_get_bits_32,uint32_t,"const uint8_t*, size_t, uint8_t" +Function,+,bit_lib_print_bits,void,"const uint8_t*, size_t" +Function,+,bit_lib_print_regions,void,"const BitLibRegion*, size_t, const uint8_t*, size_t" +Function,+,bit_lib_push_bit,void,"uint8_t*, size_t, _Bool" +Function,+,bit_lib_remove_bit_every_nth,size_t,"uint8_t*, size_t, uint8_t, uint8_t" +Function,+,bit_lib_reverse_16_fast,uint16_t,uint16_t +Function,+,bit_lib_reverse_8_fast,uint8_t,uint8_t +Function,+,bit_lib_reverse_bits,void,"uint8_t*, size_t, uint8_t" +Function,+,bit_lib_set_bit,void,"uint8_t*, size_t, _Bool" +Function,+,bit_lib_set_bits,void,"uint8_t*, size_t, uint8_t, uint8_t" +Function,+,bit_lib_test_parity,_Bool,"const uint8_t*, size_t, uint8_t, BitLibParity, uint8_t" +Function,+,bit_lib_test_parity_32,_Bool,"uint32_t, BitLibParity" Function,+,ble_app_get_key_storage_buff,void,"uint8_t**, uint16_t*" Function,+,ble_app_init,_Bool, Function,+,ble_app_thread_stop,void, @@ -488,6 +517,11 @@ Function,+,bt_disconnect,void,Bt* Function,+,bt_forget_bonded_devices,void,Bt* Function,+,bt_set_profile,_Bool,"Bt*, BtProfile" Function,+,bt_set_status_changed_callback,void,"Bt*, BtStatusChangedCallback, void*" +Function,+,buffered_file_stream_alloc,Stream*,Storage* +Function,+,buffered_file_stream_close,_Bool,Stream* +Function,+,buffered_file_stream_get_error,FS_Error,Stream* +Function,+,buffered_file_stream_open,_Bool,"Stream*, const char*, FS_AccessMode, FS_OpenMode" +Function,+,buffered_file_stream_sync,_Bool,Stream* Function,+,button_menu_add_item,ButtonMenuItem*,"ButtonMenu*, const char*, int32_t, ButtonMenuItemCallback, ButtonMenuItemType, void*" Function,+,button_menu_alloc,ButtonMenu*, Function,+,button_menu_free,void,ButtonMenu* @@ -1099,7 +1133,6 @@ Function,+,furi_hal_power_get_battery_remaining_capacity,uint32_t, Function,+,furi_hal_power_get_battery_temperature,float,FuriHalPowerIC Function,+,furi_hal_power_get_battery_voltage,float,FuriHalPowerIC Function,+,furi_hal_power_get_pct,uint8_t, -Function,-,furi_hal_power_get_system_voltage,float, Function,+,furi_hal_power_get_usb_voltage,float, Function,+,furi_hal_power_info_get,void,"FuriHalPowerInfoCallback, void*" Function,-,furi_hal_power_init,void, @@ -1468,6 +1501,31 @@ Function,-,ldexp,double,"double, int" Function,-,ldexpf,float,"float, int" Function,-,ldexpl,long double,"long double, int" Function,-,ldiv,ldiv_t,"long, long" +Function,+,lfrfid_dict_file_load,ProtocolId,"ProtocolDict*, const char*" +Function,+,lfrfid_dict_file_save,_Bool,"ProtocolDict*, ProtocolId, const char*" +Function,+,lfrfid_raw_file_alloc,LFRFIDRawFile*,Storage* +Function,+,lfrfid_raw_file_free,void,LFRFIDRawFile* +Function,+,lfrfid_raw_file_open_read,_Bool,"LFRFIDRawFile*, const char*" +Function,+,lfrfid_raw_file_open_write,_Bool,"LFRFIDRawFile*, const char*" +Function,+,lfrfid_raw_file_read_header,_Bool,"LFRFIDRawFile*, float*, float*" +Function,+,lfrfid_raw_file_read_pair,_Bool,"LFRFIDRawFile*, uint32_t*, uint32_t*, _Bool*" +Function,+,lfrfid_raw_file_write_buffer,_Bool,"LFRFIDRawFile*, uint8_t*, size_t" +Function,+,lfrfid_raw_file_write_header,_Bool,"LFRFIDRawFile*, float, float, uint32_t" +Function,+,lfrfid_raw_worker_alloc,LFRFIDRawWorker*, +Function,+,lfrfid_raw_worker_free,void,LFRFIDRawWorker* +Function,+,lfrfid_raw_worker_start_emulate,void,"LFRFIDRawWorker*, const char*, LFRFIDWorkerEmulateRawCallback, void*" +Function,+,lfrfid_raw_worker_start_read,void,"LFRFIDRawWorker*, const char*, float, float, LFRFIDWorkerReadRawCallback, void*" +Function,+,lfrfid_raw_worker_stop,void,LFRFIDRawWorker* +Function,+,lfrfid_worker_alloc,LFRFIDWorker*,ProtocolDict* +Function,+,lfrfid_worker_emulate_raw_start,void,"LFRFIDWorker*, const char*, LFRFIDWorkerEmulateRawCallback, void*" +Function,+,lfrfid_worker_emulate_start,void,"LFRFIDWorker*, LFRFIDProtocol" +Function,+,lfrfid_worker_free,void,LFRFIDWorker* +Function,+,lfrfid_worker_read_raw_start,void,"LFRFIDWorker*, const char*, LFRFIDWorkerReadType, LFRFIDWorkerReadRawCallback, void*" +Function,+,lfrfid_worker_read_start,void,"LFRFIDWorker*, LFRFIDWorkerReadType, LFRFIDWorkerReadCallback, void*" +Function,+,lfrfid_worker_start_thread,void,LFRFIDWorker* +Function,+,lfrfid_worker_stop,void,LFRFIDWorker* +Function,+,lfrfid_worker_stop_thread,void,LFRFIDWorker* +Function,+,lfrfid_worker_write_start,void,"LFRFIDWorker*, LFRFIDProtocol, LFRFIDWorkerWriteCallback, void*" Function,-,lgamma,double,double Function,-,lgamma_r,double,"double, int*" Function,-,lgammaf,float,float @@ -1659,6 +1717,26 @@ Function,+,power_reboot,void,PowerBootMode Function,+,powf,float,"float, float" Function,-,powl,long double,"long double, long double" Function,-,printf,int,"const char*, ..." +Function,+,protocol_dict_alloc,ProtocolDict*,"const ProtocolBase**, size_t" +Function,+,protocol_dict_decoders_feed,ProtocolId,"ProtocolDict*, _Bool, uint32_t" +Function,+,protocol_dict_decoders_feed_by_feature,ProtocolId,"ProtocolDict*, uint32_t, _Bool, uint32_t" +Function,+,protocol_dict_decoders_feed_by_id,ProtocolId,"ProtocolDict*, size_t, _Bool, uint32_t" +Function,+,protocol_dict_decoders_start,void,ProtocolDict* +Function,+,protocol_dict_encoder_start,_Bool,"ProtocolDict*, size_t" +Function,+,protocol_dict_encoder_yield,LevelDuration,"ProtocolDict*, size_t" +Function,+,protocol_dict_free,void,ProtocolDict* +Function,+,protocol_dict_get_data,void,"ProtocolDict*, size_t, uint8_t*, size_t" +Function,+,protocol_dict_get_data_size,size_t,"ProtocolDict*, size_t" +Function,+,protocol_dict_get_features,uint32_t,"ProtocolDict*, size_t" +Function,+,protocol_dict_get_manufacturer,const char*,"ProtocolDict*, size_t" +Function,+,protocol_dict_get_max_data_size,size_t,ProtocolDict* +Function,+,protocol_dict_get_name,const char*,"ProtocolDict*, size_t" +Function,+,protocol_dict_get_protocol_by_name,ProtocolId,"ProtocolDict*, const char*" +Function,+,protocol_dict_get_validate_count,uint32_t,"ProtocolDict*, size_t" +Function,+,protocol_dict_get_write_data,_Bool,"ProtocolDict*, size_t, void*" +Function,+,protocol_dict_render_brief_data,void,"ProtocolDict*, string_t, size_t" +Function,+,protocol_dict_render_data,void,"ProtocolDict*, string_t, size_t" +Function,+,protocol_dict_set_data,void,"ProtocolDict*, size_t, const uint8_t*, size_t" Function,-,pselect,int,"int, fd_set*, fd_set*, fd_set*, const timespec*, const sigset_t*" Function,-,putc,int,"int, FILE*" Function,-,putc_unlocked,int,"int, FILE*" @@ -2105,6 +2183,22 @@ Function,-,subghz_protocol_decoder_base_get_hash_data,uint8_t,SubGhzProtocolDeco Function,-,subghz_protocol_decoder_base_get_string,_Bool,"SubGhzProtocolDecoderBase*, string_t" Function,+,subghz_protocol_decoder_base_serialize,_Bool,"SubGhzProtocolDecoderBase*, FlipperFormat*, SubGhzPresetDefinition*" Function,-,subghz_protocol_decoder_base_set_decoder_callback,void,"SubGhzProtocolDecoderBase*, SubGhzProtocolDecoderBaseRxCallback, void*" +Function,+,subghz_protocol_decoder_raw_alloc,void*,SubGhzEnvironment* +Function,+,subghz_protocol_decoder_raw_deserialize,_Bool,"void*, FlipperFormat*" +Function,+,subghz_protocol_decoder_raw_feed,void,"void*, _Bool, uint32_t" +Function,+,subghz_protocol_decoder_raw_free,void,void* +Function,+,subghz_protocol_decoder_raw_get_string,void,"void*, string_t" +Function,+,subghz_protocol_decoder_raw_reset,void,void* +Function,+,subghz_protocol_encoder_raw_alloc,void*,SubGhzEnvironment* +Function,+,subghz_protocol_encoder_raw_deserialize,_Bool,"void*, FlipperFormat*" +Function,+,subghz_protocol_encoder_raw_free,void,void* +Function,+,subghz_protocol_encoder_raw_stop,void,void* +Function,+,subghz_protocol_encoder_raw_yield,LevelDuration,void* +Function,+,subghz_protocol_raw_file_encoder_worker_set_callback_end,void,"SubGhzProtocolEncoderRAW*, SubGhzProtocolEncoderRAWCallbackEnd, void*" +Function,+,subghz_protocol_raw_gen_fff_data,void,"FlipperFormat*, const char*" +Function,+,subghz_protocol_raw_get_sample_write,size_t,SubGhzProtocolDecoderRAW* +Function,+,subghz_protocol_raw_save_to_file_init,_Bool,"SubGhzProtocolDecoderRAW*, const char*, SubGhzPresetDefinition*" +Function,+,subghz_protocol_raw_save_to_file_stop,void,SubGhzProtocolDecoderRAW* Function,+,subghz_receiver_alloc_init,SubGhzReceiver*,SubGhzEnvironment* Function,+,subghz_receiver_decode,void,"SubGhzReceiver*, _Bool, uint32_t" Function,+,subghz_receiver_free,void,SubGhzReceiver* @@ -2144,6 +2238,7 @@ Function,+,submenu_reset,void,Submenu* Function,+,submenu_set_header,void,"Submenu*, const char*" Function,+,submenu_set_selected_item,void,"Submenu*, uint32_t" Function,-,system,int,const char* +Function,+,t5577_write,void,LFRFIDT5577* Function,-,tan,double,double Function,-,tanf,float,float Function,-,tanh,double,double @@ -2667,6 +2762,7 @@ Variable,+,gpio_usb_dp,const GpioPin, Variable,+,ibutton_gpio,const GpioPin, Variable,+,input_pins,const InputPin[], Variable,+,input_pins_count,const size_t, +Variable,+,lfrfid_protocols,const ProtocolBase*[], Variable,+,message_blink_set_color_blue,const NotificationMessage, Variable,+,message_blink_set_color_cyan,const NotificationMessage, Variable,+,message_blink_set_color_green,const NotificationMessage, @@ -2861,6 +2957,9 @@ Variable,+,sequence_set_vibro_on,const NotificationSequence, Variable,+,sequence_single_vibro,const NotificationSequence, Variable,+,sequence_solid_yellow,const NotificationSequence, Variable,+,sequence_success,const NotificationSequence, +Variable,+,subghz_protocol_raw,const SubGhzProtocol, +Variable,+,subghz_protocol_raw_decoder,const SubGhzProtocolDecoder, +Variable,+,subghz_protocol_raw_encoder,const SubGhzProtocolEncoder, Variable,-,suboptarg,char*, Variable,+,usb_cdc_dual,FuriHalUsbInterface, Variable,+,usb_cdc_single,FuriHalUsbInterface, diff --git a/firmware/targets/furi_hal_include/furi_hal_power.h b/firmware/targets/furi_hal_include/furi_hal_power.h index 16af959cf..3ab30c424 100644 --- a/firmware/targets/furi_hal_include/furi_hal_power.h +++ b/firmware/targets/furi_hal_include/furi_hal_power.h @@ -156,12 +156,6 @@ float furi_hal_power_get_battery_current(FuriHalPowerIC ic); */ float furi_hal_power_get_battery_temperature(FuriHalPowerIC ic); -/** Get System voltage in V - * - * @return voltage in V - */ -float furi_hal_power_get_system_voltage(); - /** Get USB voltage in V * * @return voltage in V diff --git a/lib/lfrfid/SConscript b/lib/lfrfid/SConscript index 8d3542883..fd29ca2ef 100644 --- a/lib/lfrfid/SConscript +++ b/lib/lfrfid/SConscript @@ -7,6 +7,14 @@ env.Append( CPPPATH=[ "#/lib/lfrfid", ], + SDK_HEADERS=[ + File("#/lib/lfrfid/lfrfid_worker.h"), + File("#/lib/lfrfid/lfrfid_raw_worker.h"), + File("#/lib/lfrfid/lfrfid_raw_file.h"), + File("#/lib/lfrfid/lfrfid_dict_file.h"), + File("#/lib/lfrfid/tools/bit_lib.h"), + File("#/lib/lfrfid/protocols/lfrfid_protocols.h"), + ], ) libenv = env.Clone(FW_LIB_NAME="lfrfid") diff --git a/lib/mbedtls.scons b/lib/mbedtls.scons index e39d9dae8..b57221a49 100644 --- a/lib/mbedtls.scons +++ b/lib/mbedtls.scons @@ -11,6 +11,14 @@ env.Append( libenv = env.Clone(FW_LIB_NAME="mbedtls") libenv.ApplyLibFlags() +libenv.AppendUnique( + CCFLAGS=[ + # Required for lib to be linkable with .faps + "-mword-relocations", + "-mlong-calls", + ], +) + sources = [ "mbedtls/library/des.c", "mbedtls/library/sha1.c", diff --git a/lib/subghz/SConscript b/lib/subghz/SConscript index 50c92cbd1..eff2f168e 100644 --- a/lib/subghz/SConscript +++ b/lib/subghz/SConscript @@ -10,6 +10,7 @@ env.Append( File("#/lib/subghz/subghz_worker.h"), File("#/lib/subghz/subghz_tx_rx_worker.h"), File("#/lib/subghz/transmitter.h"), + File("#/lib/subghz/protocols/raw.h"), ], ) diff --git a/lib/subghz/protocols/raw.h b/lib/subghz/protocols/raw.h index 00654ad28..b52a7d84e 100644 --- a/lib/subghz/protocols/raw.h +++ b/lib/subghz/protocols/raw.h @@ -4,6 +4,10 @@ #define SUBGHZ_PROTOCOL_RAW_NAME "RAW" +#ifdef __cplusplus +extern "C" { +#endif + typedef void (*SubGhzProtocolEncoderRAWCallbackEnd)(void* context); typedef struct SubGhzProtocolDecoderRAW SubGhzProtocolDecoderRAW; @@ -99,12 +103,6 @@ void subghz_protocol_encoder_raw_free(void* context); */ void subghz_protocol_encoder_raw_stop(void* context); -/** - * Сallback on completion of file transfer. - * @param context Pointer to a SubGhzProtocolEncoderRAW instance - */ -void subghz_protocol_raw_file_encoder_worker_callback_end(void* context); - /** * Set callback on completion of file transfer. * @param instance Pointer to a SubGhzProtocolEncoderRAW instance @@ -137,3 +135,7 @@ bool subghz_protocol_encoder_raw_deserialize(void* context, FlipperFormat* flipp * @return LevelDuration */ LevelDuration subghz_protocol_encoder_raw_yield(void* context); + +#ifdef __cplusplus +} +#endif diff --git a/lib/toolbox/SConscript b/lib/toolbox/SConscript index 6ced34d7c..d631431ee 100644 --- a/lib/toolbox/SConscript +++ b/lib/toolbox/SConscript @@ -23,6 +23,8 @@ env.Append( File("#/lib/toolbox/stream/stream.h"), File("#/lib/toolbox/stream/file_stream.h"), File("#/lib/toolbox/stream/string_stream.h"), + File("#/lib/toolbox/stream/buffered_file_stream.h"), + File("#/lib/toolbox/protocols/protocol_dict.h"), ], ) diff --git a/site_scons/extapps.scons b/site_scons/extapps.scons index cfffda04f..4cb5e35cf 100644 --- a/site_scons/extapps.scons +++ b/site_scons/extapps.scons @@ -63,7 +63,10 @@ def build_app_as_external(env, appdef): extapps["dist"][appdef.appid] = (appdef.fap_category, compact_elf) -apps_to_build_as_faps = [FlipperAppType.PLUGIN, FlipperAppType.EXTERNAL] +apps_to_build_as_faps = [ + FlipperAppType.PLUGIN, + FlipperAppType.EXTERNAL, +] if appenv["DEBUG_TOOLS"]: apps_to_build_as_faps.append(FlipperAppType.DEBUG) diff --git a/site_scons/fbt/appmanifest.py b/site_scons/fbt/appmanifest.py index a41717d6a..a0ab5e7c6 100644 --- a/site_scons/fbt/appmanifest.py +++ b/site_scons/fbt/appmanifest.py @@ -36,11 +36,16 @@ class FlipperApplication: icon: Optional[str] = None order: int = 0 sdk_headers: List[str] = field(default_factory=list) - version: Tuple[int] = field(default_factory=lambda: (0, 0)) + # .fap-specific sources: List[str] = field(default_factory=lambda: ["*.c*"]) + fap_version: Tuple[int] = field(default_factory=lambda: (0, 0)) fap_icon: Optional[str] = None fap_libs: List[str] = field(default_factory=list) fap_category: str = "" + fap_description: str = "" + fap_author: str = "" + fap_weburl: str = "" + # Internally used by fbt _appdir: Optional[object] = None _apppath: Optional[str] = None diff --git a/site_scons/fbt/elfmanifest.py b/site_scons/fbt/elfmanifest.py index 2f54810d9..313a64c09 100644 --- a/site_scons/fbt/elfmanifest.py +++ b/site_scons/fbt/elfmanifest.py @@ -66,8 +66,8 @@ def assemble_manifest_data( ) image_data = image.data - app_version_as_int = ((app_manifest.version[0] & 0xFFFF) << 16) | ( - app_manifest.version[1] & 0xFFFF + app_version_as_int = ((app_manifest.fap_version[0] & 0xFFFF) << 16) | ( + app_manifest.fap_version[1] & 0xFFFF ) data = ElfManifestBaseHeader( diff --git a/site_scons/fbt/sdk.py b/site_scons/fbt/sdk.py index 2e951040d..3d4a17b2f 100644 --- a/site_scons/fbt/sdk.py +++ b/site_scons/fbt/sdk.py @@ -329,7 +329,6 @@ class SdkCache: self.sdk = ApiEntries() self.disabled_entries = set() self.new_entries = set() - self.loaded_dirty = False self.loaded_dirty_version = False self.version_action = VersionBump.NONE @@ -340,8 +339,7 @@ class SdkCache: return ( self.version != SdkVersion(0, 0) and self.version_action == VersionBump.NONE - and not self.loaded_dirty - and not self.new_entries + and not self._have_pending_entries() ) def _filter_enabled(self, sdk_entries): @@ -388,21 +386,12 @@ class SdkCache: if self._load_version_only: raise Exception("Only SDK version was loaded, cannot save") - version_is_clean = True - if self.loaded_dirty: - # There are still new entries and version was already updated - version_is_clean = False - if self.version_action == VersionBump.MINOR: self.version = SdkVersion(self.version.major, self.version.minor + 1) - version_is_clean = False elif self.version_action == VersionBump.MAJOR: self.version = SdkVersion(self.version.major + 1, 0) - version_is_clean = False - if version_is_clean: - print(f"API version {self.version} is up to date") - else: + if self._have_pending_entries(): self.new_entries.add(self.version) print( f"API version is still WIP: {self.version}. Review the changes and re-run command." @@ -418,16 +407,23 @@ class SdkCache: ) ) ) + else: + print(f"API version {self.version} is up to date") - if not version_is_clean or self.loaded_dirty_version: - # Regenerate cache file + regenerate_csv = ( + self.loaded_dirty_version + or self._have_pending_entries() + or self.version_action != VersionBump.NONE + ) + + if regenerate_csv: str_cache_entries = [self.version] name_getter = operator.attrgetter("name") str_cache_entries.extend(sorted(self.sdk.headers, key=name_getter)) str_cache_entries.extend(sorted(self.sdk.functions, key=name_getter)) str_cache_entries.extend(sorted(self.sdk.variables, key=name_getter)) - with open(self.cache_file_name, "w", newline="") as f: + with open(self.cache_file_name, "wt", newline="") as f: writer = csv.DictWriter(f, fieldnames=SdkCache.CSV_FIELD_NAMES) writer.writeheader() @@ -476,28 +472,37 @@ class SdkCache: f"Cannot load symbol cache '{self.cache_file_name}'! File does not exist" ) - with open(self.cache_file_name, "r") as f: + with open(self.cache_file_name, "rt") as f: reader = csv.DictReader(f) for row in reader: self._process_entry(row) if self._load_version_only and row.get("entry") == SdkVersion.csv_type: break - self.loaded_dirty = bool(self.new_entries) - def sync_sets(self, known_set: Set[Any], new_set: Set[Any]): + def _have_pending_entries(self) -> bool: + return any( + filter( + lambda e: not isinstance(e, SdkVersion), + self.new_entries, + ) + ) + + def sync_sets( + self, known_set: Set[Any], new_set: Set[Any], update_version: bool = True + ): new_entries = new_set - known_set if new_entries: print(f"New: {new_entries}") known_set |= new_entries self.new_entries |= new_entries - if self.version_action == VersionBump.NONE: + if update_version and self.version_action == VersionBump.NONE: self.version_action = VersionBump.MINOR removed_entries = known_set - new_set if removed_entries: print(f"Removed: {removed_entries}") known_set -= removed_entries - # If any of removed entries was part of active API, that's a major bump - if any( + # If any of removed entries was a part of active API, that's a major bump + if update_version and any( filter( lambda e: e not in self.disabled_entries and e not in self.new_entries, @@ -509,6 +514,6 @@ class SdkCache: self.new_entries -= removed_entries def validate_api(self, api: ApiEntries) -> None: - self.sync_sets(self.sdk.headers, api.headers) + self.sync_sets(self.sdk.headers, api.headers, False) self.sync_sets(self.sdk.functions, api.functions) self.sync_sets(self.sdk.variables, api.variables) diff --git a/site_scons/fbt/version.py b/site_scons/fbt/version.py index 4745c7002..1b1c166f2 100644 --- a/site_scons/fbt/version.py +++ b/site_scons/fbt/version.py @@ -1,7 +1,9 @@ import subprocess import datetime +from functools import cache +@cache def get_fast_git_version_id(): try: version = ( diff --git a/site_scons/site_tools/fbt_sdk.py b/site_scons/site_tools/fbt_sdk.py index 26d663650..f6c2d452e 100644 --- a/site_scons/site_tools/fbt_sdk.py +++ b/site_scons/site_tools/fbt_sdk.py @@ -15,6 +15,7 @@ from fbt.sdk import SdkCollector, SdkCache def prebuild_sdk_emitter(target, source, env): target.append(env.ChangeFileExtension(target[0], ".d")) + target.append(env.ChangeFileExtension(target[0], ".i.c")) return target, source From 3d3c422751c7be83297ec4d369851ce51902fe3d Mon Sep 17 00:00:00 2001 From: Astra <93453568+Astrrra@users.noreply.github.com> Date: Mon, 19 Sep 2022 15:46:56 +0300 Subject: [PATCH 3/6] [FL-2674] Show error popup when NFC chip is not init/disconnected (#1722) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Show error popup when NFC chip is not init/disconnected * Move to dialogs for the error message * Fix a memory leak and wrap the hal check * F7: update api_symbols.csv, add furi_hal_nfc_is_init Co-authored-by: SG Co-authored-by: あく --- applications/main/nfc/nfc.c | 23 +++++++++++++++++++ applications/main/nfc/nfc_i.h | 2 ++ firmware/targets/f7/api_symbols.csv | 3 ++- firmware/targets/f7/furi_hal/furi_hal_nfc.c | 4 ++++ .../targets/furi_hal_include/furi_hal_nfc.h | 6 +++++ 5 files changed, 37 insertions(+), 1 deletion(-) diff --git a/applications/main/nfc/nfc.c b/applications/main/nfc/nfc.c index 432630204..f47a5bac2 100644 --- a/applications/main/nfc/nfc.c +++ b/applications/main/nfc/nfc.c @@ -231,7 +231,30 @@ void nfc_show_loading_popup(void* context, bool show) { } } +static bool nfc_is_hal_ready() { + if(!furi_hal_nfc_is_init()) { + // No connection to the chip, show an error screen + DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS); + DialogMessage* message = dialog_message_alloc(); + dialog_message_set_text( + message, + "Error!\nNFC chip failed to start\n\n\nSend a photo of this to:\nsupport@flipperzero.one", + 0, + 0, + AlignLeft, + AlignTop); + dialog_message_show(dialogs, message); + dialog_message_free(message); + furi_record_close(RECORD_DIALOGS); + return false; + } else { + return true; + } +} + int32_t nfc_app(void* p) { + if(!nfc_is_hal_ready()) return 0; + Nfc* nfc = nfc_alloc(); char* args = p; diff --git a/applications/main/nfc/nfc_i.h b/applications/main/nfc/nfc_i.h index b5d284d5b..60e1c1997 100644 --- a/applications/main/nfc/nfc_i.h +++ b/applications/main/nfc/nfc_i.h @@ -33,6 +33,8 @@ #include #include +#include + #include "rpc/rpc_app.h" #define NFC_TEXT_STORE_SIZE 128 diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 3f2a86b24..906a7b8b6 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,1.3,, +Version,+,1.4,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -1096,6 +1096,7 @@ Function,+,furi_hal_nfc_field_off,void, Function,+,furi_hal_nfc_field_on,void, Function,-,furi_hal_nfc_init,void, Function,+,furi_hal_nfc_is_busy,_Bool, +Function,+,furi_hal_nfc_is_init,_Bool, Function,+,furi_hal_nfc_listen,_Bool,"uint8_t*, uint8_t, uint8_t*, uint8_t, _Bool, uint32_t" Function,+,furi_hal_nfc_listen_rx,_Bool,"FuriHalNfcTxRxContext*, uint32_t" Function,+,furi_hal_nfc_listen_sleep,void, diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc.c b/firmware/targets/f7/furi_hal/furi_hal_nfc.c index 1a5afa1ec..de67bbc35 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_nfc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_nfc.c @@ -39,6 +39,10 @@ bool furi_hal_nfc_is_busy() { return rfalNfcGetState() != RFAL_NFC_STATE_IDLE; } +bool furi_hal_nfc_is_init() { + return rfalNfcGetState() != RFAL_NFC_STATE_NOTINIT; +} + void furi_hal_nfc_field_on() { furi_hal_nfc_exit_sleep(); st25r3916TxRxOn(); diff --git a/firmware/targets/furi_hal_include/furi_hal_nfc.h b/firmware/targets/furi_hal_include/furi_hal_nfc.h index aa1c61d9c..537e0abf0 100644 --- a/firmware/targets/furi_hal_include/furi_hal_nfc.h +++ b/firmware/targets/furi_hal_include/furi_hal_nfc.h @@ -107,6 +107,12 @@ void furi_hal_nfc_init(); */ bool furi_hal_nfc_is_busy(); +/** Check if nfc is initialized + * + * @return true if initialized + */ + bool furi_hal_nfc_is_init(); + /** NFC field on */ void furi_hal_nfc_field_on(); From d80329b323440dbb9b2f7f3a3cdb0c2175e832c9 Mon Sep 17 00:00:00 2001 From: Nikolay Minaylov Date: Mon, 19 Sep 2022 16:03:42 +0300 Subject: [PATCH 4/6] [FL-2815, FL-2821] Dummy mode (#1739) * Dummy mode implementation * dumb -> dummy * F7: Add new api_symbols: game icon * Starting snake game from dummy mode Co-authored-by: Aleksandr Kutuzov --- .../main/archive/helpers/archive_browser.c | 8 +- applications/services/desktop/desktop.c | 46 +++++-- applications/services/desktop/desktop_i.h | 4 +- .../services/desktop/desktop_settings.h | 7 +- .../services/desktop/helpers/pin_lock.c | 6 +- .../desktop/scenes/desktop_scene_lock_menu.c | 21 ++- .../desktop/scenes/desktop_scene_locked.c | 4 +- .../desktop/scenes/desktop_scene_main.c | 19 ++- .../services/desktop/views/desktop_events.h | 7 +- .../desktop/views/desktop_view_lock_menu.c | 128 +++++++++++------- .../desktop/views/desktop_view_lock_menu.h | 7 +- .../desktop/views/desktop_view_main.c | 56 +++++--- .../desktop/views/desktop_view_main.h | 1 + .../desktop_settings/desktop_settings_app.c | 2 +- .../scenes/desktop_settings_scene_favorite.c | 2 +- .../scenes/desktop_settings_scene_pin_auth.c | 2 +- .../desktop_settings_scene_pin_disable.c | 2 +- .../desktop_settings_scene_pin_setup_done.c | 2 +- .../scenes/desktop_settings_scene_start.c | 2 +- assets/icons/StatusBar/GameMode_11x8.png | Bin 0 -> 3610 bytes firmware/targets/f7/api_symbols.csv | 3 +- 21 files changed, 216 insertions(+), 113 deletions(-) create mode 100644 assets/icons/StatusBar/GameMode_11x8.png diff --git a/applications/main/archive/helpers/archive_browser.c b/applications/main/archive/helpers/archive_browser.c index b08e58983..00bb6b063 100644 --- a/applications/main/archive/helpers/archive_browser.c +++ b/applications/main/archive/helpers/archive_browser.c @@ -270,7 +270,7 @@ void archive_file_array_load(ArchiveBrowserView* browser, int8_t dir) { ArchiveFile_t* archive_get_current_file(ArchiveBrowserView* browser) { furi_assert(browser); - ArchiveFile_t* selected; + ArchiveFile_t* selected = NULL; with_view_model( browser->view, (ArchiveBrowserViewModel * model) { selected = files_array_size(model->files) ? @@ -284,7 +284,7 @@ ArchiveFile_t* archive_get_current_file(ArchiveBrowserView* browser) { ArchiveFile_t* archive_get_file_at(ArchiveBrowserView* browser, size_t idx) { furi_assert(browser); - ArchiveFile_t* selected; + ArchiveFile_t* selected = NULL; with_view_model( browser->view, (ArchiveBrowserViewModel * model) { @@ -298,7 +298,7 @@ ArchiveFile_t* archive_get_file_at(ArchiveBrowserView* browser, size_t idx) { ArchiveTabEnum archive_get_tab(ArchiveBrowserView* browser) { furi_assert(browser); - ArchiveTabEnum tab_id; + ArchiveTabEnum tab_id = 0; with_view_model( browser->view, (ArchiveBrowserViewModel * model) { tab_id = model->tab_idx; @@ -451,8 +451,6 @@ void archive_switch_tab(ArchiveBrowserView* browser, InputKey key) { archive_file_browser_set_path( browser, browser->path, archive_get_tab_ext(tab), skip_assets); tab_empty = false; // Empty check will be performed later - } else { - tab_empty = true; } } diff --git a/applications/services/desktop/desktop.c b/applications/services/desktop/desktop.c index 578066a6a..b45a9d621 100644 --- a/applications/services/desktop/desktop.c +++ b/applications/services/desktop/desktop.c @@ -32,13 +32,18 @@ static void desktop_loader_callback(const void* message, void* context) { view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopGlobalAfterAppFinished); } } - -static void desktop_lock_icon_callback(Canvas* canvas, void* context) { +static void desktop_lock_icon_draw_callback(Canvas* canvas, void* context) { UNUSED(context); furi_assert(canvas); canvas_draw_icon(canvas, 0, 0, &I_Lock_8x8); } +static void desktop_dummy_mode_icon_draw_callback(Canvas* canvas, void* context) { + UNUSED(context); + furi_assert(canvas); + canvas_draw_icon(canvas, 0, 0, &I_GameMode_11x8); +} + static bool desktop_custom_event_callback(void* context, uint32_t event) { furi_assert(context); Desktop* desktop = (Desktop*)context; @@ -52,7 +57,7 @@ static bool desktop_custom_event_callback(void* context, uint32_t event) { animation_manager_load_and_continue_animation(desktop->animation_manager); // TODO: Implement a message mechanism for loading settings and (optionally) // locking and unlocking - LOAD_DESKTOP_SETTINGS(&desktop->settings); + DESKTOP_SETTINGS_LOAD(&desktop->settings); desktop_auto_lock_arm(desktop); return true; case DesktopGlobalAutoLock: @@ -127,7 +132,7 @@ void desktop_lock(Desktop* desktop) { } void desktop_unlock(Desktop* desktop) { - view_port_enabled_set(desktop->lock_viewport, false); + view_port_enabled_set(desktop->lock_icon_viewport, false); Gui* gui = furi_record_open(RECORD_GUI); gui_set_lockdown(gui, false); furi_record_close(RECORD_GUI); @@ -136,6 +141,13 @@ void desktop_unlock(Desktop* desktop) { desktop_auto_lock_arm(desktop); } +void desktop_set_dummy_mode_state(Desktop* desktop, bool enabled) { + view_port_enabled_set(desktop->dummy_mode_icon_viewport, enabled); + desktop_main_set_dummy_mode_state(desktop->main_view, enabled); + desktop->settings.dummy_mode = enabled; + DESKTOP_SETTINGS_SAVE(&desktop->settings); +} + Desktop* desktop_alloc() { Desktop* desktop = malloc(sizeof(Desktop)); @@ -212,11 +224,20 @@ Desktop* desktop_alloc() { desktop_view_slideshow_get_view(desktop->slideshow_view)); // Lock icon - desktop->lock_viewport = view_port_alloc(); - view_port_set_width(desktop->lock_viewport, icon_get_width(&I_Lock_8x8)); - view_port_draw_callback_set(desktop->lock_viewport, desktop_lock_icon_callback, desktop); - view_port_enabled_set(desktop->lock_viewport, false); - gui_add_view_port(desktop->gui, desktop->lock_viewport, GuiLayerStatusBarLeft); + desktop->lock_icon_viewport = view_port_alloc(); + view_port_set_width(desktop->lock_icon_viewport, icon_get_width(&I_Lock_8x8)); + view_port_draw_callback_set( + desktop->lock_icon_viewport, desktop_lock_icon_draw_callback, desktop); + view_port_enabled_set(desktop->lock_icon_viewport, false); + gui_add_view_port(desktop->gui, desktop->lock_icon_viewport, GuiLayerStatusBarLeft); + + // Dummy mode icon + desktop->dummy_mode_icon_viewport = view_port_alloc(); + view_port_set_width(desktop->dummy_mode_icon_viewport, icon_get_width(&I_GameMode_11x8)); + view_port_draw_callback_set( + desktop->dummy_mode_icon_viewport, desktop_dummy_mode_icon_draw_callback, desktop); + view_port_enabled_set(desktop->dummy_mode_icon_viewport, false); + gui_add_view_port(desktop->gui, desktop->dummy_mode_icon_viewport, GuiLayerStatusBarLeft); // Special case: autostart application is already running desktop->loader = furi_record_open(RECORD_LOADER); @@ -301,12 +322,15 @@ int32_t desktop_srv(void* p) { UNUSED(p); Desktop* desktop = desktop_alloc(); - bool loaded = LOAD_DESKTOP_SETTINGS(&desktop->settings); + bool loaded = DESKTOP_SETTINGS_LOAD(&desktop->settings); if(!loaded) { memset(&desktop->settings, 0, sizeof(desktop->settings)); - SAVE_DESKTOP_SETTINGS(&desktop->settings); + DESKTOP_SETTINGS_SAVE(&desktop->settings); } + view_port_enabled_set(desktop->dummy_mode_icon_viewport, desktop->settings.dummy_mode); + desktop_main_set_dummy_mode_state(desktop->main_view, desktop->settings.dummy_mode); + scene_manager_next_scene(desktop->scene_manager, DesktopSceneMain); desktop_pin_lock_init(&desktop->settings); diff --git a/applications/services/desktop/desktop_i.h b/applications/services/desktop/desktop_i.h index 65ca563dd..8034bbc3a 100644 --- a/applications/services/desktop/desktop_i.h +++ b/applications/services/desktop/desktop_i.h @@ -57,7 +57,8 @@ struct Desktop { DesktopSettings settings; DesktopViewPinInput* pin_input_view; - ViewPort* lock_viewport; + ViewPort* lock_icon_viewport; + ViewPort* dummy_mode_icon_viewport; AnimationManager* animation_manager; @@ -75,3 +76,4 @@ Desktop* desktop_alloc(); void desktop_free(Desktop* desktop); void desktop_lock(Desktop* desktop); void desktop_unlock(Desktop* desktop); +void desktop_set_dummy_mode_state(Desktop* desktop, bool enabled); diff --git a/applications/services/desktop/desktop_settings.h b/applications/services/desktop/desktop_settings.h index 800847d56..3b10fbb17 100644 --- a/applications/services/desktop/desktop_settings.h +++ b/applications/services/desktop/desktop_settings.h @@ -8,7 +8,7 @@ #include #include -#define DESKTOP_SETTINGS_VER (4) +#define DESKTOP_SETTINGS_VER (5) #define DESKTOP_SETTINGS_PATH INT_PATH(DESKTOP_SETTINGS_FILE_NAME) #define DESKTOP_SETTINGS_MAGIC (0x17) @@ -16,7 +16,7 @@ #define DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG "run_pin_setup" -#define SAVE_DESKTOP_SETTINGS(x) \ +#define DESKTOP_SETTINGS_SAVE(x) \ saved_struct_save( \ DESKTOP_SETTINGS_PATH, \ (x), \ @@ -24,7 +24,7 @@ DESKTOP_SETTINGS_MAGIC, \ DESKTOP_SETTINGS_VER) -#define LOAD_DESKTOP_SETTINGS(x) \ +#define DESKTOP_SETTINGS_LOAD(x) \ saved_struct_load( \ DESKTOP_SETTINGS_PATH, \ (x), \ @@ -46,4 +46,5 @@ typedef struct { PinCode pin_code; uint8_t is_locked; uint32_t auto_lock_delay_ms; + uint8_t dummy_mode; } DesktopSettings; diff --git a/applications/services/desktop/helpers/pin_lock.c b/applications/services/desktop/helpers/pin_lock.c index 9e17a9250..22fcabe7d 100644 --- a/applications/services/desktop/helpers/pin_lock.c +++ b/applications/services/desktop/helpers/pin_lock.c @@ -72,7 +72,7 @@ void desktop_pin_lock(DesktopSettings* settings) { cli_session_close(cli); furi_record_close(RECORD_CLI); settings->is_locked = 1; - SAVE_DESKTOP_SETTINGS(settings); + DESKTOP_SETTINGS_SAVE(settings); } void desktop_pin_unlock(DesktopSettings* settings) { @@ -83,7 +83,7 @@ void desktop_pin_unlock(DesktopSettings* settings) { cli_session_open(cli, &cli_vcp); furi_record_close(RECORD_CLI); settings->is_locked = 0; - SAVE_DESKTOP_SETTINGS(settings); + DESKTOP_SETTINGS_SAVE(settings); } void desktop_pin_lock_init(DesktopSettings* settings) { @@ -95,7 +95,7 @@ void desktop_pin_lock_init(DesktopSettings* settings) { } else { if(desktop_pin_lock_is_locked()) { settings->is_locked = 1; - SAVE_DESKTOP_SETTINGS(settings); + DESKTOP_SETTINGS_SAVE(settings); } } } else { diff --git a/applications/services/desktop/scenes/desktop_scene_lock_menu.c b/applications/services/desktop/scenes/desktop_scene_lock_menu.c index bdd84cadb..365fe1702 100644 --- a/applications/services/desktop/scenes/desktop_scene_lock_menu.c +++ b/applications/services/desktop/scenes/desktop_scene_lock_menu.c @@ -22,10 +22,11 @@ void desktop_scene_lock_menu_callback(DesktopEvent event, void* context) { void desktop_scene_lock_menu_on_enter(void* context) { Desktop* desktop = (Desktop*)context; - LOAD_DESKTOP_SETTINGS(&desktop->settings); + DESKTOP_SETTINGS_LOAD(&desktop->settings); scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0); desktop_lock_menu_set_callback(desktop->lock_menu, desktop_scene_lock_menu_callback, desktop); - desktop_lock_menu_pin_set(desktop->lock_menu, desktop->settings.pin_code.length > 0); + desktop_lock_menu_set_pin_state(desktop->lock_menu, desktop->settings.pin_code.length > 0); + desktop_lock_menu_set_dummy_mode_state(desktop->lock_menu, desktop->settings.dummy_mode); desktop_lock_menu_set_idx(desktop->lock_menu, 0); view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdLockMenu); @@ -39,9 +40,9 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) { bool check_pin_changed = scene_manager_get_scene_state(desktop->scene_manager, DesktopSceneLockMenu); if(check_pin_changed) { - LOAD_DESKTOP_SETTINGS(&desktop->settings); + DESKTOP_SETTINGS_LOAD(&desktop->settings); if(desktop->settings.pin_code.length > 0) { - desktop_lock_menu_pin_set(desktop->lock_menu, 1); + desktop_lock_menu_set_pin_state(desktop->lock_menu, true); scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0); } } @@ -67,15 +68,21 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) { } consumed = true; break; - case DesktopLockMenuEventExit: - scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0); + case DesktopLockMenuEventDummyModeOn: + desktop_set_dummy_mode_state(desktop, true); + scene_manager_search_and_switch_to_previous_scene( + desktop->scene_manager, DesktopSceneMain); + break; + case DesktopLockMenuEventDummyModeOff: + desktop_set_dummy_mode_state(desktop, false); scene_manager_search_and_switch_to_previous_scene( desktop->scene_manager, DesktopSceneMain); - consumed = true; break; default: break; } + } else if(event.type == SceneManagerEventTypeBack) { + scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 0); } return consumed; } diff --git a/applications/services/desktop/scenes/desktop_scene_locked.c b/applications/services/desktop/scenes/desktop_scene_locked.c index c377d40ab..af19efc74 100644 --- a/applications/services/desktop/scenes/desktop_scene_locked.c +++ b/applications/services/desktop/scenes/desktop_scene_locked.c @@ -46,13 +46,13 @@ void desktop_scene_locked_on_enter(void* context) { uint32_t state = scene_manager_get_scene_state(desktop->scene_manager, DesktopSceneLocked); if(state == SCENE_LOCKED_FIRST_ENTER) { bool pin_locked = desktop_pin_lock_is_locked(); - view_port_enabled_set(desktop->lock_viewport, true); + view_port_enabled_set(desktop->lock_icon_viewport, true); Gui* gui = furi_record_open(RECORD_GUI); gui_set_lockdown(gui, true); furi_record_close(RECORD_GUI); if(pin_locked) { - LOAD_DESKTOP_SETTINGS(&desktop->settings); + DESKTOP_SETTINGS_LOAD(&desktop->settings); desktop_view_locked_lock(desktop->locked_view, true); uint32_t pin_timeout = desktop_pin_lock_get_fail_timeout(); if(pin_timeout > 0) { diff --git a/applications/services/desktop/scenes/desktop_scene_main.c b/applications/services/desktop/scenes/desktop_scene_main.c index bc4101ffd..dc9ac04d0 100644 --- a/applications/services/desktop/scenes/desktop_scene_main.c +++ b/applications/services/desktop/scenes/desktop_scene_main.c @@ -113,7 +113,7 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { } case DesktopMainEventOpenFavoritePrimary: - LOAD_DESKTOP_SETTINGS(&desktop->settings); + DESKTOP_SETTINGS_LOAD(&desktop->settings); if(desktop->settings.favorite_primary < FLIPPER_APPS_COUNT) { LoaderStatus status = loader_start( desktop->loader, FLIPPER_APPS[desktop->settings.favorite_primary].name, NULL); @@ -126,7 +126,7 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { consumed = true; break; case DesktopMainEventOpenFavoriteSecondary: - LOAD_DESKTOP_SETTINGS(&desktop->settings); + DESKTOP_SETTINGS_LOAD(&desktop->settings); if(desktop->settings.favorite_secondary < FLIPPER_APPS_COUNT) { LoaderStatus status = loader_start( desktop->loader, @@ -157,6 +157,21 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { } consumed = true; break; + case DesktopMainEventOpenPassport: { + LoaderStatus status = loader_start(desktop->loader, "Passport", NULL); + if(status != LoaderStatusOk) { + FURI_LOG_E(TAG, "loader_start failed: %d", status); + } + break; + } + case DesktopMainEventOpenGameMenu: { + LoaderStatus status = loader_start( + desktop->loader, "Applications", EXT_PATH("/apps/Games/snake_game.fap")); + if(status != LoaderStatusOk) { + FURI_LOG_E(TAG, "loader_start failed: %d", status); + } + break; + } case DesktopLockedEventUpdate: desktop_view_locked_update(desktop->locked_view); consumed = true; diff --git a/applications/services/desktop/views/desktop_events.h b/applications/services/desktop/views/desktop_events.h index 5d130be9b..a7e610fff 100644 --- a/applications/services/desktop/views/desktop_events.h +++ b/applications/services/desktop/views/desktop_events.h @@ -7,9 +7,11 @@ typedef enum { DesktopMainEventOpenFavoriteSecondary, DesktopMainEventOpenMenu, DesktopMainEventOpenDebug, - DesktopMainEventOpenPassport, /**< Broken, don't use it */ + DesktopMainEventOpenPassport, DesktopMainEventOpenPowerOff, + DesktopMainEventOpenGameMenu, + DesktopLockedEventUnlocked, DesktopLockedEventUpdate, DesktopLockedEventShowPinInput, @@ -28,7 +30,8 @@ typedef enum { DesktopLockMenuEventLock, DesktopLockMenuEventPinLock, - DesktopLockMenuEventExit, + DesktopLockMenuEventDummyModeOn, + DesktopLockMenuEventDummyModeOff, DesktopAnimationEventCheckAnimation, DesktopAnimationEventNewIdleAnimation, diff --git a/applications/services/desktop/views/desktop_view_lock_menu.c b/applications/services/desktop/views/desktop_view_lock_menu.c index 97d3c4898..294191bf2 100644 --- a/applications/services/desktop/views/desktop_view_lock_menu.c +++ b/applications/services/desktop/views/desktop_view_lock_menu.c @@ -4,7 +4,13 @@ #include "../desktop_i.h" #include "desktop_view_lock_menu.h" -#define LOCK_MENU_ITEMS_NB 3 +typedef enum { + DesktopLockMenuIndexLock, + DesktopLockMenuIndexPinLock, + DesktopLockMenuIndexDummy, + + DesktopLockMenuIndexTotalCount +} DesktopLockMenuIndex; void desktop_lock_menu_set_callback( DesktopLockMenuView* lock_menu, @@ -16,16 +22,24 @@ void desktop_lock_menu_set_callback( lock_menu->context = context; } -void desktop_lock_menu_pin_set(DesktopLockMenuView* lock_menu, bool pin_is_set) { +void desktop_lock_menu_set_pin_state(DesktopLockMenuView* lock_menu, bool pin_is_set) { with_view_model( lock_menu->view, (DesktopLockMenuViewModel * model) { - model->pin_set = pin_is_set; + model->pin_is_set = pin_is_set; + return true; + }); +} + +void desktop_lock_menu_set_dummy_mode_state(DesktopLockMenuView* lock_menu, bool dummy_mode) { + with_view_model( + lock_menu->view, (DesktopLockMenuViewModel * model) { + model->dummy_mode = dummy_mode; return true; }); } void desktop_lock_menu_set_idx(DesktopLockMenuView* lock_menu, uint8_t idx) { - furi_assert(idx < LOCK_MENU_ITEMS_NB); + furi_assert(idx < DesktopLockMenuIndexTotalCount); with_view_model( lock_menu->view, (DesktopLockMenuViewModel * model) { model->idx = idx; @@ -33,43 +47,34 @@ void desktop_lock_menu_set_idx(DesktopLockMenuView* lock_menu, uint8_t idx) { }); } -static void lock_menu_callback(void* context, uint8_t index) { - furi_assert(context); - DesktopLockMenuView* lock_menu = context; - switch(index) { - case 0: // lock - lock_menu->callback(DesktopLockMenuEventLock, lock_menu->context); - break; - case 1: // lock - lock_menu->callback(DesktopLockMenuEventPinLock, lock_menu->context); - break; - default: // wip message - with_view_model( - lock_menu->view, (DesktopLockMenuViewModel * model) { - model->hint_timeout = HINT_TIMEOUT; - return true; - }); - break; - } -} - -void desktop_lock_menu_render(Canvas* canvas, void* model) { - const char* Lockmenu_Items[LOCK_MENU_ITEMS_NB] = {"Lock", "Lock with PIN", "DUMB mode"}; - +void desktop_lock_menu_draw_callback(Canvas* canvas, void* model) { DesktopLockMenuViewModel* m = model; - canvas_clear(canvas); + canvas_set_color(canvas, ColorBlack); canvas_draw_icon(canvas, -57, 0 + STATUS_BAR_Y_SHIFT, &I_DoorLeft_70x55); canvas_draw_icon(canvas, 116, 0 + STATUS_BAR_Y_SHIFT, &I_DoorRight_70x55); canvas_set_font(canvas, FontSecondary); - for(uint8_t i = 0; i < LOCK_MENU_ITEMS_NB; ++i) { - const char* str = Lockmenu_Items[i]; + for(uint8_t i = 0; i < DesktopLockMenuIndexTotalCount; ++i) { + const char* str = NULL; - if(i == 1 && !m->pin_set) str = "Set PIN"; - if(m->hint_timeout && m->idx == 2 && m->idx == i) str = "Not Implemented"; + if(i == DesktopLockMenuIndexLock) { + str = "Lock"; + } else if(i == DesktopLockMenuIndexPinLock) { + if(m->pin_is_set) { + str = "Lock with PIN"; + } else { + str = "Set PIN"; + } + } else if(i == DesktopLockMenuIndexDummy) { + if(m->dummy_mode) { + str = "Brainiac Mode"; + } else { + str = "Dummy Mode"; + } + } - if(str != NULL) + if(str) canvas_draw_str_aligned( canvas, 64, 9 + (i * 17) + STATUS_BAR_Y_SHIFT, AlignCenter, AlignCenter, str); @@ -82,33 +87,58 @@ View* desktop_lock_menu_get_view(DesktopLockMenuView* lock_menu) { return lock_menu->view; } -bool desktop_lock_menu_input(InputEvent* event, void* context) { +bool desktop_lock_menu_input_callback(InputEvent* event, void* context) { furi_assert(event); furi_assert(context); DesktopLockMenuView* lock_menu = context; - uint8_t idx; + uint8_t idx = 0; + bool consumed = false; + bool dummy_mode = false; - if(event->type != InputTypeShort) return false; with_view_model( lock_menu->view, (DesktopLockMenuViewModel * model) { - model->hint_timeout = 0; // clear hint timeout - if(event->key == InputKeyUp) { - model->idx = CLAMP(model->idx - 1, LOCK_MENU_ITEMS_NB - 1, 0); - } else if(event->key == InputKeyDown) { - model->idx = CLAMP(model->idx + 1, LOCK_MENU_ITEMS_NB - 1, 0); + bool ret = false; + if((event->type == InputTypeShort) || (event->type == InputTypeRepeat)) { + if(event->key == InputKeyUp) { + if(model->idx == 0) { + model->idx = DesktopLockMenuIndexTotalCount - 1; + } else { + model->idx = CLAMP(model->idx - 1, DesktopLockMenuIndexTotalCount - 1, 0); + } + ret = true; + consumed = true; + } else if(event->key == InputKeyDown) { + if(model->idx == DesktopLockMenuIndexTotalCount - 1) { + model->idx = 0; + } else { + model->idx = CLAMP(model->idx + 1, DesktopLockMenuIndexTotalCount - 1, 0); + } + ret = true; + consumed = true; + } } idx = model->idx; - return true; + dummy_mode = model->dummy_mode; + return ret; }); - if(event->key == InputKeyBack) { - lock_menu->callback(DesktopLockMenuEventExit, lock_menu->context); - } else if(event->key == InputKeyOk) { - lock_menu_callback(lock_menu, idx); + if(event->key == InputKeyOk) { + if((idx == DesktopLockMenuIndexLock) && (event->type == InputTypeShort)) { + lock_menu->callback(DesktopLockMenuEventLock, lock_menu->context); + } else if((idx == DesktopLockMenuIndexPinLock) && (event->type == InputTypeShort)) { + lock_menu->callback(DesktopLockMenuEventPinLock, lock_menu->context); + } else if(idx == DesktopLockMenuIndexDummy) { + if((dummy_mode == false) && (event->type == InputTypeShort)) { + lock_menu->callback(DesktopLockMenuEventDummyModeOn, lock_menu->context); + } else if((dummy_mode == true) && (event->type == InputTypeShort)) { + lock_menu->callback(DesktopLockMenuEventDummyModeOff, lock_menu->context); + } + } + consumed = true; } - return true; + return consumed; } DesktopLockMenuView* desktop_lock_menu_alloc() { @@ -116,8 +146,8 @@ DesktopLockMenuView* desktop_lock_menu_alloc() { lock_menu->view = view_alloc(); view_allocate_model(lock_menu->view, ViewModelTypeLocking, sizeof(DesktopLockMenuViewModel)); view_set_context(lock_menu->view, lock_menu); - view_set_draw_callback(lock_menu->view, (ViewDrawCallback)desktop_lock_menu_render); - view_set_input_callback(lock_menu->view, desktop_lock_menu_input); + view_set_draw_callback(lock_menu->view, (ViewDrawCallback)desktop_lock_menu_draw_callback); + view_set_input_callback(lock_menu->view, desktop_lock_menu_input_callback); return lock_menu; } diff --git a/applications/services/desktop/views/desktop_view_lock_menu.h b/applications/services/desktop/views/desktop_view_lock_menu.h index e9928a385..812aa9f99 100644 --- a/applications/services/desktop/views/desktop_view_lock_menu.h +++ b/applications/services/desktop/views/desktop_view_lock_menu.h @@ -17,8 +17,8 @@ struct DesktopLockMenuView { typedef struct { uint8_t idx; - uint8_t hint_timeout; - bool pin_set; + bool pin_is_set; + bool dummy_mode; } DesktopLockMenuViewModel; void desktop_lock_menu_set_callback( @@ -27,7 +27,8 @@ void desktop_lock_menu_set_callback( void* context); View* desktop_lock_menu_get_view(DesktopLockMenuView* lock_menu); -void desktop_lock_menu_pin_set(DesktopLockMenuView* lock_menu, bool pin_is_set); +void desktop_lock_menu_set_pin_state(DesktopLockMenuView* lock_menu, bool pin_is_set); +void desktop_lock_menu_set_dummy_mode_state(DesktopLockMenuView* lock_menu, bool dummy_mode); void desktop_lock_menu_set_idx(DesktopLockMenuView* lock_menu, uint8_t idx); DesktopLockMenuView* desktop_lock_menu_alloc(); void desktop_lock_menu_free(DesktopLockMenuView* lock_menu); diff --git a/applications/services/desktop/views/desktop_view_main.c b/applications/services/desktop/views/desktop_view_main.c index 2b1d61f41..0edc0b703 100644 --- a/applications/services/desktop/views/desktop_view_main.c +++ b/applications/services/desktop/views/desktop_view_main.c @@ -14,6 +14,7 @@ struct DesktopMainView { DesktopMainViewCallback callback; void* context; TimerHandle_t poweroff_timer; + bool dummy_mode; }; #define DESKTOP_MAIN_VIEW_POWEROFF_TIMEOUT 5000 @@ -38,29 +39,48 @@ View* desktop_main_get_view(DesktopMainView* main_view) { return main_view->view; } -bool desktop_main_input(InputEvent* event, void* context) { +void desktop_main_set_dummy_mode_state(DesktopMainView* main_view, bool dummy_mode) { + furi_assert(main_view); + main_view->dummy_mode = dummy_mode; +} + +bool desktop_main_input_callback(InputEvent* event, void* context) { furi_assert(event); furi_assert(context); DesktopMainView* main_view = context; - if(event->type == InputTypeShort) { - if(event->key == InputKeyOk) { - main_view->callback(DesktopMainEventOpenMenu, main_view->context); - } else if(event->key == InputKeyUp) { - main_view->callback(DesktopMainEventOpenLockMenu, main_view->context); - } else if(event->key == InputKeyDown) { - main_view->callback(DesktopMainEventOpenArchive, main_view->context); - } else if(event->key == InputKeyLeft) { - main_view->callback(DesktopMainEventOpenFavoritePrimary, main_view->context); - } else if(event->key == InputKeyRight) { - main_view->callback(DesktopMainEventOpenPassport, main_view->context); + if(main_view->dummy_mode == false) { + if(event->type == InputTypeShort) { + if(event->key == InputKeyOk) { + main_view->callback(DesktopMainEventOpenMenu, main_view->context); + } else if(event->key == InputKeyUp) { + main_view->callback(DesktopMainEventOpenLockMenu, main_view->context); + } else if(event->key == InputKeyDown) { + main_view->callback(DesktopMainEventOpenArchive, main_view->context); + } else if(event->key == InputKeyLeft) { + main_view->callback(DesktopMainEventOpenFavoritePrimary, main_view->context); + } + // Right key is handled by animation manager + } else if(event->type == InputTypeLong) { + if(event->key == InputKeyDown) { + main_view->callback(DesktopMainEventOpenDebug, main_view->context); + } else if(event->key == InputKeyLeft) { + main_view->callback(DesktopMainEventOpenFavoriteSecondary, main_view->context); + } } - } else if(event->type == InputTypeLong) { - if(event->key == InputKeyDown) { - main_view->callback(DesktopMainEventOpenDebug, main_view->context); - } else if(event->key == InputKeyLeft) { - main_view->callback(DesktopMainEventOpenFavoriteSecondary, main_view->context); + } else { + if(event->type == InputTypeShort) { + if(event->key == InputKeyOk) { + main_view->callback(DesktopMainEventOpenGameMenu, main_view->context); + } else if(event->key == InputKeyUp) { + main_view->callback(DesktopMainEventOpenLockMenu, main_view->context); + } else if(event->key == InputKeyDown) { + main_view->callback(DesktopMainEventOpenPassport, main_view->context); + } else if(event->key == InputKeyLeft) { + main_view->callback(DesktopMainEventOpenPassport, main_view->context); + } + // Right key is handled by animation manager } } @@ -84,7 +104,7 @@ DesktopMainView* desktop_main_alloc() { main_view->view = view_alloc(); view_allocate_model(main_view->view, ViewModelTypeLockFree, 1); view_set_context(main_view->view, main_view); - view_set_input_callback(main_view->view, desktop_main_input); + view_set_input_callback(main_view->view, desktop_main_input_callback); main_view->poweroff_timer = xTimerCreate( NULL, diff --git a/applications/services/desktop/views/desktop_view_main.h b/applications/services/desktop/views/desktop_view_main.h index 329d95486..b5492b1be 100644 --- a/applications/services/desktop/views/desktop_view_main.h +++ b/applications/services/desktop/views/desktop_view_main.h @@ -13,5 +13,6 @@ void desktop_main_set_callback( void* context); View* desktop_main_get_view(DesktopMainView* main_view); +void desktop_main_set_dummy_mode_state(DesktopMainView* main_view, bool dummy_mode); DesktopMainView* desktop_main_alloc(); void desktop_main_free(DesktopMainView* main_view); diff --git a/applications/settings/desktop_settings/desktop_settings_app.c b/applications/settings/desktop_settings/desktop_settings_app.c index 2b9593590..a2ed8b724 100644 --- a/applications/settings/desktop_settings/desktop_settings_app.c +++ b/applications/settings/desktop_settings/desktop_settings_app.c @@ -89,7 +89,7 @@ void desktop_settings_app_free(DesktopSettingsApp* app) { extern int32_t desktop_settings_app(void* p) { DesktopSettingsApp* app = desktop_settings_app_alloc(); - LOAD_DESKTOP_SETTINGS(&app->settings); + DESKTOP_SETTINGS_LOAD(&app->settings); if(p && (strcmp(p, DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG) == 0)) { scene_manager_next_scene(app->scene_manager, DesktopSettingsAppScenePinSetupHowto); } else { diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c index 0ec18af7a..d8c579b3e 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_favorite.c @@ -56,6 +56,6 @@ bool desktop_settings_scene_favorite_on_event(void* context, SceneManagerEvent e void desktop_settings_scene_favorite_on_exit(void* context) { DesktopSettingsApp* app = context; - SAVE_DESKTOP_SETTINGS(&app->settings); + DESKTOP_SETTINGS_SAVE(&app->settings); submenu_reset(app->submenu); } diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_auth.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_auth.c index ce191487d..5fed235ce 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_auth.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_auth.c @@ -33,7 +33,7 @@ static void pin_auth_back_callback(void* context) { void desktop_settings_scene_pin_auth_on_enter(void* context) { DesktopSettingsApp* app = context; - LOAD_DESKTOP_SETTINGS(&app->settings); + DESKTOP_SETTINGS_LOAD(&app->settings); furi_assert(app->settings.pin_code.length > 0); desktop_view_pin_input_set_context(app->pin_input_view, app); diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_disable.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_disable.c index dcbba5df0..7fbcc3252 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_disable.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_disable.c @@ -20,7 +20,7 @@ void desktop_settings_scene_pin_disable_on_enter(void* context) { DesktopSettingsApp* app = context; app->settings.pin_code.length = 0; memset(app->settings.pin_code.data, '0', sizeof(app->settings.pin_code.data)); - SAVE_DESKTOP_SETTINGS(&app->settings); + DESKTOP_SETTINGS_SAVE(&app->settings); popup_set_context(app->popup, app); popup_set_callback(app->popup, pin_disable_back_callback); diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_done.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_done.c index b2d07e99f..f6ceb96de 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_done.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_pin_setup_done.c @@ -24,7 +24,7 @@ void desktop_settings_scene_pin_setup_done_on_enter(void* context) { DesktopSettingsApp* app = context; app->settings.pin_code = app->pincode_buffer; - SAVE_DESKTOP_SETTINGS(&app->settings); + DESKTOP_SETTINGS_SAVE(&app->settings); NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION); notification_message(notification, &sequence_single_vibro); furi_record_close(RECORD_NOTIFICATION); diff --git a/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c index 8e649c695..8530a1a7d 100644 --- a/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c +++ b/applications/settings/desktop_settings/scenes/desktop_settings_scene_start.c @@ -96,5 +96,5 @@ bool desktop_settings_scene_start_on_event(void* context, SceneManagerEvent even void desktop_settings_scene_start_on_exit(void* context) { DesktopSettingsApp* app = context; variable_item_list_reset(app->variable_item_list); - SAVE_DESKTOP_SETTINGS(&app->settings); + DESKTOP_SETTINGS_SAVE(&app->settings); } diff --git a/assets/icons/StatusBar/GameMode_11x8.png b/assets/icons/StatusBar/GameMode_11x8.png new file mode 100644 index 0000000000000000000000000000000000000000..49f2e25bf32025b68f659fb354abe59d61ba2235 GIT binary patch literal 3610 zcmaJ@c{o&U8$Y%hM3P-HjcCIxmY9rv8AYbCjY^C$7|hZb%m``GCR?_w2_-eODUz)s zG?plmB|8a?C1mXz@Avk8-ydJ!xz0Jy{oK#}``zogu5%T0)JjZ5K?DE*F>ACrmbZ%X z9uP=?_m&%-F9QG(Gm@DZ#@fsbOrul1Nd80sV0LBN2jdbJWeockiCdjaJEtF~_@4tH zDr``_giDUZ4FG>pLejW4@`{L)l=QX?v}4Wrb`f;umBH-2rQRmjt{jhYJgN6xxhMZw zSO|A&YUR^P`B=u-YBQ^4Ys5B5wfNB-UqBxlX@KlhjL~&w0)Rg&)D!~T7Xv1LSQ`ofodpR!vOs6fjsg%6%?G6Jwc5>Z{1R|?Jcm{1uYL_= zvyCB|g4IQQ5iZXWR{RkaLO@UqE^e!_I}nj-s@@2I_4om^o!grPz%~Neu(qoH0ykP@ zDVh(c<|H+x9BI>%DouK?5Ij5GKe%h~wf|#NyzD*+FX3TGMoPNMcJ!ElP4gB2P*`ex zwXSCrH#RyvFzPkt&;3!Gv+g%dg&6Ld>02+q&Myc^9Btutxs8l;2+->I9tBqU6`TON zoB*G`C0DI(;q2og??aZNSbD3*JF{+M>J5~3h=__#se0V5fDJ_%{?Zzt_D6*;@J`pe zL#Bb#X~wCA)wvhePU9&-Mc9}zj-V-=vN)!)UKe?GEoNWqp!VaF>eAO{a92w)5ZgM| z3v9gku7;#R$?>y@8Rg_P;e=o@fPKlX`snk`&p7_o;otfAqr`D-L4a}ioW^wp(Re_@ zTN}Yz1b~F9rC8$wd_Yr5-Vgwkf0a9VFHzR!EeHV2v(N2+WU_h7D=Buhc*ZNG@@iRr z{3dhbExW4?BuqCAN9+)}EthN}?@*2G6nyqbKp}fu+JHpyE4ZH6Sij`Sa}zY#P4048 zujR@w2@9IkgSO*$A+K!ni0OnhgJe@<1R;2|_Kk=<@c0#}W02Z_VwtB7H3Z8iG$uWVC{DH^9_p3MswK^HX2u{Z-R)?U3I~XLbSe=FEf_C#q zMQoo0ow_LT+W&l9oE6RnXLe6@Ql(h34CE|);UfI?9!SDHyJFQ4$)y^m2l8%iS*oY@h;MgGK<^fBxG{WGWS43j!dleY58aK{$g|HgY?B~m*r-j!ksH1YgPugN z!71@2aa-f;ZmcxC87`4R)?OL35zg6-%}bO#tV1*!5xjE?VVatK|5#H&)<@9&E67{N zt;yLz7^wZ_g6-OYX{t@>GG?4SjokM4X(Vsbq7QVOQ6}7bVW&mP`;<1nubaom#xMK` z-XeBM>_Q#dW3RlQ{2BRtxe|G3s?A-Y4=Jhj4zN!M#Z>Q`TW?Ywar+nchf2r4lT1P; zIVFWBjoo)}3~)4RXWbWdc;LA8!6~P(yOxemF+&ByA7vi27brQtEYK}##s*_!F)hd3 zax2}|&My161{a+-Jg#J27@IiWs5?r`?UC_1Na zNk^u0p5H4>FRTelC-+GWO2zJL+c$4d>4HzLPKr#XO>UafU%)S@E|3>mlp1$PDs>!U z915i~0vm(;Y2_1n1KMv2Y6{+rJ9{g7-ww!}(~-S52`mZ%|y5AJdDt!PAXHnfdAYujk^%pr?XP zxtv<5*lG7PLoKTVMy~I!IniIiIpdBrL=l&p#{~@E8uH%?xplenZY87-RjCr*5uO^p zc{OY0&@yK&_Gi@qYgT6FsE|9~E4~rFigOC*o(lL0C<~?v-r1}p6fN{}6LgEAwCNUM zF&AZe0<~IpR&j}-)#I(6)++rDlqr2&aT(UAX0x+nTg;^vP@hCN_3o0*c;j=>m3}M# zE2YXL`Bd4ZFsXg}5%)E}9V@nHoMtSlcd&W?~Djzc|$G`grGc|CoQ8R>p9eLo$OgyyFYI<@4#!8v2PDi5aHgT2sp=Z@Kd^Um5y1&IwDO3{zwF9_23Bu_`KZ%X?Kr?dNIlib)e_PwH?k1R_^ z2c3_)wTI5L$X#7u4wt-}nm|wFO;Fg2E>#Z?SNNK=zrQpsR;V}=J)-DFKKzAoJH&TB zrm48;U6X(gUT5k=<8yZR>}}oLg^n>bni z>;Ti*ufig1p3?UHd~d9RhhkaPXn1d_Rj^%cR_vKOXErZba3_2jRR5lbRaH-f$ynX! zooFO&Bt3%Kl|Gdg{ET*dzxZpDkym^A?uMQj!hF5m{HEtkQ(x-Yl6lYsnsuNJSry3E z$R%f^ZdY)>UeC=`I;CV)S@J8K3m+l`*6GALXJu#ZMa?V?pHCRd_sq}AJZgmcnA*cy zv{_B{b3Nu-;ceEEWhBe^Zd2m6*f95HEY@|poc05<=+UiOa-V$ak9_ z*N|A|!_~^JwQrl3w|+ZYy#AP2P455cUhUrU#$_v4T=;UjxfZ)Txp?yeR#cZYFHxn+HI70Ri5SB=*(bFIsSy8QQci-u#N>#NYki*qXx`l{P_ zf0gnK3mn6q>ct4g(}{qIC)I-pwkG4fiC7}ulXbd*XaE2Ldr1yB2F}(7NuZK7@f$Xp zOfrp!1^@#iCJj&UBQn4qL~jxW1>wG|f`Cb$D2TI;EzFi?M)V<}L+C{NkfRQS5I=&x zC&b7QY`{eF2*^YR9?T^BQv#4o6yz^nBv0N@Lm}Y5Oc;JB$iIWa*kKtN%-P`H)`0)d3Vc{lj)3&L|q_w+(y%`N|S$J?PG zJ`4s8355m+2WtjvX;SIlP`JLnJ`{$4A`lup3ylC4g@I>kPy$qbGnf+t2y_ySL84N? z8;p1lY9Ipz;RXBeEXcHfXej}ISBh6NC=*YE!Zl$VS^YM&wf+C5Wb!}O0SqkhKk@!g z;s6I0jR?gO1E_&?0zSJ9o0uTX5teYcg}EL~&&0wMp`)Xv z1&3+r>iou-it7=^wEh13{+oJew2gq#&ZFC7ntJ|CKe8^ygUg{>b+? z*7MJ?=>HK5?`nQTVKpWye!^_+JGyX&hZ|3Q|;XVW!{Koq*HeqZWEO_g$ zU%&2rzSYZ<_E?*nI54|B+y(hI?QH-Au4A?gAxs73{5Ww2vsCkj8`}uzXbDL5P literal 0 HcmV?d00001 diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 906a7b8b6..1f0490344 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,1.4,, +Version,+,1.5,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -2603,6 +2603,7 @@ Variable,+,I_FaceCharging_29x14,const Icon, Variable,+,I_FaceConfused_29x14,const Icon, Variable,+,I_FaceNopower_29x14,const Icon, Variable,+,I_FaceNormal_29x14,const Icon, +Variable,+,I_GameMode_11x8,const Icon, Variable,+,I_Health_16x16,const Icon, Variable,+,I_InfraredArrowDown_4x8,const Icon, Variable,+,I_InfraredArrowUp_4x8,const Icon, From fb476c29e6c042eaafbc0d796802a0ebffe797b8 Mon Sep 17 00:00:00 2001 From: Nikolay Minaylov Date: Mon, 19 Sep 2022 16:21:40 +0300 Subject: [PATCH 5/6] RFID: fix read info screen (#1723) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * RFID: fix read info screen * Fix line break for long data string * Protocol data redecoding before write Co-authored-by: SG Co-authored-by: あく --- .../main/lfrfid/scenes/lfrfid_scene_read_success.c | 11 +++++------ lib/lfrfid/protocols/protocol_awid.c | 4 ++++ lib/lfrfid/protocols/protocol_em4100.c | 8 ++++++++ lib/lfrfid/protocols/protocol_fdx_a.c | 4 ++++ lib/lfrfid/protocols/protocol_fdx_b.c | 4 ++++ lib/lfrfid/protocols/protocol_gallagher.c | 4 ++++ lib/lfrfid/protocols/protocol_h10301.c | 4 ++++ lib/lfrfid/protocols/protocol_hid_ex_generic.c | 4 ++++ lib/lfrfid/protocols/protocol_hid_generic.c | 4 ++++ lib/lfrfid/protocols/protocol_io_prox_xsf.c | 4 ++++ lib/lfrfid/protocols/protocol_jablotron.c | 4 ++++ lib/lfrfid/protocols/protocol_pac_stanley.c | 4 ++++ lib/lfrfid/protocols/protocol_paradox.c | 4 ++++ lib/lfrfid/protocols/protocol_pyramid.c | 4 ++++ lib/lfrfid/protocols/protocol_viking.c | 4 ++++ 15 files changed, 65 insertions(+), 6 deletions(-) diff --git a/applications/main/lfrfid/scenes/lfrfid_scene_read_success.c b/applications/main/lfrfid/scenes/lfrfid_scene_read_success.c index 6761dcfe6..5ae6f0f1a 100644 --- a/applications/main/lfrfid/scenes/lfrfid_scene_read_success.c +++ b/applications/main/lfrfid/scenes/lfrfid_scene_read_success.c @@ -24,14 +24,13 @@ void lfrfid_scene_read_success_on_enter(void* context) { uint8_t* data = (uint8_t*)malloc(size); protocol_dict_get_data(app->dict, app->protocol_id, data, size); for(uint8_t i = 0; i < size; i++) { - if(i != 0) { - string_cat_printf(tmp_string, " "); - } - if(i >= 9) { - string_cat_printf(tmp_string, "..."); + string_cat_printf(tmp_string, ".."); break; } else { + if(i != 0) { + string_cat_printf(tmp_string, " "); + } string_cat_printf(tmp_string, "%02X", data[i]); } } @@ -43,7 +42,7 @@ void lfrfid_scene_read_success_on_enter(void* context) { string_cat_printf(tmp_string, "\r\n%s", string_get_cstr(render_data)); string_clear(render_data); - widget_add_string_element( + widget_add_string_multiline_element( widget, 0, 16, AlignLeft, AlignTop, FontSecondary, string_get_cstr(tmp_string)); notification_message_block(app->notifications, &sequence_set_green_255); diff --git a/lib/lfrfid/protocols/protocol_awid.c b/lib/lfrfid/protocols/protocol_awid.c index 97c07d7b2..7131d30dc 100644 --- a/lib/lfrfid/protocols/protocol_awid.c +++ b/lib/lfrfid/protocols/protocol_awid.c @@ -205,6 +205,10 @@ bool protocol_awid_write_data(ProtocolAwid* protocol, void* data) { LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; bool result = false; + // Correct protocol data by redecoding + protocol_awid_encode(protocol->data, (uint8_t*)protocol->encoded_data); + protocol_awid_decode(protocol->encoded_data, protocol->data); + protocol_awid_encode(protocol->data, (uint8_t*)protocol->encoded_data); if(request->write_type == LFRFIDWriteTypeT5577) { diff --git a/lib/lfrfid/protocols/protocol_em4100.c b/lib/lfrfid/protocols/protocol_em4100.c index 17f57421a..6959f753b 100644 --- a/lib/lfrfid/protocols/protocol_em4100.c +++ b/lib/lfrfid/protocols/protocol_em4100.c @@ -248,6 +248,14 @@ bool protocol_em4100_write_data(ProtocolEM4100* protocol, void* data) { LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; bool result = false; + // Correct protocol data by redecoding + protocol_em4100_encoder_start(protocol); + em4100_decode( + (uint8_t*)&protocol->encoded_data, + sizeof(EM4100DecodedData), + protocol->data, + EM4100_DECODED_DATA_SIZE); + protocol_em4100_encoder_start(protocol); if(request->write_type == LFRFIDWriteTypeT5577) { diff --git a/lib/lfrfid/protocols/protocol_fdx_a.c b/lib/lfrfid/protocols/protocol_fdx_a.c index 23f9e2857..554b9071e 100644 --- a/lib/lfrfid/protocols/protocol_fdx_a.c +++ b/lib/lfrfid/protocols/protocol_fdx_a.c @@ -178,6 +178,10 @@ bool protocol_fdx_a_write_data(ProtocolFDXA* protocol, void* data) { LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; bool result = false; + // Correct protocol data by redecoding + protocol_fdx_a_encoder_start(protocol); + protocol_fdx_a_decode(protocol->encoded_data, protocol->data); + protocol_fdx_a_encoder_start(protocol); if(request->write_type == LFRFIDWriteTypeT5577) { diff --git a/lib/lfrfid/protocols/protocol_fdx_b.c b/lib/lfrfid/protocols/protocol_fdx_b.c index f68a884e8..f42b4ed93 100644 --- a/lib/lfrfid/protocols/protocol_fdx_b.c +++ b/lib/lfrfid/protocols/protocol_fdx_b.c @@ -334,6 +334,10 @@ bool protocol_fdx_b_write_data(ProtocolFDXB* protocol, void* data) { LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; bool result = false; + // Correct protocol data by redecoding + protocol_fdx_b_encoder_start(protocol); + protocol_fdx_b_decode(protocol); + protocol_fdx_b_encoder_start(protocol); if(request->write_type == LFRFIDWriteTypeT5577) { diff --git a/lib/lfrfid/protocols/protocol_gallagher.c b/lib/lfrfid/protocols/protocol_gallagher.c index c205ab8a5..5d8245301 100644 --- a/lib/lfrfid/protocols/protocol_gallagher.c +++ b/lib/lfrfid/protocols/protocol_gallagher.c @@ -249,6 +249,10 @@ bool protocol_gallagher_write_data(ProtocolGallagher* protocol, void* data) { LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; bool result = false; + // Correct protocol data by redecoding + protocol_gallagher_encoder_start(protocol); + protocol_gallagher_decode(protocol); + protocol_gallagher_encoder_start(protocol); if(request->write_type == LFRFIDWriteTypeT5577) { diff --git a/lib/lfrfid/protocols/protocol_h10301.c b/lib/lfrfid/protocols/protocol_h10301.c index f30f75fac..6c50c667a 100644 --- a/lib/lfrfid/protocols/protocol_h10301.c +++ b/lib/lfrfid/protocols/protocol_h10301.c @@ -337,6 +337,10 @@ bool protocol_h10301_write_data(ProtocolH10301* protocol, void* data) { LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; bool result = false; + // Correct protocol data by redecoding + protocol_h10301_encoder_start(protocol); + protocol_h10301_decode(protocol->encoded_data, protocol->data); + protocol_h10301_encoder_start(protocol); if(request->write_type == LFRFIDWriteTypeT5577) { diff --git a/lib/lfrfid/protocols/protocol_hid_ex_generic.c b/lib/lfrfid/protocols/protocol_hid_ex_generic.c index e0a852661..17b75528c 100644 --- a/lib/lfrfid/protocols/protocol_hid_ex_generic.c +++ b/lib/lfrfid/protocols/protocol_hid_ex_generic.c @@ -171,6 +171,10 @@ bool protocol_hid_ex_generic_write_data(ProtocolHIDEx* protocol, void* data) { LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; bool result = false; + // Correct protocol data by redecoding + protocol_hid_ex_generic_encoder_start(protocol); + protocol_hid_ex_generic_decode(protocol->encoded_data, protocol->data); + protocol_hid_ex_generic_encoder_start(protocol); if(request->write_type == LFRFIDWriteTypeT5577) { diff --git a/lib/lfrfid/protocols/protocol_hid_generic.c b/lib/lfrfid/protocols/protocol_hid_generic.c index 2516d6810..da5f5b7c8 100644 --- a/lib/lfrfid/protocols/protocol_hid_generic.c +++ b/lib/lfrfid/protocols/protocol_hid_generic.c @@ -203,6 +203,10 @@ bool protocol_hid_generic_write_data(ProtocolHID* protocol, void* data) { LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; bool result = false; + // Correct protocol data by redecoding + protocol_hid_generic_encoder_start(protocol); + protocol_hid_generic_decode(protocol->encoded_data, protocol->data); + protocol_hid_generic_encoder_start(protocol); if(request->write_type == LFRFIDWriteTypeT5577) { diff --git a/lib/lfrfid/protocols/protocol_io_prox_xsf.c b/lib/lfrfid/protocols/protocol_io_prox_xsf.c index 66b1610bf..f53eac686 100644 --- a/lib/lfrfid/protocols/protocol_io_prox_xsf.c +++ b/lib/lfrfid/protocols/protocol_io_prox_xsf.c @@ -259,6 +259,10 @@ bool protocol_io_prox_xsf_write_data(ProtocolIOProxXSF* protocol, void* data) { LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; bool result = false; + // Correct protocol data by redecoding + protocol_io_prox_xsf_encode(protocol->data, protocol->encoded_data); + protocol_io_prox_xsf_decode(protocol->encoded_data, protocol->data); + protocol_io_prox_xsf_encode(protocol->data, protocol->encoded_data); if(request->write_type == LFRFIDWriteTypeT5577) { diff --git a/lib/lfrfid/protocols/protocol_jablotron.c b/lib/lfrfid/protocols/protocol_jablotron.c index e00b1e59c..89a59a2d7 100644 --- a/lib/lfrfid/protocols/protocol_jablotron.c +++ b/lib/lfrfid/protocols/protocol_jablotron.c @@ -169,6 +169,10 @@ bool protocol_jablotron_write_data(ProtocolJablotron* protocol, void* data) { LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; bool result = false; + // Correct protocol data by redecoding + protocol_jablotron_encoder_start(protocol); + protocol_jablotron_decode(protocol); + protocol_jablotron_encoder_start(protocol); if(request->write_type == LFRFIDWriteTypeT5577) { diff --git a/lib/lfrfid/protocols/protocol_pac_stanley.c b/lib/lfrfid/protocols/protocol_pac_stanley.c index 7ab16a103..b5e1ebddc 100644 --- a/lib/lfrfid/protocols/protocol_pac_stanley.c +++ b/lib/lfrfid/protocols/protocol_pac_stanley.c @@ -182,6 +182,10 @@ bool protocol_pac_stanley_write_data(ProtocolPACStanley* protocol, void* data) { LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; bool result = false; + // Correct protocol data by redecoding + protocol_pac_stanley_encoder_start(protocol); + protocol_pac_stanley_decode(protocol); + protocol_pac_stanley_encoder_start(protocol); if(request->write_type == LFRFIDWriteTypeT5577) { diff --git a/lib/lfrfid/protocols/protocol_paradox.c b/lib/lfrfid/protocols/protocol_paradox.c index be627600b..b0b3e71d6 100644 --- a/lib/lfrfid/protocols/protocol_paradox.c +++ b/lib/lfrfid/protocols/protocol_paradox.c @@ -162,6 +162,10 @@ bool protocol_paradox_write_data(ProtocolParadox* protocol, void* data) { LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; bool result = false; + // Correct protocol data by redecoding + protocol_paradox_encode(protocol->data, (uint8_t*)protocol->encoded_data); + protocol_paradox_decode(protocol->encoded_data, protocol->data); + protocol_paradox_encode(protocol->data, (uint8_t*)protocol->encoded_data); if(request->write_type == LFRFIDWriteTypeT5577) { diff --git a/lib/lfrfid/protocols/protocol_pyramid.c b/lib/lfrfid/protocols/protocol_pyramid.c index a0404b485..1bba98718 100644 --- a/lib/lfrfid/protocols/protocol_pyramid.c +++ b/lib/lfrfid/protocols/protocol_pyramid.c @@ -219,6 +219,10 @@ bool protocol_pyramid_write_data(ProtocolPyramid* protocol, void* data) { LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; bool result = false; + // Correct protocol data by redecoding + protocol_pyramid_encode(protocol); + protocol_pyramid_decode(protocol); + protocol_pyramid_encoder_start(protocol); if(request->write_type == LFRFIDWriteTypeT5577) { diff --git a/lib/lfrfid/protocols/protocol_viking.c b/lib/lfrfid/protocols/protocol_viking.c index 6119b7348..f252cc2c3 100644 --- a/lib/lfrfid/protocols/protocol_viking.c +++ b/lib/lfrfid/protocols/protocol_viking.c @@ -157,6 +157,10 @@ bool protocol_viking_write_data(ProtocolViking* protocol, void* data) { LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data; bool result = false; + // Correct protocol data by redecoding + protocol_viking_encoder_start(protocol); + protocol_viking_decode(protocol); + protocol_viking_encoder_start(protocol); if(request->write_type == LFRFIDWriteTypeT5577) { From c7cd5721edc986c2e80cdbe85af86fbdf613d19b Mon Sep 17 00:00:00 2001 From: Patrick Cunningham Date: Mon, 19 Sep 2022 06:37:12 -0700 Subject: [PATCH 6/6] Picopass: detect and show SE / SIO (#1701) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * detect and show SE / SIO * fix fault * remove bad read check Co-authored-by: あく --- .../plugins/picopass/picopass_device.c | 6 +- .../plugins/picopass/picopass_device.h | 1 + .../plugins/picopass/picopass_worker.c | 98 +++++++++++++++---- .../plugins/picopass/picopass_worker.h | 1 + .../scenes/picopass_scene_read_card_success.c | 32 +++--- 5 files changed, 103 insertions(+), 35 deletions(-) diff --git a/applications/plugins/picopass/picopass_device.c b/applications/plugins/picopass/picopass_device.c index 04d35d19b..e7f3e0bed 100644 --- a/applications/plugins/picopass/picopass_device.c +++ b/applications/plugins/picopass/picopass_device.c @@ -309,10 +309,6 @@ ReturnCode picopass_device_decrypt(uint8_t* enc_data, uint8_t* dec_data) { ReturnCode picopass_device_parse_credential(PicopassBlock* AA1, PicopassPacs* pacs) { ReturnCode err; - // Thank you proxmark! - pacs->legacy = (memcmp(AA1[5].data, "\xff\xff\xff\xff\xff\xff\xff\xff", 8) == 0); - pacs->se_enabled = (memcmp(AA1[5].data, "\xff\xff\xff\x00\x06\xff\xff\xff", 8) == 0); - pacs->biometrics = AA1[6].data[4]; pacs->pin_length = AA1[6].data[6] & 0x0F; pacs->encryption = AA1[6].data[7]; @@ -347,6 +343,8 @@ ReturnCode picopass_device_parse_credential(PicopassBlock* AA1, PicopassPacs* pa FURI_LOG_D(TAG, "Unknown encryption"); } + pacs->sio = (AA1[10].data[0] == 0x30); // rough check + return ERR_NONE; } diff --git a/applications/plugins/picopass/picopass_device.h b/applications/plugins/picopass/picopass_device.h index 931b86306..745b64bd5 100644 --- a/applications/plugins/picopass/picopass_device.h +++ b/applications/plugins/picopass/picopass_device.h @@ -47,6 +47,7 @@ typedef struct { typedef struct { bool legacy; bool se_enabled; + bool sio; bool biometrics; uint8_t pin_length; PicopassEncryption encryption; diff --git a/applications/plugins/picopass/picopass_worker.c b/applications/plugins/picopass/picopass_worker.c index e73315248..532effd9a 100644 --- a/applications/plugins/picopass/picopass_worker.c +++ b/applications/plugins/picopass/picopass_worker.c @@ -112,18 +112,12 @@ ReturnCode picopass_detect_card(int timeout) { return ERR_NONE; } -ReturnCode picopass_read_card(PicopassBlock* AA1) { +ReturnCode picopass_read_preauth(PicopassBlock* AA1) { rfalPicoPassIdentifyRes idRes; rfalPicoPassSelectRes selRes; - rfalPicoPassReadCheckRes rcRes; - rfalPicoPassCheckRes chkRes; ReturnCode err; - uint8_t div_key[8] = {0}; - uint8_t mac[4] = {0}; - uint8_t ccnr[12] = {0}; - err = rfalPicoPassPollerIdentify(&idRes); if(err != ERR_NONE) { FURI_LOG_E(TAG, "rfalPicoPassPollerIdentify error %d", err); @@ -136,6 +130,62 @@ ReturnCode picopass_read_card(PicopassBlock* AA1) { return err; } + memcpy(AA1[PICOPASS_CSN_BLOCK_INDEX].data, selRes.CSN, sizeof(selRes.CSN)); + FURI_LOG_D( + TAG, + "csn %02x%02x%02x%02x%02x%02x%02x%02x", + AA1[PICOPASS_CSN_BLOCK_INDEX].data[0], + AA1[PICOPASS_CSN_BLOCK_INDEX].data[1], + AA1[PICOPASS_CSN_BLOCK_INDEX].data[2], + AA1[PICOPASS_CSN_BLOCK_INDEX].data[3], + AA1[PICOPASS_CSN_BLOCK_INDEX].data[4], + AA1[PICOPASS_CSN_BLOCK_INDEX].data[5], + AA1[PICOPASS_CSN_BLOCK_INDEX].data[6], + AA1[PICOPASS_CSN_BLOCK_INDEX].data[7]); + + rfalPicoPassReadBlockRes cfg = {0}; + err = rfalPicoPassPollerReadBlock(PICOPASS_CONFIG_BLOCK_INDEX, &cfg); + memcpy(AA1[PICOPASS_CONFIG_BLOCK_INDEX].data, cfg.data, sizeof(cfg.data)); + FURI_LOG_D( + TAG, + "config %02x%02x%02x%02x%02x%02x%02x%02x", + AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[0], + AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[1], + AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[2], + AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[3], + AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[4], + AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[5], + AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[6], + AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[7]); + + rfalPicoPassReadBlockRes aia; + err = rfalPicoPassPollerReadBlock(PICOPASS_AIA_BLOCK_INDEX, &aia); + memcpy(AA1[PICOPASS_AIA_BLOCK_INDEX].data, aia.data, sizeof(aia.data)); + FURI_LOG_D( + TAG, + "aia %02x%02x%02x%02x%02x%02x%02x%02x", + AA1[PICOPASS_AIA_BLOCK_INDEX].data[0], + AA1[PICOPASS_AIA_BLOCK_INDEX].data[1], + AA1[PICOPASS_AIA_BLOCK_INDEX].data[2], + AA1[PICOPASS_AIA_BLOCK_INDEX].data[3], + AA1[PICOPASS_AIA_BLOCK_INDEX].data[4], + AA1[PICOPASS_AIA_BLOCK_INDEX].data[5], + AA1[PICOPASS_AIA_BLOCK_INDEX].data[6], + AA1[PICOPASS_AIA_BLOCK_INDEX].data[7]); + + return ERR_NONE; +} + +ReturnCode picopass_read_card(PicopassBlock* AA1) { + rfalPicoPassReadCheckRes rcRes; + rfalPicoPassCheckRes chkRes; + + ReturnCode err; + + uint8_t div_key[8] = {0}; + uint8_t mac[4] = {0}; + uint8_t ccnr[12] = {0}; + err = rfalPicoPassPollerReadCheck(&rcRes); if(err != ERR_NONE) { FURI_LOG_E(TAG, "rfalPicoPassPollerReadCheck error %d", err); @@ -143,7 +193,7 @@ ReturnCode picopass_read_card(PicopassBlock* AA1) { } memcpy(ccnr, rcRes.CCNR, sizeof(rcRes.CCNR)); // last 4 bytes left 0 - loclass_diversifyKey(selRes.CSN, picopass_iclass_key, div_key); + loclass_diversifyKey(AA1[PICOPASS_CSN_BLOCK_INDEX].data, picopass_iclass_key, div_key); loclass_opt_doReaderMAC(ccnr, div_key, mac); err = rfalPicoPassPollerCheck(mac, &chkRes); @@ -152,18 +202,11 @@ ReturnCode picopass_read_card(PicopassBlock* AA1) { return err; } - rfalPicoPassReadBlockRes csn; - err = rfalPicoPassPollerReadBlock(PICOPASS_CSN_BLOCK_INDEX, &csn); - memcpy(AA1[PICOPASS_CSN_BLOCK_INDEX].data, csn.data, sizeof(csn.data)); - - rfalPicoPassReadBlockRes cfg; - err = rfalPicoPassPollerReadBlock(PICOPASS_CONFIG_BLOCK_INDEX, &cfg); - memcpy(AA1[PICOPASS_CONFIG_BLOCK_INDEX].data, cfg.data, sizeof(cfg.data)); - - size_t app_limit = cfg.data[0] < PICOPASS_MAX_APP_LIMIT ? cfg.data[0] : PICOPASS_MAX_APP_LIMIT; + size_t app_limit = AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[0] < PICOPASS_MAX_APP_LIMIT ? + AA1[PICOPASS_CONFIG_BLOCK_INDEX].data[0] : + PICOPASS_MAX_APP_LIMIT; for(size_t i = 2; i < app_limit; i++) { - FURI_LOG_D(TAG, "rfalPicoPassPollerReadBlock block %d", i); rfalPicoPassReadBlockRes block; err = rfalPicoPassPollerReadBlock(i, &block); if(err != ERR_NONE) { @@ -287,11 +330,30 @@ void picopass_worker_detect(PicopassWorker* picopass_worker) { PicopassPacs* pacs = &dev_data->pacs; ReturnCode err; + // reset device data + for(size_t i = 0; i < PICOPASS_MAX_APP_LIMIT; i++) { + memset(AA1[i].data, 0, sizeof(AA1[i].data)); + } + memset(pacs, 0, sizeof(PicopassPacs)); + PicopassWorkerEvent nextState = PicopassWorkerEventSuccess; while(picopass_worker->state == PicopassWorkerStateDetect) { if(picopass_detect_card(1000) == ERR_NONE) { // Process first found device + err = picopass_read_preauth(AA1); + if(err != ERR_NONE) { + FURI_LOG_E(TAG, "picopass_read_preauth error %d", err); + nextState = PicopassWorkerEventFail; + } + + // Thank you proxmark! + pacs->legacy = (memcmp(AA1[5].data, "\xff\xff\xff\xff\xff\xff\xff\xff", 8) == 0); + pacs->se_enabled = (memcmp(AA1[5].data, "\xff\xff\xff\x00\x06\xff\xff\xff", 8) == 0); + if(pacs->se_enabled) { + FURI_LOG_D(TAG, "SE enabled"); + } + err = picopass_read_card(AA1); if(err != ERR_NONE) { FURI_LOG_E(TAG, "picopass_read_card error %d", err); diff --git a/applications/plugins/picopass/picopass_worker.h b/applications/plugins/picopass/picopass_worker.h index 6ad709058..29a890a18 100644 --- a/applications/plugins/picopass/picopass_worker.h +++ b/applications/plugins/picopass/picopass_worker.h @@ -24,6 +24,7 @@ typedef enum { PicopassWorkerEventSuccess, PicopassWorkerEventFail, PicopassWorkerEventNoCardDetected, + PicopassWorkerEventSeEnabled, PicopassWorkerEventStartReading, } PicopassWorkerEvent; diff --git a/applications/plugins/picopass/scenes/picopass_scene_read_card_success.c b/applications/plugins/picopass/scenes/picopass_scene_read_card_success.c index c281b32ca..785f3a7dd 100644 --- a/applications/plugins/picopass/scenes/picopass_scene_read_card_success.c +++ b/applications/plugins/picopass/scenes/picopass_scene_read_card_success.c @@ -17,8 +17,10 @@ void picopass_scene_read_card_success_on_enter(void* context) { Picopass* picopass = context; string_t credential_str; string_t wiegand_str; + string_t sio_str; string_init(credential_str); string_init(wiegand_str); + string_init(sio_str); DOLPHIN_DEED(DolphinDeedNfcReadSuccess); @@ -32,6 +34,10 @@ void picopass_scene_read_card_success_on_enter(void* context) { if(pacs->record.bitLength == 0) { string_cat_printf(wiegand_str, "Read Failed"); + if(pacs->se_enabled) { + string_cat_printf(credential_str, "SE enabled"); + } + widget_add_button_element( widget, GuiButtonTypeLeft, @@ -39,8 +45,6 @@ void picopass_scene_read_card_success_on_enter(void* context) { picopass_scene_read_card_success_widget_callback, picopass); - widget_add_string_element( - widget, 64, 12, AlignCenter, AlignCenter, FontPrimary, string_get_cstr(wiegand_str)); } else { size_t bytesLength = 1 + pacs->record.bitLength / 8; string_set_str(credential_str, ""); @@ -55,6 +59,10 @@ void picopass_scene_read_card_success_on_enter(void* context) { string_cat_printf(wiegand_str, "%d bits", pacs->record.bitLength); } + if(pacs->sio) { + string_cat_printf(sio_str, "+SIO"); + } + widget_add_button_element( widget, GuiButtonTypeLeft, @@ -68,20 +76,18 @@ void picopass_scene_read_card_success_on_enter(void* context) { "More", picopass_scene_read_card_success_widget_callback, picopass); - - widget_add_string_element( - widget, 64, 12, AlignCenter, AlignCenter, FontPrimary, string_get_cstr(wiegand_str)); - widget_add_string_element( - widget, - 64, - 32, - AlignCenter, - AlignCenter, - FontSecondary, - string_get_cstr(credential_str)); } + + widget_add_string_element( + widget, 64, 12, AlignCenter, AlignCenter, FontPrimary, string_get_cstr(wiegand_str)); + widget_add_string_element( + widget, 64, 32, AlignCenter, AlignCenter, FontSecondary, string_get_cstr(credential_str)); + widget_add_string_element( + widget, 64, 42, AlignCenter, AlignCenter, FontSecondary, string_get_cstr(sio_str)); + string_clear(credential_str); string_clear(wiegand_str); + string_clear(sio_str); view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewWidget); }