diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index baef8fe1..765da29a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -32,6 +32,7 @@ jobs: with: fetch-depth: 0 submodules: true + ref: ${{ github.event.pull_request.head.sha }} - name: 'Docker cache' uses: satackey/action-docker-layer-caching@v0.0.11 @@ -47,14 +48,28 @@ jobs: run: | test -d artifacts && rm -rf artifacts || true mkdir artifacts - - - name: 'Generate tag suffix' - if: startsWith(github.ref, 'refs/tags/') == true - run: echo "SUFFIX=$(git describe --tags --abbrev=0)" >> $GITHUB_ENV - - - name: 'Generate branch suffix' - if: startsWith(github.ref, 'refs/tags/') != true - run: echo "SUFFIX=$(git rev-parse --abbrev-ref HEAD)-$(date +'%d%m%Y')-$(git rev-parse --short HEAD)" >> $GITHUB_ENV + + - name: 'Generate suffix and folder name' + id: names + run: | + REF=${{ github.ref }} + if [[ ${{ github.event_name }} == 'pull_request' ]]; then + REF=${{ github.head_ref }} + fi + BRANCH_OR_TAG=${REF##*/} + SHA=$(git rev-parse --short HEAD) + + if [[ "${{ github.ref }}" == "refs/tags/"* ]]; then + SUFFIX=${BRANCH_OR_TAG} + else + SUFFIX=${BRANCH_OR_TAG}-$(date +'%d%m%Y')-${SHA} + fi + + echo "WORKFLOW_BRANCH_OR_TAG=${BRANCH_OR_TAG}" >> $GITHUB_ENV + echo "::set-output name=artifacts-path::${BRANCH_OR_TAG}" + echo "::set-output name=suffix::${SUFFIX}" + echo "::set-output name=short-hash::${SHA}" + echo "::set-output name=latest-target::${TARGETS[${#TARGETS[@]}-1]}" - name: 'Build bootloader in docker' uses: ./.github/actions/docker @@ -95,17 +110,17 @@ jobs: for TARGET in ${TARGETS} do mv bootloader/.obj/${TARGET}/bootloader.dfu \ - artifacts/flipper-z-${TARGET}-bootloader-${SUFFIX}.dfu + artifacts/flipper-z-${TARGET}-bootloader-${{steps.names.outputs.suffix}}.dfu mv bootloader/.obj/${TARGET}/bootloader.bin \ - artifacts/flipper-z-${TARGET}-bootloader-${SUFFIX}.bin + artifacts/flipper-z-${TARGET}-bootloader-${{steps.names.outputs.suffix}}.bin mv bootloader/.obj/${TARGET}/bootloader.elf \ - artifacts/flipper-z-${TARGET}-bootloader-${SUFFIX}.elf + artifacts/flipper-z-${TARGET}-bootloader-${{steps.names.outputs.suffix}}.elf mv firmware/.obj/${TARGET}/firmware.dfu \ - artifacts/flipper-z-${TARGET}-firmware-${SUFFIX}.dfu + artifacts/flipper-z-${TARGET}-firmware-${{steps.names.outputs.suffix}}.dfu mv firmware/.obj/${TARGET}/firmware.bin \ - artifacts/flipper-z-${TARGET}-firmware-${SUFFIX}.bin + artifacts/flipper-z-${TARGET}-firmware-${{steps.names.outputs.suffix}}.bin mv firmware/.obj/${TARGET}/firmware.elf \ - artifacts/flipper-z-${TARGET}-firmware-${SUFFIX}.elf + artifacts/flipper-z-${TARGET}-firmware-${{steps.names.outputs.suffix}}.elf done - name: 'Generate full dfu file' @@ -117,7 +132,7 @@ jobs: do hex2dfu \ -i firmware/.obj/${TARGET}/full.hex \ - -o artifacts/flipper-z-${TARGET}-full-${SUFFIX}.dfu \ + -o artifacts/flipper-z-${TARGET}-full-${{steps.names.outputs.suffix}}.dfu \ -l "Flipper Zero $(echo $TARGET | tr a-z A-Z)" done @@ -127,8 +142,8 @@ jobs: for TARGET in ${TARGETS} do cp \ - artifacts/flipper-z-${TARGET}-bootloader-${SUFFIX}.bin \ - artifacts/flipper-z-${TARGET}-full-${SUFFIX}.bin + artifacts/flipper-z-${TARGET}-bootloader-${{steps.names.outputs.suffix}}.bin \ + artifacts/flipper-z-${TARGET}-full-${{steps.names.outputs.suffix}}.bin done - name: 'Full flash asssembly: bootloader padding' @@ -136,7 +151,7 @@ jobs: run: | for TARGET in ${TARGETS} do - truncate -s 32768 artifacts/flipper-z-${TARGET}-full-${SUFFIX}.bin + truncate -s 32768 artifacts/flipper-z-${TARGET}-full-${{steps.names.outputs.suffix}}.bin done - name: 'Full flash asssembly: append firmware' @@ -145,8 +160,8 @@ jobs: for TARGET in ${TARGETS} do cat \ - artifacts/flipper-z-${TARGET}-firmware-${SUFFIX}.bin \ - >> artifacts/flipper-z-${TARGET}-full-${SUFFIX}.bin + artifacts/flipper-z-${TARGET}-firmware-${{steps.names.outputs.suffix}}.bin \ + >> artifacts/flipper-z-${TARGET}-full-${{steps.names.outputs.suffix}}.bin done - name: 'Bundle core2 firmware' @@ -160,17 +175,17 @@ jobs: lib/STM32CubeWB/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x/stm32wb5x_FUS_fw_for_fus_0_5_3.bin \ lib/STM32CubeWB/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x/stm32wb5x_BLE_Stack_full_fw.bin \ core2_firmware - tar czpf artifacts/flipper-z-any-core2_firmware-${SUFFIX}.tgz core2_firmware + tar czpf artifacts/flipper-z-any-core2_firmware-${{steps.names.outputs.suffix}}.tgz core2_firmware - name: 'Bundle scripts' if: ${{ !github.event.pull_request.head.repo.fork }} run: | - tar czpf artifacts/flipper-z-any-scripts-${SUFFIX}.tgz scripts + tar czpf artifacts/flipper-z-any-scripts-${{steps.names.outputs.suffix}}.tgz scripts - name: 'Bundle resources' if: ${{ !github.event.pull_request.head.repo.fork }} run: | - tar czpf artifacts/flipper-z-any-resources-${SUFFIX}.tgz -C assets resources + tar czpf artifacts/flipper-z-any-resources-${{steps.names.outputs.suffix}}.tgz -C assets resources - name: 'Upload artifacts to update server' if: ${{ !github.event.pull_request.head.repo.fork }} @@ -178,7 +193,7 @@ jobs: with: switches: -avzP --delete path: artifacts/ - remote_path: "${{ secrets.RSYNC_DEPLOY_BASE_PATH }}${GITHUB_REF##*/}/" + remote_path: "${{ secrets.RSYNC_DEPLOY_BASE_PATH }}${{steps.names.outputs.artifacts-path}}/" remote_host: ${{ secrets.RSYNC_DEPLOY_HOST }} remote_port: ${{ secrets.RSYNC_DEPLOY_PORT }} remote_user: ${{ secrets.RSYNC_DEPLOY_USER }} @@ -190,3 +205,21 @@ jobs: with: args: -X POST -F 'key=${{ secrets.REINDEX_KEY }}' ${{ secrets.REINDEX_URL }} + - name: Find Previous Comment + if: ${{ !github.event.pull_request.head.repo.fork && github.event.pull_request }} + uses: peter-evans/find-comment@v1 + id: fc + with: + issue-number: ${{ github.event.pull_request.number }} + comment-author: 'github-actions[bot]' + body-includes: 'to flash the' + + - name: Create or update comment + if: ${{ !github.event.pull_request.head.repo.fork && github.event.pull_request}} + uses: peter-evans/create-or-update-comment@v1 + with: + comment-id: ${{ steps.fc.outputs.comment-id }} + issue-number: ${{ github.event.pull_request.number }} + body: | + [Click here](https://update.flipperzero.one/?url=https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.artifacts-path}}/flipper-z-${{steps.names.outputs.latest-target}}-full-${{steps.names.outputs.suffix}}.dfu&channel=${{steps.names.outputs.artifacts-path}}&version=${{steps.names.outputs.short-hash}}) to flash the `${{steps.names.outputs.short-hash}}` version of this branch via WebUSB. + edit-mode: replace diff --git a/.github/workflows/lint_c.yml b/.github/workflows/lint_c.yml index 828a7f70..7d4942a2 100644 --- a/.github/workflows/lint_c.yml +++ b/.github/workflows/lint_c.yml @@ -43,19 +43,19 @@ jobs: - name: 'Build docker image' uses: ./.github/actions/docker - - name: 'Check syntax' + - name: 'Check code formatting' id: syntax_check uses: ./.github/actions/docker with: run: SET_GH_OUTPUT=1 /syntax_check.sh - - name: Report syntax errors + - name: Report code formatting errors if: failure() && steps.syntax_check.outputs.errors && github.event.pull_request uses: peter-evans/create-or-update-comment@v1 with: issue-number: ${{ github.event.pull_request.number }} body: | - Please fix following syntax errors: + Please fix following code formatting errors: ``` ${{ steps.syntax_check.outputs.errors }} ``` diff --git a/applications/accessor/accessor-app.cpp b/applications/accessor/accessor-app.cpp index f7446b55..b462ec79 100644 --- a/applications/accessor/accessor-app.cpp +++ b/applications/accessor/accessor-app.cpp @@ -35,7 +35,6 @@ AccessorApp::AccessorApp() : onewire_master{&ibutton_gpio} { furi_hal_power_insomnia_enter(); notification = static_cast(furi_record_open("notification")); - notify_init(); furi_hal_power_enable_otg(); } @@ -104,17 +103,6 @@ AccessorApp::Scene AccessorApp::get_previous_scene() { /***************************** NOTIFY *******************************/ -void AccessorApp::notify_init() { - GPIO_InitTypeDef GPIO_InitStruct = {0}; - - GPIO_InitStruct.Pin = PB3_Pin; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF1_TIM2; - HAL_GPIO_Init(PB3_GPIO_Port, &GPIO_InitStruct); -} - void AccessorApp::notify_green_blink() { notification_message(notification, &sequence_blink_green_10); } diff --git a/applications/accessor/accessor-app.h b/applications/accessor/accessor-app.h index 32af88ee..daa16d7f 100644 --- a/applications/accessor/accessor-app.h +++ b/applications/accessor/accessor-app.h @@ -29,9 +29,7 @@ public: bool switch_to_previous_scene(uint8_t count = 1); Scene get_previous_scene(); - void notify_init(); void notify_green_blink(); - void notify_success(); char* get_text_store(); diff --git a/applications/applications.c b/applications/applications.c index 786b8f35..36751e09 100644 --- a/applications/applications.c +++ b/applications/applications.c @@ -148,7 +148,7 @@ const FlipperApplication FLIPPER_APPS[] = { #endif #ifdef APP_SUBGHZ - {.app = subghz_app, .name = "Sub-1 GHz", .stack_size = 2048, .icon = &A_Sub1ghz_14}, + {.app = subghz_app, .name = "Sub-GHz", .stack_size = 2048, .icon = &A_Sub1ghz_14}, #endif #ifdef APP_LF_RFID diff --git a/applications/archive/archive.c b/applications/archive/archive.c index 265ae02c..c9667e66 100644 --- a/applications/archive/archive.c +++ b/applications/archive/archive.c @@ -2,20 +2,6 @@ static bool archive_get_filenames(ArchiveApp* archive); -static bool is_favorite(ArchiveApp* archive, ArchiveFile_t* file) { - FileInfo file_info; - FS_Error fr; - string_t path; - - string_init_printf(path, "%s/%s", get_favorites_path(), string_get_cstr(file->name)); - - fr = storage_common_stat(archive->api, string_get_cstr(path), &file_info); - FURI_LOG_I("FAV", "%d", fr); - - string_clear(path); - return (fr == FSE_OK || fr == FSE_EXIST); -} - static void update_offset(ArchiveApp* archive) { furi_assert(archive); @@ -92,6 +78,7 @@ static void archive_leave_dir(ArchiveApp* archive) { }); archive_switch_dir(archive, string_get_cstr(archive->browser.path)); + update_offset(archive); } static void archive_enter_dir(ArchiveApp* archive, string_t name) { @@ -144,26 +131,200 @@ static void set_file_type(ArchiveFile_t* file, FileInfo* file_info) { } } -static bool archive_get_filenames(ArchiveApp* archive) { +static void archive_file_append(ArchiveApp* archive, const char* path, string_t string) { furi_assert(archive); + furi_assert(path); + furi_assert(string); + + FileWorker* file_worker = file_worker_alloc(false); + + if(!file_worker_open(file_worker, path, FSAM_WRITE, FSOM_OPEN_APPEND)) { + FURI_LOG_E("Archive", "Append open error"); + } + + if(!file_worker_write(file_worker, string_get_cstr(string), string_size(string))) { + FURI_LOG_E("Archive", "Append write error"); + } + + file_worker_close(file_worker); + file_worker_free(file_worker); +} + +static void archive_view_add_item(ArchiveApp* archive, FileInfo* file_info, const char* name) { + furi_assert(archive); + furi_assert(file_info); + furi_assert(name); ArchiveFile_t item; + + if(filter_by_extension(archive, file_info, name)) { + ArchiveFile_t_init(&item); + string_init_set_str(item.name, name); + set_file_type(&item, file_info); + + with_view_model( + archive->view_archive_main, (ArchiveViewModel * model) { + files_array_push_back(model->files, item); + return true; + }); + + ArchiveFile_t_clear(&item); + } +} + +static bool archive_is_favorite(ArchiveApp* archive, ArchiveFile_t* selected) { + furi_assert(selected); + string_t path; + string_t buffer; + string_init(buffer); + bool found = false; + + string_init_printf( + path, "%s/%s", string_get_cstr(archive->browser.path), string_get_cstr(selected->name)); + + bool load_result = + file_worker_open(archive->file_worker, ARCHIVE_FAV_PATH, FSAM_READ, FSOM_OPEN_ALWAYS); + + if(load_result) { + while(1) { + if(!file_worker_read_until(archive->file_worker, buffer, '\n')) { + break; + } + if(!string_size(buffer)) { + break; + } + if(!string_search(buffer, path)) { + found = true; + break; + } + } + } + + string_clear(buffer); + string_clear(path); + file_worker_close(archive->file_worker); + + return found; +} + +static bool archive_favorites_read(ArchiveApp* archive) { + string_t buffer; + FileInfo file_info; + string_init(buffer); + + bool load_result = + file_worker_open(archive->file_worker, ARCHIVE_FAV_PATH, FSAM_READ, FSOM_OPEN_EXISTING); + + if(load_result) { + while(1) { + if(!file_worker_read_until(archive->file_worker, buffer, '\n')) { + break; + } + if(!string_size(buffer)) { + break; + } + + archive_view_add_item(archive, &file_info, string_get_cstr(buffer)); + string_clean(buffer); + } + } + string_clear(buffer); + file_worker_close(archive->file_worker); + + return load_result; +} + +static bool + archive_favorites_rename(ArchiveApp* archive, ArchiveFile_t* selected, const char* dst) { + furi_assert(selected); + string_t path; + string_t buffer; + string_t temp; + + string_init(buffer); + string_init(temp); + + string_init_printf( + path, "%s/%s", string_get_cstr(archive->browser.path), string_get_cstr(selected->name)); + bool load_result = + file_worker_open(archive->file_worker, ARCHIVE_FAV_PATH, FSAM_READ, FSOM_OPEN_EXISTING); + + if(load_result) { + while(1) { + if(!file_worker_read_until(archive->file_worker, buffer, '\n')) { + break; + } + if(!string_size(buffer)) { + break; + } + + string_printf( + temp, "%s\r\n", string_search(buffer, path) ? string_get_cstr(buffer) : dst); + archive_file_append(archive, ARCHIVE_FAV_TEMP_PATH, temp); + string_clean(temp); + } + } + + string_clear(temp); + string_clear(buffer); + string_clear(path); + + file_worker_close(archive->file_worker); + file_worker_remove(archive->file_worker, ARCHIVE_FAV_PATH); + file_worker_rename(archive->file_worker, ARCHIVE_FAV_TEMP_PATH, ARCHIVE_FAV_PATH); + + return load_result; +} + +static bool archive_favorites_delete(ArchiveApp* archive, ArchiveFile_t* selected) { + furi_assert(selected); + string_t path; + string_t buffer; + string_init(buffer); + + string_init_printf( + path, "%s/%s", string_get_cstr(archive->browser.path), string_get_cstr(selected->name)); + + bool load_result = + file_worker_open(archive->file_worker, ARCHIVE_FAV_PATH, FSAM_READ, FSOM_OPEN_EXISTING); + if(load_result) { + while(1) { + if(!file_worker_read_until(archive->file_worker, buffer, '\n')) { + break; + } + if(!string_size(buffer)) { + break; + } + + if(string_search(buffer, path)) { + string_t temp; + string_init_printf(temp, "%s\r\n", string_get_cstr(buffer)); + archive_file_append(archive, ARCHIVE_FAV_TEMP_PATH, temp); + string_clear(temp); + } + } + } + + string_clear(buffer); + string_clear(path); + + file_worker_close(archive->file_worker); + file_worker_remove(archive->file_worker, ARCHIVE_FAV_PATH); + file_worker_rename(archive->file_worker, ARCHIVE_FAV_TEMP_PATH, ARCHIVE_FAV_PATH); + + return load_result; +} + +static bool archive_read_dir(ArchiveApp* archive) { FileInfo file_info; File* directory = storage_file_alloc(archive->api); char name[MAX_NAME_LEN]; - with_view_model( - archive->view_archive_main, (ArchiveViewModel * model) { - files_array_clean(model->files); - return true; - }); - if(!storage_dir_open(directory, string_get_cstr(archive->browser.path))) { storage_dir_close(directory); storage_file_free(directory); return false; } - while(1) { if(!storage_dir_read(directory, &file_info, name, MAX_NAME_LEN)) { break; @@ -180,31 +341,34 @@ static bool archive_get_filenames(ArchiveApp* archive) { if(files_cnt > MAX_FILES) { break; } else if(storage_file_get_error(directory) == FSE_OK) { - if(filter_by_extension(archive, &file_info, name)) { - ArchiveFile_t_init(&item); - string_init_set(item.name, name); - set_file_type(&item, &file_info); - - with_view_model( - archive->view_archive_main, (ArchiveViewModel * model) { - files_array_push_back(model->files, item); - return true; - }); - - ArchiveFile_t_clear(&item); - } + archive_view_add_item(archive, &file_info, name); } else { storage_dir_close(directory); storage_file_free(directory); return false; } } - storage_dir_close(directory); storage_file_free(directory); + return true; } +static bool archive_get_filenames(ArchiveApp* archive) { + furi_assert(archive); + with_view_model( + archive->view_archive_main, (ArchiveViewModel * model) { + files_array_clean(model->files); + return true; + }); + + if(archive->browser.tab_id != ArchiveTabFavorites) { + archive_read_dir(archive); + } else { + archive_favorites_read(archive); + } + return true; +} static void archive_exit_callback(ArchiveApp* archive) { furi_assert(archive); @@ -220,24 +384,17 @@ static uint32_t archive_previous_callback(void* context) { /* file menu */ static void archive_add_to_favorites(ArchiveApp* archive) { furi_assert(archive); - - storage_common_mkdir(archive->api, get_favorites_path()); - string_t buffer_src; - string_t buffer_dst; string_init_printf( buffer_src, - "%s/%s", + "%s/%s\r\n", string_get_cstr(archive->browser.path), string_get_cstr(archive->browser.name)); - string_init_printf( - buffer_dst, "%s/%s", get_favorites_path(), string_get_cstr(archive->browser.name)); - storage_common_copy(archive->api, string_get_cstr(buffer_src), string_get_cstr(buffer_dst)); + archive_file_append(archive, ARCHIVE_FAV_PATH, buffer_src); string_clear(buffer_src); - string_clear(buffer_dst); } static void archive_text_input_callback(void* context) { @@ -259,6 +416,7 @@ static void archive_text_input_callback(void* context) { string_get_cstr(archive->browser.path), archive->browser.text_input_buffer); + string_set(archive->browser.name, archive->browser.text_input_buffer); // append extension ArchiveFile_t* file; @@ -267,18 +425,38 @@ static void archive_text_input_callback(void* context) { archive->view_archive_main, (ArchiveViewModel * model) { file = files_array_get( model->files, CLAMP(model->idx, files_array_size(model->files) - 1, 0)); + file->fav = archive_is_favorite(archive, file); + return true; }); string_cat(buffer_dst, known_ext[file->type]); storage_common_rename(archive->api, string_get_cstr(buffer_src), string_get_cstr(buffer_dst)); + if(file->fav) { + archive_favorites_rename(archive, file, string_get_cstr(buffer_dst)); + } + view_dispatcher_switch_to_view(archive->view_dispatcher, ArchiveViewMain); + archive_get_filenames(archive); + + with_view_model( + archive->view_archive_main, (ArchiveViewModel * model) { + model->idx = 0; + while(model->idx < files_array_size(model->files)) { + ArchiveFile_t* current = files_array_get(model->files, model->idx); + if(!string_search(current->name, archive->browser.text_input_buffer)) { + break; + } + ++model->idx; + } + return true; + }); + + update_offset(archive); string_clear(buffer_src); string_clear(buffer_dst); - - archive_get_filenames(archive); } static void archive_enter_text_input(ArchiveApp* archive) { @@ -314,7 +492,8 @@ static void archive_show_file_menu(ArchiveApp* archive) { selected = files_array_get(model->files, model->idx); model->menu = true; model->menu_idx = 0; - selected->fav = is_favorite(archive, selected); + selected->fav = is_known_app(selected->type) ? archive_is_favorite(archive, selected) : + false; return true; }); @@ -340,29 +519,22 @@ static void archive_open_app(ArchiveApp* archive, const char* app_name, const ch loader_start(archive->loader, app_name, args); } -static void archive_delete_file(ArchiveApp* archive, ArchiveFile_t* file, bool fav, bool orig) { +static void archive_delete_file(ArchiveApp* archive, ArchiveFile_t* file) { furi_assert(archive); furi_assert(file); string_t path; string_init(path); - if(!fav && !orig) { - string_printf( - path, "%s/%s", string_get_cstr(archive->browser.path), string_get_cstr(file->name)); - storage_common_remove(archive->api, string_get_cstr(path)); + string_printf( + path, "%s/%s", string_get_cstr(archive->browser.path), string_get_cstr(file->name)); - } else { // remove from favorites - string_printf(path, "%s/%s", get_favorites_path(), string_get_cstr(file->name)); - storage_common_remove(archive->api, string_get_cstr(path)); - - if(orig) { // remove original file - string_printf( - path, "%s/%s", get_default_path(file->type), string_get_cstr(file->name)); - storage_common_remove(archive->api, string_get_cstr(path)); - } + if(archive_is_favorite(archive, file)) { // remove from favorites + archive_favorites_delete(archive, file); } + file_worker_remove(archive->file_worker, string_get_cstr(path)); + string_clear(path); archive_get_filenames(archive); @@ -375,6 +547,24 @@ static void archive_delete_file(ArchiveApp* archive, ArchiveFile_t* file, bool f update_offset(archive); } +static void + archive_run_in_app(ArchiveApp* archive, ArchiveFile_t* selected, bool full_path_provided) { + string_t full_path; + + if(!full_path_provided) { + string_init_printf( + full_path, + "%s/%s", + string_get_cstr(archive->browser.path), + string_get_cstr(selected->name)); + } else { + string_init_set(full_path, selected->name); + } + + archive_open_app(archive, flipper_app_name[selected->type], string_get_cstr(full_path)); + string_clear(full_path); +} + static void archive_file_menu_callback(ArchiveApp* archive) { furi_assert(archive); @@ -391,27 +581,17 @@ static void archive_file_menu_callback(ArchiveApp* archive) { switch(idx) { case 0: if(is_known_app(selected->type)) { - string_t full_path; - string_init_printf( - full_path, - "%s/%s", - string_get_cstr(archive->browser.path), - string_get_cstr(selected->name)); - - archive_open_app( - archive, flipper_app_name[selected->type], string_get_cstr(full_path)); - - string_clear(full_path); + archive_run_in_app(archive, selected, false); } break; case 1: if(is_known_app(selected->type)) { - if(!is_favorite(archive, selected)) { + if(!archive_is_favorite(archive, selected)) { string_set(archive->browser.name, selected->name); archive_add_to_favorites(archive); } else { // delete from favorites - archive_delete_file(archive, selected, true, false); + archive_favorites_delete(archive, selected); } archive_close_file_menu(archive); } @@ -424,13 +604,7 @@ static void archive_file_menu_callback(ArchiveApp* archive) { break; case 3: // confirmation? - if(is_favorite(archive, selected)) { - //delete both fav & original - archive_delete_file(archive, selected, true, true); - } else { - archive_delete_file(archive, selected, false, false); - } - + archive_delete_file(archive, selected); archive_close_file_menu(archive); break; @@ -545,7 +719,13 @@ static bool archive_view_input(InputEvent* event, void* context) { } } else { if(event->type == InputTypeShort) { - archive_show_file_menu(archive); + if(archive->browser.tab_id == ArchiveTabFavorites) { + if(is_known_app(selected->type)) { + archive_run_in_app(archive, selected, true); + } + } else { + archive_show_file_menu(archive); + } } } } @@ -559,6 +739,8 @@ static bool archive_view_input(InputEvent* event, void* context) { void archive_free(ArchiveApp* archive) { furi_assert(archive); + file_worker_free(archive->file_worker); + view_dispatcher_remove_view(archive->view_dispatcher, ArchiveViewMain); view_dispatcher_remove_view(archive->view_dispatcher, ArchiveViewTextInput); view_dispatcher_free(archive->view_dispatcher); @@ -598,6 +780,7 @@ ArchiveApp* archive_alloc() { archive->api = furi_record_open("storage"); archive->text_input = text_input_alloc(); archive->view_archive_main = view_alloc(); + archive->file_worker = file_worker_alloc(true); furi_check(archive->event_queue); diff --git a/applications/archive/archive_i.h b/applications/archive/archive_i.h index 006a7bbf..a7c3a901 100644 --- a/applications/archive/archive_i.h +++ b/applications/archive/archive_i.h @@ -13,10 +13,13 @@ #include #include "archive_views.h" #include "applications.h" +#include "file-worker.h" #define MAX_DEPTH 32 #define MAX_FILES 100 //temp #define MAX_FILE_SIZE 128 +#define ARCHIVE_FAV_PATH "/any/favorites.txt" +#define ARCHIVE_FAV_TEMP_PATH "/any/favorites.tmp" typedef enum { ArchiveViewMain, @@ -27,7 +30,7 @@ typedef enum { static const char* flipper_app_name[] = { [ArchiveFileTypeIButton] = "iButton", [ArchiveFileTypeNFC] = "NFC", - [ArchiveFileTypeSubOne] = "Sub-1 GHz", + [ArchiveFileTypeSubGhz] = "Sub-GHz", [ArchiveFileTypeLFRFID] = "125 kHz RFID", [ArchiveFileTypeIrda] = "Infrared", }; @@ -35,7 +38,7 @@ static const char* flipper_app_name[] = { static const char* known_ext[] = { [ArchiveFileTypeIButton] = ".ibtn", [ArchiveFileTypeNFC] = ".nfc", - [ArchiveFileTypeSubOne] = ".sub", + [ArchiveFileTypeSubGhz] = ".sub", [ArchiveFileTypeLFRFID] = ".rfid", [ArchiveFileTypeIrda] = ".ir", }; @@ -44,7 +47,7 @@ static const char* tab_default_paths[] = { [ArchiveTabFavorites] = "/any/favorites", [ArchiveTabIButton] = "/any/ibutton", [ArchiveTabNFC] = "/any/nfc", - [ArchiveTabSubOne] = "/any/subghz/saved", + [ArchiveTabSubGhz] = "/any/subghz/saved", [ArchiveTabLFRFID] = "/any/lfrfid", [ArchiveTabIrda] = "/any/irda", [ArchiveTabBrowser] = "/any", @@ -56,8 +59,8 @@ static inline const char* get_tab_ext(ArchiveTabEnum tab) { return known_ext[ArchiveFileTypeIButton]; case ArchiveTabNFC: return known_ext[ArchiveFileTypeNFC]; - case ArchiveTabSubOne: - return known_ext[ArchiveFileTypeSubOne]; + case ArchiveTabSubGhz: + return known_ext[ArchiveFileTypeSubGhz]; case ArchiveTabLFRFID: return known_ext[ArchiveFileTypeLFRFID]; case ArchiveTabIrda: @@ -73,8 +76,8 @@ static inline const char* get_default_path(ArchiveFileTypeEnum type) { return tab_default_paths[ArchiveTabIButton]; case ArchiveFileTypeNFC: return tab_default_paths[ArchiveTabNFC]; - case ArchiveFileTypeSubOne: - return tab_default_paths[ArchiveTabSubOne]; + case ArchiveFileTypeSubGhz: + return tab_default_paths[ArchiveTabSubGhz]; case ArchiveFileTypeLFRFID: return tab_default_paths[ArchiveTabLFRFID]; case ArchiveFileTypeIrda: @@ -101,6 +104,13 @@ typedef struct { EventType type; } AppEvent; +typedef enum { + FavoritesCheck, + FavoritesRead, + FavoritesDelete, + FavoritesRename, +} FavActionsEnum; + typedef struct { ArchiveTabEnum tab_id; string_t name; @@ -123,5 +133,6 @@ struct ArchiveApp { TextInput* text_input; Storage* api; + FileWorker* file_worker; ArchiveBrowser browser; }; diff --git a/applications/archive/archive_views.c b/applications/archive/archive_views.c index e2d52241..00f4d0f3 100644 --- a/applications/archive/archive_views.c +++ b/applications/archive/archive_views.c @@ -4,7 +4,7 @@ static const char* ArchiveTabNames[] = { [ArchiveTabFavorites] = "Favorites", [ArchiveTabIButton] = "iButton", [ArchiveTabNFC] = "NFC", - [ArchiveTabSubOne] = "SubGhz", + [ArchiveTabSubGhz] = "Sub-GHz", [ArchiveTabLFRFID] = "RFID LF", [ArchiveTabIrda] = "Infrared", [ArchiveTabBrowser] = "Browser"}; @@ -12,7 +12,7 @@ static const char* ArchiveTabNames[] = { static const Icon* ArchiveItemIcons[] = { [ArchiveFileTypeIButton] = &I_ibutt_10px, [ArchiveFileTypeNFC] = &I_Nfc_10px, - [ArchiveFileTypeSubOne] = &I_sub1_10px, + [ArchiveFileTypeSubGhz] = &I_sub1_10px, [ArchiveFileTypeLFRFID] = &I_125_10px, [ArchiveFileTypeIrda] = &I_ir_10px, [ArchiveFileTypeFolder] = &I_dir_10px, @@ -81,21 +81,21 @@ static void draw_list(Canvas* canvas, ArchiveViewModel* model) { size_t array_size = files_array_size(model->files); bool scrollbar = array_size > 4; - string_t str_buff; - char cstr_buff[MAX_NAME_LEN]; - string_init(str_buff); - for(size_t i = 0; i < MIN(array_size, MENU_ITEMS); ++i) { + string_t str_buff; + char cstr_buff[MAX_NAME_LEN]; + size_t idx = CLAMP(i + model->list_offset, array_size, 0); ArchiveFile_t* file = files_array_get(model->files, CLAMP(idx, array_size - 1, 0)); - strlcpy(cstr_buff, string_get_cstr(file->name), string_size(file->name) + 1); - if(is_known_app(file->type)) archive_trim_file_ext(cstr_buff); - string_set_str(str_buff, cstr_buff); + string_init_set(str_buff, file->name); + string_right(str_buff, string_search_rchar(str_buff, '/') + 1); + strlcpy(cstr_buff, string_get_cstr(str_buff), string_size(str_buff) + 1); - if(is_known_app(file->type)) { - archive_trim_file_ext(cstr_buff); - } + if(is_known_app(file->type)) archive_trim_file_ext(cstr_buff); + + string_clean(str_buff); + string_set_str(str_buff, cstr_buff); elements_string_fit_width(canvas, str_buff, scrollbar ? MAX_LEN_PX - 6 : MAX_LEN_PX); @@ -107,7 +107,7 @@ static void draw_list(Canvas* canvas, ArchiveViewModel* model) { canvas_draw_icon(canvas, 2, 16 + i * FRAME_HEIGHT, ArchiveItemIcons[file->type]); canvas_draw_str(canvas, 15, 24 + i * FRAME_HEIGHT, string_get_cstr(str_buff)); - string_clean(str_buff); + string_clear(str_buff); } if(scrollbar) { @@ -117,8 +117,6 @@ static void draw_list(Canvas* canvas, ArchiveViewModel* model) { if(model->menu) { render_item_menu(canvas, model); } - - string_clear(str_buff); } static void archive_render_status_bar(Canvas* canvas, ArchiveViewModel* model) { diff --git a/applications/archive/archive_views.h b/applications/archive/archive_views.h index ca7772d4..9c9cd8f6 100644 --- a/applications/archive/archive_views.h +++ b/applications/archive/archive_views.h @@ -14,7 +14,7 @@ typedef enum { ArchiveFileTypeIButton, ArchiveFileTypeNFC, - ArchiveFileTypeSubOne, + ArchiveFileTypeSubGhz, ArchiveFileTypeLFRFID, ArchiveFileTypeIrda, ArchiveFileTypeFolder, @@ -25,7 +25,7 @@ typedef enum { typedef enum { ArchiveTabFavorites, ArchiveTabLFRFID, - ArchiveTabSubOne, + ArchiveTabSubGhz, ArchiveTabNFC, ArchiveTabIButton, ArchiveTabIrda, diff --git a/applications/cli/cli.c b/applications/cli/cli.c index 11465a99..9a3ae259 100644 --- a/applications/cli/cli.c +++ b/applications/cli/cli.c @@ -46,7 +46,7 @@ void cli_stdout_callback(void* _cookie, const char* data, size_t size) { furi_hal_vcp_tx((const uint8_t*)data, size); } -void cli_write(Cli* cli, uint8_t* buffer, size_t size) { +void cli_write(Cli* cli, const uint8_t* buffer, size_t size) { return furi_hal_vcp_tx(buffer, size); } @@ -300,6 +300,7 @@ void cli_process_input(Cli* cli) { if(c == CliSymbolAsciiTab) { cli_handle_autocomplete(cli); } else if(c == CliSymbolAsciiSOH) { + osDelay(33); // We are too fast, Minicom is not ready yet cli_motd(); cli_prompt(cli); } else if(c == CliSymbolAsciiETX) { diff --git a/applications/cli/cli.h b/applications/cli/cli.h index c7322fdb..b6f524a1 100644 --- a/applications/cli/cli.h +++ b/applications/cli/cli.h @@ -88,7 +88,7 @@ bool cli_cmd_interrupt_received(Cli* cli); * @param size - size of buffer in bytes * @return bytes written */ -void cli_write(Cli* cli, uint8_t* buffer, size_t size); +void cli_write(Cli* cli, const uint8_t* buffer, size_t size); /* Read character * @param cli - Cli instance diff --git a/applications/debug_tools/keypad_test.c b/applications/debug_tools/keypad_test.c index 1323e95e..e390ccd5 100644 --- a/applications/debug_tools/keypad_test.c +++ b/applications/debug_tools/keypad_test.c @@ -22,42 +22,6 @@ typedef struct { EventType type; } KeypadTestEvent; -static const char* keypad_test_get_key_name(InputKey key) { - switch(key) { - case InputKeyOk: - return "Ok"; - case InputKeyBack: - return "Back"; - case InputKeyLeft: - return "Left"; - case InputKeyRight: - return "Right"; - case InputKeyUp: - return "Up"; - case InputKeyDown: - return "Down"; - default: - return "Unknown"; - } -} - -static const char* keypad_test_get_type_name(InputType type) { - switch(type) { - case InputTypePress: - return "Press"; - case InputTypeRelease: - return "Release"; - case InputTypeShort: - return "Short"; - case InputTypeLong: - return "Long"; - case InputTypeRepeat: - return "Repeat"; - default: - return "Unknown"; - } -} - static void keypad_test_reset_state(KeypadTestState* state) { state->left = 0; state->right = 0; @@ -139,8 +103,8 @@ int32_t keypad_test_app(void* p) { FURI_LOG_I( "KeypadTest", "key: %s type: %s", - keypad_test_get_key_name(event.input.key), - keypad_test_get_type_name(event.input.type)); + input_get_key_name(event.input.key), + input_get_type_name(event.input.type)); if(event.input.type == InputTypeLong && event.input.key == InputKeyBack) { release_mutex(&state_mutex, state); diff --git a/applications/dialogs/view_holder.c b/applications/dialogs/view_holder.c index c4e116ec..2307bcd8 100644 --- a/applications/dialogs/view_holder.c +++ b/applications/dialogs/view_holder.c @@ -11,6 +11,8 @@ struct ViewHolder { BackCallback back_callback; void* back_context; + + uint8_t ongoing_input; }; static void view_holder_draw_callback(Canvas* canvas, void* context); @@ -92,6 +94,7 @@ void view_holder_start(ViewHolder* view_holder) { } void view_holder_stop(ViewHolder* view_holder) { + while(view_holder->ongoing_input) osDelay(1); view_port_enabled_set(view_holder->view_port, false); } @@ -114,6 +117,21 @@ static void view_holder_draw_callback(Canvas* canvas, void* context) { static void view_holder_input_callback(InputEvent* event, void* context) { ViewHolder* view_holder = context; + + uint8_t key_bit = (1 << event->key); + if(event->type == InputTypePress) { + view_holder->ongoing_input |= key_bit; + } else if(event->type == InputTypeRelease) { + view_holder->ongoing_input &= ~key_bit; + } else if(!(view_holder->ongoing_input & key_bit)) { + FURI_LOG_W( + "ViewHolder", + "non-complementary input, discarding key: %s, type: %s", + input_get_key_name(event->key), + input_get_type_name(event->type)); + return; + } + bool is_consumed = false; if(view_holder->view) { diff --git a/applications/gpio-tester/gpio-tester.c b/applications/gpio-tester/gpio-tester.c index 4d079632..c088a195 100644 --- a/applications/gpio-tester/gpio-tester.c +++ b/applications/gpio-tester/gpio-tester.c @@ -2,143 +2,134 @@ #include #include -#include #include typedef struct { const char* name; - GpioPin pin; + const GpioPin* pin; } GpioItem; -const GpioItem GPIO_PINS[] = { - {"1.2: PA7", {GPIOA, GPIO_PIN_7}}, - {"1.3: PA6", {GPIOA, GPIO_PIN_6}}, - {"1.4: PA4", {GPIOA, GPIO_PIN_4}}, - {"1.5: PB3", {GPIOB, GPIO_PIN_3}}, - {"1.6: PB2", {GPIOB, GPIO_PIN_2}}, - {"1.7: PC3", {GPIOC, GPIO_PIN_3}}, - - {"2.7: PC1", {GPIOC, GPIO_PIN_1}}, - {"2.8: PC0", {GPIOC, GPIO_PIN_0}}, +static const GpioItem GPIO_PINS[] = { + {"1.2: PA7", &gpio_ext_pa7}, + {"1.3: PA6", &gpio_ext_pa6}, + {"1.4: PA4", &gpio_ext_pa4}, + {"1.5: PB3", &gpio_ext_pb3}, + {"1.6: PB2", &gpio_ext_pb2}, + {"1.7: PC3", &gpio_ext_pc3}, + {"2.7: PC1", &gpio_ext_pc1}, + {"2.8: PC0", &gpio_ext_pc0}, }; -typedef enum { - EventTypeTick, - EventTypeKey, -} EventType; - -typedef struct { - union { - InputEvent input; - } value; - EventType type; -} AppEvent; +static const size_t GPIO_PINS_COUNT = sizeof(GPIO_PINS) / sizeof(GPIO_PINS[0]); typedef struct { + osMessageQueueId_t input_queue; uint8_t gpio_index; -} State; + ViewPort* view_port; + Gui* gui; + NotificationApp* notification; +} GpioTest; -static void render_callback(Canvas* canvas, void* ctx) { - State* state = (State*)acquire_mutex((ValueMutex*)ctx, 25); +static void gpio_test_render_callback(Canvas* canvas, void* ctx) { + GpioTest* gpio_test = ctx; canvas_clear(canvas); canvas_set_color(canvas, ColorBlack); canvas_set_font(canvas, FontPrimary); canvas_draw_str(canvas, 2, 10, "GPIO Control"); canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 2, 25, GPIO_PINS[state->gpio_index].name); - - release_mutex((ValueMutex*)ctx, state); + canvas_draw_str(canvas, 2, 25, GPIO_PINS[gpio_test->gpio_index].name); } -static void input_callback(InputEvent* input_event, void* ctx) { - osMessageQueueId_t event_queue = ctx; +static void gpio_test_input_callback(InputEvent* input_event, void* ctx) { + GpioTest* gpio_test = ctx; - AppEvent event; - event.type = EventTypeKey; - event.value.input = *input_event; - osMessageQueuePut(event_queue, &event, 0, 0); + osMessageQueuePut(gpio_test->input_queue, input_event, 0, 0); +} + +static void gpio_test_configure_pins(GpioMode mode) { + for(size_t i = 0; i < GPIO_PINS_COUNT; i++) { + hal_gpio_write(GPIO_PINS[i].pin, false); + hal_gpio_init(GPIO_PINS[i].pin, mode, GpioPullNo, GpioSpeedLow); + } +} + +GpioTest* gpio_test_alloc() { + GpioTest* instance = furi_alloc(sizeof(GpioTest)); + + gpio_test_configure_pins(GpioModeOutputPushPull); + + instance->input_queue = osMessageQueueNew(8, sizeof(InputEvent), NULL); + furi_check(instance->input_queue); + + instance->view_port = view_port_alloc(); + view_port_draw_callback_set(instance->view_port, gpio_test_render_callback, instance); + view_port_input_callback_set(instance->view_port, gpio_test_input_callback, instance); + + instance->gui = furi_record_open("gui"); + gui_add_view_port(instance->gui, instance->view_port, GuiLayerFullscreen); + + instance->notification = furi_record_open("notification"); + + return instance; +} + +void gpio_test_free(GpioTest* instance) { + furi_assert(instance); + + furi_record_close("notification"); + + view_port_enabled_set(instance->view_port, false); + gui_remove_view_port(instance->gui, instance->view_port); + furi_record_close("gui"); + + view_port_free(instance->view_port); + + osMessageQueueDelete(instance->input_queue); + + gpio_test_configure_pins(GpioModeAnalog); + + free(instance); } int32_t gpio_test_app(void* p) { - osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(AppEvent), NULL); - furi_check(event_queue); + GpioTest* gpio_test = gpio_test_alloc(); - State _state; - _state.gpio_index = 0; + InputEvent event; + while(osMessageQueueGet(gpio_test->input_queue, &event, NULL, osWaitForever) == osOK) { + if(event.type == InputTypeShort) { + if(event.key == InputKeyBack) { + notification_message(gpio_test->notification, &sequence_reset_green); + break; + } - ValueMutex state_mutex; - if(!init_mutex(&state_mutex, &_state, sizeof(State))) { - printf("[gpio-tester] cannot create mutex\r\n"); - return 255; - } - - ViewPort* view_port = view_port_alloc(); - - view_port_draw_callback_set(view_port, render_callback, &state_mutex); - view_port_input_callback_set(view_port, input_callback, event_queue); - - // Open GUI and register view_port - Gui* gui = furi_record_open("gui"); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - - NotificationApp* notification = furi_record_open("notification"); - - // configure pin - for(uint8_t i = 0; i < sizeof(GPIO_PINS) / sizeof(GPIO_PINS[0]); i++) { - hal_gpio_init( - (GpioPin*)&GPIO_PINS[i].pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); - } - - AppEvent event; - while(1) { - osStatus_t event_status = osMessageQueueGet(event_queue, &event, NULL, osWaitForever); - State* state = (State*)acquire_mutex_block(&state_mutex); - - if(event_status == osOK) { - if(event.type == EventTypeKey) { - if(event.value.input.type == InputTypeShort && - event.value.input.key == InputKeyBack) { - printf("[gpio-tester] bye!\r\n"); - notification_message(notification, &sequence_reset_green); - furi_record_close("notification"); - - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - view_port_free(view_port); - - return 0; + if(event.key == InputKeyRight) { + if(gpio_test->gpio_index < (GPIO_PINS_COUNT - 1)) { + gpio_test->gpio_index++; } + } - if(event.value.input.type == InputTypeShort && - event.value.input.key == InputKeyRight) { - if(state->gpio_index < (sizeof(GPIO_PINS) / sizeof(GPIO_PINS[0]) - 1)) { - state->gpio_index++; - } + if(event.key == InputKeyLeft) { + if(gpio_test->gpio_index > 0) { + gpio_test->gpio_index--; } - - if(event.value.input.type == InputTypeShort && - event.value.input.key == InputKeyLeft) { - if(state->gpio_index > 0) { - state->gpio_index--; - } - } - - if(event.value.input.key == InputKeyOk) { - if(event.value.input.type == InputTypePress) { - hal_gpio_write((GpioPin*)&GPIO_PINS[state->gpio_index].pin, true); - notification_message(notification, &sequence_set_green_255); - } else if(event.value.input.type == InputTypeRelease) { - hal_gpio_write((GpioPin*)&GPIO_PINS[state->gpio_index].pin, false); - notification_message(notification, &sequence_reset_green); - } + } + } else { + if(event.key == InputKeyOk) { + if(event.type == InputTypePress) { + hal_gpio_write(GPIO_PINS[gpio_test->gpio_index].pin, true); + notification_message(gpio_test->notification, &sequence_set_green_255); + } else if(event.type == InputTypeRelease) { + hal_gpio_write(GPIO_PINS[gpio_test->gpio_index].pin, false); + notification_message(gpio_test->notification, &sequence_reset_green); } } } - release_mutex(&state_mutex, state); - view_port_update(view_port); + view_port_update(gpio_test->view_port); } + gpio_test_free(gpio_test); + return 0; } diff --git a/applications/gui/canvas.c b/applications/gui/canvas.c index 1dee2258..02341989 100644 --- a/applications/gui/canvas.c +++ b/applications/gui/canvas.c @@ -309,12 +309,15 @@ void canvas_set_orientation(Canvas* canvas, CanvasOrientation orientation) { furi_assert(canvas); if(canvas->orientation != orientation) { canvas->orientation = orientation; - if(canvas->orientation == CanvasOrientationHorizontal) + if(canvas->orientation == CanvasOrientationHorizontal) { + FURI_SWAP(canvas->width, canvas->height); u8g2_SetDisplayRotation(&canvas->fb, U8G2_R0); - else if(canvas->orientation == CanvasOrientationVertical) + } else if(canvas->orientation == CanvasOrientationVertical) { + FURI_SWAP(canvas->width, canvas->height); u8g2_SetDisplayRotation(&canvas->fb, U8G2_R3); - else + } else { furi_assert(0); + } } } diff --git a/applications/gui/gui.c b/applications/gui/gui.c index 8ad45499..b167db70 100644 --- a/applications/gui/gui.c +++ b/applications/gui/gui.c @@ -1,40 +1,5 @@ #include "gui_i.h" -static void gui_rotate_buttons(InputEvent* event) { - switch(event->key) { - case InputKeyUp: - event->key = InputKeyRight; - break; - case InputKeyDown: - event->key = InputKeyLeft; - break; - case InputKeyRight: - event->key = InputKeyDown; - break; - case InputKeyLeft: - event->key = InputKeyUp; - break; - default: - break; - } -} - -static void gui_setup_fs_orientation(const ViewPort* view_port, Canvas* canvas) { - ViewPortOrientation view_port_orientation = view_port_get_orientation(view_port); - CanvasOrientation canvas_orientation = canvas_get_orientation(canvas); - if(view_port_orientation == ViewPortOrientationHorizontal) { - canvas_frame_set(canvas, 0, 0, GUI_DISPLAY_WIDTH, GUI_DISPLAY_HEIGHT); - if(canvas_orientation != CanvasOrientationHorizontal) { - canvas_set_orientation(canvas, CanvasOrientationHorizontal); - } - } else if(view_port_orientation == ViewPortOrientationVertical) { - canvas_frame_set(canvas, 0, 0, GUI_DISPLAY_HEIGHT, GUI_DISPLAY_WIDTH); - if(canvas_orientation != CanvasOrientationVertical) { - canvas_set_orientation(canvas, CanvasOrientationVertical); - } - } -} - ViewPort* gui_view_port_find_enabled(ViewPortArray_t array) { // Iterating backward ViewPortArray_it_t it; @@ -66,9 +31,10 @@ void gui_input_events_callback(const void* value, void* ctx) { // Only Fullscreen supports vertical display for now bool gui_redraw_fs(Gui* gui) { + canvas_set_orientation(gui->canvas, CanvasOrientationHorizontal); + canvas_frame_set(gui->canvas, 0, 0, GUI_DISPLAY_WIDTH, GUI_DISPLAY_HEIGHT); ViewPort* view_port = gui_view_port_find_enabled(gui->layers[GuiLayerFullscreen]); if(view_port) { - gui_setup_fs_orientation(view_port, gui->canvas); view_port_draw(view_port, gui->canvas); return true; } else { @@ -216,20 +182,53 @@ void gui_input(Gui* gui, InputEvent* input_event) { furi_assert(gui); furi_assert(input_event); + // Check input complementarity + uint8_t key_bit = (1 << input_event->key); + if(input_event->type == InputTypeRelease) { + gui->ongoing_input &= ~key_bit; + } else if(input_event->type == InputTypePress) { + gui->ongoing_input |= key_bit; + } else if(!(gui->ongoing_input & key_bit)) { + FURI_LOG_W( + "Gui", + "non-complementary input, discarding key: %s type: %s, sequence: %p", + input_get_key_name(input_event->key), + input_get_type_name(input_event->type), + input_event->sequence); + return; + } + gui_lock(gui); - ViewPort* view_port; - - view_port = gui_view_port_find_enabled(gui->layers[GuiLayerFullscreen]); + ViewPort* view_port = gui_view_port_find_enabled(gui->layers[GuiLayerFullscreen]); if(!view_port) view_port = gui_view_port_find_enabled(gui->layers[GuiLayerMain]); if(!view_port) view_port = gui_view_port_find_enabled(gui->layers[GuiLayerNone]); - if(view_port) { - if(view_port_get_orientation(view_port) == ViewPortOrientationVertical) { - gui_rotate_buttons(input_event); - } + if(!(gui->ongoing_input & ~key_bit) && input_event->type == InputTypePress) { + gui->ongoing_input_view_port = view_port; + } + if(view_port && view_port == gui->ongoing_input_view_port) { view_port_input(view_port, input_event); + } else if(gui->ongoing_input_view_port && input_event->type == InputTypeRelease) { + FURI_LOG_W( + "Gui", + "ViewPort changed while key press %p -> %p. Sending key: %s, type: %s, sequence: %p to previous view port", + gui->ongoing_input_view_port, + view_port, + input_get_key_name(input_event->key), + input_get_type_name(input_event->type), + input_event->sequence); + view_port_input(gui->ongoing_input_view_port, input_event); + } else { + FURI_LOG_W( + "Gui", + "ViewPort changed while key press %p -> %p. Discarding key: %s, type: %s, sequence: %p", + gui->ongoing_input_view_port, + view_port, + input_get_key_name(input_event->key), + input_get_type_name(input_event->type), + input_event->sequence); } gui_unlock(gui); @@ -251,7 +250,7 @@ void gui_cli_screen_stream_callback(uint8_t* data, size_t size, void* context) { furi_assert(context); Gui* gui = context; - uint8_t magic[] = {0xF0, 0xE1, 0xD2, 0xC3}; + const uint8_t magic[] = {0xF0, 0xE1, 0xD2, 0xC3}; cli_write(gui->cli, magic, sizeof(magic)); cli_write(gui->cli, data, size); } @@ -329,6 +328,10 @@ void gui_remove_view_port(Gui* gui, ViewPort* view_port) { } } + if(gui->ongoing_input_view_port == view_port) { + gui->ongoing_input_view_port = NULL; + } + gui_unlock(gui); } diff --git a/applications/gui/gui_i.h b/applications/gui/gui_i.h index 441722c7..d67b4599 100644 --- a/applications/gui/gui_i.h +++ b/applications/gui/gui_i.h @@ -35,14 +35,19 @@ struct Gui { // Thread and lock osThreadId_t thread; osMutexId_t mutex; + // Layers and Canvas ViewPortArray_t layers[GuiLayerMAX]; Canvas* canvas; GuiCanvasCommitCallback canvas_callback; void* canvas_callback_context; + // Input osMessageQueueId_t input_queue; PubSub* input_events; + uint8_t ongoing_input; + ViewPort* ongoing_input_view_port; + // Cli Cli* cli; }; diff --git a/applications/gui/modules/widget.c b/applications/gui/modules/widget.c index 87ec54fe..64a05605 100755 --- a/applications/gui/modules/widget.c +++ b/applications/gui/modules/widget.c @@ -150,3 +150,15 @@ void widget_add_icon_element(Widget* widget, uint8_t x, uint8_t y, const Icon* i WidgetElement* icon_element = widget_element_icon_create(x, y, icon); widget_add_element(widget, icon_element); } + +void widget_add_frame_element( + Widget* widget, + uint8_t x, + uint8_t y, + uint8_t width, + uint8_t height, + uint8_t radius) { + furi_assert(widget); + WidgetElement* frame_element = widget_element_frame_create(x, y, width, height, radius); + widget_add_element(widget, frame_element); +} diff --git a/applications/gui/modules/widget.h b/applications/gui/modules/widget.h index e1280023..17c53dd9 100755 --- a/applications/gui/modules/widget.h +++ b/applications/gui/modules/widget.h @@ -59,8 +59,24 @@ void widget_add_button_element( /** Add Icon Element * @param widget Widget instance - * @param x - x coordinate - * @param y - y coordinate + * @param x top left x coordinate + * @param y top left y coordinate * @param icon Icon instance */ void widget_add_icon_element(Widget* widget, uint8_t x, uint8_t y, const Icon* icon); + +/** Add Frame Element + * @param widget Widget instance + * @param x top left x coordinate + * @param y top left y coordinate + * @param width frame width + * @param height frame height + * @param radius frame radius + */ +void widget_add_frame_element( + Widget* widget, + uint8_t x, + uint8_t y, + uint8_t width, + uint8_t height, + uint8_t radius); diff --git a/applications/gui/modules/widget_elements/widget_element_frame.c b/applications/gui/modules/widget_elements/widget_element_frame.c new file mode 100755 index 00000000..a8e00d9a --- /dev/null +++ b/applications/gui/modules/widget_elements/widget_element_frame.c @@ -0,0 +1,48 @@ +#include "widget_element_i.h" + +typedef struct { + uint8_t x; + uint8_t y; + uint8_t width; + uint8_t height; + uint8_t radius; +} GuiFrameModel; + +static void gui_frame_draw(Canvas* canvas, WidgetElement* element) { + furi_assert(canvas); + furi_assert(element); + GuiFrameModel* model = element->model; + canvas_draw_rframe(canvas, model->x, model->y, model->width, model->height, model->radius); +} + +static void gui_frame_free(WidgetElement* gui_frame) { + furi_assert(gui_frame); + + free(gui_frame->model); + free(gui_frame); +} + +WidgetElement* widget_element_frame_create( + uint8_t x, + uint8_t y, + uint8_t width, + uint8_t height, + uint8_t radius) { + // Allocate and init model + GuiFrameModel* model = furi_alloc(sizeof(GuiFrameModel)); + model->x = x; + model->y = y; + model->width = width; + model->height = height; + model->radius = radius; + + // Allocate and init Element + WidgetElement* gui_frame = furi_alloc(sizeof(WidgetElement)); + gui_frame->parent = NULL; + gui_frame->input = NULL; + gui_frame->draw = gui_frame_draw; + gui_frame->free = gui_frame_free; + gui_frame->model = model; + + return gui_frame; +} diff --git a/applications/gui/modules/widget_elements/widget_element_i.h b/applications/gui/modules/widget_elements/widget_element_i.h index e7243b89..d35325aa 100755 --- a/applications/gui/modules/widget_elements/widget_element_i.h +++ b/applications/gui/modules/widget_elements/widget_element_i.h @@ -44,5 +44,13 @@ WidgetElement* widget_element_button_create( ButtonCallback callback, void* context); -/* Create icon element element */ +/* Create icon element */ WidgetElement* widget_element_icon_create(uint8_t x, uint8_t y, const Icon* icon); + +/* Create frame element */ +WidgetElement* widget_element_frame_create( + uint8_t x, + uint8_t y, + uint8_t width, + uint8_t height, + uint8_t radius); \ No newline at end of file diff --git a/applications/gui/modules/widget_elements/widget_element_icon.c b/applications/gui/modules/widget_elements/widget_element_icon.c index 5ad1302a..e9ff3a97 100644 --- a/applications/gui/modules/widget_elements/widget_element_icon.c +++ b/applications/gui/modules/widget_elements/widget_element_icon.c @@ -1,5 +1,4 @@ #include "widget_element_i.h" -#include typedef struct { uint8_t x; diff --git a/applications/gui/view.c b/applications/gui/view.c index a992e246..8dea6a43 100644 --- a/applications/gui/view.c +++ b/applications/gui/view.c @@ -35,11 +35,6 @@ void view_set_previous_callback(View* view, ViewNavigationCallback callback) { view->previous_callback = callback; } -void view_set_next_callback(View* view, ViewNavigationCallback callback) { - furi_assert(view); - view->next_callback = callback; -} - void view_set_enter_callback(View* view, ViewCallback callback) { furi_assert(view); view->enter_callback = callback; @@ -169,15 +164,6 @@ uint32_t view_previous(View* view) { } } -uint32_t view_next(View* view) { - furi_assert(view); - if(view->next_callback) { - return view->next_callback(view->context); - } else { - return VIEW_IGNORE; - } -} - void view_enter(View* view) { furi_assert(view); if(view->enter_callback) view->enter_callback(view->context); diff --git a/applications/gui/view.h b/applications/gui/view.h index 38127a7b..4cef59fa 100644 --- a/applications/gui/view.h +++ b/applications/gui/view.h @@ -14,11 +14,6 @@ extern "C" { #define VIEW_NONE 0xFFFFFFFF /* Ignore navigation event */ #define VIEW_IGNORE 0xFFFFFFFE -/* Deatch from gui, deallocate Views and ViewDispatcher - * BE SUPER CAREFUL, deallocation happens automatically on GUI thread - * You ARE NOT owning ViewDispatcher and Views instances - */ -#define VIEW_DESTROY 0xFFFFFFFA typedef enum { ViewOrientationHorizontal, @@ -119,12 +114,6 @@ void view_set_custom_callback(View* view, ViewCustomCallback callback); */ void view_set_previous_callback(View* view, ViewNavigationCallback callback); -/* Set Navigation Next callback - * @param view, pointer to View - * @param callback, input callback - */ -void view_set_next_callback(View* view, ViewNavigationCallback callback); - /* Set Enter callback * @param view, pointer to View * @param callback, callback diff --git a/applications/gui/view_dispatcher.c b/applications/gui/view_dispatcher.c old mode 100755 new mode 100644 index c86efff5..b89e1c9b --- a/applications/gui/view_dispatcher.c +++ b/applications/gui/view_dispatcher.c @@ -37,7 +37,7 @@ void view_dispatcher_free(ViewDispatcher* view_dispatcher) { void view_dispatcher_enable_queue(ViewDispatcher* view_dispatcher) { furi_assert(view_dispatcher); furi_assert(view_dispatcher->queue == NULL); - view_dispatcher->queue = osMessageQueueNew(8, sizeof(ViewDispatcherMessage), NULL); + view_dispatcher->queue = osMessageQueueNew(16, sizeof(ViewDispatcherMessage), NULL); } void view_dispatcher_set_event_callback_context(ViewDispatcher* view_dispatcher, void* context) { @@ -91,6 +91,19 @@ void view_dispatcher_run(ViewDispatcher* view_dispatcher) { view_dispatcher_handle_custom_event(view_dispatcher, message.custom_event); } } + + // Wait till all input events delivered + while(view_dispatcher->ongoing_input) { + osMessageQueueGet(view_dispatcher->queue, &message, NULL, osWaitForever); + if(message.type == ViewDispatcherMessageTypeInput) { + uint8_t key_bit = (1 << message.input.key); + if(message.input.type == InputTypePress) { + view_dispatcher->ongoing_input |= key_bit; + } else if(message.input.type == InputTypeRelease) { + view_dispatcher->ongoing_input &= ~key_bit; + } + } + } } void view_dispatcher_stop(ViewDispatcher* view_dispatcher) { @@ -136,6 +149,10 @@ void view_dispatcher_remove_view(ViewDispatcher* view_dispatcher, uint32_t view_ if(view_dispatcher->current_view == view) { view_dispatcher_set_current_view(view_dispatcher, NULL); } + // Check if view is recieving input + if(view_dispatcher->ongoing_input_view == view) { + view_dispatcher->ongoing_input_view = NULL; + } // Remove view ViewDict_erase(view_dispatcher->views, view_id); @@ -153,8 +170,6 @@ void view_dispatcher_switch_to_view(ViewDispatcher* view_dispatcher, uint32_t vi if(view_id == VIEW_NONE) { view_dispatcher_set_current_view(view_dispatcher, NULL); } else if(view_id == VIEW_IGNORE) { - } else if(view_id == VIEW_DESTROY) { - view_dispatcher_free(view_dispatcher); } else { View** view_pp = ViewDict_get(view_dispatcher->views, view_id); furi_check(view_pp != NULL); @@ -202,29 +217,61 @@ void view_dispatcher_input_callback(InputEvent* event, void* context) { } void view_dispatcher_handle_input(ViewDispatcher* view_dispatcher, InputEvent* event) { - bool is_consumed = false; - if(view_dispatcher->current_view) { - is_consumed = view_input(view_dispatcher->current_view, event); + // Check input complementarity + uint8_t key_bit = (1 << event->key); + if(event->type == InputTypePress) { + view_dispatcher->ongoing_input |= key_bit; + } else if(event->type == InputTypeRelease) { + view_dispatcher->ongoing_input &= ~key_bit; + } else if(!(view_dispatcher->ongoing_input & key_bit)) { + FURI_LOG_W( + "ViewDispatcher", + "non-complementary input, discarding key: %s, type: %s, sequence: %p", + input_get_key_name(event->key), + input_get_type_name(event->type), + event->sequence); + return; } - if(!is_consumed && event->type == InputTypeShort) { - // TODO remove view navigation handlers - uint32_t view_id = VIEW_IGNORE; - if(event->key == InputKeyBack) { - view_id = view_previous(view_dispatcher->current_view); - if((view_id == VIEW_IGNORE) && (view_dispatcher->navigation_event_callback)) { - is_consumed = - view_dispatcher->navigation_event_callback(view_dispatcher->event_context); - if(!is_consumed) { - view_dispatcher_stop(view_dispatcher); - return; + + // Set ongoing input view if this is event is first press event + if(!(view_dispatcher->ongoing_input & ~key_bit) && event->type == InputTypePress) { + view_dispatcher->ongoing_input_view = view_dispatcher->current_view; + } + + // Deliver event + if(view_dispatcher->ongoing_input_view == view_dispatcher->current_view) { + bool is_consumed = false; + if(view_dispatcher->current_view) { + is_consumed = view_input(view_dispatcher->current_view, event); + } + if(!is_consumed && event->type == InputTypeShort) { + // TODO remove view navigation handlers + uint32_t view_id = VIEW_IGNORE; + if(event->key == InputKeyBack) { + view_id = view_previous(view_dispatcher->current_view); + if((view_id == VIEW_IGNORE) && (view_dispatcher->navigation_event_callback)) { + is_consumed = + view_dispatcher->navigation_event_callback(view_dispatcher->event_context); + if(!is_consumed) { + view_dispatcher_stop(view_dispatcher); + return; + } } } - } else if(event->key == InputKeyOk) { - view_id = view_next(view_dispatcher->current_view); - } - if(!is_consumed) { - view_dispatcher_switch_to_view(view_dispatcher, view_id); + if(!is_consumed) { + view_dispatcher_switch_to_view(view_dispatcher, view_id); + } } + } else if(view_dispatcher->ongoing_input_view && event->type == InputTypeRelease) { + FURI_LOG_W( + "ViewDispatcher", + "View changed while key press %p -> %p. Sending key: %s, type: %s, sequence: %p to previous view port", + view_dispatcher->ongoing_input_view, + view_dispatcher->current_view, + input_get_key_name(event->key), + input_get_type_name(event->type), + event->sequence); + view_input(view_dispatcher->ongoing_input_view, event); } } diff --git a/applications/gui/view_dispatcher.h b/applications/gui/view_dispatcher.h index fd8b874f..895c9b78 100755 --- a/applications/gui/view_dispatcher.h +++ b/applications/gui/view_dispatcher.h @@ -113,6 +113,7 @@ void view_dispatcher_remove_view(ViewDispatcher* view_dispatcher, uint32_t view_ /** Switch to View * @param view_dispatcher ViewDispatcher instance * @param view_id View id to register + * @warning switching may be delayed till input events complementarity reached */ void view_dispatcher_switch_to_view(ViewDispatcher* view_dispatcher, uint32_t view_id); diff --git a/applications/gui/view_dispatcher_i.h b/applications/gui/view_dispatcher_i.h index c921d994..60c9aa47 100644 --- a/applications/gui/view_dispatcher_i.h +++ b/applications/gui/view_dispatcher_i.h @@ -14,7 +14,12 @@ struct ViewDispatcher { Gui* gui; ViewPort* view_port; ViewDict_t views; + View* current_view; + + View* ongoing_input_view; + uint8_t ongoing_input; + ViewDispatcherCustomEventCallback custom_event_callback; ViewDispatcherNavigationEventCallback navigation_event_callback; ViewDispatcherTickEventCallback tick_event_callback; diff --git a/applications/gui/view_i.h b/applications/gui/view_i.h index 9f75f528..a03f3c4e 100644 --- a/applications/gui/view_i.h +++ b/applications/gui/view_i.h @@ -15,7 +15,6 @@ struct View { ViewModelType model_type; ViewNavigationCallback previous_callback; - ViewNavigationCallback next_callback; ViewCallback enter_callback; ViewCallback exit_callback; ViewOrientation orientation; @@ -42,9 +41,6 @@ bool view_custom(View* view, uint32_t event); /* Previous Callback for View dispatcher */ uint32_t view_previous(View* view); -/* Next Callback for View dispatcher */ -uint32_t view_next(View* view); - /* Enter Callback for View dispatcher */ void view_enter(View* view); diff --git a/applications/gui/view_port.c b/applications/gui/view_port.c index d65b9f7a..66560bbc 100644 --- a/applications/gui/view_port.c +++ b/applications/gui/view_port.c @@ -7,6 +7,33 @@ // TODO add mutex to view_port ops +static void view_port_rotate_buttons(InputEvent* event) { + switch(event->key) { + case InputKeyUp: + event->key = InputKeyRight; + break; + case InputKeyDown: + event->key = InputKeyLeft; + break; + case InputKeyRight: + event->key = InputKeyDown; + break; + case InputKeyLeft: + event->key = InputKeyUp; + break; + default: + break; + } +} + +static void view_port_setup_canvas_orientation(const ViewPort* view_port, Canvas* canvas) { + if(view_port->orientation == ViewPortOrientationHorizontal) { + canvas_set_orientation(canvas, CanvasOrientationHorizontal); + } else if(view_port->orientation == ViewPortOrientationVertical) { + canvas_set_orientation(canvas, CanvasOrientationVertical); + } +} + ViewPort* view_port_alloc() { ViewPort* view_port = furi_alloc(sizeof(ViewPort)); view_port->orientation = ViewPortOrientationHorizontal; @@ -84,6 +111,7 @@ void view_port_draw(ViewPort* view_port, Canvas* canvas) { furi_check(view_port->gui); if(view_port->draw_callback) { + view_port_setup_canvas_orientation(view_port, canvas); view_port->draw_callback(canvas, view_port->draw_callback_context); } } @@ -94,6 +122,9 @@ void view_port_input(ViewPort* view_port, InputEvent* event) { furi_check(view_port->gui); if(view_port->input_callback) { + if(view_port_get_orientation(view_port) == ViewPortOrientationVertical) { + view_port_rotate_buttons(event); + } view_port->input_callback(event, view_port->input_callback_context); } } diff --git a/applications/ibutton/ibutton-cli.cpp b/applications/ibutton/ibutton-cli.cpp index f865a26e..1fbccdab 100644 --- a/applications/ibutton/ibutton-cli.cpp +++ b/applications/ibutton/ibutton-cli.cpp @@ -10,18 +10,20 @@ #include void ibutton_cli(Cli* cli, string_t args, void* context); +void onewire_cli(Cli* cli, string_t args, void* context); // app cli function extern "C" void ibutton_cli_init() { Cli* cli = static_cast(furi_record_open("cli")); - cli_add_command(cli, "tm", CliCommandFlagDefault, ibutton_cli, cli); + cli_add_command(cli, "ikey", CliCommandFlagDefault, ibutton_cli, cli); + cli_add_command(cli, "onewire", CliCommandFlagDefault, onewire_cli, cli); furi_record_close("cli"); } void ibutton_cli_print_usage() { printf("Usage:\r\n"); - printf("tm read\r\n"); - printf("tm \r\n"); + printf("ikey read\r\n"); + printf("ikey \r\n"); printf("\t choose from:\r\n"); printf("\tDallas (8 bytes key_data)\r\n"); printf("\tCyfral (2 bytes key_data)\r\n"); @@ -230,5 +232,53 @@ void ibutton_cli(Cli* cli, string_t args, void* context) { ibutton_cli_print_usage(); } + string_clear(cmd); +} + +void onewire_cli_print_usage() { + printf("Usage:\r\n"); + printf("onewire search\r\n"); +}; + +void onewire_cli_search(Cli* cli) { + OneWireMaster onewire(&ibutton_gpio); + uint8_t address[8]; + bool done = false; + + printf("Search started\r\n"); + + onewire.start(); + while(!done) { + if(onewire.search(address, true) != 1) { + printf("Search finished\r\n"); + onewire.reset_search(); + done = true; + return; + } else { + printf("Found: "); + for(uint8_t i = 0; i < 8; i++) { + printf("%02X", address[i]); + } + printf("\r\n"); + } + delay(100); + } + onewire.stop(); +} + +void onewire_cli(Cli* cli, string_t args, void* context) { + string_t cmd; + string_init(cmd); + + if(!args_read_string_and_trim(args, cmd)) { + string_clear(cmd); + onewire_cli_print_usage(); + return; + } + + if(string_cmp_str(cmd, "search") == 0) { + onewire_cli_search(cli); + } + string_clear(cmd); } \ No newline at end of file diff --git a/applications/input/input.c b/applications/input/input.c index 32a35597..62be3dba 100644 --- a/applications/input/input.c +++ b/applications/input/input.c @@ -23,6 +23,7 @@ inline static void input_timer_stop(osTimerId_t timer_id) { void input_press_timer_callback(void* arg) { InputPinState* input_pin = arg; InputEvent event; + event.sequence = input_pin->counter; event.key = input_pin->pin->key; input_pin->press_counter++; if(input_pin->press_counter == INPUT_LONG_PRESS_COUNTS) { @@ -91,6 +92,31 @@ void input_cli_send(Cli* cli, string_t args, void* context) { notify_pubsub(&input->event_pubsub, &event); } +const char* input_get_key_name(InputKey key) { + for(size_t i = 0; i < input_pins_count; i++) { + if(input_pins[i].key == key) { + return input_pins[i].name; + } + } + return "Unknown"; +} + +const char* input_get_type_name(InputType type) { + switch(type) { + case InputTypePress: + return "Press"; + case InputTypeRelease: + return "Release"; + case InputTypeShort: + return "Short"; + case InputTypeLong: + return "Long"; + case InputTypeRepeat: + return "Repeat"; + } + return "Unknown"; +} + int32_t input_srv() { input = furi_alloc(sizeof(Input)); input->thread = osThreadGetId(); @@ -103,10 +129,9 @@ int32_t input_srv() { input->cli, "input_send", CliCommandFlagParallelSafe, input_cli_send, input); } - const size_t pin_count = input_pins_count; - input->pin_states = furi_alloc(pin_count * sizeof(InputPinState)); + input->pin_states = furi_alloc(input_pins_count * sizeof(InputPinState)); - for(size_t i = 0; i < pin_count; i++) { + for(size_t i = 0; i < input_pins_count; i++) { GpioPin gpio = {(GPIO_TypeDef*)input_pins[i].port, (uint16_t)input_pins[i].pin}; hal_gpio_add_int_callback(&gpio, input_isr, NULL); input->pin_states[i].pin = &input_pins[i]; @@ -119,7 +144,7 @@ int32_t input_srv() { while(1) { bool is_changing = false; - for(size_t i = 0; i < pin_count; i++) { + for(size_t i = 0; i < input_pins_count; i++) { bool state = GPIO_Read(input->pin_states[i]); if(input->pin_states[i].debounce > 0 && input->pin_states[i].debounce < INPUT_DEBOUNCE_TICKS) { @@ -131,14 +156,15 @@ int32_t input_srv() { // Common state info InputEvent event; event.key = input->pin_states[i].pin->key; - event.type = input->pin_states[i].state ? InputTypePress : InputTypeRelease; - // Send Press/Release event - notify_pubsub(&input->event_pubsub, &event); // Short / Long / Repeat timer routine if(state) { + input->counter++; + input->pin_states[i].counter = input->counter; + event.sequence = input->pin_states[i].counter; input_timer_start(input->pin_states[i].press_timer, INPUT_PRESS_TICKS); } else { + event.sequence = input->pin_states[i].counter; input_timer_stop(input->pin_states[i].press_timer); if(input->pin_states[i].press_counter < INPUT_LONG_PRESS_COUNTS) { event.type = InputTypeShort; @@ -146,6 +172,10 @@ int32_t input_srv() { } input->pin_states[i].press_counter = 0; } + + // Send Press/Release event + event.type = input->pin_states[i].state ? InputTypePress : InputTypeRelease; + notify_pubsub(&input->event_pubsub, &event); } } diff --git a/applications/input/input.h b/applications/input/input.h index 1ad82555..fd6da95d 100644 --- a/applications/input/input.h +++ b/applications/input/input.h @@ -15,6 +15,19 @@ typedef enum { /* Input Event, dispatches with PubSub */ typedef struct { + uint32_t sequence; InputKey key; InputType type; } InputEvent; + +/** Get human readable input key name + * @param key - InputKey + * @return string + */ +const char* input_get_key_name(InputKey key); + +/** Get human readable input type name + * @param type - InputType + * @return string + */ +const char* input_get_type_name(InputType type); diff --git a/applications/input/input_i.h b/applications/input/input_i.h index a0f6cfc3..d0cdfa76 100644 --- a/applications/input/input_i.h +++ b/applications/input/input_i.h @@ -24,6 +24,7 @@ typedef struct { volatile uint8_t debounce; volatile osTimerId_t press_timer; volatile uint8_t press_counter; + volatile uint32_t counter; } InputPinState; /* Input state */ @@ -32,6 +33,7 @@ typedef struct { PubSub event_pubsub; InputPinState* pin_states; Cli* cli; + volatile uint32_t counter; } Input; /* Input press timer callback */ diff --git a/applications/music-player/music-player.c b/applications/music-player/music-player.c index 9fa7708d..99081804 100644 --- a/applications/music-player/music-player.c +++ b/applications/music-player/music-player.c @@ -383,11 +383,6 @@ int32_t music_player_app(void* p) { Gui* gui = furi_record_open("gui"); gui_add_view_port(gui, view_port, GuiLayerFullscreen); - // open input record - PubSub* input_events_record = furi_record_open("input_events"); - // prepare "do nothing" event - InputEvent input_event = {InputKeyRight, true}; - // start player thread // TODO change to fuirac_start osThreadAttr_t player_attr = {.name = "music_player_thread", .stack_size = 512}; @@ -410,14 +405,8 @@ int32_t music_player_app(void* p) { // press events if(event.value.input.type == InputTypeShort && event.value.input.key == InputKeyBack) { - osThreadTerminate(player); - hal_pwm_stop(&SPEAKER_TIM, SPEAKER_CH); - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - view_port_free(view_port); - osMessageQueueDelete(event_queue); - - return 0; + release_mutex(&state_mutex, state); + break; } if(event.value.input.type == InputTypePress && @@ -442,9 +431,6 @@ int32_t music_player_app(void* p) { } } else if(event.type == EventTypeNote) { - // send "do nothing" event to prevent display backlight off - notify_pubsub(input_events_record, &input_event); - state->note_record = event.value.note_record; for(size_t i = note_stack_size - 1; i > 0; i--) { @@ -460,5 +446,14 @@ int32_t music_player_app(void* p) { release_mutex(&state_mutex, state); } + osThreadTerminate(player); + hal_pwm_stop(&SPEAKER_TIM, SPEAKER_CH); + view_port_enabled_set(view_port, false); + gui_remove_view_port(gui, view_port); + furi_record_close("gui"); + view_port_free(view_port); + osMessageQueueDelete(event_queue); + delete_mutex(&state_mutex); + return 0; } diff --git a/applications/nfc/helpers/nfc_emv_parser.c b/applications/nfc/helpers/nfc_emv_parser.c new file mode 100755 index 00000000..b84d35c3 --- /dev/null +++ b/applications/nfc/helpers/nfc_emv_parser.c @@ -0,0 +1,49 @@ +#include "nfc_emv_parser.h" + +#include + +static bool + nfc_emv_parser_get_value(const char* file_path, string_t key, char delimiter, string_t value) { + bool found = false; + FileWorker* file_worker = file_worker_alloc(true); + + if(file_worker_open(file_worker, file_path, FSAM_READ, FSOM_OPEN_EXISTING)) { + if(file_worker_get_value_from_key(file_worker, key, delimiter, value)) { + found = true; + } + } + + file_worker_close(file_worker); + file_worker_free(file_worker); + return found; +} + +bool nfc_emv_parser_get_aid_name(uint8_t* aid, uint8_t aid_len, string_t aid_name) { + bool result = false; + string_t key; + string_init(key); + for(uint8_t i = 0; i < aid_len; i++) { + string_cat_printf(key, "%02X", aid[i]); + } + result = nfc_emv_parser_get_value("/ext/nfc/emv/aid.nfc", key, ' ', aid_name); + string_clear(key); + return result; +} + +bool nfc_emv_parser_get_country_name(uint16_t country_code, string_t country_name) { + bool result = false; + string_t key; + string_init_printf(key, "%04X", country_code); + result = nfc_emv_parser_get_value("/ext/nfc/emv/country_code.nfc", key, ' ', country_name); + string_clear(key); + return result; +} + +bool nfc_emv_parser_get_currency_name(uint16_t currency_code, string_t currency_name) { + bool result = false; + string_t key; + string_init_printf(key, "%04X", currency_code); + result = nfc_emv_parser_get_value("/ext/nfc/emv/currency_code.nfc", key, ' ', currency_name); + string_clear(key); + return result; +} diff --git a/applications/nfc/helpers/nfc_emv_parser.h b/applications/nfc/helpers/nfc_emv_parser.h new file mode 100755 index 00000000..b81a06ee --- /dev/null +++ b/applications/nfc/helpers/nfc_emv_parser.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include +#include + +/** Get EMV application name by number + * @param aid - AID number array + * @param aid_len - AID length + * @param aid_name - string to keep AID name + * @return - true if AID found, false otherwies + */ +bool nfc_emv_parser_get_aid_name(uint8_t* aid, uint8_t aid_len, string_t aid_name); + +/** Get country name by country code + * @param country_code - ISO 3166 country code + * @param country_name - string to keep country name + * @return - true if country found, false otherwies + */ +bool nfc_emv_parser_get_country_name(uint16_t country_code, string_t country_name); + +/** Get currency name by currency code + * @param currency_code - ISO 3166 currency code + * @param currency_name - string to keep currency name + * @return - true if currency found, false otherwies + */ +bool nfc_emv_parser_get_currency_name(uint16_t currency_code, string_t currency_name); diff --git a/applications/nfc/nfc_cli.c b/applications/nfc/nfc_cli.c index e2ddb5ed..0326048a 100755 --- a/applications/nfc/nfc_cli.c +++ b/applications/nfc/nfc_cli.c @@ -54,7 +54,7 @@ void nfc_cli_emulate(Cli* cli, string_t args, void* context) { printf("Emulating NFC-A Type: T2T UID: CF72D440 SAK: 20 ATQA: 00/04\r\n"); printf("Press Ctrl+C to abort\r\n"); - NfcDeviceCommomData params = { + NfcDeviceCommonData params = { .uid = {0x36, 0x9C, 0xe7, 0xb1, 0x0A, 0xC1, 0x34}, .uid_len = 7, .atqa = {0x44, 0x00}, diff --git a/applications/nfc/nfc_device.c b/applications/nfc/nfc_device.c index bdb3d547..46947a2e 100755 --- a/applications/nfc/nfc_device.c +++ b/applications/nfc/nfc_device.c @@ -10,7 +10,7 @@ static const char* nfc_app_folder = "/any/nfc"; static const char* nfc_app_extension = ".nfc"; static const char* nfc_app_shadow_extension = ".shd"; -static bool nfc_device_read_hex(string_t str, uint8_t* buff, uint16_t len) { +static bool nfc_device_read_hex(string_t str, uint8_t* buff, uint16_t len, uint8_t delim_len) { string_strim(str); uint8_t nibble_high = 0; uint8_t nibble_low = 0; @@ -20,7 +20,7 @@ static bool nfc_device_read_hex(string_t str, uint8_t* buff, uint16_t len) { if(hex_char_to_hex_nibble(string_get_char(str, 0), &nibble_high) && hex_char_to_hex_nibble(string_get_char(str, 1), &nibble_low)) { buff[i] = (nibble_high << 4) | nibble_low; - string_right(str, 3); + string_right(str, delim_len + 2); } else { parsed = false; break; @@ -60,7 +60,7 @@ bool nfc_device_parse_format_string(NfcDevice* dev, string_t format_string) { } uint16_t nfc_device_prepare_uid_string(NfcDevice* dev, string_t uid_string) { - NfcDeviceCommomData* uid_data = &dev->dev_data.nfc_data; + NfcDeviceCommonData* uid_data = &dev->dev_data.nfc_data; string_printf(uid_string, "UID len: %02X UID: ", dev->dev_data.nfc_data.uid_len); for(uint8_t i = 0; i < uid_data->uid_len; i++) { string_cat_printf(uid_string, "%02X ", uid_data->uid[i]); @@ -75,28 +75,28 @@ uint16_t nfc_device_prepare_uid_string(NfcDevice* dev, string_t uid_string) { } bool nfc_device_parse_uid_string(NfcDevice* dev, string_t uid_string) { - NfcDeviceCommomData* uid_data = &dev->dev_data.nfc_data; + NfcDeviceCommonData* uid_data = &dev->dev_data.nfc_data; bool parsed = false; do { // strlen("UID len: ") = 9 string_right(uid_string, 9); - if(!nfc_device_read_hex(uid_string, &uid_data->uid_len, 1)) { + if(!nfc_device_read_hex(uid_string, &uid_data->uid_len, 1, 1)) { break; } // strlen("UID: ") = 5 string_right(uid_string, 5); - if(!nfc_device_read_hex(uid_string, uid_data->uid, uid_data->uid_len)) { + if(!nfc_device_read_hex(uid_string, uid_data->uid, uid_data->uid_len, 1)) { break; } // strlen("ATQA: ") = 6 string_right(uid_string, 6); - if(!nfc_device_read_hex(uid_string, uid_data->atqa, 2)) { + if(!nfc_device_read_hex(uid_string, uid_data->atqa, 2, 1)) { break; } // strlen("SAK: ") = 5 string_right(uid_string, 5); - if(!nfc_device_read_hex(uid_string, &uid_data->sak, 1)) { + if(!nfc_device_read_hex(uid_string, &uid_data->sak, 1, 1)) { break; } parsed = true; @@ -149,13 +149,13 @@ bool nfc_device_parse_mifare_ul_string(NfcDevice* dev, string_t mifare_ul_string do { // strlen("Signature: ") = 11 string_right(mifare_ul_string, 11); - if(!nfc_device_read_hex(mifare_ul_string, data->signature, sizeof(data->signature))) { + if(!nfc_device_read_hex(mifare_ul_string, data->signature, sizeof(data->signature), 1)) { break; } // strlen("Version: ") = 9 string_right(mifare_ul_string, 9); if(!nfc_device_read_hex( - mifare_ul_string, (uint8_t*)&data->version, sizeof(data->version))) { + mifare_ul_string, (uint8_t*)&data->version, sizeof(data->version), 1)) { break; } string_strim(mifare_ul_string); @@ -184,7 +184,7 @@ bool nfc_device_parse_mifare_ul_string(NfcDevice* dev, string_t mifare_ul_string string_right(mifare_ul_string, ws + 1); // Read data for(uint16_t i = 0; i < data->data_size; i += 4) { - if(!nfc_device_read_hex(mifare_ul_string, &data->data[i], 4)) { + if(!nfc_device_read_hex(mifare_ul_string, &data->data[i], 4, 1)) { break; } } @@ -208,6 +208,12 @@ uint16_t nfc_device_prepare_bank_card_string(NfcDevice* dev, string_t bank_card_ string_cat_printf( bank_card_string, "\nExp date: %02X/%02X", data->exp_mon, data->exp_year); } + if(data->country_code) { + string_cat_printf(bank_card_string, "\nCountry code: %04X", data->country_code); + } + if(data->currency_code) { + string_cat_printf(bank_card_string, "\nCurrency code: %04X", data->currency_code); + } return string_size(bank_card_string); } @@ -215,6 +221,7 @@ bool nfc_device_parse_bank_card_string(NfcDevice* dev, string_t bank_card_string NfcEmvData* data = &dev->dev_data.emv_data; bool parsed = false; int res = 0; + uint8_t code[2] = {}; memset(data, 0, sizeof(NfcEmvData)); do { @@ -226,7 +233,7 @@ bool nfc_device_parse_bank_card_string(NfcDevice* dev, string_t bank_card_string string_right(bank_card_string, 9); size_t ws = string_search_char(bank_card_string, ':'); string_right(bank_card_string, ws + 1); - if(!nfc_device_read_hex(bank_card_string, data->aid, data->aid_len)) { + if(!nfc_device_read_hex(bank_card_string, data->aid, data->aid_len, 1)) { break; } res = sscanf(string_get_cstr(bank_card_string), "Name: %s\n", data->name); @@ -237,7 +244,7 @@ bool nfc_device_parse_bank_card_string(NfcDevice* dev, string_t bank_card_string string_right(bank_card_string, ws + 1); // strlen("Number: ") = 8 string_right(bank_card_string, 8); - if(!nfc_device_read_hex(bank_card_string, data->number, sizeof(data->number))) { + if(!nfc_device_read_hex(bank_card_string, data->number, sizeof(data->number), 1)) { break; } parsed = true; @@ -246,8 +253,24 @@ bool nfc_device_parse_bank_card_string(NfcDevice* dev, string_t bank_card_string if(ws != STRING_FAILURE) { // strlen("Exp date: ") = 10 string_right(bank_card_string, 10); - nfc_device_read_hex(bank_card_string, &data->exp_mon, 1); - nfc_device_read_hex(bank_card_string, &data->exp_year, 1); + nfc_device_read_hex(bank_card_string, &data->exp_mon, 1, 1); + nfc_device_read_hex(bank_card_string, &data->exp_year, 1, 1); + } + // Check country code presence + ws = string_search_str(bank_card_string, "Country code: "); + if(ws != STRING_FAILURE) { + // strlen("Country code: ") = 14 + string_right(bank_card_string, 14); + nfc_device_read_hex(bank_card_string, code, 2, 0); + data->country_code = code[0] << 8 | code[1]; + } + // Check currency code presence + ws = string_search_str(bank_card_string, "Currency code: "); + if(ws != STRING_FAILURE) { + // strlen("Currency code: ") = 15 + string_right(bank_card_string, 15); + nfc_device_read_hex(bank_card_string, code, 2, 0); + data->currency_code = code[0] << 8 | code[1]; } } while(0); diff --git a/applications/nfc/nfc_device.h b/applications/nfc/nfc_device.h index 25f0e42f..aa9764b5 100644 --- a/applications/nfc/nfc_device.h +++ b/applications/nfc/nfc_device.h @@ -34,7 +34,7 @@ typedef struct { uint8_t sak; NfcDeviceType device; NfcProtocol protocol; -} NfcDeviceCommomData; +} NfcDeviceCommonData; typedef struct { char name[32]; @@ -43,11 +43,12 @@ typedef struct { uint8_t number[8]; uint8_t exp_mon; uint8_t exp_year; - char cardholder[32]; + uint16_t country_code; + uint16_t currency_code; } NfcEmvData; typedef struct { - NfcDeviceCommomData nfc_data; + NfcDeviceCommonData nfc_data; union { NfcEmvData emv_data; MifareUlData mf_ul_data; diff --git a/applications/nfc/nfc_worker.c b/applications/nfc/nfc_worker.c index 9fd6dc64..81a1ed67 100755 --- a/applications/nfc/nfc_worker.c +++ b/applications/nfc/nfc_worker.c @@ -100,7 +100,7 @@ void nfc_worker_detect(NfcWorker* nfc_worker) { rfalNfcDevice* dev_list; rfalNfcDevice* dev; uint8_t dev_cnt; - NfcDeviceCommomData* result = &nfc_worker->dev_data->nfc_data; + NfcDeviceCommonData* result = &nfc_worker->dev_data->nfc_data; while(nfc_worker->state == NfcWorkerStateDetect) { if(furi_hal_nfc_detect(&dev_list, &dev_cnt, 1000, true)) { @@ -141,7 +141,7 @@ void nfc_worker_detect(NfcWorker* nfc_worker) { } void nfc_worker_emulate(NfcWorker* nfc_worker) { - NfcDeviceCommomData* data = &nfc_worker->dev_data->nfc_data; + NfcDeviceCommonData* data = &nfc_worker->dev_data->nfc_data; while(nfc_worker->state == NfcWorkerStateEmulate) { if(furi_hal_nfc_listen(data->uid, data->uid_len, data->atqa, data->sak, false, 100)) { FURI_LOG_I(NFC_WORKER_TAG, "Reader detected"); @@ -328,6 +328,12 @@ void nfc_worker_read_emv(NfcWorker* nfc_worker) { result->emv_data.exp_mon = emv_app.exp_month; result->emv_data.exp_year = emv_app.exp_year; } + if(emv_app.country_code) { + result->emv_data.country_code = emv_app.country_code; + } + if(emv_app.currency_code) { + result->emv_data.currency_code = emv_app.currency_code; + } // Notify caller and exit if(nfc_worker->callback) { nfc_worker->callback(nfc_worker->context); @@ -358,7 +364,7 @@ void nfc_worker_emulate_apdu(NfcWorker* nfc_worker) { uint16_t tx_len = 0; uint8_t* rx_buff; uint16_t* rx_len; - NfcDeviceCommomData params = { + NfcDeviceCommonData params = { .uid = {0xCF, 0x72, 0xd4, 0x40}, .uid_len = 4, .atqa = {0x00, 0x04}, diff --git a/applications/nfc/scenes/nfc_scene_delete.c b/applications/nfc/scenes/nfc_scene_delete.c index 1e3dc292..9098759b 100755 --- a/applications/nfc/scenes/nfc_scene_delete.c +++ b/applications/nfc/scenes/nfc_scene_delete.c @@ -18,7 +18,7 @@ void nfc_scene_delete_on_enter(void* context) { widget_add_button_element( nfc->widget, GuiButtonTypeRight, "Delete", nfc_scene_delete_widget_callback, nfc); char uid_str[32]; - NfcDeviceCommomData* data = &nfc->dev.dev_data.nfc_data; + NfcDeviceCommonData* data = &nfc->dev.dev_data.nfc_data; if(data->uid_len == 4) { snprintf( uid_str, diff --git a/applications/nfc/scenes/nfc_scene_device_info.c b/applications/nfc/scenes/nfc_scene_device_info.c old mode 100644 new mode 100755 index 6bd097d3..032834c5 --- a/applications/nfc/scenes/nfc_scene_device_info.c +++ b/applications/nfc/scenes/nfc_scene_device_info.c @@ -1,6 +1,6 @@ #include "../nfc_i.h" -#define NFC_SCENE_DEVICE_INFO_TEXTBOX_CUSTOM_EVENT (0UL) +#define NFC_SCENE_DEVICE_INFO_BACK_EVENT (0UL) enum { NfcSceneDeviceInfoUid, @@ -8,26 +8,27 @@ enum { }; void nfc_scene_device_info_widget_callback(GuiButtonType result, void* context) { - Nfc* nfc = (Nfc*)context; - + Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, result); } void nfc_scene_device_info_dialog_callback(DialogExResult result, void* context) { - Nfc* nfc = (Nfc*)context; - + Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, result); } void nfc_scene_device_info_text_box_callback(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; + view_dispatcher_send_custom_event(nfc->view_dispatcher, NFC_SCENE_DEVICE_INFO_BACK_EVENT); +} - view_dispatcher_send_custom_event( - nfc->view_dispatcher, NFC_SCENE_DEVICE_INFO_TEXTBOX_CUSTOM_EVENT); +void nfc_scene_device_info_bank_card_callback(GuiButtonType result, void* context) { + Nfc* nfc = context; + view_dispatcher_send_custom_event(nfc->view_dispatcher, NFC_SCENE_DEVICE_INFO_BACK_EVENT); } void nfc_scene_device_info_on_enter(void* context) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; // Setup Custom Widget view widget_add_string_element( @@ -37,7 +38,7 @@ void nfc_scene_device_info_on_enter(void* context) { widget_add_button_element( nfc->widget, GuiButtonTypeRight, "Data", nfc_scene_device_info_widget_callback, nfc); char uid_str[32]; - NfcDeviceCommomData* data = &nfc->dev.dev_data.nfc_data; + NfcDeviceCommonData* data = &nfc->dev.dev_data.nfc_data; if(data->uid_len == 4) { snprintf( uid_str, @@ -107,19 +108,23 @@ void nfc_scene_device_info_on_enter(void* context) { BankCard* bank_card = nfc->bank_card; bank_card_set_name(bank_card, emv_data->name); bank_card_set_number(bank_card, emv_data->number); - if(!strcmp(emv_data->name, "")) { - bank_card_set_cardholder_name(bank_card, emv_data->cardholder); - } + bank_card_set_back_callback(bank_card, nfc_scene_device_info_bank_card_callback, nfc); if(emv_data->exp_mon) { bank_card_set_exp_date(bank_card, emv_data->exp_mon, emv_data->exp_year); } + if(emv_data->country_code) { + bank_card_set_country_name(bank_card, emv_data->country_code); + } + if(emv_data->currency_code) { + bank_card_set_currency_name(bank_card, emv_data->currency_code); + } } scene_manager_set_scene_state(nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoUid); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); } const bool nfc_scene_device_info_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = (Nfc*)context; + Nfc* nfc = context; bool consumed = false; uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneDeviceInfo); diff --git a/applications/nfc/scenes/nfc_scene_emulate_uid.c b/applications/nfc/scenes/nfc_scene_emulate_uid.c index faaf9c7e..3810bec4 100755 --- a/applications/nfc/scenes/nfc_scene_emulate_uid.c +++ b/applications/nfc/scenes/nfc_scene_emulate_uid.c @@ -5,7 +5,7 @@ const void nfc_scene_emulate_uid_on_enter(void* context) { // Setup view Popup* popup = nfc->popup; - NfcDeviceCommomData* data = &nfc->dev.dev_data.nfc_data; + NfcDeviceCommonData* data = &nfc->dev.dev_data.nfc_data; if(strcmp(nfc->dev.dev_name, "")) { nfc_text_store_set(nfc, "%s", nfc->dev.dev_name); diff --git a/applications/nfc/scenes/nfc_scene_read_card_success.c b/applications/nfc/scenes/nfc_scene_read_card_success.c index 42d5cbee..93223a70 100755 --- a/applications/nfc/scenes/nfc_scene_read_card_success.c +++ b/applications/nfc/scenes/nfc_scene_read_card_success.c @@ -18,7 +18,7 @@ void nfc_scene_read_card_success_on_enter(void* context) { notification_message(nfc->notifications, &sequence_success); // Setup view - NfcDeviceCommomData* data = (NfcDeviceCommomData*)&nfc->dev.dev_data.nfc_data; + NfcDeviceCommonData* data = (NfcDeviceCommonData*)&nfc->dev.dev_data.nfc_data; DialogEx* dialog_ex = nfc->dialog_ex; dialog_ex_set_left_button_text(dialog_ex, "Retry"); dialog_ex_set_right_button_text(dialog_ex, "More"); diff --git a/applications/nfc/scenes/nfc_scene_read_emv_app_success.c b/applications/nfc/scenes/nfc_scene_read_emv_app_success.c index 631b0456..dc95bfe6 100755 --- a/applications/nfc/scenes/nfc_scene_read_emv_app_success.c +++ b/applications/nfc/scenes/nfc_scene_read_emv_app_success.c @@ -1,4 +1,5 @@ #include "../nfc_i.h" +#include "../helpers/nfc_emv_parser.h" #define NFC_SCENE_READ_SUCCESS_SHIFT " " @@ -12,7 +13,7 @@ void nfc_scene_read_emv_app_success_on_enter(void* context) { Nfc* nfc = (Nfc*)context; // Setup view - NfcDeviceCommomData* nfc_data = &nfc->dev.dev_data.nfc_data; + NfcDeviceCommonData* nfc_data = &nfc->dev.dev_data.nfc_data; NfcEmvData* emv_data = &nfc->dev.dev_data.emv_data; DialogEx* dialog_ex = nfc->dialog_ex; dialog_ex_set_left_button_text(dialog_ex, "Retry"); @@ -21,9 +22,12 @@ void nfc_scene_read_emv_app_success_on_enter(void* context) { dialog_ex_set_icon(dialog_ex, 8, 13, &I_Medium_chip_22x21); // Display UID and AID string_t aid; - string_init_printf(aid, "AID:"); - for(uint8_t i = 0; i < emv_data->aid_len; i++) { - string_cat_printf(aid, " %02X", emv_data->aid[i]); + string_init(aid); + bool aid_found = nfc_emv_parser_get_aid_name(emv_data->aid, emv_data->aid_len, aid); + if(!aid_found) { + for(uint8_t i = 0; i < emv_data->aid_len; i++) { + string_cat_printf(aid, " %02X", emv_data->aid[i]); + } } nfc_text_store_set( nfc, diff --git a/applications/nfc/scenes/nfc_scene_read_emv_data.c b/applications/nfc/scenes/nfc_scene_read_emv_data.c index 38c5008e..0aeb6fe0 100644 --- a/applications/nfc/scenes/nfc_scene_read_emv_data.c +++ b/applications/nfc/scenes/nfc_scene_read_emv_data.c @@ -16,6 +16,8 @@ const void nfc_scene_read_emv_data_on_enter(void* context) { popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); + // Clear emv data + memset(&nfc->dev.dev_data.emv_data, 0, sizeof(nfc->dev.dev_data.emv_data)); // Start worker nfc_worker_start( nfc->worker, diff --git a/applications/nfc/scenes/nfc_scene_read_emv_data_success.c b/applications/nfc/scenes/nfc_scene_read_emv_data_success.c index c6a9280c..927adb42 100755 --- a/applications/nfc/scenes/nfc_scene_read_emv_data_success.c +++ b/applications/nfc/scenes/nfc_scene_read_emv_data_success.c @@ -1,4 +1,5 @@ #include "../nfc_i.h" +#include "../helpers/nfc_emv_parser.h" void nfc_scene_read_emv_data_success_widget_callback(GuiButtonType result, void* context) { Nfc* nfc = (Nfc*)context; @@ -9,12 +10,15 @@ void nfc_scene_read_emv_data_success_widget_callback(GuiButtonType result, void* void nfc_scene_read_emv_data_success_on_enter(void* context) { Nfc* nfc = (Nfc*)context; NfcEmvData* emv_data = &nfc->dev.dev_data.emv_data; - NfcDeviceCommomData* nfc_data = &nfc->dev.dev_data.nfc_data; + NfcDeviceCommonData* nfc_data = &nfc->dev.dev_data.nfc_data; // Clear device name nfc_device_set_name(&nfc->dev, ""); // Setup Custom Widget view + // Add frame + widget_add_frame_element(nfc->widget, 0, 0, 128, 64, 6); + // Add buttons widget_add_button_element( nfc->widget, GuiButtonTypeLeft, @@ -27,8 +31,10 @@ void nfc_scene_read_emv_data_success_on_enter(void* context) { "Save", nfc_scene_read_emv_data_success_widget_callback, nfc); + // Add card name widget_add_string_element( nfc->widget, 64, 3, AlignCenter, AlignTop, FontSecondary, nfc->dev.dev_data.emv_data.name); + // Add cad number char pan_str[32]; snprintf( pan_str, @@ -43,9 +49,41 @@ void nfc_scene_read_emv_data_success_on_enter(void* context) { emv_data->number[6], emv_data->number[7]); widget_add_string_element(nfc->widget, 64, 13, AlignCenter, AlignTop, FontSecondary, pan_str); + // Parse country code + string_t country_name; + string_init(country_name); + if((emv_data->country_code) && + nfc_emv_parser_get_country_name(emv_data->country_code, country_name)) { + string_t disp_country; + string_init_printf(disp_country, "Reg:%s", country_name); + widget_add_string_element( + nfc->widget, 7, 23, AlignLeft, AlignTop, FontSecondary, string_get_cstr(disp_country)); + string_clear(disp_country); + } + string_clear(country_name); + // Parse currency code + string_t currency_name; + string_init(currency_name); + if((emv_data->currency_code) && + nfc_emv_parser_get_currency_name(emv_data->currency_code, currency_name)) { + string_t disp_currency; + string_init_printf(disp_currency, "Cur:%s", currency_name); + widget_add_string_element( + nfc->widget, + 121, + 23, + AlignRight, + AlignTop, + FontSecondary, + string_get_cstr(disp_currency)); + string_clear(disp_currency); + } + string_clear(currency_name); + // Add ATQA char atqa_str[16]; snprintf(atqa_str, sizeof(atqa_str), "ATQA: %02X%02X", nfc_data->atqa[0], nfc_data->atqa[1]); widget_add_string_element(nfc->widget, 121, 32, AlignRight, AlignTop, FontSecondary, atqa_str); + // Add UID char uid_str[32]; snprintf( uid_str, @@ -56,9 +94,11 @@ void nfc_scene_read_emv_data_success_on_enter(void* context) { nfc_data->uid[2], nfc_data->uid[3]); widget_add_string_element(nfc->widget, 7, 42, AlignLeft, AlignTop, FontSecondary, uid_str); + // Add SAK char sak_str[16]; snprintf(sak_str, sizeof(sak_str), "SAK: %02X", nfc_data->sak); widget_add_string_element(nfc->widget, 121, 42, AlignRight, AlignTop, FontSecondary, sak_str); + // Add expiration date if(emv_data->exp_mon) { char exp_str[16]; snprintf( diff --git a/applications/nfc/scenes/nfc_scene_read_mifare_ul_success.c b/applications/nfc/scenes/nfc_scene_read_mifare_ul_success.c index caf9f5b5..c0a2a9f3 100755 --- a/applications/nfc/scenes/nfc_scene_read_mifare_ul_success.c +++ b/applications/nfc/scenes/nfc_scene_read_mifare_ul_success.c @@ -30,7 +30,7 @@ const void nfc_scene_read_mifare_ul_success_on_enter(void* context) { notification_message(nfc->notifications, &sequence_success); // Setup dialog view - NfcDeviceCommomData* data = (NfcDeviceCommomData*)&nfc->dev.dev_data.nfc_data; + NfcDeviceCommonData* data = (NfcDeviceCommonData*)&nfc->dev.dev_data.nfc_data; DialogEx* dialog_ex = nfc->dialog_ex; dialog_ex_set_left_button_text(dialog_ex, "Retry"); dialog_ex_set_right_button_text(dialog_ex, "More"); diff --git a/applications/nfc/views/bank_card.c b/applications/nfc/views/bank_card.c index f4354792..1be14ba7 100755 --- a/applications/nfc/views/bank_card.c +++ b/applications/nfc/views/bank_card.c @@ -1,5 +1,5 @@ #include "bank_card.h" -#include +#include "../helpers/nfc_emv_parser.h" #include struct BankCard { @@ -43,10 +43,20 @@ void bank_card_set_number(BankCard* bank_card, uint8_t* number) { for(uint8_t i = 0; i < 8; i += 2) { string_cat_printf(num_str, "%02X%02X ", number[i], number[i + 1]); } + // Add number widget_add_string_element( - bank_card->widget, 25, 22, AlignLeft, AlignTop, FontSecondary, string_get_cstr(num_str)); - widget_add_icon_element(bank_card->widget, 6, 20, &I_EMV_Chip_14x11); + bank_card->widget, 64, 32, AlignCenter, AlignTop, FontSecondary, string_get_cstr(num_str)); string_clear(num_str); + // Add icon + widget_add_icon_element(bank_card->widget, 8, 15, &I_Detailed_chip_17x13); + // Add frame + widget_add_frame_element(bank_card->widget, 0, 0, 128, 64, 6); +} + +void bank_card_set_back_callback(BankCard* bank_card, ButtonCallback callback, void* context) { + furi_assert(bank_card); + furi_assert(callback); + widget_add_button_element(bank_card->widget, GuiButtonTypeLeft, "Back", callback, context); } void bank_card_set_exp_date(BankCard* bank_card, uint8_t mon, uint8_t year) { @@ -57,8 +67,42 @@ void bank_card_set_exp_date(BankCard* bank_card, uint8_t mon, uint8_t year) { bank_card->widget, 122, 54, AlignRight, AlignBottom, FontSecondary, exp_date_str); } -void bank_card_set_cardholder_name(BankCard* bank_card, char* name) { +void bank_card_set_country_name(BankCard* bank_card, uint16_t country_code) { furi_assert(bank_card); - furi_assert(name); - widget_add_string_element(bank_card->widget, 6, 37, AlignLeft, AlignTop, FontSecondary, name); + string_t country_name; + string_init(country_name); + if(nfc_emv_parser_get_country_name(country_code, country_name)) { + string_t disp_country; + string_init_printf(disp_country, "Reg:%s", country_name); + widget_add_string_element( + bank_card->widget, + 120, + 18, + AlignRight, + AlignTop, + FontSecondary, + string_get_cstr(disp_country)); + string_clear(disp_country); + } + string_clear(country_name); +} + +void bank_card_set_currency_name(BankCard* bank_card, uint16_t currency_code) { + furi_assert(bank_card); + string_t currency_name; + string_init(currency_name); + if(nfc_emv_parser_get_currency_name(currency_code, currency_name)) { + string_t disp_currency; + string_init_printf(disp_currency, "Cur:%s", currency_name); + widget_add_string_element( + bank_card->widget, + 31, + 18, + AlignLeft, + AlignTop, + FontSecondary, + string_get_cstr(disp_currency)); + string_clear(disp_currency); + } + string_clear(currency_name); } diff --git a/applications/nfc/views/bank_card.h b/applications/nfc/views/bank_card.h index f7252a80..e50309fa 100644 --- a/applications/nfc/views/bank_card.h +++ b/applications/nfc/views/bank_card.h @@ -1,11 +1,10 @@ #pragma once #include #include +#include typedef struct BankCard BankCard; -typedef void (*BankCardBackCallback)(void); - BankCard* bank_card_alloc(); void bank_card_free(BankCard* bank_card); @@ -14,10 +13,14 @@ void bank_card_clear(BankCard* bank_card); View* bank_card_get_view(BankCard* bank_card); +void bank_card_set_back_callback(BankCard* bank_card, ButtonCallback callback, void* context); + void bank_card_set_name(BankCard* bank_card, char* name); void bank_card_set_number(BankCard* bank_card, uint8_t* number); void bank_card_set_exp_date(BankCard* bank_card, uint8_t mon, uint8_t year); -void bank_card_set_cardholder_name(BankCard* bank_card, char* name); +void bank_card_set_country_name(BankCard* bank_card, uint16_t country_code); + +void bank_card_set_currency_name(BankCard* bank_card, uint16_t currency_code); diff --git a/applications/subghz/scenes/subghz_scene_analyze.c b/applications/subghz/scenes/subghz_scene_analyze.c deleted file mode 100644 index 33a891f2..00000000 --- a/applications/subghz/scenes/subghz_scene_analyze.c +++ /dev/null @@ -1,19 +0,0 @@ -#include "../subghz_i.h" - -const void subghz_scene_analyze_on_enter(void* context) { - SubGhz* subghz = context; - view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewAnalyze); -} - -const bool subghz_scene_analyze_on_event(void* context, SceneManagerEvent event) { - SubGhz* subghz = context; - if(event.type == SceneManagerEventTypeTick) { - notification_message(subghz->notifications, &sequence_blink_blue_10); - return true; - } - return false; -} - -const void subghz_scene_analyze_on_exit(void* context) { - // SubGhz* subghz = context; -} diff --git a/applications/subghz/scenes/subghz_scene_config.h b/applications/subghz/scenes/subghz_scene_config.h index 460001d2..10ecd1c6 100644 --- a/applications/subghz/scenes/subghz_scene_config.h +++ b/applications/subghz/scenes/subghz_scene_config.h @@ -1,13 +1,12 @@ ADD_SCENE(subghz, start, Start) -ADD_SCENE(subghz, analyze, Analyze) -ADD_SCENE(subghz, read, Read) ADD_SCENE(subghz, receiver, Receiver) ADD_SCENE(subghz, save_name, SaveName) ADD_SCENE(subghz, save_success, SaveSuccess) ADD_SCENE(subghz, saved, Saved) ADD_SCENE(subghz, transmitter, Transmitter) -ADD_SCENE(subghz, static, Static) +ADD_SCENE(subghz, no_man, NoMan) ADD_SCENE(subghz, test, Test) +ADD_SCENE(subghz, test_static, TestStatic) ADD_SCENE(subghz, test_carrier, TestCarrier) ADD_SCENE(subghz, test_packet, TestPacket) ADD_SCENE(subghz, set_type, SetType) diff --git a/applications/subghz/scenes/subghz_scene_no_man.c b/applications/subghz/scenes/subghz_scene_no_man.c new file mode 100644 index 00000000..d5f2e0de --- /dev/null +++ b/applications/subghz/scenes/subghz_scene_no_man.c @@ -0,0 +1,48 @@ +#include "../subghz_i.h" + +#define SCENE_NO_MAN_CUSTOM_EVENT (11UL) + +void subghz_scene_no_man_popup_callback(void* context) { + SubGhz* subghz = context; + view_dispatcher_send_custom_event(subghz->view_dispatcher, SCENE_NO_MAN_CUSTOM_EVENT); +} + +const void subghz_scene_no_man_on_enter(void* context) { + SubGhz* subghz = context; + + // Setup view + Popup* popup = subghz->popup; + popup_set_icon(popup, 32, 12, &I_DolphinFirstStart7_61x51); + popup_set_header(popup, "No manufactory key", 13, 8, AlignLeft, AlignBottom); + popup_set_timeout(popup, 1500); + popup_set_context(popup, subghz); + popup_set_callback(popup, subghz_scene_no_man_popup_callback); + popup_enable_timeout(popup); + view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewPopup); +} + +const bool subghz_scene_no_man_on_event(void* context, SceneManagerEvent event) { + SubGhz* subghz = context; + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SCENE_NO_MAN_CUSTOM_EVENT) { + scene_manager_search_and_switch_to_previous_scene( + subghz->scene_manager, SubGhzSceneStart); + return true; + } + } + return false; +} + +const void subghz_scene_no_man_on_exit(void* context) { + SubGhz* subghz = context; + + // Clear view + Popup* popup = subghz->popup; + popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); + popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); + popup_set_icon(popup, 0, 0, NULL); + popup_set_callback(popup, NULL); + popup_set_context(popup, NULL); + popup_set_timeout(popup, 0); + popup_disable_timeout(popup); +} diff --git a/applications/subghz/scenes/subghz_scene_read.c b/applications/subghz/scenes/subghz_scene_read.c deleted file mode 100644 index 7cab340d..00000000 --- a/applications/subghz/scenes/subghz_scene_read.c +++ /dev/null @@ -1,62 +0,0 @@ -#include "../subghz_i.h" - -#define GUBGHZ_READ_CUSTOM_EVENT (10UL) - -void subghz_read_protocol_callback(SubGhzProtocolCommon* parser, void* context) { - furi_assert(context); - SubGhz* subghz = context; - subghz->protocol_result = parser; - view_dispatcher_send_custom_event(subghz->view_dispatcher, GUBGHZ_READ_CUSTOM_EVENT); -} -void subghz_scene_read_callback(DialogExResult result, void* context) { - SubGhz* subghz = context; - view_dispatcher_send_custom_event(subghz->view_dispatcher, result); -} - -const void subghz_scene_read_on_enter(void* context) { - SubGhz* subghz = context; - - // Setup view - DialogEx* dialog_ex = subghz->dialog_ex; - - dialog_ex_set_header(dialog_ex, "SubGhz 433.92", 36, 6, AlignLeft, AlignCenter); - dialog_ex_set_icon(dialog_ex, 10, 12, &I_RFIDDolphinReceive_97x61); - - //Start CC1101 rx - subghz_begin(FuriHalSubGhzPresetOokAsync); - subghz_rx(433920000); - - furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, subghz->worker); - subghz_worker_start(subghz->worker); - subghz_protocol_enable_dump(subghz->protocol, subghz_read_protocol_callback, subghz); - - view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewDialogEx); -} - -const bool subghz_scene_read_on_event(void* context, SceneManagerEvent event) { - SubGhz* subghz = context; - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GUBGHZ_READ_CUSTOM_EVENT) { - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiver); - notification_message(subghz->notifications, &sequence_success); - return true; - } - } else if(event.type == SceneManagerEventTypeTick) { - notification_message(subghz->notifications, &sequence_blink_blue_10); - return true; - } - return false; -} - -const void subghz_scene_read_on_exit(void* context) { - SubGhz* subghz = context; - - // Stop CC1101 - subghz_worker_stop(subghz->worker); - furi_hal_subghz_stop_async_rx(); - subghz_end(); - - DialogEx* dialog_ex = subghz->dialog_ex; - dialog_ex_set_header(dialog_ex, NULL, 0, 0, AlignCenter, AlignCenter); - dialog_ex_set_icon(dialog_ex, 0, 0, NULL); -} diff --git a/applications/subghz/scenes/subghz_scene_receiver.c b/applications/subghz/scenes/subghz_scene_receiver.c index 1fe9a466..3c9ba375 100644 --- a/applications/subghz/scenes/subghz_scene_receiver.c +++ b/applications/subghz/scenes/subghz_scene_receiver.c @@ -13,7 +13,9 @@ const void subghz_scene_receiver_on_enter(void* context) { subghz_receiver_set_callback(subghz_receiver, subghz_scene_receiver_callback, subghz); - subghz_receiver_set_protocol(subghz_receiver, subghz->protocol_result); + subghz_receiver_set_protocol(subghz_receiver, subghz->protocol_result, subghz->protocol); + subghz_receiver_set_worker(subghz_receiver, subghz->worker); + subghz->state_notifications = NOTIFICATION_RX_STATE; view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewReceiver); } @@ -21,12 +23,57 @@ const bool subghz_scene_receiver_on_event(void* context, SceneManagerEvent event SubGhz* subghz = context; if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubghzReceverEventSave) { + switch(event.event) { + case SubghzReceverEventSave: + subghz->state_notifications = NOTIFICATION_IDLE_STATE; + subghz->frequency = subghz_receiver_get_frequency(subghz->subghz_receiver); + subghz->preset = subghz_receiver_get_preset(subghz->subghz_receiver); + subghz->protocol_result = subghz_receiver_get_protocol(subghz->subghz_receiver); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName); return true; - } else if(event.event == SubghzReceverEventBack) { + break; + case SubghzReceverEventBack: scene_manager_previous_scene(subghz->scene_manager); return true; + break; + case SubghzReceverEventSendStart: + subghz->state_notifications = NOTIFICATION_TX_STATE; + subghz->frequency = subghz_receiver_get_frequency(subghz->subghz_receiver); + subghz->preset = subghz_receiver_get_preset(subghz->subghz_receiver); + subghz->protocol_result = subghz_receiver_get_protocol(subghz->subghz_receiver); + subghz_transmitter_tx_start(subghz); + return true; + break; + case SubghzReceverEventSendStop: + subghz->state_notifications = NOTIFICATION_IDLE_STATE; + subghz_transmitter_tx_stop(subghz); + return true; + break; + case SubghzReceverEventMain: + subghz->state_notifications = NOTIFICATION_RX_STATE; + return true; + break; + case SubghzReceverEventConfig: + subghz->state_notifications = NOTIFICATION_IDLE_STATE; + return true; + break; + case SubghzReceverEventSendHistoryFull: + subghz->state_notifications = NOTIFICATION_IDLE_STATE; + return true; + break; + default: + break; + } + } else if(event.type == SceneManagerEventTypeTick) { + switch(subghz->state_notifications) { + case NOTIFICATION_TX_STATE: + notification_message(subghz->notifications, &sequence_blink_red_10); + break; + case NOTIFICATION_RX_STATE: + notification_message(subghz->notifications, &sequence_blink_blue_10); + break; + default: + break; } } return false; diff --git a/applications/subghz/scenes/subghz_scene_save_name.c b/applications/subghz/scenes/subghz_scene_save_name.c index 5a3452f8..fba0c622 100644 --- a/applications/subghz/scenes/subghz_scene_save_name.c +++ b/applications/subghz/scenes/subghz_scene_save_name.c @@ -19,7 +19,7 @@ const void subghz_scene_save_name_on_enter(void* context) { set_random_name(subghz->text_store, sizeof(subghz->text_store)); dev_name_empty = true; - text_input_set_header_text(text_input, "Name the KEY"); + text_input_set_header_text(text_input, "Name signal"); text_input_set_result_callback( text_input, subghz_scene_save_name_text_input_callback, diff --git a/applications/subghz/scenes/subghz_scene_save_success.c b/applications/subghz/scenes/subghz_scene_save_success.c index 4cbc9fcd..4d26ff54 100644 --- a/applications/subghz/scenes/subghz_scene_save_success.c +++ b/applications/subghz/scenes/subghz_scene_save_success.c @@ -25,8 +25,12 @@ const bool subghz_scene_save_success_on_event(void* context, SceneManagerEvent e SubGhz* subghz = context; if(event.type == SceneManagerEventTypeCustom) { if(event.event == SCENE_SAVE_SUCCESS_CUSTOM_EVENT) { - return scene_manager_search_and_switch_to_previous_scene( - subghz->scene_manager, SubGhzSceneStart); + if(!scene_manager_search_and_switch_to_previous_scene( + subghz->scene_manager, SubGhzSceneReceiver)) { + scene_manager_search_and_switch_to_previous_scene( + subghz->scene_manager, SubGhzSceneStart); + } + return true; } } return false; diff --git a/applications/subghz/scenes/subghz_scene_saved.c b/applications/subghz/scenes/subghz_scene_saved.c index 09b7a4ac..3bfec82a 100644 --- a/applications/subghz/scenes/subghz_scene_saved.c +++ b/applications/subghz/scenes/subghz_scene_saved.c @@ -3,7 +3,7 @@ const void subghz_scene_saved_on_enter(void* context) { SubGhz* subghz = context; - if(subghz_saved_protocol_select(subghz)) { + if(subghz_load_protocol_from_file(subghz)) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneTransmitter); } else { scene_manager_search_and_switch_to_previous_scene(subghz->scene_manager, SubGhzSceneStart); diff --git a/applications/subghz/scenes/subghz_scene_set_type.c b/applications/subghz/scenes/subghz_scene_set_type.c index d3c36f54..d0981792 100644 --- a/applications/subghz/scenes/subghz_scene_set_type.c +++ b/applications/subghz/scenes/subghz_scene_set_type.c @@ -32,31 +32,31 @@ const void subghz_scene_set_type_on_enter(void* context) { submenu_add_item( subghz->submenu, - "Pricenton", + "Princeton_433", SubmenuIndexPricenton, subghz_scene_set_type_submenu_callback, subghz); submenu_add_item( subghz->submenu, - "Nice Flo 12bit", + "Nice Flo 12bit_433", SubmenuIndexNiceFlo12bit, subghz_scene_set_type_submenu_callback, subghz); submenu_add_item( subghz->submenu, - "Nice Flo 24bit", + "Nice Flo 24bit_433", SubmenuIndexNiceFlo24bit, subghz_scene_set_type_submenu_callback, subghz); submenu_add_item( subghz->submenu, - "CAME 12bit", + "CAME 12bit_433", SubmenuIndexCAME12bit, subghz_scene_set_type_submenu_callback, subghz); submenu_add_item( subghz->submenu, - "CAME 24bit", + "CAME 24bit_433", SubmenuIndexCAME24bit, subghz_scene_set_type_submenu_callback, subghz); @@ -64,13 +64,13 @@ const void subghz_scene_set_type_on_enter(void* context) { // subghz->submenu, "Nero Sketch", SubmenuIndexNeroSketch, subghz_scene_set_type_submenu_callback, subghz); submenu_add_item( subghz->submenu, - "Gate TX", + "Gate TX_433", SubmenuIndexGateTX, subghz_scene_set_type_submenu_callback, subghz); submenu_add_item( subghz->submenu, - "DoorHan", + "DoorHan_433", SubmenuIndexDoorHan, subghz_scene_set_type_submenu_callback, subghz); @@ -146,11 +146,15 @@ const bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event subghz->protocol_result->serial = key & 0x0FFFFFFF; subghz->protocol_result->btn = 0x2; //btn 0x1, 0x2, 0x4, 0x8 subghz->protocol_result->cnt = 0x0003; - subghz_protocol_keeloq_set_manufacture_name(subghz->protocol_result, "DoorHan"); - subghz->protocol_result->code_last_found = - subghz_protocol_keeloq_gen_key(subghz->protocol_result); - - generated_protocol = true; + if(subghz_protocol_keeloq_set_manufacture_name( + subghz->protocol_result, "DoorHan")) { + subghz->protocol_result->code_last_found = + subghz_protocol_keeloq_gen_key(subghz->protocol_result); + generated_protocol = true; + } else { + generated_protocol = false; + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneNoMan); + } } break; @@ -159,6 +163,8 @@ const bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event break; } if(generated_protocol) { + subghz->frequency = subghz_frequencies[subghz_frequencies_433_92]; + subghz->preset = FuriHalSubGhzPresetOok650Async; scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName); return true; } diff --git a/applications/subghz/scenes/subghz_scene_start.c b/applications/subghz/scenes/subghz_scene_start.c index d30536a5..2baac87a 100644 --- a/applications/subghz/scenes/subghz_scene_start.c +++ b/applications/subghz/scenes/subghz_scene_start.c @@ -1,10 +1,8 @@ #include "../subghz_i.h" enum SubmenuIndex { - SubmenuIndexAnalyze, SubmenuIndexRead, SubmenuIndexSaved, - SubmenuIndexStatic, SubmenuIndexTest, SubmenuIndexAddManualy, }; @@ -19,12 +17,6 @@ const void subghz_scene_start_on_enter(void* context) { if(subghz->state_notifications == NOTIFICATION_STARTING_STATE) { subghz->state_notifications = NOTIFICATION_IDLE_STATE; } - submenu_add_item( - subghz->submenu, - "Analyze", - SubmenuIndexAnalyze, - subghz_scene_start_submenu_callback, - subghz); submenu_add_item( subghz->submenu, "Read", SubmenuIndexRead, subghz_scene_start_submenu_callback, subghz); submenu_add_item( @@ -35,8 +27,6 @@ const void subghz_scene_start_on_enter(void* context) { SubmenuIndexAddManualy, subghz_scene_start_submenu_callback, subghz); - submenu_add_item( - subghz->submenu, "Static", SubmenuIndexStatic, subghz_scene_start_submenu_callback, subghz); submenu_add_item( subghz->submenu, "Test", SubmenuIndexTest, subghz_scene_start_submenu_callback, subghz); @@ -50,15 +40,10 @@ const bool subghz_scene_start_on_event(void* context, SceneManagerEvent event) { SubGhz* subghz = context; if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubmenuIndexAnalyze) { - scene_manager_set_scene_state( - subghz->scene_manager, SubGhzSceneStart, SubmenuIndexAnalyze); - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneAnalyze); - return true; - } else if(event.event == SubmenuIndexRead) { + if(event.event == SubmenuIndexRead) { scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneStart, SubmenuIndexRead); - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneRead); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReceiver); return true; } else if(event.event == SubmenuIndexSaved) { scene_manager_set_scene_state( @@ -70,11 +55,6 @@ const bool subghz_scene_start_on_event(void* context, SceneManagerEvent event) { subghz->scene_manager, SubGhzSceneStart, SubmenuIndexAddManualy); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSetType); return true; - } else if(event.event == SubmenuIndexStatic) { - scene_manager_set_scene_state( - subghz->scene_manager, SubGhzSceneStart, SubmenuIndexStatic); - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneStatic); - return true; } else if(event.event == SubmenuIndexTest) { scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneStart, SubmenuIndexTest); diff --git a/applications/subghz/scenes/subghz_scene_test.c b/applications/subghz/scenes/subghz_scene_test.c index 69b6c28e..03f0b595 100644 --- a/applications/subghz/scenes/subghz_scene_test.c +++ b/applications/subghz/scenes/subghz_scene_test.c @@ -3,6 +3,7 @@ enum SubmenuIndex { SubmenuIndexCarrier, SubmenuIndexPacket, + SubmenuIndexStatic, }; void subghz_scene_test_submenu_callback(void* context, uint32_t index) { @@ -21,6 +22,8 @@ const void subghz_scene_test_on_enter(void* context) { subghz); submenu_add_item( subghz->submenu, "Packet", SubmenuIndexPacket, subghz_scene_test_submenu_callback, subghz); + submenu_add_item( + subghz->submenu, "Static", SubmenuIndexStatic, subghz_scene_test_submenu_callback, subghz); submenu_set_selected_item( subghz->submenu, scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneTest)); @@ -42,6 +45,11 @@ const bool subghz_scene_test_on_event(void* context, SceneManagerEvent event) { subghz->scene_manager, SubGhzSceneTest, SubmenuIndexPacket); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneTestPacket); return true; + } else if(event.event == SubmenuIndexStatic) { + scene_manager_set_scene_state( + subghz->scene_manager, SubGhzSceneTest, SubmenuIndexStatic); + scene_manager_next_scene(subghz->scene_manager, SubGhzSceneTestStatic); + return true; } } return false; diff --git a/applications/subghz/scenes/subghz_scene_static.c b/applications/subghz/scenes/subghz_scene_test_static.c similarity index 51% rename from applications/subghz/scenes/subghz_scene_static.c rename to applications/subghz/scenes/subghz_scene_test_static.c index 64d593d1..6d1403f5 100644 --- a/applications/subghz/scenes/subghz_scene_static.c +++ b/applications/subghz/scenes/subghz_scene_test_static.c @@ -1,15 +1,15 @@ #include "../subghz_i.h" -const void subghz_scene_static_on_enter(void* context) { +const void subghz_scene_test_static_on_enter(void* context) { SubGhz* subghz = context; view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewStatic); } -const bool subghz_scene_static_on_event(void* context, SceneManagerEvent event) { +const bool subghz_scene_test_static_on_event(void* context, SceneManagerEvent event) { // SubGhz* subghz = context; return false; } -const void subghz_scene_static_on_exit(void* context) { +const void subghz_scene_test_static_on_exit(void* context) { // SubGhz* subghz = context; } diff --git a/applications/subghz/scenes/subghz_scene_transmitter.c b/applications/subghz/scenes/subghz_scene_transmitter.c index e28e6d88..c363fff6 100644 --- a/applications/subghz/scenes/subghz_scene_transmitter.c +++ b/applications/subghz/scenes/subghz_scene_transmitter.c @@ -13,6 +13,7 @@ const void subghz_scene_transmitter_on_enter(void* context) { subghz_transmitter_set_callback(subghz_transmitter, subghz_scene_transmitter_callback, subghz); subghz_transmitter_set_protocol(subghz_transmitter, subghz->protocol_result); + subghz_transmitter_set_frequency_preset(subghz_transmitter, subghz->frequency, subghz->preset); view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewTransmitter); @@ -30,12 +31,18 @@ const bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent ev } else if(event.event == SubghzTransmitterEventSendStop) { subghz->state_notifications = NOTIFICATION_IDLE_STATE; subghz_transmitter_tx_stop(subghz); + subghz_sleep(); return true; } else if(event.event == SubghzTransmitterEventBack) { subghz->state_notifications = NOTIFICATION_IDLE_STATE; scene_manager_search_and_switch_to_previous_scene( subghz->scene_manager, SubGhzSceneStart); return true; + } else if(event.event == SubghzTransmitterEventNoMan) { + subghz->state_notifications = NOTIFICATION_IDLE_STATE; + scene_manager_search_and_switch_to_previous_scene( + subghz->scene_manager, SubGhzSceneNoMan); + return true; } } else if(event.type == SceneManagerEventTypeTick) { if(subghz->state_notifications == NOTIFICATION_TX_STATE) { diff --git a/applications/subghz/subghz.c b/applications/subghz/subghz.c index acc054ab..865ec8df 100644 --- a/applications/subghz/subghz.c +++ b/applications/subghz/subghz.c @@ -70,13 +70,6 @@ SubGhz* subghz_alloc() { view_dispatcher_add_view( subghz->view_dispatcher, SubGhzViewMenu, submenu_get_view(subghz->submenu)); - // Analyze - subghz->subghz_analyze = subghz_analyze_alloc(); - view_dispatcher_add_view( - subghz->view_dispatcher, - SubGhzViewAnalyze, - subghz_analyze_get_view(subghz->subghz_analyze)); - // Receiver subghz->subghz_receiver = subghz_receiver_alloc(); view_dispatcher_add_view( @@ -121,9 +114,11 @@ SubGhz* subghz_alloc() { subghz_test_packet_get_view(subghz->subghz_test_packet)); // Static send - subghz->subghz_static = subghz_static_alloc(); + subghz->subghz_test_static = subghz_test_static_alloc(); view_dispatcher_add_view( - subghz->view_dispatcher, SubGhzViewStatic, subghz_static_get_view(subghz->subghz_static)); + subghz->view_dispatcher, + SubGhzViewStatic, + subghz_test_static_get_view(subghz->subghz_test_static)); //init Worker & Protocol subghz->worker = subghz_worker_alloc(); @@ -134,8 +129,8 @@ SubGhz* subghz_alloc() { subghz->worker, (SubGhzWorkerPairCallback)subghz_protocol_parse); subghz_worker_set_context(subghz->worker, subghz->protocol); - subghz_protocol_load_keeloq_file(subghz->protocol, "/ext/assets/subghz/keeloq_mfcodes"); - subghz_protocol_load_nice_flor_s_file(subghz->protocol, "/ext/assets/subghz/nice_floor_s_rx"); + subghz_protocol_load_keeloq_file(subghz->protocol, "/ext/subghz/keeloq_mfcodes"); + subghz_protocol_load_nice_flor_s_file(subghz->protocol, "/ext/subghz/nice_floor_s_rx"); //subghz_protocol_enable_dump_text(subghz->protocol, subghz_text_callback, subghz); @@ -155,11 +150,7 @@ void subghz_free(SubGhz* subghz) { // Static view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewStatic); - subghz_static_free(subghz->subghz_static); - - // Analyze - view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewAnalyze); - subghz_analyze_free(subghz->subghz_analyze); + subghz_test_static_free(subghz->subghz_test_static); // Receiver view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewReceiver); diff --git a/applications/subghz/subghz_cli.c b/applications/subghz/subghz_cli.c index 0e4eb7fe..e5da483e 100644 --- a/applications/subghz/subghz_cli.c +++ b/applications/subghz/subghz_cli.c @@ -42,7 +42,7 @@ void subghz_cli_command_tx_carrier(Cli* cli, string_t args, void* context) { } furi_hal_subghz_reset(); - furi_hal_subghz_load_preset(FuriHalSubGhzPresetOokAsync); + furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); frequency = furi_hal_subghz_set_frequency_and_path(frequency); hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); @@ -79,7 +79,7 @@ void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context) { } furi_hal_subghz_reset(); - furi_hal_subghz_load_preset(FuriHalSubGhzPresetOokAsync); + furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); frequency = furi_hal_subghz_set_frequency_and_path(frequency); printf("Receiving at frequency %lu Hz\r\n", frequency); printf("Press CTRL+C to stop\r\n"); @@ -134,12 +134,12 @@ void subghz_cli_command_tx(Cli* cli, string_t args, void* context) { protocol->common.code_last_found = key; protocol->common.code_last_count_bit = 24; - SubGhzProtocolEncoderCommon* encoder = subghz_protocol_encoder_common_alloc(); + SubGhzProtocolCommonEncoder* encoder = subghz_protocol_encoder_common_alloc(); encoder->repeat = repeat; subghz_protocol_princeton_send_key(protocol, encoder); furi_hal_subghz_reset(); - furi_hal_subghz_load_preset(FuriHalSubGhzPresetOokAsync); + furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); frequency = furi_hal_subghz_set_frequency_and_path(frequency); furi_hal_subghz_start_async_tx(subghz_protocol_encoder_common_yield, encoder); @@ -206,13 +206,13 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) { furi_check(instance->stream); SubGhzProtocol* protocol = subghz_protocol_alloc(); - subghz_protocol_load_keeloq_file(protocol, "/ext/assets/subghz/keeloq_mfcodes"); - subghz_protocol_load_nice_flor_s_file(protocol, "/ext/assets/subghz/nice_floor_s_rx"); + subghz_protocol_load_keeloq_file(protocol, "/ext/subghz/keeloq_mfcodes"); + subghz_protocol_load_nice_flor_s_file(protocol, "/ext/subghz/nice_floor_s_rx"); subghz_protocol_enable_dump_text(protocol, subghz_cli_command_rx_text_callback, instance); // Configure radio furi_hal_subghz_reset(); - furi_hal_subghz_load_preset(FuriHalSubGhzPresetOokAsync); + furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); frequency = furi_hal_subghz_set_frequency_and_path(frequency); hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); diff --git a/applications/subghz/subghz_history.c b/applications/subghz/subghz_history.c new file mode 100644 index 00000000..16fac74b --- /dev/null +++ b/applications/subghz/subghz_history.c @@ -0,0 +1,164 @@ +#include "subghz_history.h" +#include +#include +#include + +#include +#include + +#define SUBGHZ_HISTORY_MAX 50 + +typedef struct SubGhzHistoryStruct SubGhzHistoryStruct; + +struct SubGhzHistoryStruct { + const char* name; + const char* manufacture_name; + uint8_t type_protocol; + uint8_t code_count_bit; + uint64_t code_found; + uint16_t te; + FuriHalSubGhzPreset preset; + uint32_t real_frequency; +}; + +struct SubGhzHistory { + uint32_t last_update_timestamp; + uint16_t last_index_write; + uint64_t code_last_found; + SubGhzHistoryStruct history[SUBGHZ_HISTORY_MAX]; + SubGhzProtocolCommonLoad data; +}; + +SubGhzHistory* subghz_history_alloc(void) { + SubGhzHistory* instance = furi_alloc(sizeof(SubGhzHistory)); + return instance; +} + +void subghz_history_free(SubGhzHistory* instance) { + furi_assert(instance); + free(instance); +} + +void subghz_history_set_frequency_preset( + SubGhzHistory* instance, + uint16_t idx, + uint32_t frequency, + FuriHalSubGhzPreset preset) { + furi_assert(instance); + if(instance->last_index_write >= SUBGHZ_HISTORY_MAX) return; + instance->history[idx].preset = preset; + instance->history[idx].real_frequency = frequency; +} + +uint32_t subghz_history_get_frequency(SubGhzHistory* instance, uint16_t idx) { + furi_assert(instance); + return instance->history[idx].real_frequency; +} + +FuriHalSubGhzPreset subghz_history_get_preset(SubGhzHistory* instance, uint16_t idx) { + furi_assert(instance); + return instance->history[idx].preset; +} + +void subghz_history_clean(SubGhzHistory* instance) { + furi_assert(instance); + instance->last_index_write = 0; + instance->code_last_found = 0; +} + +uint16_t subghz_history_get_item(SubGhzHistory* instance) { + furi_assert(instance); + return instance->last_index_write; +} + +uint8_t subghz_history_get_type_protocol(SubGhzHistory* instance, uint16_t idx) { + furi_assert(instance); + return instance->history[idx].type_protocol; +} + +const char* subghz_history_get_name(SubGhzHistory* instance, uint16_t idx) { + furi_assert(instance); + return instance->history[idx].name; +} + +SubGhzProtocolCommonLoad* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx) { + furi_assert(instance); + instance->data.code_found = instance->history[idx].code_found; + instance->data.code_count_bit = instance->history[idx].code_count_bit; + instance->data.param1 = instance->history[idx].te; + return &instance->data; +} +bool subghz_history_get_text_space_left(SubGhzHistory* instance, string_t output) { + furi_assert(instance); + if(instance->last_index_write == SUBGHZ_HISTORY_MAX) { + if(output != NULL) string_printf(output, "Memory is FULL"); + return true; + } + if(output != NULL) + string_printf(output, "%02u/%02u", instance->last_index_write, SUBGHZ_HISTORY_MAX); + return false; +} +void subghz_history_get_text_item_menu(SubGhzHistory* instance, string_t output, uint16_t idx) { + if(instance->history[idx].code_count_bit < 33) { + string_printf( + output, + "%s %lX", + instance->history[idx].name, + (uint32_t)(instance->history[idx].code_found & 0xFFFFFFFF)); + } else { + string_t str_buff; + string_init(str_buff); + if(strcmp(instance->history[idx].name, "KeeLoq") == 0) { + string_set(str_buff, "KL "); + string_cat(str_buff, instance->history[idx].manufacture_name); + } else if(strcmp(instance->history[idx].name, "Star Line") == 0) { + string_set(str_buff, "SL "); + string_cat(str_buff, instance->history[idx].manufacture_name); + } else { + string_set(str_buff, instance->history[idx].name); + } + + string_printf( + output, + "%s %lX%08lX", + string_get_cstr(str_buff), + (uint32_t)(instance->history[idx].code_found >> 32), + (uint32_t)(instance->history[idx].code_found & 0xFFFFFFFF)); + string_clear(str_buff); + } +} + +void subghz_history_add_to_history(SubGhzHistory* instance, void* context) { + furi_assert(instance); + furi_assert(context); + SubGhzProtocolCommon* protocol = context; + + if(instance->last_index_write >= SUBGHZ_HISTORY_MAX) return; + if((instance->code_last_found == (protocol->code_last_found & 0xFFFF0FFFFFFFFFFF)) && + ((millis() - instance->last_update_timestamp) < 500)) { + instance->last_update_timestamp = millis(); + return; + } + + instance->code_last_found = protocol->code_last_found & 0xFFFF0FFFFFFFFFFF; + instance->last_update_timestamp = millis(); + + instance->history[instance->last_index_write].te = 0; + instance->history[instance->last_index_write].manufacture_name = NULL; + instance->history[instance->last_index_write].name = protocol->name; + instance->history[instance->last_index_write].code_count_bit = protocol->code_last_count_bit; + instance->history[instance->last_index_write].code_found = protocol->code_last_found; + if(strcmp(protocol->name, "KeeLoq") == 0) { + instance->history[instance->last_index_write].manufacture_name = + subghz_protocol_keeloq_find_and_get_manufacture_name(protocol); + } else if(strcmp(protocol->name, "Star Line") == 0) { + instance->history[instance->last_index_write].manufacture_name = + subghz_protocol_star_line_find_and_get_manufacture_name(protocol); + } else if(strcmp(protocol->name, "Princeton") == 0) { + instance->history[instance->last_index_write].te = + subghz_protocol_princeton_get_te(protocol); + } + instance->history[instance->last_index_write].type_protocol = protocol->type_protocol; + + instance->last_index_write++; +} \ No newline at end of file diff --git a/applications/subghz/subghz_history.h b/applications/subghz/subghz_history.h new file mode 100644 index 00000000..a1f7ee7f --- /dev/null +++ b/applications/subghz/subghz_history.h @@ -0,0 +1,106 @@ +#pragma once + +#include + +typedef struct SubGhzHistory SubGhzHistory; + +/** Allocate SubGhzHistory + * + * @return SubGhzHistory* + */ +SubGhzHistory* subghz_history_alloc(void); + +/** Free SubGhzHistory + * + * @param instance - SubGhzHistory instance + */ +void subghz_history_free(SubGhzHistory* instance); + +/** Clear history + * + * @param instance - SubGhzHistory instance + */ +void subghz_history_clean(SubGhzHistory* instance); + +/** Set frequency and preset to history[idx] + * + * @param instance - SubGhzHistory instance + * @param idx - record index + * @param frequency - frequency Hz + * @param preset - FuriHalSubGhzPreset preset + */ +void subghz_history_set_frequency_preset( + SubGhzHistory* instance, + uint16_t idx, + uint32_t frequency, + FuriHalSubGhzPreset preset); + +/** Get frequency to history[idx] + * + * @param instance - SubGhzHistory instance + * @param idx - record index + * @return frequency - frequency Hz + */ +uint32_t subghz_history_get_frequency(SubGhzHistory* instance, uint16_t idx); + +/** Get preset to history[idx] + * + * @param instance - SubGhzHistory instance + * @param idx - record index + * @return preset - FuriHalSubGhzPreset preset + */ +FuriHalSubGhzPreset subghz_history_get_preset(SubGhzHistory* instance, uint16_t idx); + +/** Get history index write + * + * @param instance - SubGhzHistory instance + * @return idx - current record index + */ +uint16_t subghz_history_get_item(SubGhzHistory* instance); + +/** Get type protocol to history[idx] + * + * @param instance - SubGhzHistory instance + * @param idx - record index + * @return type - type protocol + */ +uint8_t subghz_history_get_type_protocol(SubGhzHistory* instance, uint16_t idx); + +/** Get name protocol to history[idx] + * + * @param instance - SubGhzHistory instance + * @param idx - record index + * @return name - const char* name protocol + */ +const char* subghz_history_get_name(SubGhzHistory* instance, uint16_t idx); + +/** Get string item menu to history[idx] + * + * @param instance - SubGhzHistory instance + * @param output - string_t output + * @param idx - record index + */ +void subghz_history_get_text_item_menu(SubGhzHistory* instance, string_t output, uint16_t idx); + +/** Get string the remaining number of records to history + * + * @param instance - SubGhzHistory instance + * @param output - string_t output + * @return bool - is FUUL + */ +bool subghz_history_get_text_space_left(SubGhzHistory* instance, string_t output); + +/** Add protocol to history + * + * @param instance - SubGhzHistory instance + * @param context - SubGhzProtocolCommon context + */ +void subghz_history_add_to_history(SubGhzHistory* instance, void* context); + +/** Get SubGhzProtocolCommonLoad to load into the protocol decoder bin data + * + * @param instance - SubGhzHistory instance + * @param idx - record index + * @return SubGhzProtocolCommonLoad* + */ +SubGhzProtocolCommonLoad* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx); diff --git a/applications/subghz/subghz_i.c b/applications/subghz/subghz_i.c index 03ebbc26..a339edfb 100644 --- a/applications/subghz/subghz_i.c +++ b/applications/subghz/subghz_i.c @@ -8,6 +8,7 @@ #include #include "file-worker.h" #include "../notification/notification.h" +#include "views/subghz_receiver.h" void subghz_begin(FuriHalSubGhzPreset preset) { furi_hal_subghz_reset(); @@ -16,30 +17,59 @@ void subghz_begin(FuriHalSubGhzPreset preset) { hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); } -void subghz_rx(uint32_t frequency) { +uint32_t subghz_rx(void* context, uint32_t frequency) { + furi_assert(context); + SubGhzWorker* worker = context; + furi_hal_subghz_idle(); - furi_hal_subghz_set_frequency_and_path(frequency); + uint32_t value = furi_hal_subghz_set_frequency_and_path(frequency); hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); furi_hal_subghz_flush_rx(); furi_hal_subghz_rx(); + + furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, worker); + subghz_worker_start(worker); + return value; } -void subghz_tx(uint32_t frequency) { +uint32_t subghz_tx(uint32_t frequency) { furi_hal_subghz_idle(); - furi_hal_subghz_set_frequency_and_path(frequency); + uint32_t value = furi_hal_subghz_set_frequency_and_path(frequency); hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); hal_gpio_write(&gpio_cc1101_g0, true); furi_hal_subghz_tx(); + return value; } void subghz_idle(void) { furi_hal_subghz_idle(); } -void subghz_end(void) { +void subghz_rx_end(void* context) { + furi_assert(context); + SubGhzWorker* worker = context; + + if(subghz_worker_is_running(worker)) { + subghz_worker_stop(worker); + furi_hal_subghz_stop_async_rx(); + } +} + +void subghz_sleep(void) { furi_hal_subghz_sleep(); } +void subghz_frequency_preset_to_str(void* context, string_t output) { + furi_assert(context); + SubGhz* subghz = context; + string_cat_printf( + output, + "Frequency: %d\n" + "Preset: %d\n", + (int)subghz->frequency, + (int)subghz->preset); +} + void subghz_transmitter_tx_start(void* context) { SubGhz* subghz = context; subghz->encoder = subghz_protocol_encoder_common_alloc(); @@ -47,8 +77,17 @@ void subghz_transmitter_tx_start(void* context) { //get upload if(subghz->protocol_result->get_upload_protocol) { if(subghz->protocol_result->get_upload_protocol(subghz->protocol_result, subghz->encoder)) { - subghz_begin(FuriHalSubGhzPresetOokAsync); - subghz_tx(433920000); + if(subghz->preset) { + subghz_begin(subghz->preset); + } else { + subghz_begin(FuriHalSubGhzPresetOok650Async); + } + if(subghz->frequency) { + subghz_tx(subghz->frequency); + } else { + subghz_tx(433920000); + } + //Start TX furi_hal_subghz_start_async_tx(subghz_protocol_encoder_common_yield, subghz->encoder); } @@ -59,7 +98,6 @@ void subghz_transmitter_tx_stop(void* context) { SubGhz* subghz = context; //Stop TX furi_hal_subghz_stop_async_tx(); - subghz_end(); subghz_protocol_encoder_common_free(subghz->encoder); //if protocol dynamic then we save the last upload if(subghz->protocol_result->type_protocol == TYPE_PROTOCOL_DYNAMIC) { @@ -79,12 +117,35 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path) { string_init_set_str(path, file_path); string_t temp_str; string_init(temp_str); + int res = 0; + int data = 0; do { if(!file_worker_open(file_worker, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { break; } - // Read and parse name protocol from 1st line + + // Read and parse frequency from 1st line + if(!file_worker_read_until(file_worker, temp_str, '\n')) { + break; + } + res = sscanf(string_get_cstr(temp_str), "Frequency: %d\n", &data); + if(res != 1) { + break; + } + subghz->frequency = (uint32_t)data; + + // Read and parse preset from 2st line + if(!file_worker_read_until(file_worker, temp_str, '\n')) { + break; + } + res = sscanf(string_get_cstr(temp_str), "Preset: %d\n", &data); + if(res != 1) { + break; + } + subghz->preset = (FuriHalSubGhzPreset)data; + + // Read and parse name protocol from 2st line if(!file_worker_read_until(file_worker, temp_str, '\n')) { break; } @@ -93,16 +154,18 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path) { subghz->protocol_result = subghz_protocol_get_by_name(subghz->protocol, string_get_cstr(temp_str)); if(subghz->protocol_result == NULL) { - file_worker_show_error(file_worker, "Cannot parse\nfile"); break; } - if(!subghz->protocol_result->to_load_protocol(file_worker, subghz->protocol_result)) { - file_worker_show_error(file_worker, "Cannot parse\nfile"); + if(!subghz->protocol_result->to_load_protocol_from_file( + file_worker, subghz->protocol_result)) { break; } loaded = true; } while(0); + if(!loaded) { + file_worker_show_error(file_worker, "Cannot parse\nfile"); + } string_clear(temp_str); string_clear(path); file_worker_close(file_worker); @@ -113,6 +176,7 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path) { bool subghz_save_protocol_to_file(void* context, const char* dev_name) { SubGhz* subghz = context; + furi_assert(subghz->protocol_result); FileWorker* file_worker = file_worker_alloc(false); string_t dev_file_name; string_init(dev_file_name); @@ -140,6 +204,11 @@ bool subghz_save_protocol_to_file(void* context, const char* dev_name) { file_worker, string_get_cstr(dev_file_name), FSAM_WRITE, FSOM_CREATE_ALWAYS)) { break; } + //Get string frequency preset protocol + subghz_frequency_preset_to_str(subghz, temp_str); + if(!file_worker_write(file_worker, string_get_cstr(temp_str), string_size(temp_str))) { + break; + } //Get string save subghz->protocol_result->to_save_string(subghz->protocol_result, temp_str); // Prepare and write data to file @@ -157,7 +226,7 @@ bool subghz_save_protocol_to_file(void* context, const char* dev_name) { return saved; } -bool subghz_saved_protocol_select(SubGhz* subghz) { +bool subghz_load_protocol_from_file(SubGhz* subghz) { furi_assert(subghz); FileWorker* file_worker = file_worker_alloc(false); @@ -165,6 +234,8 @@ bool subghz_saved_protocol_select(SubGhz* subghz) { string_init(protocol_file_name); string_t temp_str; string_init(temp_str); + int sscanf_res = 0; + int data = 0; // Input events and views are managed by file_select bool res = file_worker_file_select( @@ -197,7 +268,27 @@ bool subghz_saved_protocol_select(SubGhz* subghz) { file_worker, string_get_cstr(protocol_file_name), FSAM_READ, FSOM_OPEN_EXISTING)) { break; } - // Read and parse name protocol from 1st line + // Read and parse frequency from 1st line + if(!file_worker_read_until(file_worker, temp_str, '\n')) { + break; + } + sscanf_res = sscanf(string_get_cstr(temp_str), "Frequency: %d\n", &data); + if(sscanf_res != 1) { + break; + } + subghz->frequency = (uint32_t)data; + + // Read and parse preset from 2st line + if(!file_worker_read_until(file_worker, temp_str, '\n')) { + break; + } + sscanf_res = sscanf(string_get_cstr(temp_str), "Preset: %d\n", &data); + if(sscanf_res != 1) { + break; + } + subghz->preset = (FuriHalSubGhzPreset)data; + + // Read and parse name protocol from 3st line if(!file_worker_read_until(file_worker, temp_str, '\n')) { break; } @@ -206,16 +297,19 @@ bool subghz_saved_protocol_select(SubGhz* subghz) { subghz->protocol_result = subghz_protocol_get_by_name(subghz->protocol, string_get_cstr(temp_str)); if(subghz->protocol_result == NULL) { - file_worker_show_error(file_worker, "Cannot parse\nfile"); break; } - if(!subghz->protocol_result->to_load_protocol(file_worker, subghz->protocol_result)) { - file_worker_show_error(file_worker, "Cannot parse\nfile"); + if(!subghz->protocol_result->to_load_protocol_from_file( + file_worker, subghz->protocol_result)) { break; } res = true; } while(0); + if(!res) { + file_worker_show_error(file_worker, "Cannot parse\nfile"); + } + string_clear(temp_str); string_clear(protocol_file_name); diff --git a/applications/subghz/subghz_i.h b/applications/subghz/subghz_i.h index 8149363d..8d4ab93c 100644 --- a/applications/subghz/subghz_i.h +++ b/applications/subghz/subghz_i.h @@ -1,11 +1,10 @@ #pragma once #include "subghz.h" -#include "views/subghz_analyze.h" #include "views/subghz_receiver.h" #include "views/subghz_transmitter.h" -#include "views/subghz_static.h" +#include "views/subghz_test_static.h" #include "views/subghz_test_carrier.h" #include "views/subghz_test_packet.h" @@ -25,12 +24,14 @@ #include #include #include +#include "subghz_history.h" #define SUBGHZ_TEXT_STORE_SIZE 128 #define NOTIFICATION_STARTING_STATE 0u #define NOTIFICATION_IDLE_STATE 1u #define NOTIFICATION_TX_STATE 2u +#define NOTIFICATION_RX_STATE 3u extern const uint32_t subghz_frequencies[]; extern const uint32_t subghz_frequencies_count; @@ -43,10 +44,11 @@ struct SubGhz { SubGhzWorker* worker; SubGhzProtocol* protocol; SubGhzProtocolCommon* protocol_result; - SubGhzProtocolEncoderCommon* encoder; + SubGhzProtocolCommonEncoder* encoder; + uint32_t frequency; + FuriHalSubGhzPreset preset; SceneManager* scene_manager; - ViewDispatcher* view_dispatcher; Submenu* submenu; @@ -56,11 +58,10 @@ struct SubGhz { char text_store[SUBGHZ_TEXT_STORE_SIZE + 1]; uint8_t state_notifications; - SubghzAnalyze* subghz_analyze; SubghzReceiver* subghz_receiver; SubghzTransmitter* subghz_transmitter; - SubghzStatic* subghz_static; + SubghzTestStatic* subghz_test_static; SubghzTestCarrier* subghz_test_carrier; SubghzTestPacket* subghz_test_packet; }; @@ -68,7 +69,6 @@ struct SubGhz { typedef enum { SubGhzViewMenu, - SubGhzViewAnalyze, SubGhzViewDialogEx, SubGhzViewReceiver, SubGhzViewPopup, @@ -81,13 +81,14 @@ typedef enum { } SubGhzView; void subghz_begin(FuriHalSubGhzPreset preset); -void subghz_rx(uint32_t frequency); -void subghz_tx(uint32_t frequency); +uint32_t subghz_rx(void* context, uint32_t frequency); +uint32_t subghz_tx(uint32_t frequency); void subghz_idle(void); -void subghz_end(void); +void subghz_rx_end(void* context); +void subghz_sleep(void); void subghz_transmitter_tx_start(void* context); void subghz_transmitter_tx_stop(void* context); bool subghz_key_load(SubGhz* subghz, const char* file_path); bool subghz_save_protocol_to_file(void* context, const char* dev_name); -bool subghz_saved_protocol_select(SubGhz* subghz); +bool subghz_load_protocol_from_file(SubGhz* subghz); uint32_t subghz_random_serial(void); diff --git a/applications/subghz/views/subghz_analyze.c b/applications/subghz/views/subghz_analyze.c deleted file mode 100644 index 7380a026..00000000 --- a/applications/subghz/views/subghz_analyze.c +++ /dev/null @@ -1,233 +0,0 @@ -#include "subghz_analyze.h" -#include "../subghz_i.h" - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -struct SubghzAnalyze { - View* view; - SubGhzWorker* worker; - SubGhzProtocol* protocol; -}; - -typedef struct { - uint8_t frequency; - uint32_t real_frequency; - uint32_t counter; - string_t text; - uint16_t scene; - SubGhzProtocolCommon parser; -} SubghzAnalyzeModel; - -static const char subghz_symbols[] = {'-', '\\', '|', '/'}; - -void subghz_analyze_draw(Canvas* canvas, SubghzAnalyzeModel* model) { - char buffer[64]; - - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontPrimary); - - snprintf( - buffer, - sizeof(buffer), - "Analyze: %03ld.%03ldMHz %c", - model->real_frequency / 1000000 % 1000, - model->real_frequency / 1000 % 1000, - subghz_symbols[model->counter % 4]); - canvas_draw_str(canvas, 0, 8, buffer); - - switch(model->scene) { - case 1: - canvas_draw_icon(canvas, 0, 10, &I_RFIDDolphinReceive_97x61); - canvas_invert_color(canvas); - canvas_draw_box(canvas, 80, 12, 20, 20); - canvas_invert_color(canvas); - canvas_draw_icon(canvas, 75, 18, &I_sub1_10px); - elements_multiline_text_aligned( - canvas, 90, 38, AlignCenter, AlignTop, "Detecting\r\nSubGhz"); - break; - - default: - canvas_set_font(canvas, FontSecondary); - elements_multiline_text(canvas, 0, 20, string_get_cstr(model->text)); - break; - } -} - -bool subghz_analyze_input(InputEvent* event, void* context) { - furi_assert(context); - SubghzAnalyze* subghz_analyze = context; - - if(event->type != InputTypeShort) return false; - - if(event->key == InputKeyBack) { - return false; - } - - with_view_model( - subghz_analyze->view, (SubghzAnalyzeModel * model) { - bool model_updated = false; - - if(event->key == InputKeyLeft) { - if(model->frequency > 0) model->frequency--; - model_updated = true; - } else if(event->key == InputKeyRight) { - if(model->frequency < subghz_frequencies_count - 1) model->frequency++; - model_updated = true; - } - - if(model_updated) { - furi_hal_subghz_idle(); - model->real_frequency = - furi_hal_subghz_set_frequency_and_path(subghz_frequencies[model->frequency]); - furi_hal_subghz_rx(); - } - - return model_updated; - }); - - return true; -} - -void subghz_analyze_text_callback(string_t text, void* context) { - furi_assert(context); - SubghzAnalyze* subghz_analyze = context; - - with_view_model( - subghz_analyze->view, (SubghzAnalyzeModel * model) { - model->counter++; - string_set(model->text, text); - model->scene = 0; - return true; - }); -} - -void subghz_analyze_protocol_callback(SubGhzProtocolCommon* parser, void* context) { - furi_assert(context); - SubghzAnalyze* subghz_analyze = context; - char buffer[64]; - snprintf( - buffer, - sizeof(buffer), - "%s\r\n" - "K:%lX%lX\r\n" - "SN:%lX\r\n" - "BTN:%X", - parser->name, - (uint32_t)(parser->code_found >> 32), - (uint32_t)(parser->code_found & 0x00000000FFFFFFFF), - parser->serial, - parser->btn); - - with_view_model( - subghz_analyze->view, (SubghzAnalyzeModel * model) { - model->counter++; - model->parser = *parser; - string_set(model->text, buffer); - model->scene = 0; - return true; - }); -} - -void subghz_analyze_enter(void* context) { - furi_assert(context); - SubghzAnalyze* subghz_analyze = context; - - furi_hal_subghz_reset(); - furi_hal_subghz_idle(); - furi_hal_subghz_load_preset(FuriHalSubGhzPresetOokAsync); - - with_view_model( - subghz_analyze->view, (SubghzAnalyzeModel * model) { - model->frequency = subghz_frequencies_433_92; - model->real_frequency = - furi_hal_subghz_set_frequency_and_path(subghz_frequencies[model->frequency]); - model->scene = 1; - return true; - }); - - hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); - - furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, subghz_analyze->worker); - - subghz_worker_start(subghz_analyze->worker); - - furi_hal_subghz_flush_rx(); - furi_hal_subghz_rx(); -} - -void subghz_analyze_exit(void* context) { - furi_assert(context); - SubghzAnalyze* subghz_analyze = context; - - subghz_worker_stop(subghz_analyze->worker); - - furi_hal_subghz_stop_async_rx(); - furi_hal_subghz_sleep(); -} - -SubghzAnalyze* subghz_analyze_alloc() { - SubghzAnalyze* subghz_analyze = furi_alloc(sizeof(SubghzAnalyze)); - - // View allocation and configuration - subghz_analyze->view = view_alloc(); - view_allocate_model(subghz_analyze->view, ViewModelTypeLocking, sizeof(SubghzAnalyzeModel)); - view_set_context(subghz_analyze->view, subghz_analyze); - view_set_draw_callback(subghz_analyze->view, (ViewDrawCallback)subghz_analyze_draw); - view_set_input_callback(subghz_analyze->view, subghz_analyze_input); - view_set_enter_callback(subghz_analyze->view, subghz_analyze_enter); - view_set_exit_callback(subghz_analyze->view, subghz_analyze_exit); - - with_view_model( - subghz_analyze->view, (SubghzAnalyzeModel * model) { - string_init(model->text); - return true; - }); - - subghz_analyze->worker = subghz_worker_alloc(); - subghz_analyze->protocol = subghz_protocol_alloc(); - - subghz_worker_set_overrun_callback( - subghz_analyze->worker, (SubGhzWorkerOverrunCallback)subghz_protocol_reset); - subghz_worker_set_pair_callback( - subghz_analyze->worker, (SubGhzWorkerPairCallback)subghz_protocol_parse); - subghz_worker_set_context(subghz_analyze->worker, subghz_analyze->protocol); - - subghz_protocol_load_keeloq_file( - subghz_analyze->protocol, "/ext/assets/subghz/keeloq_mfcodes"); - subghz_protocol_load_nice_flor_s_file( - subghz_analyze->protocol, "/ext/assets/subghz/nice_floor_s_rx"); - subghz_protocol_enable_dump_text( - subghz_analyze->protocol, subghz_analyze_text_callback, subghz_analyze); - - return subghz_analyze; -} - -void subghz_analyze_free(SubghzAnalyze* subghz_analyze) { - furi_assert(subghz_analyze); - - subghz_protocol_free(subghz_analyze->protocol); - subghz_worker_free(subghz_analyze->worker); - - with_view_model( - subghz_analyze->view, (SubghzAnalyzeModel * model) { - string_clear(model->text); - return true; - }); - view_free(subghz_analyze->view); - free(subghz_analyze); -} - -View* subghz_analyze_get_view(SubghzAnalyze* subghz_analyze) { - furi_assert(subghz_analyze); - return subghz_analyze->view; -} diff --git a/applications/subghz/views/subghz_analyze.h b/applications/subghz/views/subghz_analyze.h deleted file mode 100644 index b1a553e6..00000000 --- a/applications/subghz/views/subghz_analyze.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include - -typedef struct SubghzAnalyze SubghzAnalyze; - -SubghzAnalyze* subghz_analyze_alloc(); - -void subghz_analyze_free(SubghzAnalyze* subghz_analyze); - -View* subghz_analyze_get_view(SubghzAnalyze* subghz_analyze); diff --git a/applications/subghz/views/subghz_receiver.c b/applications/subghz/views/subghz_receiver.c index a4d9aef7..df70786b 100644 --- a/applications/subghz/views/subghz_receiver.c +++ b/applications/subghz/views/subghz_receiver.c @@ -1,25 +1,74 @@ #include "subghz_receiver.h" #include "../subghz_i.h" - #include #include #include #include #include #include +#include #include +#define FRAME_HEIGHT 12 +#define MAX_LEN_PX 100 +#define MENU_ITEMS 4 + +#define COUNT_FREQUNCY_HOPPER 3 +const uint32_t subghz_frequencies_hopper[] = { + /* 300 - 348 */ + 315000000, + /* 387 - 464 */ + 433920000, /* LPD433 mid */ + /* 779 - 928 */ + 868350000, +}; + +typedef enum { + ReceiverSceneStart, + ReceiverSceneMain, + ReceiverSceneConfig, + ReceiverSceneInfo, +} SubghzReceiverScene; + +typedef enum { + SubGhzHopperStateOFF, + SubGhzHopperStatePause, + SubGhzHopperStateRunnig, + SubGhzHopperStateRSSITimeOut, +} SubGhzHopperState; + +static const Icon* ReceiverItemIcons[] = { + [TYPE_PROTOCOL_UNKNOWN] = &I_Quest_7x8, + [TYPE_PROTOCOL_STATIC] = &I_Unlock_7x8, + [TYPE_PROTOCOL_DYNAMIC] = &I_Lock_7x8, +}; + struct SubghzReceiver { View* view; SubghzReceiverCallback callback; void* context; + SubGhzWorker* worker; + SubGhzProtocol* protocol; + osTimerId timer; + SubGhzHopperState hopper_state; + uint8_t hopper_timeout; + uint32_t event_key_sequence; }; typedef struct { string_t text; uint16_t scene; - SubGhzProtocolCommon* protocol; + SubGhzProtocolCommon* protocol_result; + SubGhzHistory* history; + uint8_t frequency; + uint8_t temp_frequency; + uint32_t real_frequency; + + uint16_t idx; + uint16_t list_offset; + uint16_t history_item; + bool menu; } SubghzReceiverModel; void subghz_receiver_set_callback( @@ -32,48 +81,393 @@ void subghz_receiver_set_callback( subghz_receiver->context = context; } -void subghz_receiver_set_protocol(SubghzReceiver* subghz_receiver, SubGhzProtocolCommon* protocol) { +void subghz_receiver_set_protocol( + SubghzReceiver* subghz_receiver, + SubGhzProtocolCommon* protocol_result, + SubGhzProtocol* protocol) { + furi_assert(subghz_receiver); with_view_model( subghz_receiver->view, (SubghzReceiverModel * model) { - model->protocol = protocol; + model->protocol_result = protocol_result; + return true; + }); + subghz_receiver->protocol = protocol; +} + +SubGhzProtocolCommon* subghz_receiver_get_protocol(SubghzReceiver* subghz_receiver) { + furi_assert(subghz_receiver); + SubGhzProtocolCommon* result = NULL; + with_view_model( + subghz_receiver->view, (SubghzReceiverModel * model) { + result = model->protocol_result; + return false; + }); + return result; +} + +void subghz_receiver_set_worker(SubghzReceiver* subghz_receiver, SubGhzWorker* worker) { + furi_assert(subghz_receiver); + subghz_receiver->worker = worker; +} + +static void subghz_receiver_update_offset(SubghzReceiver* subghz_receiver) { + furi_assert(subghz_receiver); + + with_view_model( + subghz_receiver->view, (SubghzReceiverModel * model) { + size_t history_item = model->history_item; + uint16_t bounds = history_item > 3 ? 2 : history_item; + + if(history_item > 3 && model->idx >= history_item - 1) { + model->list_offset = model->idx - 3; + } else if(model->list_offset < model->idx - bounds) { + model->list_offset = CLAMP(model->list_offset + 1, history_item - bounds, 0); + } else if(model->list_offset > model->idx - bounds) { + model->list_offset = CLAMP(model->idx - 1, history_item - bounds, 0); + } return true; }); } +static void subghz_receiver_draw_frame(Canvas* canvas, uint16_t idx, bool scrollbar) { + canvas_set_color(canvas, ColorBlack); + canvas_draw_box(canvas, 0, 0 + idx * FRAME_HEIGHT, scrollbar ? 122 : 127, FRAME_HEIGHT); + + canvas_set_color(canvas, ColorWhite); + canvas_draw_dot(canvas, 0, 0 + idx * FRAME_HEIGHT); + canvas_draw_dot(canvas, 1, 0 + idx * FRAME_HEIGHT); + canvas_draw_dot(canvas, 0, (0 + idx * FRAME_HEIGHT) + 1); + + canvas_draw_dot(canvas, 0, (0 + idx * FRAME_HEIGHT) + 11); + canvas_draw_dot(canvas, scrollbar ? 121 : 126, 0 + idx * FRAME_HEIGHT); + canvas_draw_dot(canvas, scrollbar ? 121 : 126, (0 + idx * FRAME_HEIGHT) + 11); +} + void subghz_receiver_draw(Canvas* canvas, SubghzReceiverModel* model) { + bool scrollbar = model->history_item > 4; + string_t str_buff; + char buffer[64]; + uint32_t frequency; + string_init(str_buff); + canvas_clear(canvas); canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontSecondary); - elements_multiline_text(canvas, 0, 10, string_get_cstr(model->text)); - elements_button_left(canvas, "Back"); - if(model->protocol && model->protocol->to_save_string && - strcmp(model->protocol->name, "KeeLoq")) { - elements_button_right(canvas, "Save"); + switch(model->scene) { + case ReceiverSceneMain: + for(size_t i = 0; i < MIN(model->history_item, MENU_ITEMS); ++i) { + size_t idx = CLAMP(i + model->list_offset, model->history_item, 0); + subghz_history_get_text_item_menu(model->history, str_buff, idx); + elements_string_fit_width(canvas, str_buff, scrollbar ? MAX_LEN_PX - 6 : MAX_LEN_PX); + if(model->idx == idx) { + subghz_receiver_draw_frame(canvas, i, scrollbar); + } else { + canvas_set_color(canvas, ColorBlack); + } + canvas_draw_icon( + canvas, + 1, + 2 + i * FRAME_HEIGHT, + ReceiverItemIcons[subghz_history_get_type_protocol(model->history, idx)]); + canvas_draw_str(canvas, 15, 9 + i * FRAME_HEIGHT, string_get_cstr(str_buff)); + string_clean(str_buff); + } + if(scrollbar) { + elements_scrollbar_pos(canvas, 128, 0, 49, model->idx, model->history_item); + } + canvas_set_color(canvas, ColorBlack); + canvas_set_font(canvas, FontSecondary); + + elements_button_left(canvas, "Config"); + canvas_draw_line(canvas, 46, 51, 125, 51); + if(subghz_history_get_text_space_left(model->history, str_buff)) { + canvas_draw_str(canvas, 54, 62, string_get_cstr(str_buff)); + } else { + if((model->real_frequency / 1000 % 10) > 4) { + frequency = model->real_frequency + 10000; + } else { + frequency = model->real_frequency; + } + snprintf( + buffer, + sizeof(buffer), + "%03ld.%02ld", + frequency / 1000000 % 1000, + frequency / 10000 % 100); + canvas_draw_str(canvas, 44, 62, buffer); + canvas_draw_str(canvas, 79, 62, "AM"); + canvas_draw_str(canvas, 96, 62, string_get_cstr(str_buff)); + } + break; + + case ReceiverSceneStart: + canvas_draw_icon(canvas, 0, 0, &I_Scanning_123x52); + canvas_set_font(canvas, FontPrimary); + canvas_draw_str(canvas, 63, 46, "Scanning..."); + canvas_set_color(canvas, ColorBlack); + canvas_set_font(canvas, FontSecondary); + elements_button_left(canvas, "Config"); + if((model->real_frequency / 1000 % 10) > 4) { + frequency = model->real_frequency + 10000; + } else { + frequency = model->real_frequency; + } + snprintf( + buffer, + sizeof(buffer), + "%03ld.%02ld", + frequency / 1000000 % 1000, + frequency / 10000 % 100); + canvas_draw_str(canvas, 44, 62, buffer); + canvas_draw_str(canvas, 79, 62, "AM"); + subghz_history_get_text_space_left(model->history, str_buff); + canvas_draw_str(canvas, 96, 62, string_get_cstr(str_buff)); + canvas_draw_line(canvas, 46, 51, 125, 51); + break; + + case ReceiverSceneConfig: + if(model->frequency < subghz_frequencies_count) { + snprintf( + buffer, + sizeof(buffer), + "Frequency: < %03ld.%03ldMHz >", + model->real_frequency / 1000000 % 1000, + model->real_frequency / 1000 % 1000); + canvas_draw_str(canvas, 0, 8, buffer); + canvas_draw_str(canvas, 0, 18, "Frequency Hopping: "); + } else { + canvas_draw_str(canvas, 0, 8, "Frequency: < --- >"); + canvas_draw_str(canvas, 0, 18, "Frequency Hopping: "); + } + canvas_draw_str(canvas, 0, 28, "Modulation: "); + + elements_button_center(canvas, "Save"); + break; + + case ReceiverSceneInfo: + canvas_set_font(canvas, FontSecondary); + elements_multiline_text(canvas, 0, 8, string_get_cstr(model->text)); + snprintf( + buffer, + sizeof(buffer), + "%03ld.%03ld", + subghz_history_get_frequency(model->history, model->idx) / 1000000 % 1000, + subghz_history_get_frequency(model->history, model->idx) / 1000 % 1000); + canvas_draw_str(canvas, 90, 8, buffer); + if(model->protocol_result && model->protocol_result->to_save_string && + strcmp(model->protocol_result->name, "KeeLoq")) { + elements_button_right(canvas, "Save"); + elements_button_center(canvas, "Send"); + } + break; + + default: + + break; } + + string_clear(str_buff); +} + +void subghz_receiver_history_full(void* context) { + furi_assert(context); + SubghzReceiver* subghz_receiver = context; + subghz_receiver->callback(SubghzReceverEventSendHistoryFull, subghz_receiver->context); + subghz_receiver->hopper_state = SubGhzHopperStateOFF; } bool subghz_receiver_input(InputEvent* event, void* context) { furi_assert(context); + + uint8_t scene = 0; SubghzReceiver* subghz_receiver = context; - - if(event->type != InputTypeShort) return false; - - bool can_be_saved = false; with_view_model( subghz_receiver->view, (SubghzReceiverModel * model) { - can_be_saved = - (model->protocol && model->protocol->to_save_string && - strcmp(model->protocol->name, "KeeLoq")); + scene = model->scene; return false; }); - if(event->key == InputKeyBack) { - return false; - } else if(event->key == InputKeyLeft) { - subghz_receiver->callback(SubghzReceverEventBack, subghz_receiver->context); - } else if(can_be_saved && event->key == InputKeyRight) { - subghz_receiver->callback(SubghzReceverEventSave, subghz_receiver->context); + bool can_be_saved = false; + + switch(scene) { + case ReceiverSceneMain: + if(event->key == InputKeyBack && event->type == InputTypeShort) { + with_view_model( + subghz_receiver->view, (SubghzReceiverModel * model) { + model->idx = 0; + model->list_offset = 0; + model->history_item = 0; + subghz_history_clean(model->history); + return true; + }); + return false; + } else if( + event->key == InputKeyUp && + (event->type == InputTypeShort || event->type == InputTypeRepeat)) { + with_view_model( + subghz_receiver->view, (SubghzReceiverModel * model) { + if(model->idx != 0) model->idx--; + return true; + }); + } else if( + event->key == InputKeyDown && + (event->type == InputTypeShort || event->type == InputTypeRepeat)) { + with_view_model( + subghz_receiver->view, (SubghzReceiverModel * model) { + if(model->idx != subghz_history_get_item(model->history) - 1) model->idx++; + return true; + }); + } else if(event->key == InputKeyLeft && event->type == InputTypeShort) { + subghz_receiver->hopper_state = SubGhzHopperStatePause; + with_view_model( + subghz_receiver->view, (SubghzReceiverModel * model) { + model->scene = ReceiverSceneConfig; + model->temp_frequency = model->frequency; + return true; + }); + subghz_receiver->callback(SubghzReceverEventConfig, subghz_receiver->context); + } else if(event->key == InputKeyOk && event->type == InputTypeShort) { + subghz_receiver->event_key_sequence = event->sequence; + with_view_model( + subghz_receiver->view, (SubghzReceiverModel * model) { + string_clean(model->text); + model->protocol_result = subghz_protocol_get_by_name( + subghz_receiver->protocol, + subghz_history_get_name(model->history, model->idx)); + if(model->protocol_result->to_load_protocol != NULL) { + model->protocol_result->to_load_protocol( + model->protocol_result, + subghz_history_get_raw_data(model->history, model->idx)); + model->protocol_result->to_string(model->protocol_result, model->text); + model->scene = ReceiverSceneInfo; + } + return true; + }); + } + break; + + case ReceiverSceneInfo: + with_view_model( + subghz_receiver->view, (SubghzReceiverModel * model) { + can_be_saved = + (model->protocol_result && model->protocol_result->to_save_string && + strcmp(model->protocol_result->name, "KeeLoq")); + return false; + }); + if(event->key == InputKeyBack && event->type == InputTypeShort) { + with_view_model( + subghz_receiver->view, (SubghzReceiverModel * model) { + subghz_rx_end(subghz_receiver->worker); + model->real_frequency = + subghz_rx(subghz_receiver->worker, subghz_frequencies[model->frequency]); + subghz_receiver->hopper_state = SubGhzHopperStateRunnig; + model->scene = ReceiverSceneMain; + return true; + }); + subghz_receiver->callback(SubghzReceverEventMain, subghz_receiver->context); + } else if(can_be_saved && event->key == InputKeyRight) { + subghz_receiver->callback(SubghzReceverEventSave, subghz_receiver->context); + return false; + } else if( + can_be_saved && event->key == InputKeyOk && event->type == InputTypePress && + subghz_receiver->event_key_sequence != event->sequence) { + subghz_receiver->hopper_state = SubGhzHopperStatePause; + subghz_rx_end(subghz_receiver->worker); + subghz_receiver->callback(SubghzReceverEventSendStart, subghz_receiver->context); + return true; + } else if( + can_be_saved && event->key == InputKeyOk && event->type == InputTypeRelease && + subghz_receiver->event_key_sequence != event->sequence) { + subghz_receiver->callback(SubghzReceverEventSendStop, subghz_receiver->context); + return true; + } + break; + + case ReceiverSceneConfig: + if(event->type != InputTypeShort) return false; + if(event->key == InputKeyBack) { + with_view_model( + subghz_receiver->view, (SubghzReceiverModel * model) { + model->frequency = model->temp_frequency; + model->real_frequency = subghz_frequencies[model->frequency]; + subghz_receiver->hopper_state = SubGhzHopperStateRunnig; + if(subghz_history_get_item(model->history) == 0) { + model->scene = ReceiverSceneStart; + } else { + model->scene = ReceiverSceneMain; + } + return true; + }); + subghz_receiver->callback(SubghzReceverEventMain, subghz_receiver->context); + } else if(event->key == InputKeyOk) { + with_view_model( + subghz_receiver->view, (SubghzReceiverModel * model) { + if(model->frequency < subghz_frequencies_count) { + subghz_rx_end(subghz_receiver->worker); + model->real_frequency = subghz_rx( + subghz_receiver->worker, subghz_frequencies[model->frequency]); + subghz_receiver->hopper_state = SubGhzHopperStateOFF; + } else { + osTimerStart(subghz_receiver->timer, 1024 / 10); + subghz_receiver->hopper_state = SubGhzHopperStateRunnig; + } + if(subghz_history_get_item(model->history) == 0) { + model->scene = ReceiverSceneStart; + } else { + model->scene = ReceiverSceneMain; + } + return true; + }); + subghz_receiver->callback(SubghzReceverEventMain, subghz_receiver->context); + } else { + with_view_model( + subghz_receiver->view, (SubghzReceiverModel * model) { + bool model_updated = false; + + if(event->key == InputKeyLeft) { + if(model->frequency > 0) model->frequency--; + model_updated = true; + } else if(event->key == InputKeyRight) { + if(model->frequency < subghz_frequencies_count) model->frequency++; + model_updated = true; + } + if(model_updated) { + model->real_frequency = subghz_frequencies[model->frequency]; + } + return model_updated; + }); + } + break; + + case ReceiverSceneStart: + if(event->type != InputTypeShort) return false; + if(event->key == InputKeyBack) { + return false; + } else if(event->key == InputKeyLeft) { + subghz_receiver->hopper_state = SubGhzHopperStatePause; + with_view_model( + subghz_receiver->view, (SubghzReceiverModel * model) { + model->temp_frequency = model->frequency; + model->scene = ReceiverSceneConfig; + return true; + }); + subghz_receiver->callback(SubghzReceverEventConfig, subghz_receiver->context); + } + break; + + default: + break; + } + + subghz_receiver_update_offset(subghz_receiver); + if(scene != ReceiverSceneInfo) { + with_view_model( + subghz_receiver->view, (SubghzReceiverModel * model) { + if(subghz_history_get_text_space_left(model->history, NULL)) { + subghz_receiver_history_full(subghz_receiver); + } + return false; + }); } return true; @@ -86,7 +480,88 @@ void subghz_receiver_text_callback(string_t text, void* context) { with_view_model( subghz_receiver->view, (SubghzReceiverModel * model) { string_set(model->text, text); - model->scene = 0; + model->scene = ReceiverSceneMain; + return true; + }); +} + +void subghz_receiver_protocol_callback(SubGhzProtocolCommon* parser, void* context) { + furi_assert(context); + SubghzReceiver* subghz_receiver = context; + + with_view_model( + subghz_receiver->view, (SubghzReceiverModel * model) { + model->protocol_result = parser; + subghz_history_set_frequency_preset( + model->history, + model->history_item, + model->real_frequency, + FuriHalSubGhzPresetOok650Async); + subghz_history_add_to_history(model->history, parser); + + model->history_item = subghz_history_get_item(model->history); + model->scene = ReceiverSceneMain; + if(subghz_history_get_text_space_left(model->history, NULL)) { + subghz_receiver_history_full(subghz_receiver); + } + return true; + }); + subghz_protocol_reset(subghz_receiver->protocol); + subghz_receiver_update_offset(subghz_receiver); +} + +static void subghz_receiver_timer_callback(void* context) { + furi_assert(context); + SubghzReceiver* subghz_receiver = context; + + switch(subghz_receiver->hopper_state) { + case SubGhzHopperStatePause: + return; + break; + case SubGhzHopperStateOFF: + osTimerStop(subghz_receiver->timer); + return; + break; + case SubGhzHopperStateRSSITimeOut: + if(subghz_receiver->hopper_timeout != 0) { + subghz_receiver->hopper_timeout--; + return; + } + break; + default: + break; + } + float rssi = -127.0f; + with_view_model( + subghz_receiver->view, (SubghzReceiverModel * model) { + if(subghz_receiver->hopper_state != SubGhzHopperStateRSSITimeOut) { + // See RSSI Calculation timings in CC1101 17.3 RSSI + rssi = furi_hal_subghz_get_rssi(); + + // Stay if RSSI is high enough + if(rssi > -90.0f) { + subghz_receiver->hopper_timeout = 10; + subghz_receiver->hopper_state = SubGhzHopperStateRSSITimeOut; + return false; + } + } else { + subghz_receiver->hopper_state = SubGhzHopperStateRunnig; + } + + // Select next frequency + if(model->frequency < COUNT_FREQUNCY_HOPPER - 1) { + model->frequency++; + } else { + model->frequency = 0; + } + + // Restart radio + furi_hal_subghz_idle(); + subghz_protocol_reset(subghz_receiver->protocol); + model->real_frequency = furi_hal_subghz_set_frequency_and_path( + subghz_frequencies_hopper[model->frequency]); + furi_hal_subghz_rx(); + return true; }); } @@ -94,21 +569,37 @@ void subghz_receiver_text_callback(string_t text, void* context) { void subghz_receiver_enter(void* context) { furi_assert(context); SubghzReceiver* subghz_receiver = context; + //Start CC1101 Rx + subghz_begin(FuriHalSubGhzPresetOok650Async); with_view_model( subghz_receiver->view, (SubghzReceiverModel * model) { - model->protocol->to_string(model->protocol, model->text); + subghz_rx_end(subghz_receiver->worker); + model->frequency = subghz_frequencies_433_92; + model->real_frequency = + subghz_rx(subghz_receiver->worker, subghz_frequencies[model->frequency]); + if(subghz_history_get_item(model->history) == 0) { + model->scene = ReceiverSceneStart; + } else { + model->scene = ReceiverSceneMain; + } return true; }); + subghz_protocol_enable_dump( + subghz_receiver->protocol, subghz_receiver_protocol_callback, subghz_receiver); } void subghz_receiver_exit(void* context) { furi_assert(context); SubghzReceiver* subghz_receiver = context; + osTimerStop(subghz_receiver->timer); with_view_model( subghz_receiver->view, (SubghzReceiverModel * model) { string_clean(model->text); return true; }); + // Stop CC1101 Rx + subghz_rx_end(subghz_receiver->worker); + subghz_sleep(); } SubghzReceiver* subghz_receiver_alloc() { @@ -126,8 +617,13 @@ SubghzReceiver* subghz_receiver_alloc() { with_view_model( subghz_receiver->view, (SubghzReceiverModel * model) { string_init(model->text); + model->history = subghz_history_alloc(); return true; }); + + subghz_receiver->timer = + osTimerNew(subghz_receiver_timer_callback, osTimerPeriodic, subghz_receiver, NULL); + subghz_receiver->hopper_state = SubGhzHopperStateOFF; return subghz_receiver; } @@ -137,8 +633,10 @@ void subghz_receiver_free(SubghzReceiver* subghz_receiver) { with_view_model( subghz_receiver->view, (SubghzReceiverModel * model) { string_clear(model->text); - return true; + subghz_history_free(model->history); + return false; }); + osTimerDelete(subghz_receiver->timer); view_free(subghz_receiver->view); free(subghz_receiver); } @@ -147,3 +645,44 @@ View* subghz_receiver_get_view(SubghzReceiver* subghz_receiver) { furi_assert(subghz_receiver); return subghz_receiver->view; } + +uint32_t subghz_receiver_get_frequency(SubghzReceiver* subghz_receiver) { + furi_assert(subghz_receiver); + uint32_t frequency; + with_view_model( + subghz_receiver->view, (SubghzReceiverModel * model) { + frequency = subghz_history_get_frequency(model->history, model->idx); + return false; + }); + return frequency; +} + +FuriHalSubGhzPreset subghz_receiver_get_preset(SubghzReceiver* subghz_receiver) { + furi_assert(subghz_receiver); + FuriHalSubGhzPreset preset; + with_view_model( + subghz_receiver->view, (SubghzReceiverModel * model) { + preset = subghz_history_get_preset(model->history, model->idx); + return false; + }); + return preset; +} + +void subghz_receiver_frequency_preset_to_str(SubghzReceiver* subghz_receiver, string_t output) { + furi_assert(subghz_receiver); + uint32_t frequency; + uint32_t preset; + with_view_model( + subghz_receiver->view, (SubghzReceiverModel * model) { + frequency = subghz_history_get_frequency(model->history, model->idx); + preset = (uint32_t)subghz_history_get_preset(model->history, model->idx); + return false; + }); + + string_cat_printf( + output, + "Frequency: %d\n" + "Preset: %d\n", + (int)frequency, + (int)preset); +} diff --git a/applications/subghz/views/subghz_receiver.h b/applications/subghz/views/subghz_receiver.h index 924f90b8..513f438c 100644 --- a/applications/subghz/views/subghz_receiver.h +++ b/applications/subghz/views/subghz_receiver.h @@ -2,10 +2,20 @@ #include #include +#include +#include +#include "../subghz_history.h" typedef enum { + SubghzReceverEventOK, + SubghzReceverEventConfig, + SubghzReceverEventMain, SubghzReceverEventSave, SubghzReceverEventBack, + SubghzReceverEventMore, + SubghzReceverEventSendStart, + SubghzReceverEventSendStop, + SubghzReceverEventSendHistoryFull, } SubghzReceverEvent; typedef struct SubghzReceiver SubghzReceiver; @@ -23,4 +33,17 @@ void subghz_receiver_free(SubghzReceiver* subghz_receiver); View* subghz_receiver_get_view(SubghzReceiver* subghz_receiver); -void subghz_receiver_set_protocol(SubghzReceiver* subghz_receiver, SubGhzProtocolCommon* protocol); +void subghz_receiver_set_protocol( + SubghzReceiver* subghz_receiver, + SubGhzProtocolCommon* protocol_result, + SubGhzProtocol* protocol); + +SubGhzProtocolCommon* subghz_receiver_get_protocol(SubghzReceiver* subghz_receiver); + +void subghz_receiver_set_worker(SubghzReceiver* subghz_receiver, SubGhzWorker* worker); + +uint32_t subghz_receiver_get_frequency(SubghzReceiver* subghz_receiver); + +FuriHalSubGhzPreset subghz_receiver_get_preset(SubghzReceiver* subghz_receiver); + +void subghz_receiver_frequency_preset_to_str(SubghzReceiver* subghz_receiver, string_t output); diff --git a/applications/subghz/views/subghz_static.h b/applications/subghz/views/subghz_static.h deleted file mode 100644 index f80f8735..00000000 --- a/applications/subghz/views/subghz_static.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include - -typedef struct SubghzStatic SubghzStatic; - -SubghzStatic* subghz_static_alloc(); - -void subghz_static_free(SubghzStatic* subghz_static); - -View* subghz_static_get_view(SubghzStatic* subghz_static); diff --git a/applications/subghz/views/subghz_test_carrier.c b/applications/subghz/views/subghz_test_carrier.c index 14fb9daa..82d11650 100644 --- a/applications/subghz/views/subghz_test_carrier.c +++ b/applications/subghz/views/subghz_test_carrier.c @@ -71,41 +71,37 @@ bool subghz_test_carrier_input(InputEvent* event, void* context) { furi_assert(context); SubghzTestCarrier* subghz_test_carrier = context; - if(event->key == InputKeyBack) { + if(event->key == InputKeyBack || event->type != InputTypeShort) { return false; } with_view_model( subghz_test_carrier->view, (SubghzTestCarrierModel * model) { - osTimerStop(subghz_test_carrier->timer); furi_hal_subghz_idle(); - if(event->type == InputTypeShort) { - if(event->key == InputKeyLeft) { - if(model->frequency > 0) model->frequency--; - } else if(event->key == InputKeyRight) { - if(model->frequency < subghz_frequencies_count - 1) model->frequency++; - } else if(event->key == InputKeyDown) { - if(model->path > 0) model->path--; - } else if(event->key == InputKeyUp) { - if(model->path < FuriHalSubGhzPath868) model->path++; - } else if(event->key == InputKeyOk) { - if(model->status == SubghzTestCarrierModelStatusTx) { - model->status = SubghzTestCarrierModelStatusRx; - } else { - model->status = SubghzTestCarrierModelStatusTx; - } + if(event->key == InputKeyLeft) { + if(model->frequency > 0) model->frequency--; + } else if(event->key == InputKeyRight) { + if(model->frequency < subghz_frequencies_count - 1) model->frequency++; + } else if(event->key == InputKeyDown) { + if(model->path > 0) model->path--; + } else if(event->key == InputKeyUp) { + if(model->path < FuriHalSubGhzPath868) model->path++; + } else if(event->key == InputKeyOk) { + if(model->status == SubghzTestCarrierModelStatusTx) { + model->status = SubghzTestCarrierModelStatusRx; + } else { + model->status = SubghzTestCarrierModelStatusTx; } - - model->real_frequency = - furi_hal_subghz_set_frequency(subghz_frequencies[model->frequency]); - furi_hal_subghz_set_path(model->path); } + model->real_frequency = + furi_hal_subghz_set_frequency(subghz_frequencies[model->frequency]); + furi_hal_subghz_set_path(model->path); + if(model->status == SubghzTestCarrierModelStatusRx) { hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); furi_hal_subghz_rx(); - osTimerStart(subghz_test_carrier->timer, 1024 / 4); } else { hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); hal_gpio_write(&gpio_cc1101_g0, true); @@ -123,7 +119,7 @@ void subghz_test_carrier_enter(void* context) { SubghzTestCarrier* subghz_test_carrier = context; furi_hal_subghz_reset(); - furi_hal_subghz_load_preset(FuriHalSubGhzPresetOokAsync); + furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); @@ -159,8 +155,11 @@ void subghz_test_carrier_rssi_timer_callback(void* context) { with_view_model( subghz_test_carrier->view, (SubghzTestCarrierModel * model) { - model->rssi = furi_hal_subghz_get_rssi(); - return true; + if(model->status == SubghzTestCarrierModelStatusRx) { + model->rssi = furi_hal_subghz_get_rssi(); + return true; + } + return false; }); } @@ -170,7 +169,7 @@ SubghzTestCarrier* subghz_test_carrier_alloc() { // View allocation and configuration subghz_test_carrier->view = view_alloc(); view_allocate_model( - subghz_test_carrier->view, ViewModelTypeLockFree, sizeof(SubghzTestCarrierModel)); + subghz_test_carrier->view, ViewModelTypeLocking, sizeof(SubghzTestCarrierModel)); view_set_context(subghz_test_carrier->view, subghz_test_carrier); view_set_draw_callback(subghz_test_carrier->view, (ViewDrawCallback)subghz_test_carrier_draw); view_set_input_callback(subghz_test_carrier->view, subghz_test_carrier_input); diff --git a/applications/subghz/views/subghz_test_packet.c b/applications/subghz/views/subghz_test_packet.c index a15cc33f..f1c48179 100644 --- a/applications/subghz/views/subghz_test_packet.c +++ b/applications/subghz/views/subghz_test_packet.c @@ -116,7 +116,7 @@ static bool subghz_test_packet_input(InputEvent* event, void* context) { furi_assert(context); SubghzTestPacket* instance = context; - if(event->key == InputKeyBack) { + if(event->key == InputKeyBack || event->type != InputTypeShort) { return false; } @@ -128,28 +128,26 @@ static bool subghz_test_packet_input(InputEvent* event, void* context) { furi_hal_subghz_stop_async_tx(); } - if(event->type == InputTypeShort) { - if(event->key == InputKeyLeft) { - if(model->frequency > 0) model->frequency--; - } else if(event->key == InputKeyRight) { - if(model->frequency < subghz_frequencies_count - 1) model->frequency++; - } else if(event->key == InputKeyDown) { - if(model->path > 0) model->path--; - } else if(event->key == InputKeyUp) { - if(model->path < FuriHalSubGhzPath868) model->path++; - } else if(event->key == InputKeyOk) { - if(model->status == SubghzTestPacketModelStatusTx) { - model->status = SubghzTestPacketModelStatusRx; - } else { - model->status = SubghzTestPacketModelStatusTx; - } + if(event->key == InputKeyLeft) { + if(model->frequency > 0) model->frequency--; + } else if(event->key == InputKeyRight) { + if(model->frequency < subghz_frequencies_count - 1) model->frequency++; + } else if(event->key == InputKeyDown) { + if(model->path > 0) model->path--; + } else if(event->key == InputKeyUp) { + if(model->path < FuriHalSubGhzPath868) model->path++; + } else if(event->key == InputKeyOk) { + if(model->status == SubghzTestPacketModelStatusTx) { + model->status = SubghzTestPacketModelStatusRx; + } else { + model->status = SubghzTestPacketModelStatusTx; } - - model->real_frequency = - furi_hal_subghz_set_frequency(subghz_frequencies[model->frequency]); - furi_hal_subghz_set_path(model->path); } + model->real_frequency = + furi_hal_subghz_set_frequency(subghz_frequencies[model->frequency]); + furi_hal_subghz_set_path(model->path); + if(model->status == SubghzTestPacketModelStatusRx) { furi_hal_subghz_start_async_rx(subghz_test_packet_rx_callback, instance); } else { @@ -168,7 +166,7 @@ void subghz_test_packet_enter(void* context) { SubghzTestPacket* instance = context; furi_hal_subghz_reset(); - furi_hal_subghz_load_preset(FuriHalSubGhzPresetOokAsync); + furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); with_view_model( instance->view, (SubghzTestPacketModel * model) { @@ -210,7 +208,7 @@ SubghzTestPacket* subghz_test_packet_alloc() { // View allocation and configuration instance->view = view_alloc(); - view_allocate_model(instance->view, ViewModelTypeLockFree, sizeof(SubghzTestPacketModel)); + view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(SubghzTestPacketModel)); view_set_context(instance->view, instance); view_set_draw_callback(instance->view, (ViewDrawCallback)subghz_test_packet_draw); view_set_input_callback(instance->view, subghz_test_packet_input); diff --git a/applications/subghz/views/subghz_static.c b/applications/subghz/views/subghz_test_static.c similarity index 63% rename from applications/subghz/views/subghz_static.c rename to applications/subghz/views/subghz_test_static.c index d8937bf3..240dc215 100644 --- a/applications/subghz/views/subghz_static.c +++ b/applications/subghz/views/subghz_test_static.c @@ -1,4 +1,4 @@ -#include "subghz_static.h" +#include "subghz_test_static.h" #include "../subghz_i.h" #include @@ -8,30 +8,30 @@ #include #include -static const uint32_t subghz_static_keys[] = { +static const uint32_t subghz_test_static_keys[] = { 0x0074BADE, 0x0074BADD, 0x0074BADB, 0x00E34A4E, }; -struct SubghzStatic { +struct SubghzTestStatic { View* view; SubGhzEncoderPrinceton* encoder; }; typedef enum { - SubghzStaticStatusRx, - SubghzStaticStatusTx, -} SubghzStaticStatus; + SubghzTestStaticStatusRx, + SubghzTestStaticStatusTx, +} SubghzTestStaticStatus; typedef struct { uint8_t frequency; uint32_t real_frequency; uint8_t button; -} SubghzStaticModel; +} SubghzTestStaticModel; -void subghz_static_draw(Canvas* canvas, SubghzStaticModel* model) { +void subghz_test_static_draw(Canvas* canvas, SubghzTestStaticModel* model) { char buffer[64]; canvas_set_color(canvas, ColorBlack); @@ -52,24 +52,21 @@ void subghz_static_draw(Canvas* canvas, SubghzStaticModel* model) { canvas_draw_str(canvas, 0, 31, buffer); } -bool subghz_static_input(InputEvent* event, void* context) { +bool subghz_test_static_input(InputEvent* event, void* context) { furi_assert(context); - SubghzStatic* instance = context; + SubghzTestStatic* instance = context; if(event->key == InputKeyBack) { return false; } with_view_model( - instance->view, (SubghzStaticModel * model) { - bool reconfigure = false; + instance->view, (SubghzTestStaticModel * model) { if(event->type == InputTypeShort) { if(event->key == InputKeyLeft) { if(model->frequency > 0) model->frequency--; - reconfigure = true; } else if(event->key == InputKeyRight) { if(model->frequency < subghz_frequencies_count - 1) model->frequency++; - reconfigure = true; } else if(event->key == InputKeyDown) { if(model->button > 0) model->button--; } else if(event->key == InputKeyUp) { @@ -77,28 +74,29 @@ bool subghz_static_input(InputEvent* event, void* context) { } } - if(reconfigure) { - furi_hal_subghz_idle(); - model->real_frequency = - furi_hal_subghz_set_frequency_and_path(subghz_frequencies[model->frequency]); - furi_hal_subghz_tx(); - } + model->real_frequency = subghz_frequencies[model->frequency]; if(event->key == InputKeyOk) { + NotificationApp* notification = furi_record_open("notification"); if(event->type == InputTypePress) { - NotificationApp* notification = furi_record_open("notification"); notification_message_block(notification, &sequence_set_red_255); + FURI_LOG_I("SubghzTestStatic", "TX Start"); + furi_hal_subghz_idle(); + furi_hal_subghz_set_frequency_and_path(subghz_frequencies[model->frequency]); + subghz_encoder_princeton_set( - instance->encoder, subghz_static_keys[model->button], 20); + instance->encoder, subghz_test_static_keys[model->button], 10000); + furi_hal_subghz_start_async_tx( subghz_encoder_princeton_yield, instance->encoder); - while(!furi_hal_subghz_is_async_tx_complete()) osDelay(33); + } else if(event->type == InputTypeRelease) { + FURI_LOG_I("SubghzTestStatic", "TX Stop"); furi_hal_subghz_stop_async_tx(); notification_message(notification, &sequence_reset_red); - furi_record_close("notification"); } + furi_record_close("notification"); } return true; @@ -107,58 +105,55 @@ bool subghz_static_input(InputEvent* event, void* context) { return true; } -void subghz_static_enter(void* context) { +void subghz_test_static_enter(void* context) { furi_assert(context); - SubghzStatic* instance = context; + SubghzTestStatic* instance = context; furi_hal_subghz_reset(); - furi_hal_subghz_load_preset(FuriHalSubGhzPresetOokAsync); + furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); hal_gpio_write(&gpio_cc1101_g0, false); with_view_model( - instance->view, (SubghzStaticModel * model) { + instance->view, (SubghzTestStaticModel * model) { model->frequency = subghz_frequencies_433_92; - model->real_frequency = - furi_hal_subghz_set_frequency_and_path(subghz_frequencies[model->frequency]); + model->real_frequency = subghz_frequencies[model->frequency]; model->button = 0; return true; }); - - furi_hal_subghz_tx(); } -void subghz_static_exit(void* context) { +void subghz_test_static_exit(void* context) { furi_assert(context); furi_hal_subghz_sleep(); } -SubghzStatic* subghz_static_alloc() { - SubghzStatic* instance = furi_alloc(sizeof(SubghzStatic)); +SubghzTestStatic* subghz_test_static_alloc() { + SubghzTestStatic* instance = furi_alloc(sizeof(SubghzTestStatic)); // View allocation and configuration instance->view = view_alloc(); - view_allocate_model(instance->view, ViewModelTypeLockFree, sizeof(SubghzStaticModel)); + view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(SubghzTestStaticModel)); view_set_context(instance->view, instance); - view_set_draw_callback(instance->view, (ViewDrawCallback)subghz_static_draw); - view_set_input_callback(instance->view, subghz_static_input); - view_set_enter_callback(instance->view, subghz_static_enter); - view_set_exit_callback(instance->view, subghz_static_exit); + view_set_draw_callback(instance->view, (ViewDrawCallback)subghz_test_static_draw); + view_set_input_callback(instance->view, subghz_test_static_input); + view_set_enter_callback(instance->view, subghz_test_static_enter); + view_set_exit_callback(instance->view, subghz_test_static_exit); instance->encoder = subghz_encoder_princeton_alloc(); return instance; } -void subghz_static_free(SubghzStatic* instance) { +void subghz_test_static_free(SubghzTestStatic* instance) { furi_assert(instance); subghz_encoder_princeton_free(instance->encoder); view_free(instance->view); free(instance); } -View* subghz_static_get_view(SubghzStatic* instance) { +View* subghz_test_static_get_view(SubghzTestStatic* instance) { furi_assert(instance); return instance->view; } diff --git a/applications/subghz/views/subghz_test_static.h b/applications/subghz/views/subghz_test_static.h new file mode 100644 index 00000000..ddcd8315 --- /dev/null +++ b/applications/subghz/views/subghz_test_static.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +typedef struct SubghzTestStatic SubghzTestStatic; + +SubghzTestStatic* subghz_test_static_alloc(); + +void subghz_test_static_free(SubghzTestStatic* subghz_static); + +View* subghz_test_static_get_view(SubghzTestStatic* subghz_static); diff --git a/applications/subghz/views/subghz_transmitter.c b/applications/subghz/views/subghz_transmitter.c index 1ba76d97..1dd4e7d9 100644 --- a/applications/subghz/views/subghz_transmitter.c +++ b/applications/subghz/views/subghz_transmitter.c @@ -7,8 +7,7 @@ #include #include #include - -#include +#include struct SubghzTransmitter { View* view; @@ -19,6 +18,8 @@ struct SubghzTransmitter { typedef struct { string_t text; uint16_t scene; + uint32_t real_frequency; + FuriHalSubGhzPreset preset; SubGhzProtocolCommon* protocol; } SubghzTransmitterModel; @@ -42,36 +43,102 @@ void subghz_transmitter_set_protocol( }); } +void subghz_transmitter_set_frequency_preset( + SubghzTransmitter* subghz_transmitter, + uint32_t frequency, + FuriHalSubGhzPreset preset) { + with_view_model( + subghz_transmitter->view, (SubghzTransmitterModel * model) { + model->real_frequency = frequency; + model->preset = preset; + return true; + }); +} + +static void subghz_transmitter_button_right(Canvas* canvas, const char* str) { + const uint8_t button_height = 13; + const uint8_t vertical_offset = 3; + const uint8_t horizontal_offset = 1; + const uint8_t string_width = canvas_string_width(canvas, str); + const Icon* icon = &I_ButtonCenter_7x7; + const uint8_t icon_offset = 3; + const uint8_t icon_width_with_offset = icon_get_width(icon) + icon_offset; + const uint8_t button_width = string_width + horizontal_offset * 2 + icon_width_with_offset; + + const uint8_t x = (canvas_width(canvas) - button_width) / 2 + 40; + const uint8_t y = canvas_height(canvas); + + canvas_draw_box(canvas, x, y - button_height, button_width, button_height); + + canvas_draw_line(canvas, x - 1, y, x - 1, y - button_height + 0); + canvas_draw_line(canvas, x - 2, y, x - 2, y - button_height + 1); + canvas_draw_line(canvas, x - 3, y, x - 3, y - button_height + 2); + + canvas_draw_line(canvas, x + button_width + 0, y, x + button_width + 0, y - button_height + 0); + canvas_draw_line(canvas, x + button_width + 1, y, x + button_width + 1, y - button_height + 1); + canvas_draw_line(canvas, x + button_width + 2, y, x + button_width + 2, y - button_height + 2); + + canvas_invert_color(canvas); + canvas_draw_icon( + canvas, x + horizontal_offset, y - button_height + vertical_offset, &I_ButtonCenter_7x7); + canvas_draw_str( + canvas, x + horizontal_offset + icon_width_with_offset, y - vertical_offset, str); + canvas_invert_color(canvas); +} + void subghz_transmitter_draw(Canvas* canvas, SubghzTransmitterModel* model) { + char buffer[64]; canvas_clear(canvas); canvas_set_color(canvas, ColorBlack); canvas_set_font(canvas, FontSecondary); - elements_multiline_text(canvas, 0, 10, string_get_cstr(model->text)); + elements_multiline_text(canvas, 0, 8, string_get_cstr(model->text)); + snprintf( + buffer, + sizeof(buffer), + "%03ld.%03ld", + model->real_frequency / 1000000 % 1000, + model->real_frequency / 1000 % 1000); + canvas_draw_str(canvas, 90, 8, buffer); if(model->protocol && model->protocol->get_upload_protocol) { - elements_button_center(canvas, "Send"); + if((!strcmp(model->protocol->name, "KeeLoq")) && + (!strcmp(subghz_protocol_keeloq_get_manufacture_name(model->protocol), "Unknown"))) { + return; + } + subghz_transmitter_button_right(canvas, "Send"); } } bool subghz_transmitter_input(InputEvent* event, void* context) { furi_assert(context); SubghzTransmitter* subghz_transmitter = context; - bool can_be_send = false; + bool can_be_sent = false; + + if(event->key == InputKeyBack) { + return false; + } + with_view_model( subghz_transmitter->view, (SubghzTransmitterModel * model) { - can_be_send = (model->protocol && model->protocol->get_upload_protocol); + if(model->protocol && model->protocol->get_upload_protocol) { + if((!strcmp(model->protocol->name, "KeeLoq")) && + (!strcmp( + subghz_protocol_keeloq_get_manufacture_name(model->protocol), "Unknown"))) { + return false; + } + can_be_sent = true; + } + //can_be_sent = (model->protocol && model->protocol->get_upload_protocol); string_clean(model->text); model->protocol->to_string(model->protocol, model->text); return true; }); //if(event->type != InputTypeShort) return false; - if(event->key == InputKeyBack) { - return false; - } else if(can_be_send && event->key == InputKeyOk && event->type == InputTypePress) { + if(can_be_sent && event->key == InputKeyOk && event->type == InputTypePress) { subghz_transmitter->callback(SubghzTransmitterEventSendStart, subghz_transmitter->context); return true; - } else if(can_be_send && event->key == InputKeyOk && event->type == InputTypeRelease) { + } else if(can_be_sent && event->key == InputKeyOk && event->type == InputTypeRelease) { subghz_transmitter->callback(SubghzTransmitterEventSendStop, subghz_transmitter->context); return true; } @@ -96,6 +163,7 @@ void subghz_transmitter_enter(void* context) { SubghzTransmitter* subghz_transmitter = context; with_view_model( subghz_transmitter->view, (SubghzTransmitterModel * model) { + string_clean(model->text); model->protocol->to_string(model->protocol, model->text); return true; }); diff --git a/applications/subghz/views/subghz_transmitter.h b/applications/subghz/views/subghz_transmitter.h index 2c1f1b72..c4dd5982 100644 --- a/applications/subghz/views/subghz_transmitter.h +++ b/applications/subghz/views/subghz_transmitter.h @@ -7,6 +7,7 @@ typedef enum { SubghzTransmitterEventSendStart, SubghzTransmitterEventSendStop, SubghzTransmitterEventBack, + SubghzTransmitterEventNoMan, } SubghzTransmitterEvent; typedef struct SubghzTransmitter SubghzTransmitter; @@ -27,3 +28,7 @@ View* subghz_transmitter_get_view(SubghzTransmitter* subghz_transmitter); void subghz_transmitter_set_protocol( SubghzTransmitter* subghz_transmitter, SubGhzProtocolCommon* protocol); +void subghz_transmitter_set_frequency_preset( + SubghzTransmitter* subghz_transmitter, + uint32_t frequency, + FuriHalSubGhzPreset preset); diff --git a/applications/tests/irda_decoder_encoder/irda_decoder_encoder_test.c b/applications/tests/irda_decoder_encoder/irda_decoder_encoder_test.c index dc5a21c1..66ec689d 100644 --- a/applications/tests/irda_decoder_encoder/irda_decoder_encoder_test.c +++ b/applications/tests/irda_decoder_encoder/irda_decoder_encoder_test.c @@ -1,11 +1,12 @@ #include #include "../minunit.h" #include "irda.h" -#include "irda_common_i.h" +#include "common/irda_common_i.h" #include "test_data/irda_nec_test_data.srcdata" #include "test_data/irda_necext_test_data.srcdata" #include "test_data/irda_samsung_test_data.srcdata" #include "test_data/irda_rc6_test_data.srcdata" +#include "test_data/irda_rc5_test_data.srcdata" #define RUN_ENCODER(data, expected) \ run_encoder((data), COUNT_OF(data), (expected), COUNT_OF(expected)) @@ -153,16 +154,19 @@ MU_TEST(test_decoder_samsung32) { } MU_TEST(test_mix) { + RUN_DECODER(test_decoder_rc5_input2, test_decoder_rc5_expected2); RUN_DECODER(test_decoder_necext_input1, test_decoder_necext_expected1); // can use encoder data for decoding, but can't do opposite RUN_DECODER(test_encoder_rc6_expected1, test_encoder_rc6_input1); RUN_DECODER(test_decoder_samsung32_input1, test_decoder_samsung32_expected1); RUN_DECODER(test_decoder_rc6_input1, test_decoder_rc6_expected1); RUN_DECODER(test_decoder_samsung32_input1, test_decoder_samsung32_expected1); + RUN_DECODER(test_decoder_rc5_input1, test_decoder_rc5_expected1); RUN_DECODER(test_decoder_necext_input1, test_decoder_necext_expected1); RUN_DECODER(test_decoder_nec_input2, test_decoder_nec_expected2); RUN_DECODER(test_decoder_rc6_input1, test_decoder_rc6_expected1); RUN_DECODER(test_decoder_necext_input1, test_decoder_necext_expected1); + RUN_DECODER(test_decoder_rc5_input5, test_decoder_rc5_expected5); RUN_DECODER(test_decoder_samsung32_input1, test_decoder_samsung32_expected1); } @@ -187,6 +191,25 @@ MU_TEST(test_decoder_necext1) { RUN_DECODER(test_decoder_necext_input1, test_decoder_necext_expected1); } +MU_TEST(test_decoder_rc5) { + RUN_DECODER(test_decoder_rc5x_input1, test_decoder_rc5x_expected1); + RUN_DECODER(test_decoder_rc5_input1, test_decoder_rc5_expected1); + RUN_DECODER(test_decoder_rc5_input2, test_decoder_rc5_expected2); + RUN_DECODER(test_decoder_rc5_input3, test_decoder_rc5_expected3); + RUN_DECODER(test_decoder_rc5_input4, test_decoder_rc5_expected4); + RUN_DECODER(test_decoder_rc5_input5, test_decoder_rc5_expected5); + RUN_DECODER(test_decoder_rc5_input6, test_decoder_rc5_expected6); + RUN_DECODER(test_decoder_rc5_input_all_repeats, test_decoder_rc5_expected_all_repeats); +} + +MU_TEST(test_encoder_rc5x) { + RUN_ENCODER(test_decoder_rc5x_expected1, test_decoder_rc5x_input1); +} + +MU_TEST(test_encoder_rc5) { + RUN_ENCODER(test_decoder_rc5_expected_all_repeats, test_decoder_rc5_input_all_repeats); +} + MU_TEST(test_decoder_rc6) { RUN_DECODER(test_decoder_rc6_input1, test_decoder_rc6_expected1); } @@ -200,20 +223,24 @@ MU_TEST(test_encoder_decoder_all) { run_encoder_decoder(test_necext_all, COUNT_OF(test_necext_all)); run_encoder_decoder(test_samsung32_all, COUNT_OF(test_samsung32_all)); run_encoder_decoder(test_rc6_all, COUNT_OF(test_rc6_all)); + run_encoder_decoder(test_rc5_all, COUNT_OF(test_rc5_all)); } MU_TEST_SUITE(test_irda_decoder_encoder) { MU_SUITE_CONFIGURE(&test_setup, &test_teardown); - MU_RUN_TEST(test_encoder_decoder_all); + MU_RUN_TEST(test_encoder_rc5x); + MU_RUN_TEST(test_encoder_rc5); + MU_RUN_TEST(test_decoder_rc5); + MU_RUN_TEST(test_decoder_rc6); + MU_RUN_TEST(test_encoder_rc6); MU_RUN_TEST(test_decoder_unexpected_end_in_sequence); MU_RUN_TEST(test_decoder_nec1); MU_RUN_TEST(test_decoder_nec2); MU_RUN_TEST(test_decoder_samsung32); MU_RUN_TEST(test_decoder_necext1); MU_RUN_TEST(test_mix); - MU_RUN_TEST(test_decoder_rc6); - MU_RUN_TEST(test_encoder_rc6); + MU_RUN_TEST(test_encoder_decoder_all); } int run_minunit_test_irda_decoder_encoder() { diff --git a/applications/tests/irda_decoder_encoder/test_data/irda_rc5_test_data.srcdata b/applications/tests/irda_decoder_encoder/test_data/irda_rc5_test_data.srcdata new file mode 100644 index 00000000..4cd39742 --- /dev/null +++ b/applications/tests/irda_decoder_encoder/test_data/irda_rc5_test_data.srcdata @@ -0,0 +1,160 @@ +/* +_______----__--____----__--____--__----____----__--__--__--__ + | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | + s1 s2 t | address | command | +*/ + +const uint32_t test_decoder_rc5x_input1[] = { +27000 + 888, 1776, 888, 888, 1776, 1776, 888, 888, 1776, 888, 888, 1776, 1776, 1776, 888, 888, 888, 888, 888, 888, +}; + +const IrdaMessage test_decoder_rc5x_expected1[] = { + {IrdaProtocolRC5X, 0x13, 0x10, false}, // toggle 0 +}; + +/* +_______--__----____----__--____--__----____----__--__--__--__ + | 1 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | + s1 s2 t | address | command | +*/ + +const uint32_t test_decoder_rc5_input1[] = { +27000 + 888, 888, 888, 1776, 1776, 1776, 888, 888, 1776, 888, 888, 1776, 1776, 1776, 888, 888, 888, 888, 888, 888, +}; + +const IrdaMessage test_decoder_rc5_expected1[] = { + {IrdaProtocolRC5, 0x13, 0x10, false}, // toggle 0 +}; + + +/* +_______--__--__--__----__--____--__----____----__--__--__--__ + | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | + s1 s2 t | address | command | +*/ + +const uint32_t test_decoder_rc5_input2[] = { +27000 + 888, 888, 888, 888, 888, 888, 888, 1776, 888, 888, 1776, 888, 888, 1776, 1776, 1776, 888, 888, 888, 888, 888, 888, +}; + +const IrdaMessage test_decoder_rc5_expected2[] = { + {IrdaProtocolRC5, 0x13, 0x10, false}, // toggle 1 +}; + +/* +_______--__----____----__--____--__----____----__--__--____-- + | 1 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | + s1 s2 t | address | command | +*/ + +const uint32_t test_decoder_rc5_input3[] = { +27000 + 888, 888, 888, 1776, 1776, 1776, 888, 888, 1776, 888, 888, 1776, 1776, 1776, 888, 888, 888, 888, 1776, 888, +}; + +const IrdaMessage test_decoder_rc5_expected3[] = { + {IrdaProtocolRC5, 0x13, 0x11, false}, // toggle 0 +}; + + +/* +_______--__--__--__----__--____--__----____----__--__--____-- + | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | + s1 s2 t | address | command | +*/ + +const uint32_t test_decoder_rc5_input4[] = { +27000 + 888, 888, 888, 888, 888, 888, 888, 1776, 888, 888, 1776, 888, 888, 1776, 1776, 1776, 888, 888, 888, 888, 1776, 888, +}; + +const IrdaMessage test_decoder_rc5_expected4[] = { + {IrdaProtocolRC5, 0x13, 0x11, false}, // toggle 1 +}; + +/* +_______--__----____--__--__--__--__--__--__--__--__--__--__-- + | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | + s1 s2 t | address | command | +*/ + +const uint32_t test_decoder_rc5_input5[] = { +27000 + 888, 888, 888, 1776, 1776, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, +}; + +const IrdaMessage test_decoder_rc5_expected5[] = { + {IrdaProtocolRC5, 0x1F, 0x3F, false}, // toggle 0 +}; + +/* +_______--__--__--__--__--__--__--__--__--__--__--__--__--__-- + | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | + s1 s2 t | address | command | +*/ + +const uint32_t test_decoder_rc5_input6[] = { +27000 + 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, +}; + +const IrdaMessage test_decoder_rc5_expected6[] = { + {IrdaProtocolRC5, 0x1F, 0x3F, false}, // toggle 1 +}; + + +const uint32_t test_decoder_rc5_input_all_repeats[] = { +27000 + 888, 888, 888, 1776, 1776, 1776, 888, 888, 1776, 888, 888, 1776, 1776, 1776, 888, 888, 888, 888, 1776, 888, +27000 + 888, 888, 888, 888, 888, 888, 888, 1776, 888, 888, 1776, 888, 888, 1776, 1776, 1776, 888, 888, 888, 888, 1776, 888, +27000 + 888, 888, 888, 888, 888, 888, 888, 1776, 888, 888, 1776, 888, 888, 1776, 1776, 1776, 888, 888, 888, 888, 1776, 888, +27000 + 888, 888, 888, 888, 888, 888, 888, 1776, 888, 888, 1776, 888, 888, 1776, 1776, 1776, 888, 888, 888, 888, 1776, 888, +27000 + 888, 888, 888, 1776, 1776, 1776, 888, 888, 1776, 888, 888, 1776, 1776, 1776, 888, 888, 888, 888, 1776, 888, +27000 + 888, 888, 888, 888, 888, 888, 888, 1776, 888, 888, 1776, 888, 888, 1776, 1776, 1776, 888, 888, 888, 888, 888, 888, +27000 + 888, 888, 888, 1776, 1776, 1776, 888, 888, 1776, 888, 888, 1776, 1776, 1776, 888, 888, 888, 888, 888, 888, +27000 + 888, 888, 888, 1776, 1776, 1776, 888, 888, 1776, 888, 888, 1776, 1776, 1776, 888, 888, 888, 888, 888, 888, +27000 + 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, +27000 + 888, 888, 888, 1776, 1776, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, +27000 + 888, 888, 888, 1776, 1776, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, +}; + +const IrdaMessage test_decoder_rc5_expected_all_repeats[] = { + {IrdaProtocolRC5, 0x13, 0x11, false}, // toggle 0 + {IrdaProtocolRC5, 0x13, 0x11, false}, // toggle 1 + {IrdaProtocolRC5, 0x13, 0x11, true}, // toggle 1 + {IrdaProtocolRC5, 0x13, 0x11, true}, // toggle 1 + {IrdaProtocolRC5, 0x13, 0x11, false}, // toggle 0 + {IrdaProtocolRC5, 0x13, 0x10, false}, // toggle 1 + {IrdaProtocolRC5, 0x13, 0x10, false}, // toggle 0 + {IrdaProtocolRC5, 0x13, 0x10, true}, // toggle 0 + {IrdaProtocolRC5, 0x1F, 0x3F, false}, // toggle 1 + {IrdaProtocolRC5, 0x1F, 0x3F, false}, // toggle 0 + {IrdaProtocolRC5, 0x1F, 0x3F, true}, // toggle 0 +}; + + +const IrdaMessage test_rc5_all[] = { + {IrdaProtocolRC5, 0x1F, 0x3F, false}, + {IrdaProtocolRC5, 0x00, 0x00, false}, + {IrdaProtocolRC5, 0x10, 0x01, false}, + {IrdaProtocolRC5, 0x01, 0x20, false}, + {IrdaProtocolRC5, 0x01, 0x20, false}, + {IrdaProtocolRC5, 0x01, 0x20, true}, + {IrdaProtocolRC5, 0x01, 0x20, true}, + {IrdaProtocolRC5, 0x01, 0x20, true}, + {IrdaProtocolRC5, 0x01, 0x20, true}, + {IrdaProtocolRC5, 0x1F, 0x3F, false}, + {IrdaProtocolRC5, 0x0A, 0x2A, false}, + {IrdaProtocolRC5, 0x15, 0x15, false}, + {IrdaProtocolRC5, 0x15, 0x15, true}, + + {IrdaProtocolRC5X, 0x1F, 0x3F, false}, + {IrdaProtocolRC5X, 0x00, 0x00, false}, + {IrdaProtocolRC5X, 0x10, 0x01, false}, + {IrdaProtocolRC5X, 0x01, 0x20, false}, + {IrdaProtocolRC5X, 0x01, 0x20, false}, + {IrdaProtocolRC5X, 0x01, 0x20, true}, + {IrdaProtocolRC5X, 0x01, 0x20, true}, + {IrdaProtocolRC5X, 0x01, 0x20, true}, + {IrdaProtocolRC5X, 0x01, 0x20, true}, + {IrdaProtocolRC5X, 0x1F, 0x3F, false}, + {IrdaProtocolRC5X, 0x0A, 0x2A, false}, + {IrdaProtocolRC5X, 0x15, 0x15, false}, + {IrdaProtocolRC5X, 0x15, 0x15, true}, +}; + diff --git a/applications/tests/irda_decoder_encoder/test_data/irda_rc6_test_data.srcdata b/applications/tests/irda_decoder_encoder/test_data/irda_rc6_test_data.srcdata index eb31c6d4..ea764d43 100644 --- a/applications/tests/irda_decoder_encoder/test_data/irda_rc6_test_data.srcdata +++ b/applications/tests/irda_decoder_encoder/test_data/irda_rc6_test_data.srcdata @@ -15,17 +15,17 @@ _____---------______--____--__--__------____--____--__----____--__----__--__--__ */ const uint32_t test_decoder_rc6_input1[] = { -2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, -2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444 + 888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, -2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 888, // failed -2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, -2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, -2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, -2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444 + 888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, -2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 888, // failed -2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, -2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444 + 888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 888, -2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 888, // failed +27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, +27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444 + 888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, +27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 888, // failed +27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, +27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, +27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, +27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444 + 888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, +27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 888, // failed +27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, +27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444 + 888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 888, +27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 888, // failed }; const IrdaMessage test_decoder_rc6_expected1[] = { @@ -54,14 +54,14 @@ const IrdaMessage test_encoder_rc6_input1[] = { }; const uint32_t test_encoder_rc6_expected1[] = { -2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 888, 888+444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, -2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 888, 888+444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, -2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444+888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 888, -2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444+888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 888, -2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444+888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 888, -2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 888, 888+444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, -2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444+888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, -2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444+888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, +27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 888, 888+444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, +27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 888, 888+444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, +27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444+888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 888, +27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444+888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 888, +27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444+888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 888, +27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 888, 888+444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, +27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444+888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, +27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444+888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, }; diff --git a/assets/compiled/assets_icons.c b/assets/compiled/assets_icons.c index 8a2d5b35..f95f04c1 100644 --- a/assets/compiled/assets_icons.c +++ b/assets/compiled/assets_icons.c @@ -53,6 +53,9 @@ const uint8_t *_I_ButtonLeft_4x7[] = {_I_ButtonLeft_4x7_0}; const uint8_t _I_ButtonLeftSmall_3x5_0[] = {0x04,0x06,0x07,0x06,0x04,}; const uint8_t *_I_ButtonLeftSmall_3x5[] = {_I_ButtonLeftSmall_3x5_0}; +const uint8_t _I_DFU_128x50_0[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x8F,0x01,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x7F,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xFF,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x75,0x00,0x00,0xF0,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xFF,0x0A,0x00,0x00,0x0F,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xE0,0x0F,0x00,0xC0,0xE0,0x4F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x18,0x00,0x30,0x1E,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x18,0x00,0x8C,0x01,0xA0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x81,0xFF,0x19,0x00,0x63,0x00,0xC0,0xF0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x60,0x5E,0x1F,0x80,0x18,0x00,0xE0,0x0E,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x18,0xAF,0x0F,0x40,0x06,0x00,0xF8,0x01,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x06,0x57,0x01,0x20,0x01,0x00,0x78,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x84,0x81,0xAF,0x02,0x90,0x00,0x00,0x38,0x80,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x80,0x57,0x01,0x48,0x00,0x00,0x10,0x60,0x40,0x00,0x00,0x00,0x00,0x00,0xC0,0x10,0x80,0xAB,0x00,0x24,0x00,0x00,0x08,0x10,0x40,0x3F,0x00,0x00,0x00,0x00,0x38,0x0C,0xC0,0x57,0x01,0x12,0x00,0x00,0x04,0x08,0x40,0xC0,0x0F,0x00,0x00,0xC0,0x07,0x03,0xF0,0xAB,0x00,0x0A,0x00,0x00,0x02,0x04,0x40,0x00,0xF0,0x1F,0x80,0x3F,0xC0,0x00,0xFC,0x55,0x01,0x05,0xE0,0x00,0x01,0x04,0x40,0x00,0x00,0xE0,0x7F,0x00,0x30,0x00,0xFF,0xAB,0x00,0x05,0xE0,0x80,0x00,0x02,0x40,0x0F,0x00,0x00,0x00,0x80,0x0F,0xE0,0xCF,0x55,0x81,0x02,0xF0,0x40,0x00,0x02,0x40,0xF0,0x0F,0x00,0x00,0x7F,0x00,0xFE,0xC3,0xAB,0x80,0x02,0x78,0x20,0x00,0x01,0x40,0x00,0xF0,0xFF,0xFF,0x00,0xF0,0xFF,0xC0,0xD5,0x81,0x01,0x7E,0x10,0x80,0x00,0x20,0x00,0x00,0x00,0x00,0xC0,0xFF,0x0F,0xE0,0xFA,0x83,0xC1,0x3F,0x08,0x80,0x00,0x20,0x00,0x00,0x00,0x00,0xFF,0xFF,0x01,0xD8,0x07,0x83,0xF1,0x1F,0x04,0x40,0x00,0x20,0x00,0xE0,0xFF,0xFF,0xFF,0x0F,0x80,0xC7,0x01,0x83,0xF1,0x0F,0x00,0x20,0x00,0x10,0xE0,0xFF,0xFF,0xFF,0x3F,0xC0,0x7F,0x40,0x80,0x83,0xE1,0x01,0x00,0x20,0x00,0x18,0xFC,0xFF,0xFF,0xFF,0x03,0x3F,0x00,0x20,0xFC,0x83,0x01,0x00,0x00,0x10,0x00,0x18,0xFF,0xFF,0xFF,0x3F,0xF0,0x00,0x00,0x10,0xD7,0x01,0x03,0x00,0x00,0x08,0x00,0x1C,0xFF,0xFF,0x01,0x00,0x0F,0x00,0x00,0x88,0xAB,0x02,0xE3,0x01,0x00,0x08,0x00,0x0C,0xFF,0x07,0x00,0xE0,0x00,0x00,0x00,0xC4,0x55,0x05,0x1E,0x00,0x00,0x04,0x00,0x0E,0x7F,0x00,0x00,0x1C,0x00,0x00,0x00,0xA3,0xAB,0x02,0x06,0x00,0x00,0x02,0x00,0x0F,0x0F,0x00,0x80,0x03,0x00,0x00,0xC0,0x10,0x57,0x05,0x02,0x00,0x00,0x01,0x80,0x07,0x03,0x00,0x70,0x00,0x00,0x00,0x30,0x08,0xAB,0x0A,0x02,0x00,0xC0,0x00,0xC0,0x07,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x84,0x57,0x15,0x01,0x00,0x30,0x00,0xE0,0x07,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0xC3,0xFF,0x2A,0x01,0x00,0x0C,0x00,0xF0,0x0F,0x00,0xC0,0x00,0x00,0x00,0xE0,0xC0,0xE0,0xFE,0x55,0x01,0x82,0x03,0x00,0xF8,0x15,0x00,0x30,0x00,0x00,0x00,0x1C,0x30,0x78,0xFE,0xAA,0x01,0x7C,0x00,0x00,0xFC,0x23,0x00,0x0E,0x00,0x00,0xC0,0x03,0x0C,0x3C,0x7F,0x5D,0x01,0x00,0x00,0x00,0xFF,0x45,0xC0,0x01,0x00,0x00,0x3E,0x00,0x02,0x8F,0xBF,0xAE,0x03,0x00,0x00,0xC0,0xFF,0x82,0x30,0x00,0x00,0xC0,0x01,0x80,0xC1,0x43,0xFE,0x5D,0x01,0x00,0x00,0xF0,0xFF,0x05,0x0F,0x00,0x80,0x3F,0x00,0x60,0xF0,0x31,0xF6,0xAE,0x03,0x00,0x00,0xFA,0xAF,0x02,0xFC,0xFF,0x7F,0x00,0x00,0x18,0x7C,0x08,0x23,0xFF,0x05,0x00,0x00,0xFD,0x55,0x01,0x00,0x00,0x00,0x00,0x00,0x86,0x1F,0x84,0x30,0xFE,0x0A,0x00,0x00,0xAA,0xAA,0x00,0x00,0x00,0x00,0x00,0x80,0xF1,0x07,0x43,0x18,0xFF,0x15,0x00,0x00,0x54,0x15,0x00,0x00,0x00,0x00,0x00,0xF8,0xFF,0x80,0x20,0x8C,0xFF,0xAA,0x00,0x00,0x00,0x00,0x00,}; +const uint8_t *_I_DFU_128x50[] = {_I_DFU_128x50_0}; + const uint8_t _I_Warning_30x23_0[] = {0x00,0xC0,0x00,0x00,0x00,0xE0,0x01,0x00,0x00,0xF0,0x03,0x00,0x00,0xF0,0x03,0x00,0x00,0xF8,0x07,0x00,0x00,0x3C,0x0F,0x00,0x00,0x3C,0x0F,0x00,0x00,0x3E,0x1F,0x00,0x00,0x3F,0x3F,0x00,0x00,0x3F,0x3F,0x00,0x80,0x3F,0x7F,0x00,0xC0,0x3F,0xFF,0x00,0xC0,0x3F,0xFF,0x00,0xE0,0x3F,0xFF,0x01,0xF0,0x3F,0xFF,0x03,0xF0,0x3F,0xFF,0x03,0xF8,0x3F,0xFF,0x07,0xFC,0xFF,0xFF,0x0F,0xFC,0xFF,0xFF,0x0F,0xFE,0x3F,0xFF,0x1F,0xFF,0x3F,0xFF,0x3F,0xFF,0xFF,0xFF,0x3F,0xFE,0xFF,0xFF,0x1F,}; const uint8_t *_I_Warning_30x23[] = {_I_Warning_30x23_0}; @@ -95,6 +98,18 @@ const uint8_t *_I_Flipper_young_80x60[] = {_I_Flipper_young_80x60_0}; const uint8_t _I_DolphinFirstStart3_57x48_0[] = {0x00,0x00,0x00,0x80,0xFF,0x07,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x04,0x00,0x00,0xF8,0x03,0x01,0x00,0x00,0x08,0x00,0x00,0x04,0xBC,0x00,0x00,0x00,0x10,0x00,0x00,0x02,0xC0,0x00,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x01,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x02,0x00,0x38,0x40,0x00,0x00,0x02,0x00,0x04,0x00,0x3E,0x40,0x00,0x00,0xF4,0x03,0x08,0x80,0x07,0x80,0x00,0x00,0x5C,0x0D,0x10,0xE0,0x01,0x80,0x00,0x00,0xA8,0x3A,0x20,0xE0,0x00,0x00,0x01,0x00,0x58,0x55,0x00,0xC0,0x01,0x00,0x01,0x00,0xB0,0xAA,0x00,0x80,0x07,0x00,0x01,0x00,0x60,0x55,0x01,0x00,0x1E,0x00,0x01,0x0E,0xC0,0xAA,0x02,0xE0,0x5C,0x00,0x01,0x11,0x80,0x55,0x05,0x00,0xA9,0x00,0x01,0x21,0x00,0xAB,0x0A,0x00,0x56,0x07,0x01,0x41,0x00,0x56,0x15,0x00,0xEC,0x08,0x01,0x81,0x00,0xBF,0x2A,0x00,0x34,0x08,0x01,0x01,0xF1,0xC0,0x57,0x00,0x0C,0x08,0x01,0x02,0x0A,0x00,0xBE,0x00,0x04,0x08,0x01,0x02,0x06,0x00,0x78,0x83,0x02,0x04,0x01,0x02,0x0C,0x00,0xF0,0x7F,0x01,0x04,0x01,0x02,0xF4,0x01,0xFE,0x81,0x00,0x04,0x01,0x04,0x08,0xFF,0x6B,0x40,0x00,0x02,0x01,0x04,0x88,0x55,0x1D,0x40,0x00,0x02,0x01,0x04,0x50,0xAA,0x06,0x20,0x00,0x02,0x01,0x04,0x30,0xD4,0x01,0x20,0x00,0x01,0x01,0x04,0x10,0x68,0x00,0x10,0x00,0x01,0x01,0x04,0x18,0x18,0x00,0x10,0x00,0x01,0x01,0x08,0x18,0x06,0x80,0x10,0x00,0x01,0x01,0x08,0xE8,0x01,0x60,0x08,0x80,0x00,0x01,0x08,0x08,0x00,0x18,0x08,0x80,0x00,0x00,0x08,0x10,0x00,0x06,0x08,0x80,0x00,0x00,0x08,0x60,0xE0,0x01,0x08,0x80,0x00,0x00,0x08,0x80,0x1F,0x00,0x08,0x80,0x00,0x00,0x08,0x80,0x04,0x00,0x04,0x00,0x01,0x00,0x08,0x80,0x04,0x00,0x04,0x00,0x01,0x00,0x10,0x00,0x03,0x00,0x04,0x00,0x01,0x00,0x10,0x00,0x03,0x00,0x04,0x00,0x01,0x00,0x10,0x00,0x01,0x00,0x04,0x00,0x02,0x00,0x10,0x00,0x01,0x00,0x04,0x00,0x02,0x00,0x10,0x80,0x00,0x00,0x04,0x00,0x02,0x00,0x10,0x80,0x00,0x00,0x04,0x00,0x06,0x00,}; const uint8_t *_I_DolphinFirstStart3_57x48[] = {_I_DolphinFirstStart3_57x48_0}; +const uint8_t _I_Scanning_123x52_0[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x07,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAC,0x03,0x18,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x56,0x05,0x60,0x00,0x00,0x00,0x80,0x02,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x81,0x0A,0x80,0x00,0x00,0x00,0x80,0x02,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x80,0x00,0x15,0x00,0x01,0x00,0x00,0x40,0x02,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x40,0x00,0x38,0x00,0x02,0x00,0x00,0x40,0x02,0x00,0x00,0x00,0x00,0x82,0x00,0x00,0x20,0x00,0x74,0x00,0x04,0x00,0x00,0x40,0x82,0x01,0x00,0x00,0x00,0x41,0x00,0x00,0x20,0x00,0x68,0x00,0x04,0x00,0x00,0x20,0x82,0x02,0x06,0x00,0x00,0x21,0x00,0x00,0x10,0x00,0xD0,0xE0,0x0F,0x00,0x00,0x20,0x82,0x02,0x0A,0x0C,0x80,0x20,0x08,0x00,0x10,0x00,0xA0,0x1C,0x10,0x00,0x00,0x20,0x82,0x02,0x0A,0x14,0x80,0x10,0x04,0x00,0x08,0xE0,0xD3,0x03,0x10,0x00,0x00,0x10,0x82,0x02,0x0A,0x14,0x80,0x10,0x02,0x00,0x08,0x90,0xA7,0x40,0x24,0x00,0x00,0x10,0x82,0x02,0x0A,0x14,0x80,0x10,0x02,0x00,0x08,0xC8,0x7F,0x84,0x28,0x00,0x00,0x10,0x84,0x02,0x0A,0xFF,0x80,0x10,0x02,0x00,0x88,0x67,0x3E,0x88,0x28,0x00,0x00,0x10,0x84,0xFA,0xFF,0xFF,0x80,0x10,0x02,0x00,0x44,0x64,0x2E,0x88,0x28,0x00,0x00,0x10,0xFC,0xAF,0xFF,0x15,0x80,0x10,0x04,0x00,0x44,0xE4,0x2F,0x88,0x2A,0x00,0x00,0x18,0xD4,0xDF,0x1F,0x14,0x80,0x20,0x08,0x00,0x44,0xE4,0x2F,0x50,0xFF,0x00,0xFE,0x1F,0xEC,0x3F,0x0A,0x14,0x00,0x21,0x00,0x00,0x44,0xC4,0x2F,0xEA,0x00,0x01,0x01,0x1A,0xFC,0x02,0x0A,0x14,0x00,0x41,0x00,0x00,0x84,0x88,0x2F,0x1D,0x00,0x82,0x7D,0x1E,0x84,0x02,0x0A,0x18,0x00,0x82,0x00,0x00,0x86,0x1F,0xC6,0x06,0x00,0x84,0x7D,0x16,0x84,0x02,0x0A,0x00,0x00,0x02,0x00,0x00,0x46,0xF5,0xC3,0x01,0x00,0x44,0x01,0x22,0x84,0x02,0x0C,0x00,0x00,0x04,0x00,0x00,0x87,0x0A,0x7C,0x00,0x00,0x44,0x03,0x22,0x88,0x02,0x00,0x00,0x00,0x08,0x00,0x00,0x45,0x05,0x08,0x00,0x7E,0xA4,0x03,0x42,0x88,0x02,0x00,0x00,0x00,0x10,0x00,0x00,0x86,0x06,0x00,0xC0,0x81,0xA5,0x07,0x42,0x08,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x30,0x00,0xD2,0xFF,0x81,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x0C,0x00,0xD2,0x1F,0x80,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x80,0x00,0x03,0x00,0xD1,0x1F,0x00,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0xE1,0x00,0x80,0xE9,0x0F,0x00,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x1E,0x00,0xC0,0xE8,0x0F,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x70,0xEE,0x0F,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x3C,0xF9,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0xAA,0x9F,0xF0,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x40,0x55,0xFD,0x5F,0xF0,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x80,0xEA,0xFF,0x3F,0xE0,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x40,0xD5,0xFF,0x1F,0xE0,0x17,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x80,0xAA,0xFF,0x0F,0xE0,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x55,0x55,0x03,0xF0,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0xAA,0xAA,0x00,0xB0,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x54,0x75,0x00,0x58,0x0D,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0xA8,0x0F,0x00,0xA8,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x7C,0x00,0x00,0x5C,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0xAE,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0xD7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x00,0x00,0x80,0x7B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x00,0x00,0x00,0xC0,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2A,0x00,0x00,0x00,0xF0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x55,0x00,0x00,0x00,0xFC,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAA,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,}; +const uint8_t *_I_Scanning_123x52[] = {_I_Scanning_123x52_0}; + +const uint8_t _I_Quest_7x8_0[] = {0x1E,0x33,0x33,0x30,0x18,0x0C,0x00,0x0C,}; +const uint8_t *_I_Quest_7x8[] = {_I_Quest_7x8_0}; + +const uint8_t _I_Unlock_7x8_0[] = {0x1C,0x22,0x02,0x4F,0x67,0x73,0x79,0x3C,}; +const uint8_t *_I_Unlock_7x8[] = {_I_Unlock_7x8_0}; + +const uint8_t _I_Lock_7x8_0[] = {0x1C,0x22,0x22,0x7F,0x7F,0x77,0x7F,0x3E,}; +const uint8_t *_I_Lock_7x8[] = {_I_Lock_7x8_0}; + const uint8_t _I_PassportBottom_128x17_0[] = {0x2C,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8F,0x34,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x95,0x2C,0x00,0x00,0x00,0x00,0x00,0x00,0xA8,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0x9A,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x95,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0xA8,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0x9A,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x95,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xA8,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0x9A,0xF2,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8F,0xF9,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0D,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x05,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x05,0xF2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0x05,0xFA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x1F,0x09,0x79,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0xD5,0x80,0x55,0xD5,0x00,0xF3,0xCC,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0x6A,0x00,0xAB,0x6A,0x00,0x06,0x86,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0x00,0xFE,0x3F,0x00,0xFC,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,}; const uint8_t *_I_PassportBottom_128x17[] = {_I_PassportBottom_128x17_0}; @@ -321,12 +336,12 @@ const uint8_t _A_iButton_14_5[] = {0x00,0x00,0x00,0x38,0x00,0x24,0x00,0x22,0x80, const uint8_t _A_iButton_14_6[] = {0x00,0x00,0x00,0x38,0x00,0x24,0x00,0x23,0x80,0x20,0xF0,0x10,0x0C,0x0D,0xE2,0x02,0x91,0x01,0x69,0x01,0x15,0x01,0x8D,0x00,0x4D,0x00,0x3E,0x00,}; const uint8_t *_A_iButton_14[] = {_A_iButton_14_0,_A_iButton_14_1,_A_iButton_14_2,_A_iButton_14_3,_A_iButton_14_4,_A_iButton_14_5,_A_iButton_14_6}; +const uint8_t _I_Detailed_chip_17x13_0[] = {0xFC,0x7F,0x00,0x02,0x80,0x00,0x11,0x11,0x01,0x91,0x12,0x01,0x5F,0xF0,0x01,0x21,0x08,0x01,0x21,0x08,0x01,0x21,0x08,0x01,0x5F,0xF4,0x01,0x91,0x12,0x01,0x11,0x11,0x01,0x02,0x80,0x00,0xFC,0x7F,0x00,}; +const uint8_t *_I_Detailed_chip_17x13[] = {_I_Detailed_chip_17x13_0}; + const uint8_t _I_Medium_chip_22x21_0[] = {0xFC,0xFF,0x0F,0x02,0x00,0x10,0xF9,0xFF,0x27,0x85,0x52,0x28,0xC5,0xFF,0x28,0x25,0x00,0x29,0x95,0x67,0x2A,0x5D,0x60,0x2E,0x55,0x00,0x2A,0x1D,0x80,0x2E,0x55,0x80,0x2A,0x1D,0x80,0x2E,0x55,0x80,0x2A,0x5D,0x80,0x2E,0x95,0x7D,0x2A,0x25,0x00,0x29,0xC5,0xFF,0x28,0x85,0x52,0x28,0xF9,0xFF,0x27,0x02,0x00,0x10,0xFC,0xFF,0x0F,}; const uint8_t *_I_Medium_chip_22x21[] = {_I_Medium_chip_22x21_0}; -const uint8_t _I_EMV_Chip_14x11_0[] = {0xFC,0x0F,0x02,0x10,0xC9,0x24,0x2F,0x3C,0x11,0x22,0x11,0x22,0x11,0x22,0x2F,0x3D,0xC9,0x24,0x02,0x10,0xFC,0x0F,}; -const uint8_t *_I_EMV_Chip_14x11[] = {_I_EMV_Chip_14x11_0}; - const uint8_t _I_Health_16x16_0[] = {0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x01,0x40,0x01,0x40,0x01,0x78,0x0F,0x08,0x08,0x78,0x0F,0x40,0x01,0x40,0x01,0xC0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,}; const uint8_t *_I_Health_16x16[] = {_I_Health_16x16_0}; @@ -442,6 +457,7 @@ const Icon I_125_10px = {.width=10,.height=10,.frame_count=1,.frame_rate=0,.fram const Icon I_ButtonRightSmall_3x5 = {.width=3,.height=5,.frame_count=1,.frame_rate=0,.frames=_I_ButtonRightSmall_3x5}; const Icon I_ButtonLeft_4x7 = {.width=4,.height=7,.frame_count=1,.frame_rate=0,.frames=_I_ButtonLeft_4x7}; const Icon I_ButtonLeftSmall_3x5 = {.width=3,.height=5,.frame_count=1,.frame_rate=0,.frames=_I_ButtonLeftSmall_3x5}; +const Icon I_DFU_128x50 = {.width=128,.height=50,.frame_count=1,.frame_rate=0,.frames=_I_DFU_128x50}; const Icon I_Warning_30x23 = {.width=30,.height=23,.frame_count=1,.frame_rate=0,.frames=_I_Warning_30x23}; const Icon I_ButtonRight_4x7 = {.width=4,.height=7,.frame_count=1,.frame_rate=0,.frames=_I_ButtonRight_4x7}; const Icon I_ButtonCenter_7x7 = {.width=7,.height=7,.frame_count=1,.frame_rate=0,.frames=_I_ButtonCenter_7x7}; @@ -456,6 +472,10 @@ const Icon I_DolphinFirstStart8_56x51 = {.width=56,.height=51,.frame_count=1,.fr const Icon I_DolphinFirstStart7_61x51 = {.width=61,.height=51,.frame_count=1,.frame_rate=0,.frames=_I_DolphinFirstStart7_61x51}; const Icon I_Flipper_young_80x60 = {.width=80,.height=60,.frame_count=1,.frame_rate=0,.frames=_I_Flipper_young_80x60}; const Icon I_DolphinFirstStart3_57x48 = {.width=57,.height=48,.frame_count=1,.frame_rate=0,.frames=_I_DolphinFirstStart3_57x48}; +const Icon I_Scanning_123x52 = {.width=123,.height=52,.frame_count=1,.frame_rate=0,.frames=_I_Scanning_123x52}; +const Icon I_Quest_7x8 = {.width=7,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Quest_7x8}; +const Icon I_Unlock_7x8 = {.width=7,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Unlock_7x8}; +const Icon I_Lock_7x8 = {.width=7,.height=8,.frame_count=1,.frame_rate=0,.frames=_I_Lock_7x8}; const Icon I_PassportBottom_128x17 = {.width=128,.height=17,.frame_count=1,.frame_rate=0,.frames=_I_PassportBottom_128x17}; const Icon I_DoorLeft_8x56 = {.width=8,.height=56,.frame_count=1,.frame_rate=0,.frames=_I_DoorLeft_8x56}; const Icon I_DoorLocked_10x56 = {.width=10,.height=56,.frame_count=1,.frame_rate=0,.frames=_I_DoorLocked_10x56}; @@ -503,8 +523,8 @@ const Icon A_Sub1ghz_14 = {.width=14,.height=14,.frame_count=6,.frame_rate=3,.fr const Icon A_Tamagotchi_14 = {.width=14,.height=14,.frame_count=6,.frame_rate=3,.frames=_A_Tamagotchi_14}; const Icon A_U2F_14 = {.width=14,.height=14,.frame_count=4,.frame_rate=3,.frames=_A_U2F_14}; const Icon A_iButton_14 = {.width=14,.height=14,.frame_count=7,.frame_rate=3,.frames=_A_iButton_14}; +const Icon I_Detailed_chip_17x13 = {.width=17,.height=13,.frame_count=1,.frame_rate=0,.frames=_I_Detailed_chip_17x13}; const Icon I_Medium_chip_22x21 = {.width=22,.height=21,.frame_count=1,.frame_rate=0,.frames=_I_Medium_chip_22x21}; -const Icon I_EMV_Chip_14x11 = {.width=14,.height=11,.frame_count=1,.frame_rate=0,.frames=_I_EMV_Chip_14x11}; const Icon I_Health_16x16 = {.width=16,.height=16,.frame_count=1,.frame_rate=0,.frames=_I_Health_16x16}; const Icon I_FaceCharging_29x14 = {.width=29,.height=14,.frame_count=1,.frame_rate=0,.frames=_I_FaceCharging_29x14}; const Icon I_BatteryBody_52x28 = {.width=52,.height=28,.frame_count=1,.frame_rate=0,.frames=_I_BatteryBody_52x28}; diff --git a/assets/compiled/assets_icons.h b/assets/compiled/assets_icons.h index 1ae1b19a..689ce0d7 100644 --- a/assets/compiled/assets_icons.h +++ b/assets/compiled/assets_icons.h @@ -14,6 +14,7 @@ extern const Icon I_125_10px; extern const Icon I_ButtonRightSmall_3x5; extern const Icon I_ButtonLeft_4x7; extern const Icon I_ButtonLeftSmall_3x5; +extern const Icon I_DFU_128x50; extern const Icon I_Warning_30x23; extern const Icon I_ButtonRight_4x7; extern const Icon I_ButtonCenter_7x7; @@ -28,6 +29,10 @@ extern const Icon I_DolphinFirstStart8_56x51; extern const Icon I_DolphinFirstStart7_61x51; extern const Icon I_Flipper_young_80x60; extern const Icon I_DolphinFirstStart3_57x48; +extern const Icon I_Scanning_123x52; +extern const Icon I_Quest_7x8; +extern const Icon I_Unlock_7x8; +extern const Icon I_Lock_7x8; extern const Icon I_PassportBottom_128x17; extern const Icon I_DoorLeft_8x56; extern const Icon I_DoorLocked_10x56; @@ -75,8 +80,8 @@ extern const Icon A_Sub1ghz_14; extern const Icon A_Tamagotchi_14; extern const Icon A_U2F_14; extern const Icon A_iButton_14; +extern const Icon I_Detailed_chip_17x13; extern const Icon I_Medium_chip_22x21; -extern const Icon I_EMV_Chip_14x11; extern const Icon I_Health_16x16; extern const Icon I_FaceCharging_29x14; extern const Icon I_BatteryBody_52x28; diff --git a/assets/icons/Common/DFU_128x50.png b/assets/icons/Common/DFU_128x50.png new file mode 100644 index 00000000..951cdc19 Binary files /dev/null and b/assets/icons/Common/DFU_128x50.png differ diff --git a/assets/icons/GubGHz/Scanning_123x52.png b/assets/icons/GubGHz/Scanning_123x52.png new file mode 100644 index 00000000..ec785948 Binary files /dev/null and b/assets/icons/GubGHz/Scanning_123x52.png differ diff --git a/assets/icons/NFC/EMV_Chip_14x11.png b/assets/icons/GubGHz/lock_7x8.png similarity index 74% rename from assets/icons/NFC/EMV_Chip_14x11.png rename to assets/icons/GubGHz/lock_7x8.png index c3c3af79..f7c9ca2c 100644 Binary files a/assets/icons/NFC/EMV_Chip_14x11.png and b/assets/icons/GubGHz/lock_7x8.png differ diff --git a/assets/icons/GubGHz/quest_7x8.png b/assets/icons/GubGHz/quest_7x8.png new file mode 100644 index 00000000..6825247f Binary files /dev/null and b/assets/icons/GubGHz/quest_7x8.png differ diff --git a/assets/icons/GubGHz/unlock_7x8.png b/assets/icons/GubGHz/unlock_7x8.png new file mode 100644 index 00000000..9d82b4da Binary files /dev/null and b/assets/icons/GubGHz/unlock_7x8.png differ diff --git a/assets/icons/NFC/Detailed_chip_17x13.png b/assets/icons/NFC/Detailed_chip_17x13.png new file mode 100644 index 00000000..9aaa1c55 Binary files /dev/null and b/assets/icons/NFC/Detailed_chip_17x13.png differ diff --git a/assets/resources/nfc/emv/aid.nfc b/assets/resources/nfc/emv/aid.nfc new file mode 100644 index 00000000..2655df56 --- /dev/null +++ b/assets/resources/nfc/emv/aid.nfc @@ -0,0 +1,148 @@ +A00000000305076010 VISA ELO Credit +A0000000031010 VISA Debit/Credit (Classic) +A000000003101001 VISA Credit +A000000003101002 VISA Debit +A0000000032010 VISA Electron +A0000000032020 VISA +A0000000033010 VISA Interlink +A0000000034010 VISA Specific +A0000000035010 VISA Specific +A0000000036010 Domestic Visa Cash +A0000000036020 International Visa Cash +A0000000038002 VISA Auth EMV-CAP (DPA) +A0000000038010 VISA Plus +A0000000039010 VISA Loyalty +A000000003999910 VISA Proprietary ATM +A00000000401 MasterCard PayPass +A0000000041010 MasterCard Global +A00000000410101213 MasterCard Credit +A00000000410101215 MasterCard Credit +A0000000042010 MasterCard Specific +A0000000043010 MasterCard Specific +A0000000043060 Maestro (Debit) +A000000004306001 Maestro (Debit) +A0000000044010 MasterCard Specific +A0000000045010 MasterCard Specific +A0000000046000 Cirrus +A0000000048002 SecureCode EMV-CAP +A0000000049999 MasterCard PayPass +A0000000050001 Maestro UK +A0000000050002 Solo +A00000002401 Self Service +A000000025 American Express +A0000000250000 American Express +A00000002501 American Express +A000000025010402 American Express +A000000025010701 ExpressPay +A000000025010801 American Express +A0000000291010 Link / American Express +A0000000421010 Cartes Bancaire EMV Card +A0000000426010 Apple Pay +A00000006510 JCB +A0000000651010 JCB J Smart Credit +A00000006900 Moneo +A000000077010000021000000000003B Visa AEPN +A000000098 Debit Card +A0000000980848 Debit Card +A0000001211010 Dankort VISA GEM Vision +A0000001410001 PagoBANCOMAT +A0000001523010 Discover, Pulse D Pas +A0000001524010 Discover +A0000001544442 Banricompras Debito +A000000172950001 BAROC Taiwan +A0000002281010 SPAN (M/Chip) +A0000002282010 SPAN (VIS) +A0000002771010 INTERAC +A00000031510100528 Currence PuC +A0000003156020 Chipknip +A0000003591010028001 Girocard EAPS +A0000003710001 InterSwitch Verve Card +A0000004540010 Etranzact Genesis Card +A0000004540011 Etranzact Genesis Card 2 +A0000004766C GOOGLE_PAYMENT +A0000005241010 RuPay +A0000006723010 TROY chip credit card +A0000006723020 TROY chip debit card +A0000007705850 XTRAPOWER +B012345678 Maestro TEST +D27600002545500100 Girocard +D5780000021010 Bankaxept +F0000000030001 BRADESCO +A000000003000000 (VISA) Card Manager +A000000003534441 Schlumberger SD +A0000000035350 Security Domain +A000000003535041 Security Domain +A0000000040000 MasterCard Card Manager +A000000018434D Gemplus card manager +A000000018434D00 Gemplus Security Domain +A0000000960200 Proton WISD +A0000001510000 Global Platform SD +A00000015153504341534400 CASD_AID +A000000476A010 GSD_MANAGER_AID +A000000476A110 GSD_MANAGER_AID +315041592E5359532E4444463031 Visa PSE +325041592E5359532E4444463031 Visa PPSE +A0000000042203 MasterCard Specific +A0000000045555 APDULogger +A0000000090001FF44FF1289 Orange +A0000000101030 Maestro-CH +A00000001800 Gemplus +A0000000181001 gemplus util packages +A000000025010104 American Express +A00000002949034010100001 HSBC +A00000002949282010100000 Barclay +A00000005945430100 Girocard Electronic Cash +A0000000980840 Visa Common Debit +A0000001570010 AMEX +A0000001570020 MasterCard +A0000001570021 Maestro +A0000001570022 Maestro +A0000001570023 CASH +A0000001570030 VISA +A0000001570031 VISA +A0000001570040 JCB +A0000001570050 Postcard +A0000001570051 Postcard +A0000001570100 MCard +A0000001570104 MyOne +A000000157010C WIRCard +A000000157010D Power Card +A0000001574443 DINERS CLUB +A0000001574444 Supercard Plus +A00000022820101010 SPAN +A000000308000010000100 ID-ONE PIV BIO +A0000003241010 Discover Zip +A000000333010101 UnionPay Debit +A000000333010102 UnionPay Credit +A000000333010103 UnionPay Quasi Credit +A000000333010106 UnionPay Electronic Cash +A000000333010108 U.S. UnionPay Common Debit +A000000337102000 Classic +A000000337101001 Prepaye Online +A000000337102001 Prepaye Possibile Offiline +A000000337601001 Porte Monnaie Electronique +A0000006581010 MIR Credit +A0000006581011 MIR Credit +A0000006582010 MIR Debit +D040000001000002 Paylife Quick IEP +D040000002000002 RFU +D040000003000002 POS +D040000004000002 ATM +D04000000B000002 Retail +D04000000C000002 Bank_Data +D04000000D000002 Shopping +D040000013000001 DF_UNI_Kepler1 +D040000013000001 DF_Schüler1 +D040000013000002 DF_UNI_Kepler2 +D040000013000002 DF_Schüler2 +D040000014000001 DF_Mensa +D040000015000001 DF_UNI_Ausweis +D040000015000001 DF_Ausweis +D0400000190001 EMV ATM Maestro +D0400000190002 EMV POS Maestro +D0400000190003 EMV ATM MasterCard +D0400000190004 EMV POS MasterCard +D276000025 Girocard +D27600002547410100 Girocard ATM +D7560000010101 Reka Card +D7560000300101 M Budget \ No newline at end of file diff --git a/assets/resources/nfc/emv/country_code.nfc b/assets/resources/nfc/emv/country_code.nfc new file mode 100644 index 00000000..e43c35f3 --- /dev/null +++ b/assets/resources/nfc/emv/country_code.nfc @@ -0,0 +1,249 @@ +0004 AFG +0008 ALB +0010 ATA +0012 DZA +0016 ASM +0020 AND +0024 AGO +0028 ATG +0031 AZE +0032 ARG +0036 AUS +0040 AUT +0044 BHS +0048 BHR +0050 BGD +0051 ARM +0052 BRB +0056 BEL +0060 BMU +0064 BTN +0068 BOL +0070 BIH +0072 BWA +0074 BVT +0076 BRA +0084 BLZ +0086 IOT +0090 SLB +0092 VGB +0096 BRN +0100 BGR +0104 MMR +0108 BDI +0112 BLR +0116 KHM +0120 CMR +0124 CAN +0132 CPV +0136 CYM +0140 CAF +0144 LKA +0148 TCD +0152 CHL +0156 CHN +0158 TWN +0162 CXR +0166 CCK +0170 COL +0174 COM +0175 MYT +0178 COG +0180 COD +0184 COK +0188 CRI +0191 HRV +0192 CUB +0196 CYP +0203 CZE +0204 BEN +0208 DNK +0212 DMA +0214 DOM +0218 ECU +0222 SLV +0226 GNQ +0231 ETH +0232 ERI +0233 EST +0234 FRO +0238 FLK +0239 SGS +0242 FJI +0246 FIN +0248 ALA +0250 FRA +0254 GUF +0258 PYF +0260 ATF +0262 DJI +0266 GAB +0268 GEO +0270 GMB +0275 PSE +0276 DEU +0288 GHA +0292 GIB +0296 KIR +0300 GRC +0304 GRL +0308 GRD +0312 GLP +0316 GUM +0320 GTM +0324 GIN +0328 GUY +0332 HTI +0334 HMD +0336 VAT +0340 HND +0344 HKG +0348 HUN +0352 ISL +0356 IND +0360 IDN +0364 IRN +0368 IRQ +0372 IRL +0376 ISR +0380 ITA +0384 CIV +0388 JAM +0392 JPN +0398 KAZ +0400 JOR +0404 KEN +0408 PRK +0410 KOR +0414 KWT +0417 KGZ +0418 LAO +0422 LBN +0426 LSO +0428 LVA +0430 LBR +0434 LBY +0438 LIE +0440 LTU +0442 LUX +0446 MAC +0450 MDG +0454 MWI +0458 MYS +0462 MDV +0466 MLI +0470 MLT +0474 MTQ +0478 MRT +0480 MUS +0484 MEX +0492 MCO +0496 MNG +0498 MDA +0499 MNE +0500 MSR +0504 MAR +0508 MOZ +0512 OMN +0516 NAM +0520 NRU +0524 NPL +0528 NLD +0531 CUW +0533 ABW +0534 SXM +0535 BES +0540 NCL +0548 VUT +0554 NZL +0558 NIC +0562 NER +0566 NGA +0570 NIU +0574 NFK +0578 NOR +0580 MNP +0581 UMI +0583 FSM +0584 MHL +0585 PLW +0586 PAK +0591 PAN +0598 PNG +0600 PRY +0604 PER +0608 PHL +0612 PCN +0616 POL +0620 PRT +0624 GNB +0626 TLS +0630 PRI +0634 QAT +0638 REU +0642 ROU +0643 RUS +0646 RWA +0652 BLM +0654 SHN +0659 KNA +0660 AIA +0662 LCA +0663 MAF +0666 SPM +0670 VCT +0674 SMR +0678 STP +0682 SAU +0686 SEN +0688 SRB +0690 SYC +0694 SLE +0702 SGP +0703 SVK +0704 VNM +0705 SVN +0706 SOM +0710 ZAF +0716 ZWE +0724 ESP +0728 SSD +0729 SDN +0732 ESH +0740 SUR +0744 SJM +0748 SWZ +0752 SWE +0756 CHE +0760 SYR +0762 TJK +0764 THA +0768 TGO +0772 TKL +0776 TON +0780 TTO +0784 ARE +0788 TUN +0792 TUR +0795 TKM +0796 TCA +0798 TUV +0800 UGA +0804 UKR +0807 MKD +0818 EGY +0826 GBR +0831 GGY +0832 JEY +0833 IMN +0834 TZA +0840 USA +0850 VIR +0854 BFA +0858 URY +0860 UZB +0862 VEN +0876 WLF +0882 WSM +0887 YEM +0894 ZMB \ No newline at end of file diff --git a/assets/resources/nfc/emv/currency_code.nfc b/assets/resources/nfc/emv/currency_code.nfc new file mode 100644 index 00000000..4ee69181 --- /dev/null +++ b/assets/resources/nfc/emv/currency_code.nfc @@ -0,0 +1,168 @@ +0997 USN +0994 XSU +0990 CLF +0986 BRL +0985 PLN +0984 BOV +0981 GEL +0980 UAH +0979 MXV +0978 EUR +0977 BAM +0976 CDF +0975 BGN +0973 AOA +0972 TJS +0971 AFN +0970 COU +0969 MGA +0968 SRD +0967 ZMW +0965 XUA +0960 XDR +0953 XPF +0952 XOF +0951 XCD +0950 XAF +0949 TRY +0948 CHW +0947 CHE +0946 RON +0944 AZN +0943 MZN +0941 RSD +0940 UYI +0938 SDG +0937 VEF +0936 GHS +0934 TMT +0933 BYN +0932 ZWL +0931 CUC +0930 STN +0929 MRU +0901 TWD +0886 YER +0882 WST +0860 UZS +0858 UYU +0840 USD +0834 TZS +0826 GBP +0818 EGP +0807 MKD +0800 UGX +0788 TND +0784 AED +0780 TTD +0776 TOP +0764 THB +0760 SYP +0756 CHF +0752 SEK +0748 SZL +0728 SSP +0710 ZAR +0706 SOS +0704 VND +0702 SGD +0694 SLL +0690 SCR +0682 SAR +0654 SHP +0646 RWF +0643 RUB +0634 QAR +0608 PHP +0604 PEN +0600 PYG +0598 PGK +0590 PAB +0586 PKR +0578 NOK +0566 NGN +0558 NIO +0554 NZD +0548 VUV +0533 AWG +0532 ANG +0524 NPR +0516 NAD +0512 OMR +0504 MAD +0498 MDL +0496 MNT +0484 MXN +0480 MUR +0462 MVR +0458 MYR +0454 MWK +0446 MOP +0434 LYD +0430 LRD +0426 LSL +0422 LBP +0418 LAK +0417 KGS +0414 KWD +0410 KRW +0408 KPW +0404 KES +0400 JOD +0398 KZT +0392 JPY +0388 JMD +0376 ILS +0368 IQD +0364 IRR +0360 IDR +0356 INR +0352 ISK +0348 HUF +0344 HKD +0340 HNL +0332 HTG +0328 GYD +0324 GNF +0320 GTQ +0292 GIP +0270 GMD +0262 DJF +0242 FJD +0238 FKP +0232 ERN +0230 ETB +0222 SVC +0214 DOP +0208 DKK +0203 CZK +0192 CUP +0191 HRK +0188 CRC +0174 KMF +0170 COP +0156 CNY +0152 CLP +0144 LKR +0136 KYD +0132 CVE +0124 CAD +0116 KHR +0108 BIF +0104 MMK +0096 BND +0090 SBD +0084 BZD +0072 BWP +0068 BOB +0064 BTN +0060 BMD +0052 BBD +0051 AMD +0050 BDT +0048 BHD +0044 BSD +0036 AUD +0032 ARS +0012 DZD +0008 ALL \ No newline at end of file diff --git a/bootloader/targets/f6/target.c b/bootloader/targets/f6/target.c index 51dbb672..da1d6397 100644 --- a/bootloader/targets/f6/target.c +++ b/bootloader/targets/f6/target.c @@ -13,13 +13,57 @@ #include #include -const uint8_t I_Warning_30x23_0[] = { - 0x00, 0xC0, 0x00, 0x00, 0x00, 0xE0, 0x01, 0x00, 0x00, 0xF0, 0x03, 0x00, 0x00, 0xF0, 0x03, 0x00, - 0x00, 0xF8, 0x07, 0x00, 0x00, 0x3C, 0x0F, 0x00, 0x00, 0x3C, 0x0F, 0x00, 0x00, 0x3E, 0x1F, 0x00, - 0x00, 0x3F, 0x3F, 0x00, 0x00, 0x3F, 0x3F, 0x00, 0x80, 0x3F, 0x7F, 0x00, 0xC0, 0x3F, 0xFF, 0x00, - 0xC0, 0x3F, 0xFF, 0x00, 0xE0, 0x3F, 0xFF, 0x01, 0xF0, 0x3F, 0xFF, 0x03, 0xF0, 0x3F, 0xFF, 0x03, - 0xF8, 0x3F, 0xFF, 0x07, 0xFC, 0xFF, 0xFF, 0x0F, 0xFC, 0xFF, 0xFF, 0x0F, 0xFE, 0x3F, 0xFF, 0x1F, - 0xFF, 0x3F, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0x3F, 0xFE, 0xFF, 0xFF, 0x1F, +const uint8_t I_DFU_128x50[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8F, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7F, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x75, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x0A, 0x00, 0x00, 0x0F, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xE0, 0x0F, 0x00, 0xC0, 0xE0, 0x4F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x30, 0x1E, 0x90, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x18, 0x00, 0x8C, 0x01, 0xA0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x81, 0xFF, 0x19, 0x00, 0x63, 0x00, 0xC0, 0xF0, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x60, 0x5E, 0x1F, 0x80, 0x18, 0x00, 0xE0, 0x0E, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x18, 0xAF, 0x0F, 0x40, 0x06, 0x00, 0xF8, 0x01, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x06, 0x57, 0x01, 0x20, 0x01, 0x00, 0x78, 0x00, 0x3E, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x81, 0xAF, 0x02, 0x90, 0x00, 0x00, 0x38, 0x80, 0x41, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x80, 0x57, 0x01, 0x48, 0x00, 0x00, 0x10, 0x60, 0x40, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x10, 0x80, 0xAB, 0x00, 0x24, 0x00, 0x00, 0x08, 0x10, 0x40, + 0x3F, 0x00, 0x00, 0x00, 0x00, 0x38, 0x0C, 0xC0, 0x57, 0x01, 0x12, 0x00, 0x00, 0x04, 0x08, 0x40, + 0xC0, 0x0F, 0x00, 0x00, 0xC0, 0x07, 0x03, 0xF0, 0xAB, 0x00, 0x0A, 0x00, 0x00, 0x02, 0x04, 0x40, + 0x00, 0xF0, 0x1F, 0x80, 0x3F, 0xC0, 0x00, 0xFC, 0x55, 0x01, 0x05, 0xE0, 0x00, 0x01, 0x04, 0x40, + 0x00, 0x00, 0xE0, 0x7F, 0x00, 0x30, 0x00, 0xFF, 0xAB, 0x00, 0x05, 0xE0, 0x80, 0x00, 0x02, 0x40, + 0x0F, 0x00, 0x00, 0x00, 0x80, 0x0F, 0xE0, 0xCF, 0x55, 0x81, 0x02, 0xF0, 0x40, 0x00, 0x02, 0x40, + 0xF0, 0x0F, 0x00, 0x00, 0x7F, 0x00, 0xFE, 0xC3, 0xAB, 0x80, 0x02, 0x78, 0x20, 0x00, 0x01, 0x40, + 0x00, 0xF0, 0xFF, 0xFF, 0x00, 0xF0, 0xFF, 0xC0, 0xD5, 0x81, 0x01, 0x7E, 0x10, 0x80, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x0F, 0xE0, 0xFA, 0x83, 0xC1, 0x3F, 0x08, 0x80, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x01, 0xD8, 0x07, 0x83, 0xF1, 0x1F, 0x04, 0x40, 0x00, 0x20, + 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0x0F, 0x80, 0xC7, 0x01, 0x83, 0xF1, 0x0F, 0x00, 0x20, 0x00, 0x10, + 0xE0, 0xFF, 0xFF, 0xFF, 0x3F, 0xC0, 0x7F, 0x40, 0x80, 0x83, 0xE1, 0x01, 0x00, 0x20, 0x00, 0x18, + 0xFC, 0xFF, 0xFF, 0xFF, 0x03, 0x3F, 0x00, 0x20, 0xFC, 0x83, 0x01, 0x00, 0x00, 0x10, 0x00, 0x18, + 0xFF, 0xFF, 0xFF, 0x3F, 0xF0, 0x00, 0x00, 0x10, 0xD7, 0x01, 0x03, 0x00, 0x00, 0x08, 0x00, 0x1C, + 0xFF, 0xFF, 0x01, 0x00, 0x0F, 0x00, 0x00, 0x88, 0xAB, 0x02, 0xE3, 0x01, 0x00, 0x08, 0x00, 0x0C, + 0xFF, 0x07, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xC4, 0x55, 0x05, 0x1E, 0x00, 0x00, 0x04, 0x00, 0x0E, + 0x7F, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xA3, 0xAB, 0x02, 0x06, 0x00, 0x00, 0x02, 0x00, 0x0F, + 0x0F, 0x00, 0x80, 0x03, 0x00, 0x00, 0xC0, 0x10, 0x57, 0x05, 0x02, 0x00, 0x00, 0x01, 0x80, 0x07, + 0x03, 0x00, 0x70, 0x00, 0x00, 0x00, 0x30, 0x08, 0xAB, 0x0A, 0x02, 0x00, 0xC0, 0x00, 0xC0, 0x07, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x84, 0x57, 0x15, 0x01, 0x00, 0x30, 0x00, 0xE0, 0x07, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0xC3, 0xFF, 0x2A, 0x01, 0x00, 0x0C, 0x00, 0xF0, 0x0F, + 0x00, 0xC0, 0x00, 0x00, 0x00, 0xE0, 0xC0, 0xE0, 0xFE, 0x55, 0x01, 0x82, 0x03, 0x00, 0xF8, 0x15, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x1C, 0x30, 0x78, 0xFE, 0xAA, 0x01, 0x7C, 0x00, 0x00, 0xFC, 0x23, + 0x00, 0x0E, 0x00, 0x00, 0xC0, 0x03, 0x0C, 0x3C, 0x7F, 0x5D, 0x01, 0x00, 0x00, 0x00, 0xFF, 0x45, + 0xC0, 0x01, 0x00, 0x00, 0x3E, 0x00, 0x02, 0x8F, 0xBF, 0xAE, 0x03, 0x00, 0x00, 0xC0, 0xFF, 0x82, + 0x30, 0x00, 0x00, 0xC0, 0x01, 0x80, 0xC1, 0x43, 0xFE, 0x5D, 0x01, 0x00, 0x00, 0xF0, 0xFF, 0x05, + 0x0F, 0x00, 0x80, 0x3F, 0x00, 0x60, 0xF0, 0x31, 0xF6, 0xAE, 0x03, 0x00, 0x00, 0xFA, 0xAF, 0x02, + 0xFC, 0xFF, 0x7F, 0x00, 0x00, 0x18, 0x7C, 0x08, 0x23, 0xFF, 0x05, 0x00, 0x00, 0xFD, 0x55, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x1F, 0x84, 0x30, 0xFE, 0x0A, 0x00, 0x00, 0xAA, 0xAA, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0xF1, 0x07, 0x43, 0x18, 0xFF, 0x15, 0x00, 0x00, 0x54, 0x15, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x80, 0x20, 0x8C, 0xFF, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, }; // Boot request enum @@ -138,8 +182,6 @@ void target_version_save(void) { void target_usb_wire_reset() { LL_GPIO_ResetOutputPin(BOOT_USB_PORT, BOOT_USB_PIN); - LL_mDelay(10); - LL_GPIO_SetOutputPin(BOOT_USB_PORT, BOOT_USB_PIN); } void target_display_init() { @@ -155,10 +197,9 @@ void target_display_init() { u8g2_ClearBuffer(&fb); u8g2_SetDrawColor(&fb, 0x01); u8g2_SetFont(&fb, u8g2_font_helvB08_tf); - u8g2_DrawStr(&fb, 2, 8, "Recovery & Update Mode"); - u8g2_DrawXBM(&fb, 49, 14, 30, 23, I_Warning_30x23_0); - u8g2_DrawStr(&fb, 2, 50, "DFU Bootloader activated"); - u8g2_DrawStr(&fb, 6, 62, "www.flipp.dev/recovery"); + u8g2_DrawXBM(&fb, 0, 64 - 50, 128, 50, I_DFU_128x50); + u8g2_DrawStr(&fb, 2, 8, "Update & Recovery Mode"); + u8g2_DrawStr(&fb, 2, 21, "DFU started"); // Send buffer u8g2_SetPowerSave(&fb, 0); u8g2_SendBuffer(&fb); diff --git a/core/furi-hal/api-spi.h b/core/furi-hal/api-spi.h deleted file mode 100644 index 8640d0d3..00000000 --- a/core/furi-hal/api-spi.h +++ /dev/null @@ -1,144 +0,0 @@ -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* -struct used for handling SPI info. -*/ -typedef struct { - SPI_HandleTypeDef* spi; - PubSubCallback cb; - void* ctx; -} SpiHandle; - -/* -For transmit/receive data use `spi_xfer` function. - -* `tx_data` and `rx_data` size must be equal (and equal `len`) -* `cb` called after spi operation is completed, `(NULL, ctx)` passed to callback. -*/ -bool spi_xfer( - SPI_HandleTypeDef* spi, - uint8_t* tx_data, - uint8_t* rx_data, - size_t len, - PubSubCallback cb, - void* ctx); - -/* -Blocking verison: -*/ -static inline bool - spi_xfer_block(SPI_HandleTypeDef* spi, uint8_t* tx_data, uint8_t* rx_data, size_t len) { - semaphoreInfo s; - osSemaphore block = createSemaphoreStatic(s); - if(!spi_xfer(spi, tx_data, rx_data, len, RELEASE_SEMAPHORE, (void*)block)) { - osReleaseSemaphore(block); - return false; - } - osWaitSemaphore(block); - return false; -} - -/* -Common implementation of SPI bus: serial interface + CS pin -*/ -typedef struct { - GpioPin* cs; ///< CS pin - ValueMutex* spi; ///< -} SpiBus; - -/* -For dedicated work with one device there is `SpiDevice` entity. -It contains ValueMutex around SpiBus: after you acquire device -you can acquire spi to work with it (don't forget SPI bus is shared -around many device, release it after every transaction as quick as possible). -*/ -typedef struct { - ValueMutex* bus; ///< -} SpiDevice; - -##SPI IRQ device - - /* -Many devices (like CC1101 and NFC) present as SPI bus and IRQ line. -For work with it there is special entity `SpiIrqDevice`. -Use `subscribe_pubsub` for subscribinq to irq events. -*/ - - typedef struct { - ValueMutex* bus; ///< - PubSub* irq; -} SpiIrqDevice; - -/* -Special implementation of SPI bus: serial interface + CS, Res, D/I lines. -*/ -typedef struct { - GpioPin* cs; ///< CS pin - GpioPin* res; ///< reset pin - GpioPin* di; ///< D/I pin - ValueMutex* spi; ///< -} DisplayBus; - -typedef struct { - ValueMutex* bus; ///< -} DisplayDevice; - -/* -# SPI devices (F2) - -* `/dev/sdcard` - SD card SPI, `SpiDevice` -* `/dev/cc1101_bus` - Sub-GHz radio (CC1101), `SpiIrqDevice` -* `/dev/nfc` - NFC (ST25R3916), `SpiIrqDevice` -* `/dev/display` - `DisplayDevice` -* `/dev/spiext` - External SPI (warning! Lock PA4, PA5, PA6, PA7) - -### Application example - -```C -// Be careful, this function called from IRQ context -void handle_irq(void* _arg, void* _ctx) { -} - -void cc1101_example() { - SpiIrqDevice* cc1101_device = open_input("/dev/cc1101_bus"); - if(cc1101_device == NULL) return; // bus not available, critical error - - subscribe_pubsub(cc1101_device->irq, handle_irq, NULL); - - { - // acquire device as device bus - SpiBus* spi_bus = acquire_mutex(cc1101_device->bus, 0); - if(spi_bus == NULL) { - printf("Device busy\n"); - // wait for device - spi_bus = acquire_mutex_block(cc1101_device->bus); - } - - // make transaction - uint8_t request[4] = {0xDE, 0xAD, 0xBE, 0xEF}; - uint8_t response[4]; - - { - SPI_HandleTypeDef* spi = acquire_mutex_block(spi_bus->spi); - - gpio_write(spi_bus->cs, false); - spi_xfer_block(spi, request, response, 4); - gpio_write(spi_bus->cs, true); - - release_mutex(cc1101_device->spi, spi); - } - - // release device (device bus) - release_mutex(cc1101_device->bus, spi_bus); - } -} -``` -*/ - -#ifdef __cplusplus -} -#endif diff --git a/core/furi/check.c b/core/furi/check.c index 13d176bf..77e239bc 100644 --- a/core/furi/check.c +++ b/core/furi/check.c @@ -1,37 +1,30 @@ #include "check.h" #include "furi-hal-task.h" +#include #include void __furi_abort(void); -// TODO printf doesnt work in ISR context -void __furi_check(void) { - printf("assertion failed in release mode, switch to debug mode to see full assert info"); - __furi_abort(); +void __furi_print_name(void) { + furi_hal_console_puts("\r\n\033[0;31m[E]"); + if(task_is_isr_context()) { + furi_hal_console_puts("[ISR] "); + } else { + const char* name = osThreadGetName(osThreadGetId()); + if(name == NULL) { + furi_hal_console_puts("[main] "); + } else { + furi_hal_console_puts("["); + furi_hal_console_puts(name); + furi_hal_console_puts("] "); + } + } + furi_hal_console_puts("\033[0m"); } -// TODO printf doesnt work in ISR context -void __furi_check_debug(const char* file, int line, const char* function, const char* condition) { - printf( - "assertion \"%s\" failed: file \"%s\", line %d%s%s", - condition, - file, - line, - function ? ", function: " : "", - function ? function : ""); - - if(task_is_isr_context()) { - printf(" in [ISR] context"); - } else { - // FuriApp* app = find_task(xTaskGetCurrentTaskHandle()); - - // if(app == NULL) { - // printf(", in [main] context"); - // } else { - // printf(", in [%s] app context", app->name); - // } - } - +void __furi_check(void) { + __furi_print_name(); + furi_hal_console_puts("assertion failed\r\n"); __furi_abort(); } diff --git a/core/furi/check.h b/core/furi/check.h index 00a0e34d..4f65aa72 100644 --- a/core/furi/check.h +++ b/core/furi/check.h @@ -38,7 +38,6 @@ extern "C" { // !NDEBUG void __furi_check(void); -void __furi_check_debug(const char* file, int line, const char* function, const char* condition); #ifdef __cplusplus } diff --git a/core/furi/common_defines.h b/core/furi/common_defines.h index ceac90ae..011af99e 100644 --- a/core/furi/common_defines.h +++ b/core/furi/common_defines.h @@ -31,3 +31,12 @@ #ifndef COUNT_OF #define COUNT_OF(x) (sizeof(x) / sizeof(x[0])) #endif + +#ifndef FURI_SWAP +#define FURI_SWAP(x, y) \ + do { \ + typeof(x) SWAP = x; \ + x = y; \ + y = SWAP; \ + } while(0) +#endif diff --git a/docker/Dockerfile b/docker/Dockerfile index f6ab89c3..547c2bc3 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,10 +1,10 @@ -FROM ubuntu:focal +FROM ubuntu:hirsute RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \ ca-certificates \ build-essential \ python3 \ - python-lxml \ + python3-lxml \ git \ clang-format-12 \ dfu-util \ @@ -14,10 +14,10 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install --no-instal wget && \ apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* -RUN wget --progress=dot:giga "https://developer.arm.com/-/media/Files/downloads/gnu-rm/10-2020q4/gcc-arm-none-eabi-10-2020-q4-major-$(uname -m)-linux.tar.bz2" && \ - tar xjf gcc-arm-none-eabi-10-2020-q4-major-$(uname -m)-linux.tar.bz2 && \ - rm gcc-arm-none-eabi-10-2020-q4-major-$(uname -m)-linux.tar.bz2 && \ - cd gcc-arm-none-eabi-10-2020-q4-major/bin/ && \ +RUN wget --progress=dot:giga "https://developer.arm.com/-/media/Files/downloads/gnu-rm/10.3-2021.07/gcc-arm-none-eabi-10.3-2021.07-$(uname -m)-linux.tar.bz2" && \ + tar xjf gcc-arm-none-eabi-10.3-2021.07-$(uname -m)-linux.tar.bz2 && \ + rm gcc-arm-none-eabi-10.3-2021.07-$(uname -m)-linux.tar.bz2 && \ + cd gcc-arm-none-eabi-10.3-2021.07/bin/ && \ rm -rf ../share && \ for file in * ; do ln -s "${PWD}/${file}" "/usr/bin/${file}" ; done && \ cd / && arm-none-eabi-gcc -v && arm-none-eabi-gdb -v diff --git a/firmware/targets/f6/Inc/usb_device.h b/firmware/targets/f6/Inc/usb_device.h deleted file mode 100644 index 5d7a3f9c..00000000 --- a/firmware/targets/f6/Inc/usb_device.h +++ /dev/null @@ -1,105 +0,0 @@ -/* USER CODE BEGIN Header */ -/** - ****************************************************************************** - * @file : usb_device.h - * @version : v3.0_Cube - * @brief : Header for usb_device.c file. - ****************************************************************************** - * @attention - * - *

© Copyright (c) 2020 STMicroelectronics. - * All rights reserved.

- * - * This software component is licensed by ST under Ultimate Liberty license - * SLA0044, the "License"; You may not use this file except in compliance with - * the License. You may obtain a copy of the License at: - * www.st.com/SLA0044 - * - ****************************************************************************** - */ -/* USER CODE END Header */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USB_DEVICE__H__ -#define __USB_DEVICE__H__ - -#ifdef __cplusplus - extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "stm32wbxx.h" -#include "stm32wbxx_hal.h" -#include "usbd_def.h" - -/* USER CODE BEGIN INCLUDE */ - -/* USER CODE END INCLUDE */ - -/** @addtogroup USBD_OTG_DRIVER - * @{ - */ - -/** @defgroup USBD_DEVICE USBD_DEVICE - * @brief Device file for Usb otg low level driver. - * @{ - */ - -/** @defgroup USBD_DEVICE_Exported_Variables USBD_DEVICE_Exported_Variables - * @brief Public variables. - * @{ - */ - -/* Private variables ---------------------------------------------------------*/ -/* USER CODE BEGIN PV */ - -/* USER CODE END PV */ - -/* Private function prototypes -----------------------------------------------*/ -/* USER CODE BEGIN PFP */ - -/* USER CODE END PFP */ - -/* - * -- Insert your variables declaration here -- - */ -/* USER CODE BEGIN VARIABLES */ - -/* USER CODE END VARIABLES */ -/** - * @} - */ - -/** @defgroup USBD_DEVICE_Exported_FunctionsPrototype USBD_DEVICE_Exported_FunctionsPrototype - * @brief Declaration of public functions for Usb device. - * @{ - */ - -/** USB Device initialization function. */ -void MX_USB_Device_Init(void); - -/* - * -- Insert functions declaration here -- - */ -/* USER CODE BEGIN FD */ - -/* USER CODE END FD */ -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* __USB_DEVICE__H__ */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/firmware/targets/f6/Inc/usbd_cdc_if.h b/firmware/targets/f6/Inc/usbd_cdc_if.h deleted file mode 100644 index 40223874..00000000 --- a/firmware/targets/f6/Inc/usbd_cdc_if.h +++ /dev/null @@ -1,134 +0,0 @@ -/* USER CODE BEGIN Header */ -/** - ****************************************************************************** - * @file : usbd_cdc_if.h - * @version : v3.0_Cube - * @brief : Header for usbd_cdc_if.c file. - ****************************************************************************** - * @attention - * - *

© Copyright (c) 2020 STMicroelectronics. - * All rights reserved.

- * - * This software component is licensed by ST under Ultimate Liberty license - * SLA0044, the "License"; You may not use this file except in compliance with - * the License. You may obtain a copy of the License at: - * www.st.com/SLA0044 - * - ****************************************************************************** - */ -/* USER CODE END Header */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USBD_CDC_IF_H__ -#define __USBD_CDC_IF_H__ - -#ifdef __cplusplus - extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "usbd_cdc.h" - -/* USER CODE BEGIN INCLUDE */ - -/* USER CODE END INCLUDE */ - -/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY - * @brief For Usb device. - * @{ - */ - -/** @defgroup USBD_CDC_IF USBD_CDC_IF - * @brief Usb VCP device module - * @{ - */ - -/** @defgroup USBD_CDC_IF_Exported_Defines USBD_CDC_IF_Exported_Defines - * @brief Defines. - * @{ - */ -/* USER CODE BEGIN EXPORTED_DEFINES */ -/* Define size for the receive and transmit buffer over CDC */ -/* It's up to user to redefine and/or remove those define */ -#define APP_RX_DATA_SIZE CDC_DATA_HS_MAX_PACKET_SIZE -#define APP_TX_DATA_SIZE CDC_DATA_HS_MAX_PACKET_SIZE - -/* USER CODE END EXPORTED_DEFINES */ - -/** - * @} - */ - -/** @defgroup USBD_CDC_IF_Exported_Types USBD_CDC_IF_Exported_Types - * @brief Types. - * @{ - */ - -/* USER CODE BEGIN EXPORTED_TYPES */ - -/* USER CODE END EXPORTED_TYPES */ - -/** - * @} - */ - -/** @defgroup USBD_CDC_IF_Exported_Macros USBD_CDC_IF_Exported_Macros - * @brief Aliases. - * @{ - */ - -/* USER CODE BEGIN EXPORTED_MACRO */ - -/* USER CODE END EXPORTED_MACRO */ - -/** - * @} - */ - -/** @defgroup USBD_CDC_IF_Exported_Variables USBD_CDC_IF_Exported_Variables - * @brief Public variables. - * @{ - */ - -/** CDC Interface callback. */ -extern USBD_CDC_ItfTypeDef USBD_Interface_fops_FS; - -/* USER CODE BEGIN EXPORTED_VARIABLES */ - -/* USER CODE END EXPORTED_VARIABLES */ - -/** - * @} - */ - -/** @defgroup USBD_CDC_IF_Exported_FunctionsPrototype USBD_CDC_IF_Exported_FunctionsPrototype - * @brief Public functions declaration. - * @{ - */ - -uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len); - -/* USER CODE BEGIN EXPORTED_FUNCTIONS */ - -/* USER CODE END EXPORTED_FUNCTIONS */ - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* __USBD_CDC_IF_H__ */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/firmware/targets/f6/Inc/usbd_conf.h b/firmware/targets/f6/Inc/usbd_conf.h deleted file mode 100644 index 49b801ef..00000000 --- a/firmware/targets/f6/Inc/usbd_conf.h +++ /dev/null @@ -1,176 +0,0 @@ -/* USER CODE BEGIN Header */ -/** - ****************************************************************************** - * @file : usbd_conf.h - * @version : v3.0_Cube - * @brief : Header for usbd_conf.c file. - ****************************************************************************** - * @attention - * - *

© Copyright (c) 2020 STMicroelectronics. - * All rights reserved.

- * - * This software component is licensed by ST under Ultimate Liberty license - * SLA0044, the "License"; You may not use this file except in compliance with - * the License. You may obtain a copy of the License at: - * www.st.com/SLA0044 - * - ****************************************************************************** - */ -/* USER CODE END Header */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USBD_CONF__H__ -#define __USBD_CONF__H__ - -#ifdef __cplusplus - extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include -#include -#include -#include "stm32wbxx.h" -#include "stm32wbxx_hal.h" - -/* USER CODE BEGIN INCLUDE */ - -/* USER CODE END INCLUDE */ - -/** @addtogroup USBD_OTG_DRIVER - * @brief Driver for Usb device. - * @{ - */ - -/** @defgroup USBD_CONF USBD_CONF - * @brief Configuration file for Usb otg low level driver. - * @{ - */ - -/** @defgroup USBD_CONF_Exported_Variables USBD_CONF_Exported_Variables - * @brief Public variables. - * @{ - */ - -/* Private variables ---------------------------------------------------------*/ -/* USER CODE BEGIN PV */ -/* USER CODE END PV */ -/** - * @} - */ - -/** @defgroup USBD_CONF_Exported_Defines USBD_CONF_Exported_Defines - * @brief Defines for configuration of the Usb device. - * @{ - */ - -/*---------- -----------*/ -#define USBD_MAX_NUM_INTERFACES 1U -/*---------- -----------*/ -#define USBD_MAX_NUM_CONFIGURATION 1U -/*---------- -----------*/ -#define USBD_MAX_STR_DESC_SIZ 512U -/*---------- -----------*/ -#define USBD_DEBUG_LEVEL 0U -/*---------- -----------*/ -#define USBD_LPM_ENABLED 1U -/*---------- -----------*/ -#define USBD_SELF_POWERED 1U - -/****************************************/ -/* #define for FS and HS identification */ -#define DEVICE_FS 0 - -/** - * @} - */ - -/** @defgroup USBD_CONF_Exported_Macros USBD_CONF_Exported_Macros - * @brief Aliases. - * @{ - */ - -/* Memory management macros */ - -/** Alias for memory allocation. */ -#define USBD_malloc (void *)USBD_static_malloc - -/** Alias for memory release. */ -#define USBD_free USBD_static_free - -/** Alias for memory set. */ -#define USBD_memset memset - -/** Alias for memory copy. */ -#define USBD_memcpy memcpy - -/** Alias for delay. */ -#define USBD_Delay HAL_Delay -/* DEBUG macros */ - -#if (USBD_DEBUG_LEVEL > 0) -#define USBD_UsrLog(...) printf(__VA_ARGS__);\ - printf("\n"); -#else -#define USBD_UsrLog(...) -#endif - -#if (USBD_DEBUG_LEVEL > 1) - -#define USBD_ErrLog(...) printf("ERROR: ") ;\ - printf(__VA_ARGS__);\ - printf("\n"); -#else -#define USBD_ErrLog(...) -#endif - -#if (USBD_DEBUG_LEVEL > 2) -#define USBD_DbgLog(...) printf("DEBUG : ") ;\ - printf(__VA_ARGS__);\ - printf("\n"); -#else -#define USBD_DbgLog(...) -#endif - -/** - * @} - */ - -/** @defgroup USBD_CONF_Exported_Types USBD_CONF_Exported_Types - * @brief Types. - * @{ - */ - -/** - * @} - */ - -/** @defgroup USBD_CONF_Exported_FunctionsPrototype USBD_CONF_Exported_FunctionsPrototype - * @brief Declaration of public functions for Usb device. - * @{ - */ - -/* Exported functions -------------------------------------------------------*/ -void *USBD_static_malloc(uint32_t size); -void USBD_static_free(void *p); - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* __USBD_CONF__H__ */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/firmware/targets/f6/Inc/usbd_desc.h b/firmware/targets/f6/Inc/usbd_desc.h deleted file mode 100644 index d5362ee2..00000000 --- a/firmware/targets/f6/Inc/usbd_desc.h +++ /dev/null @@ -1,145 +0,0 @@ -/* USER CODE BEGIN Header */ -/** - ****************************************************************************** - * @file : usbd_desc.c - * @version : v3.0_Cube - * @brief : Header for usbd_conf.c file. - ****************************************************************************** - * @attention - * - *

© Copyright (c) 2020 STMicroelectronics. - * All rights reserved.

- * - * This software component is licensed by ST under Ultimate Liberty license - * SLA0044, the "License"; You may not use this file except in compliance with - * the License. You may obtain a copy of the License at: - * www.st.com/SLA0044 - * - ****************************************************************************** - */ -/* USER CODE END Header */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USBD_DESC__C__ -#define __USBD_DESC__C__ - -#ifdef __cplusplus - extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include "usbd_def.h" - -/* USER CODE BEGIN INCLUDE */ - -/* USER CODE END INCLUDE */ - -/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY - * @{ - */ - -/** @defgroup USBD_DESC USBD_DESC - * @brief Usb device descriptors module. - * @{ - */ - -/** @defgroup USBD_DESC_Exported_Constants USBD_DESC_Exported_Constants - * @brief Constants. - * @{ - */ -#define DEVICE_ID1 (UID_BASE) -#define DEVICE_ID2 (UID_BASE + 0x4) -#define DEVICE_ID3 (UID_BASE + 0x8) - -#define USB_SIZ_STRING_SERIAL 0x1E - -/* USER CODE BEGIN EXPORTED_CONSTANTS */ - -/* USER CODE END EXPORTED_CONSTANTS */ - -/** - * @} - */ - -/** @defgroup USBD_DESC_Exported_Defines USBD_DESC_Exported_Defines - * @brief Defines. - * @{ - */ - -/* USER CODE BEGIN EXPORTED_DEFINES */ - -/* USER CODE END EXPORTED_DEFINES */ - -/** - * @} - */ - -/** @defgroup USBD_DESC_Exported_TypesDefinitions USBD_DESC_Exported_TypesDefinitions - * @brief Types. - * @{ - */ - -/* USER CODE BEGIN EXPORTED_TYPES */ - -/* USER CODE END EXPORTED_TYPES */ - -/** - * @} - */ - -/** @defgroup USBD_DESC_Exported_Macros USBD_DESC_Exported_Macros - * @brief Aliases. - * @{ - */ - -/* USER CODE BEGIN EXPORTED_MACRO */ - -/* USER CODE END EXPORTED_MACRO */ - -/** - * @} - */ - -/** @defgroup USBD_DESC_Exported_Variables USBD_DESC_Exported_Variables - * @brief Public variables. - * @{ - */ - -extern USBD_DescriptorsTypeDef CDC_Desc; - -/* USER CODE BEGIN EXPORTED_VARIABLES */ - -/* USER CODE END EXPORTED_VARIABLES */ - -/** - * @} - */ - -/** @defgroup USBD_DESC_Exported_FunctionsPrototype USBD_DESC_Exported_FunctionsPrototype - * @brief Public functions declaration. - * @{ - */ - -/* USER CODE BEGIN EXPORTED_FUNCTIONS */ - -/* USER CODE END EXPORTED_FUNCTIONS */ - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* __USBD_DESC__C__ */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/firmware/targets/f6/Src/usb_device.c b/firmware/targets/f6/Src/usb_device.c deleted file mode 100644 index 2cbfa7dd..00000000 --- a/firmware/targets/f6/Src/usb_device.c +++ /dev/null @@ -1,99 +0,0 @@ -/* USER CODE BEGIN Header */ -/** - ****************************************************************************** - * @file : usb_device.c - * @version : v3.0_Cube - * @brief : This file implements the USB Device - ****************************************************************************** - * @attention - * - *

© Copyright (c) 2020 STMicroelectronics. - * All rights reserved.

- * - * This software component is licensed by ST under Ultimate Liberty license - * SLA0044, the "License"; You may not use this file except in compliance with - * the License. You may obtain a copy of the License at: - * www.st.com/SLA0044 - * - ****************************************************************************** - */ -/* USER CODE END Header */ - -/* Includes ------------------------------------------------------------------*/ - -#include "usb_device.h" -#include "usbd_core.h" -#include "usbd_desc.h" -#include "usbd_cdc.h" -#include "usbd_cdc_if.h" - -/* USER CODE BEGIN Includes */ - -/* USER CODE END Includes */ - -/* USER CODE BEGIN PV */ -/* Private variables ---------------------------------------------------------*/ - -/* USER CODE END PV */ - -/* USER CODE BEGIN PFP */ -/* Private function prototypes -----------------------------------------------*/ - -/* USER CODE END PFP */ - -extern void Error_Handler(void); -/* USB Device Core handle declaration. */ -USBD_HandleTypeDef hUsbDeviceFS; -extern USBD_DescriptorsTypeDef CDC_Desc; - -/* - * -- Insert your variables declaration here -- - */ -/* USER CODE BEGIN 0 */ - -/* USER CODE END 0 */ - -/* - * -- Insert your external function declaration here -- - */ -/* USER CODE BEGIN 1 */ - -/* USER CODE END 1 */ - -/** - * Init USB device Library, add supported class and start the library - * @retval None - */ -void MX_USB_Device_Init(void) -{ - /* USER CODE BEGIN USB_Device_Init_PreTreatment */ - - /* USER CODE END USB_Device_Init_PreTreatment */ - - /* Init Device Library, add supported class and start the library. */ - if (USBD_Init(&hUsbDeviceFS, &CDC_Desc, DEVICE_FS) != USBD_OK) { - Error_Handler(); - } - if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC) != USBD_OK) { - Error_Handler(); - } - if (USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS) != USBD_OK) { - Error_Handler(); - } - if (USBD_Start(&hUsbDeviceFS) != USBD_OK) { - Error_Handler(); - } - /* USER CODE BEGIN USB_Device_Init_PostTreatment */ - - /* USER CODE END USB_Device_Init_PostTreatment */ -} - -/** - * @} - */ - -/** - * @} - */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/firmware/targets/f6/Src/usbd_cdc_if.c b/firmware/targets/f6/Src/usbd_cdc_if.c deleted file mode 100644 index b18c5a56..00000000 --- a/firmware/targets/f6/Src/usbd_cdc_if.c +++ /dev/null @@ -1,313 +0,0 @@ -/* USER CODE BEGIN Header */ -/** - ****************************************************************************** - * @file : usbd_cdc_if.c - * @version : v3.0_Cube - * @brief : Usb device for Virtual Com Port. - ****************************************************************************** - * @attention - * - *

© Copyright (c) 2020 STMicroelectronics. - * All rights reserved.

- * - * This software component is licensed by ST under Ultimate Liberty license - * SLA0044, the "License"; You may not use this file except in compliance with - * the License. You may obtain a copy of the License at: - * www.st.com/SLA0044 - * - ****************************************************************************** - */ -/* USER CODE END Header */ - -/* Includes ------------------------------------------------------------------*/ -#include "usbd_cdc_if.h" - -/* USER CODE BEGIN INCLUDE */ - -/* USER CODE END INCLUDE */ - -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -/* Private macro -------------------------------------------------------------*/ - -/* USER CODE BEGIN PV */ -/* Private variables ---------------------------------------------------------*/ - -/* USER CODE END PV */ - -/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY - * @brief Usb device library. - * @{ - */ - -/** @addtogroup USBD_CDC_IF - * @{ - */ - -/** @defgroup USBD_CDC_IF_Private_TypesDefinitions USBD_CDC_IF_Private_TypesDefinitions - * @brief Private types. - * @{ - */ - -/* USER CODE BEGIN PRIVATE_TYPES */ - -extern void _furi_hal_vcp_init(); -extern void _furi_hal_vcp_deinit(); -extern void _furi_hal_vcp_control_line(uint8_t state); -extern void _furi_hal_vcp_rx_callback(char* buffer, size_t size); -extern void _furi_hal_vcp_tx_complete(size_t size); - -/* USER CODE END PRIVATE_TYPES */ - -/** - * @} - */ - -/** @defgroup USBD_CDC_IF_Private_Defines USBD_CDC_IF_Private_Defines - * @brief Private defines. - * @{ - */ - -/* USER CODE BEGIN PRIVATE_DEFINES */ -/* USER CODE END PRIVATE_DEFINES */ - -/** - * @} - */ - -/** @defgroup USBD_CDC_IF_Private_Macros USBD_CDC_IF_Private_Macros - * @brief Private macros. - * @{ - */ - -/* USER CODE BEGIN PRIVATE_MACRO */ - -/* USER CODE END PRIVATE_MACRO */ - -/** - * @} - */ - -/** @defgroup USBD_CDC_IF_Private_Variables USBD_CDC_IF_Private_Variables - * @brief Private variables. - * @{ - */ -/* Create buffer for reception and transmission */ -/* It's up to user to redefine and/or remove those define */ -/** Received data over USB are stored in this buffer */ -uint8_t UserRxBufferFS[APP_RX_DATA_SIZE]; - -/** Data to send over USB CDC are stored in this buffer */ -uint8_t UserTxBufferFS[APP_TX_DATA_SIZE]; - -/* USER CODE BEGIN PRIVATE_VARIABLES */ - -/* USER CODE END PRIVATE_VARIABLES */ - -/** - * @} - */ - -/** @defgroup USBD_CDC_IF_Exported_Variables USBD_CDC_IF_Exported_Variables - * @brief Public variables. - * @{ - */ - -extern USBD_HandleTypeDef hUsbDeviceFS; - -/* USER CODE BEGIN EXPORTED_VARIABLES */ - -/* USER CODE END EXPORTED_VARIABLES */ - -/** - * @} - */ - -/** @defgroup USBD_CDC_IF_Private_FunctionPrototypes USBD_CDC_IF_Private_FunctionPrototypes - * @brief Private functions declaration. - * @{ - */ - -static int8_t CDC_Init_FS(void); -static int8_t CDC_DeInit_FS(void); -static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length); -static int8_t CDC_Receive_FS(uint8_t* pbuf, uint32_t *Len); -static int8_t CDC_TransmitCplt_FS(uint8_t *pbuf, uint32_t *Len, uint8_t epnum); - -/* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */ - -/* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */ - -/** - * @} - */ - -USBD_CDC_ItfTypeDef USBD_Interface_fops_FS = -{ - CDC_Init_FS, - CDC_DeInit_FS, - CDC_Control_FS, - CDC_Receive_FS, - CDC_TransmitCplt_FS -}; - -/* Private functions ---------------------------------------------------------*/ -/** - * @brief Initializes the CDC media low layer over the FS USB IP - * @retval USBD_OK if all operations are OK else USBD_FAIL - */ -static int8_t CDC_Init_FS(void) -{ - /* USER CODE BEGIN 3 */ - /* Set Application Buffers */ - USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, 0); - USBD_CDC_SetRxBuffer(&hUsbDeviceFS, UserRxBufferFS); - _furi_hal_vcp_init(); - return (USBD_OK); - /* USER CODE END 3 */ -} - -/** - * @brief DeInitializes the CDC media low layer - * @retval USBD_OK if all operations are OK else USBD_FAIL - */ -static int8_t CDC_DeInit_FS(void) -{ - /* USER CODE BEGIN 4 */ - _furi_hal_vcp_deinit(); - return (USBD_OK); - /* USER CODE END 4 */ -} - -/** - * @brief Manage the CDC class requests - * @param cmd: Command code - * @param pbuf: Buffer containing command data (request parameters) - * @param length: Number of data to be sent (in bytes) - * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL - */ -static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length) -{ - /* USER CODE BEGIN 5 */ - if (cmd == CDC_SEND_ENCAPSULATED_COMMAND) { - } else if (cmd == CDC_GET_ENCAPSULATED_RESPONSE) { - } else if (cmd == CDC_SET_COMM_FEATURE) { - } else if (cmd == CDC_GET_COMM_FEATURE) { - } else if (cmd == CDC_CLEAR_COMM_FEATURE) { - } else if (cmd == CDC_SET_LINE_CODING) { - /*******************************************************************************/ - /* Line Coding Structure */ - /*-----------------------------------------------------------------------------*/ - /* Offset | Field | Size | Value | Description */ - /* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/ - /* 4 | bCharFormat | 1 | Number | Stop bits */ - /* 0 - 1 Stop bit */ - /* 1 - 1.5 Stop bits */ - /* 2 - 2 Stop bits */ - /* 5 | bParityType | 1 | Number | Parity */ - /* 0 - None */ - /* 1 - Odd */ - /* 2 - Even */ - /* 3 - Mark */ - /* 4 - Space */ - /* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */ - /*******************************************************************************/ - } else if (cmd == CDC_GET_LINE_CODING) { - } else if (cmd == CDC_SET_CONTROL_LINE_STATE) { - _furi_hal_vcp_control_line(((USBD_SetupReqTypedef*)pbuf)->wValue); - } else if (cmd == CDC_SEND_BREAK) { - } else { - } - - return (USBD_OK); - /* USER CODE END 5 */ -} - -/** - * @brief Data received over USB OUT endpoint are sent over CDC interface - * through this function. - * - * @note - * This function will issue a NAK packet on any OUT packet received on - * USB endpoint until exiting this function. If you exit this function - * before transfer is complete on CDC interface (ie. using DMA controller) - * it will result in receiving more data while previous ones are still - * not sent. - * - * @param Buf: Buffer of data to be received - * @param Len: Number of data received (in bytes) - * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL - */ -static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len) -{ - /* USER CODE BEGIN 6 */ - if (*Len) { - _furi_hal_vcp_rx_callback((char*)Buf, *Len); - } - USBD_CDC_ReceivePacket(&hUsbDeviceFS); - return (USBD_OK); - /* USER CODE END 6 */ -} - -/** - * @brief CDC_Transmit_FS - * Data to send over USB IN endpoint are sent over CDC interface - * through this function. - * @note - * - * - * @param Buf: Buffer of data to be sent - * @param Len: Number of data to be sent (in bytes) - * @retval USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY - */ -uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len) -{ - uint8_t result = USBD_OK; - /* USER CODE BEGIN 7 */ - USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData; - if (hcdc->TxState != 0){ - return USBD_BUSY; - } - memcpy(UserTxBufferFS, Buf, Len); - USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, Len); - result = USBD_CDC_TransmitPacket(&hUsbDeviceFS); - /* USER CODE END 7 */ - return result; -} - -/** - * @brief CDC_TransmitCplt_FS - * Data transmited callback - * - * @note - * This function is IN transfer complete callback used to inform user that - * the submitted Data is successfully sent over USB. - * - * @param Buf: Buffer of data to be received - * @param Len: Number of data received (in bytes) - * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL - */ -static int8_t CDC_TransmitCplt_FS(uint8_t *Buf, uint32_t *Len, uint8_t epnum) -{ - uint8_t result = USBD_OK; - /* USER CODE BEGIN 13 */ - UNUSED(Buf); - UNUSED(epnum); - _furi_hal_vcp_tx_complete(*Len); - /* USER CODE END 13 */ - return result; -} - -/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */ - -/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */ - -/** - * @} - */ - -/** - * @} - */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/firmware/targets/f6/Src/usbd_conf.c b/firmware/targets/f6/Src/usbd_conf.c deleted file mode 100644 index e3744a3b..00000000 --- a/firmware/targets/f6/Src/usbd_conf.c +++ /dev/null @@ -1,808 +0,0 @@ -/* USER CODE BEGIN Header */ -/** - ****************************************************************************** - * @file : usbd_conf.c - * @version : v3.0_Cube - * @brief : This file implements the board support package for the USB device library - ****************************************************************************** - * @attention - * - *

© Copyright (c) 2020 STMicroelectronics. - * All rights reserved.

- * - * This software component is licensed by ST under Ultimate Liberty license - * SLA0044, the "License"; You may not use this file except in compliance with - * the License. You may obtain a copy of the License at: - * www.st.com/SLA0044 - * - ****************************************************************************** - */ -/* USER CODE END Header */ - -/* Includes ------------------------------------------------------------------*/ -#include "stm32wbxx.h" -#include "stm32wbxx_hal.h" -#include "usbd_def.h" -#include "usbd_core.h" - -#include "usbd_cdc.h" - -/* USER CODE BEGIN Includes */ - -/* USER CODE END Includes */ - -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -/* Private macro -------------------------------------------------------------*/ - -/* Private variables ---------------------------------------------------------*/ -/* USER CODE BEGIN PV */ - -/* USER CODE END PV */ - -PCD_HandleTypeDef hpcd_USB_FS; -void Error_Handler(void); - -/* USER CODE BEGIN 0 */ - -/* USER CODE END 0 */ - -/* Exported function prototypes ----------------------------------------------*/ - -/* USER CODE BEGIN PFP */ -/* Private function prototypes -----------------------------------------------*/ - -/* USER CODE END PFP */ - -/* Private functions ---------------------------------------------------------*/ -static USBD_StatusTypeDef USBD_Get_USB_Status(HAL_StatusTypeDef hal_status); -/* USER CODE BEGIN 1 */ -static void SystemClockConfig_Resume(void); - -/* USER CODE END 1 */ - -/******************************************************************************* - LL Driver Callbacks (PCD -> USB Device Library) -*******************************************************************************/ -/* MSP Init */ - -#if (USE_HAL_PCD_REGISTER_CALLBACK == 1U) -static void HAL_PCD_MspInit(PCD_HandleTypeDef* pcdHandle) -#else -void HAL_PCD_MspInit(PCD_HandleTypeDef* pcdHandle) -#endif /* USE_HAL_PCD_REGISTER_CALLBACK */ -{ - GPIO_InitTypeDef GPIO_InitStruct = {0}; - if(pcdHandle->Instance==USB) - { - /* USER CODE BEGIN USB_MspInit 0 */ - - /* USER CODE END USB_MspInit 0 */ - - __HAL_RCC_GPIOA_CLK_ENABLE(); - /**USB GPIO Configuration - PA11 ------> USB_DM - PA12 ------> USB_DP - */ - GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF10_USB; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - - /* Peripheral clock enable */ - __HAL_RCC_USB_CLK_ENABLE(); - - /* Peripheral interrupt init */ - HAL_NVIC_SetPriority(USB_LP_IRQn, 5, 0); - HAL_NVIC_EnableIRQ(USB_LP_IRQn); - /* USER CODE BEGIN USB_MspInit 1 */ - - /* USER CODE END USB_MspInit 1 */ - } -} - -#if (USE_HAL_PCD_REGISTER_CALLBACK == 1U) -static void HAL_PCD_MspDeInit(PCD_HandleTypeDef* pcdHandle) -#else -void HAL_PCD_MspDeInit(PCD_HandleTypeDef* pcdHandle) -#endif /* USE_HAL_PCD_REGISTER_CALLBACK */ -{ - if(pcdHandle->Instance==USB) - { - /* USER CODE BEGIN USB_MspDeInit 0 */ - - /* USER CODE END USB_MspDeInit 0 */ - /* Peripheral clock disable */ - __HAL_RCC_USB_CLK_DISABLE(); - - /**USB GPIO Configuration - PA11 ------> USB_DM - PA12 ------> USB_DP - */ - HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12); - - /* Peripheral interrupt Deinit*/ - HAL_NVIC_DisableIRQ(USB_LP_IRQn); - - /* USER CODE BEGIN USB_MspDeInit 1 */ - - /* USER CODE END USB_MspDeInit 1 */ - } -} - -/** - * @brief Setup stage callback - * @param hpcd: PCD handle - * @retval None - */ -#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U) -static void PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd) -#else -void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd) -#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */ -{ - /* USER CODE BEGIN HAL_PCD_SetupStageCallback_PreTreatment */ - - /* USER CODE END HAL_PCD_SetupStageCallback_PreTreatment */ - USBD_LL_SetupStage((USBD_HandleTypeDef*)hpcd->pData, (uint8_t *)hpcd->Setup); - /* USER CODE BEGIN HAL_PCD_SetupStageCallback_PostTreatment */ - - /* USER CODE END HAL_PCD_SetupStageCallback_PostTreatment */ -} - -/** - * @brief Data Out stage callback. - * @param hpcd: PCD handle - * @param epnum: Endpoint number - * @retval None - */ -#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U) -static void PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) -#else -void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) -#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */ -{ - /* USER CODE BEGIN HAL_PCD_DataOutStageCallback_PreTreatment */ - - /* USER CODE END HAL_PCD_DataOutStageCallback_PreTreatment */ - USBD_LL_DataOutStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->OUT_ep[epnum].xfer_buff); - /* USER CODE BEGIN HAL_PCD_DataOutStageCallback_PostTreatment */ - - /* USER CODE END HAL_PCD_DataOutStageCallback_PostTreatment */ -} - -/** - * @brief Data In stage callback. - * @param hpcd: PCD handle - * @param epnum: Endpoint number - * @retval None - */ -#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U) -static void PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) -#else -void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) -#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */ -{ - /* USER CODE BEGIN HAL_PCD_DataInStageCallback_PreTreatment */ - - /* USER CODE END HAL_PCD_DataInStageCallback_PreTreatment */ - USBD_LL_DataInStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->IN_ep[epnum].xfer_buff); - /* USER CODE BEGIN HAL_PCD_DataInStageCallback_PostTreatment */ - - /* USER CODE END HAL_PCD_DataInStageCallback_PostTreatment */ -} - -/** - * @brief SOF callback. - * @param hpcd: PCD handle - * @retval None - */ -#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U) -static void PCD_SOFCallback(PCD_HandleTypeDef *hpcd) -#else -void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) -#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */ -{ - /* USER CODE BEGIN HAL_PCD_SOFCallback_PreTreatment */ - - /* USER CODE END HAL_PCD_SOFCallback_PreTreatment */ - USBD_LL_SOF((USBD_HandleTypeDef*)hpcd->pData); - /* USER CODE BEGIN HAL_PCD_SOFCallback_PostTreatment */ - - /* USER CODE END HAL_PCD_SOFCallback_PostTreatment */ -} - -/** - * @brief Reset callback. - * @param hpcd: PCD handle - * @retval None - */ -#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U) -static void PCD_ResetCallback(PCD_HandleTypeDef *hpcd) -#else -void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd) -#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */ -{ - /* USER CODE BEGIN HAL_PCD_ResetCallback_PreTreatment */ - - /* USER CODE END HAL_PCD_ResetCallback_PreTreatment */ - USBD_SpeedTypeDef speed = USBD_SPEED_FULL; - - if ( hpcd->Init.speed != PCD_SPEED_FULL) - { - Error_Handler(); - } - /* Set Speed. */ - USBD_LL_SetSpeed((USBD_HandleTypeDef*)hpcd->pData, speed); - - /* Reset Device. */ - USBD_LL_Reset((USBD_HandleTypeDef*)hpcd->pData); - /* USER CODE BEGIN HAL_PCD_ResetCallback_PostTreatment */ - - /* USER CODE END HAL_PCD_ResetCallback_PostTreatment */ -} - -/** - * @brief Suspend callback. - * When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it) - * @param hpcd: PCD handle - * @retval None - */ -#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U) -static void PCD_SuspendCallback(PCD_HandleTypeDef *hpcd) -#else -void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd) -#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */ -{ - /* USER CODE BEGIN HAL_PCD_SuspendCallback_PreTreatment */ - - /* USER CODE END HAL_PCD_SuspendCallback_PreTreatment */ - /* Inform USB library that core enters in suspend Mode. */ - USBD_LL_Suspend((USBD_HandleTypeDef*)hpcd->pData); - /* Enter in STOP mode. */ - /* USER CODE BEGIN 2 */ - if (hpcd->Init.low_power_enable) - { - /* Set SLEEPDEEP bit and SleepOnExit of Cortex System Control Register. */ - SCB->SCR |= (uint32_t)((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk)); - } - /* USER CODE END 2 */ - /* USER CODE BEGIN HAL_PCD_SuspendCallback_PostTreatment */ - - /* USER CODE END HAL_PCD_SuspendCallback_PostTreatment */ -} - -/** - * @brief Resume callback. - * When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it) - * @param hpcd: PCD handle - * @retval None - */ -#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U) -static void PCD_ResumeCallback(PCD_HandleTypeDef *hpcd) -#else -void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd) -#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */ -{ - /* USER CODE BEGIN HAL_PCD_ResumeCallback_PreTreatment */ - - /* USER CODE END HAL_PCD_ResumeCallback_PreTreatment */ - - /* USER CODE BEGIN 3 */ - if (hpcd->Init.low_power_enable) - { - /* Reset SLEEPDEEP bit of Cortex System Control Register. */ - SCB->SCR &= (uint32_t)~((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk)); - SystemClockConfig_Resume(); - } - /* USER CODE END 3 */ - - USBD_LL_Resume((USBD_HandleTypeDef*)hpcd->pData); - /* USER CODE BEGIN HAL_PCD_ResumeCallback_PostTreatment */ - - /* USER CODE END HAL_PCD_ResumeCallback_PostTreatment */ -} - -/** - * @brief ISOOUTIncomplete callback. - * @param hpcd: PCD handle - * @param epnum: Endpoint number - * @retval None - */ -#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U) -static void PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) -#else -void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) -#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */ -{ - /* USER CODE BEGIN HAL_PCD_ISOOUTIncompleteCallback_PreTreatment */ - - /* USER CODE END HAL_PCD_ISOOUTIncompleteCallback_PreTreatment */ - USBD_LL_IsoOUTIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum); - /* USER CODE BEGIN HAL_PCD_ISOOUTIncompleteCallback_PostTreatment */ - - /* USER CODE END HAL_PCD_ISOOUTIncompleteCallback_PostTreatment */ -} - -/** - * @brief ISOINIncomplete callback. - * @param hpcd: PCD handle - * @param epnum: Endpoint number - * @retval None - */ -#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U) -static void PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) -#else -void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) -#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */ -{ - /* USER CODE BEGIN HAL_PCD_ISOINIncompleteCallback_PreTreatment */ - - /* USER CODE END HAL_PCD_ISOINIncompleteCallback_PreTreatment */ - USBD_LL_IsoINIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum); - /* USER CODE BEGIN HAL_PCD_ISOINIncompleteCallback_PostTreatment */ - - /* USER CODE END HAL_PCD_ISOINIncompleteCallback_PostTreatment */ -} - -/** - * @brief Connect callback. - * @param hpcd: PCD handle - * @retval None - */ -#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U) -static void PCD_ConnectCallback(PCD_HandleTypeDef *hpcd) -#else -void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd) -#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */ -{ - /* USER CODE BEGIN HAL_PCD_ConnectCallback_PreTreatment */ - - /* USER CODE END HAL_PCD_ConnectCallback_PreTreatment */ - USBD_LL_DevConnected((USBD_HandleTypeDef*)hpcd->pData); - /* USER CODE BEGIN HAL_PCD_ConnectCallback_PostTreatment */ - - /* USER CODE END HAL_PCD_ConnectCallback_PostTreatment */ -} - -/** - * @brief Disconnect callback. - * @param hpcd: PCD handle - * @retval None - */ -#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U) -static void PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd) -#else -void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd) -#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */ -{ - /* USER CODE BEGIN HAL_PCD_DisconnectCallback_PreTreatment */ - - /* USER CODE END HAL_PCD_DisconnectCallback_PreTreatment */ - USBD_LL_DevDisconnected((USBD_HandleTypeDef*)hpcd->pData); - /* USER CODE BEGIN HAL_PCD_DisconnectCallback_PostTreatment */ - - /* USER CODE END HAL_PCD_DisconnectCallback_PostTreatment */ -} - - /* USER CODE BEGIN LowLevelInterface */ - - /* USER CODE END LowLevelInterface */ - -/******************************************************************************* - LL Driver Interface (USB Device Library --> PCD) -*******************************************************************************/ - -/** - * @brief Initializes the low level portion of the device driver. - * @param pdev: Device handle - * @retval USBD status - */ -USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev) -{ - /* Init USB Ip. */ - hpcd_USB_FS.pData = pdev; - /* Link the driver to the stack. */ - pdev->pData = &hpcd_USB_FS; -/* Enable USB power on Pwrctrl CR2 register. */ - HAL_PWREx_EnableVddUSB(); - - hpcd_USB_FS.Instance = USB; - hpcd_USB_FS.Init.dev_endpoints = 8; - hpcd_USB_FS.Init.speed = PCD_SPEED_FULL; - hpcd_USB_FS.Init.phy_itface = PCD_PHY_EMBEDDED; - hpcd_USB_FS.Init.Sof_enable = DISABLE; - hpcd_USB_FS.Init.low_power_enable = DISABLE; - hpcd_USB_FS.Init.lpm_enable = DISABLE; - hpcd_USB_FS.Init.battery_charging_enable = DISABLE; - - #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U) - /* register Msp Callbacks (before the Init) */ - HAL_PCD_RegisterCallback(&hpcd_USB_FS, HAL_PCD_MSPINIT_CB_ID, PCD_MspInit); - HAL_PCD_RegisterCallback(&hpcd_USB_FS, HAL_PCD_MSPDEINIT_CB_ID, PCD_MspDeInit); - #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */ - - if (HAL_PCD_Init(&hpcd_USB_FS) != HAL_OK) - { - Error_Handler( ); - } - -#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U) - /* Register USB PCD CallBacks */ - HAL_PCD_RegisterCallback(&hpcd_USB_FS, HAL_PCD_SOF_CB_ID, PCD_SOFCallback); - HAL_PCD_RegisterCallback(&hpcd_USB_FS, HAL_PCD_SETUPSTAGE_CB_ID, PCD_SetupStageCallback); - HAL_PCD_RegisterCallback(&hpcd_USB_FS, HAL_PCD_RESET_CB_ID, PCD_ResetCallback); - HAL_PCD_RegisterCallback(&hpcd_USB_FS, HAL_PCD_SUSPEND_CB_ID, PCD_SuspendCallback); - HAL_PCD_RegisterCallback(&hpcd_USB_FS, HAL_PCD_RESUME_CB_ID, PCD_ResumeCallback); - HAL_PCD_RegisterCallback(&hpcd_USB_FS, HAL_PCD_CONNECT_CB_ID, PCD_ConnectCallback); - HAL_PCD_RegisterCallback(&hpcd_USB_FS, HAL_PCD_DISCONNECT_CB_ID, PCD_DisconnectCallback); - /* USER CODE BEGIN RegisterCallBackFirstPart */ - - /* USER CODE END RegisterCallBackFirstPart */ - HAL_PCD_RegisterLpmCallback(&hpcd_USB_FS, PCDEx_LPM_Callback); - HAL_PCD_RegisterDataOutStageCallback(&hpcd_USB_FS, PCD_DataOutStageCallback); - HAL_PCD_RegisterDataInStageCallback(&hpcd_USB_FS, PCD_DataInStageCallback); - HAL_PCD_RegisterIsoOutIncpltCallback(&hpcd_USB_FS, PCD_ISOOUTIncompleteCallback); - HAL_PCD_RegisterIsoInIncpltCallback(&hpcd_USB_FS, PCD_ISOINIncompleteCallback); - /* USER CODE BEGIN RegisterCallBackSecondPart */ - - /* USER CODE END RegisterCallBackSecondPart */ -#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */ - /* USER CODE BEGIN EndPoint_Configuration */ - HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x00 , PCD_SNG_BUF, 0x18); - HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x80 , PCD_SNG_BUF, 0x58); - /* USER CODE END EndPoint_Configuration */ - /* USER CODE BEGIN EndPoint_Configuration_CDC */ - HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x81 , PCD_SNG_BUF, 0xC0); - HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x01 , PCD_SNG_BUF, 0x110); - HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x82 , PCD_SNG_BUF, 0x100); - /* USER CODE END EndPoint_Configuration_CDC */ - return USBD_OK; -} - -/** - * @brief De-Initializes the low level portion of the device driver. - * @param pdev: Device handle - * @retval USBD status - */ -USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev) -{ - HAL_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_DeInit(pdev->pData); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** - * @brief Starts the low level portion of the device driver. - * @param pdev: Device handle - * @retval USBD status - */ -USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev) -{ - HAL_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_Start(pdev->pData); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** - * @brief Stops the low level portion of the device driver. - * @param pdev: Device handle - * @retval USBD status - */ -USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev) -{ - HAL_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_Stop(pdev->pData); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** - * @brief Opens an endpoint of the low level driver. - * @param pdev: Device handle - * @param ep_addr: Endpoint number - * @param ep_type: Endpoint type - * @param ep_mps: Endpoint max packet size - * @retval USBD status - */ -USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps) -{ - HAL_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_EP_Open(pdev->pData, ep_addr, ep_mps, ep_type); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** - * @brief Closes an endpoint of the low level driver. - * @param pdev: Device handle - * @param ep_addr: Endpoint number - * @retval USBD status - */ -USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) -{ - HAL_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_EP_Close(pdev->pData, ep_addr); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** - * @brief Flushes an endpoint of the Low Level Driver. - * @param pdev: Device handle - * @param ep_addr: Endpoint number - * @retval USBD status - */ -USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) -{ - HAL_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_EP_Flush(pdev->pData, ep_addr); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** - * @brief Sets a Stall condition on an endpoint of the Low Level Driver. - * @param pdev: Device handle - * @param ep_addr: Endpoint number - * @retval USBD status - */ -USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) -{ - HAL_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_EP_SetStall(pdev->pData, ep_addr); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** - * @brief Clears a Stall condition on an endpoint of the Low Level Driver. - * @param pdev: Device handle - * @param ep_addr: Endpoint number - * @retval USBD status - */ -USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) -{ - HAL_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_EP_ClrStall(pdev->pData, ep_addr); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** - * @brief Returns Stall condition. - * @param pdev: Device handle - * @param ep_addr: Endpoint number - * @retval Stall (1: Yes, 0: No) - */ -uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) -{ - PCD_HandleTypeDef *hpcd = (PCD_HandleTypeDef*) pdev->pData; - - if((ep_addr & 0x80) == 0x80) - { - return hpcd->IN_ep[ep_addr & 0x7F].is_stall; - } - else - { - return hpcd->OUT_ep[ep_addr & 0x7F].is_stall; - } -} - -/** - * @brief Assigns a USB address to the device. - * @param pdev: Device handle - * @param dev_addr: Device address - * @retval USBD status - */ -USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr) -{ - HAL_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_SetAddress(pdev->pData, dev_addr); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** - * @brief Transmits data over an endpoint. - * @param pdev: Device handle - * @param ep_addr: Endpoint number - * @param pbuf: Pointer to data to be sent - * @param size: Data size - * @retval USBD status - */ -USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint32_t size) -{ - HAL_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_EP_Transmit(pdev->pData, ep_addr, pbuf, size); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** - * @brief Prepares an endpoint for reception. - * @param pdev: Device handle - * @param ep_addr: Endpoint number - * @param pbuf: Pointer to data to be received - * @param size: Data size - * @retval USBD status - */ -USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint32_t size) -{ - HAL_StatusTypeDef hal_status = HAL_OK; - USBD_StatusTypeDef usb_status = USBD_OK; - - hal_status = HAL_PCD_EP_Receive(pdev->pData, ep_addr, pbuf, size); - - usb_status = USBD_Get_USB_Status(hal_status); - - return usb_status; -} - -/** - * @brief Returns the last transfered packet size. - * @param pdev: Device handle - * @param ep_addr: Endpoint number - * @retval Recived Data Size - */ -uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr) -{ - return HAL_PCD_EP_GetRxCount((PCD_HandleTypeDef*) pdev->pData, ep_addr); -} - -/** - * @brief Send LPM message to user layer - * @param hpcd: PCD handle - * @param msg: LPM message - * @retval None - */ -#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U) -static void PCDEx_LPM_Callback(PCD_HandleTypeDef *hpcd, PCD_LPM_MsgTypeDef msg) -#else -void HAL_PCDEx_LPM_Callback(PCD_HandleTypeDef *hpcd, PCD_LPM_MsgTypeDef msg) -#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */ -{ - /* USER CODE BEGIN LPM_Callback */ - switch (msg) - { - case PCD_LPM_L0_ACTIVE: - if (hpcd->Init.low_power_enable) - { - SystemClockConfig_Resume(); - - /* Reset SLEEPDEEP bit of Cortex System Control Register. */ - SCB->SCR &= (uint32_t)~((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk)); - } - USBD_LL_Resume(hpcd->pData); - break; - - case PCD_LPM_L1_ACTIVE: - USBD_LL_Suspend(hpcd->pData); - - /* Enter in STOP mode. */ - if (hpcd->Init.low_power_enable) - { - /* Set SLEEPDEEP bit and SleepOnExit of Cortex System Control Register. */ - SCB->SCR |= (uint32_t)((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk)); - } - break; - } - /* USER CODE END LPM_Callback */ -} - -/** - * @brief Delays routine for the USB Device Library. - * @param Delay: Delay in ms - * @retval None - */ -void USBD_LL_Delay(uint32_t Delay) -{ - HAL_Delay(Delay); -} - -/** - * @brief Static single allocation. - * @param size: Size of allocated memory - * @retval None - */ -void *USBD_static_malloc(uint32_t size) -{ - static uint32_t mem[(sizeof(USBD_CDC_HandleTypeDef)/4)+1];/* On 32-bit boundary */ - return mem; -} - -/** - * @brief Dummy memory free - * @param p: Pointer to allocated memory address - * @retval None - */ -void USBD_static_free(void *p) -{ - -} - -/* USER CODE BEGIN 5 */ -/** - * @brief Configures system clock after wake-up from USB resume callBack: - * enable HSI, PLL and select PLL as system clock source. - * @retval None - */ -static void SystemClockConfig_Resume(void) -{ -} -/* USER CODE END 5 */ - -/** - * @brief Retuns the USB status depending on the HAL status: - * @param hal_status: HAL status - * @retval USB status - */ -USBD_StatusTypeDef USBD_Get_USB_Status(HAL_StatusTypeDef hal_status) -{ - USBD_StatusTypeDef usb_status = USBD_OK; - - switch (hal_status) - { - case HAL_OK : - usb_status = USBD_OK; - break; - case HAL_ERROR : - usb_status = USBD_FAIL; - break; - case HAL_BUSY : - usb_status = USBD_BUSY; - break; - case HAL_TIMEOUT : - usb_status = USBD_FAIL; - break; - default : - usb_status = USBD_FAIL; - break; - } - return usb_status; -} -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/firmware/targets/f6/Src/usbd_desc.c b/firmware/targets/f6/Src/usbd_desc.c deleted file mode 100644 index 9e7c5483..00000000 --- a/firmware/targets/f6/Src/usbd_desc.c +++ /dev/null @@ -1,391 +0,0 @@ -/* USER CODE BEGIN Header */ -/** - ****************************************************************************** - * @file : usbd_desc.c - * @version : v3.0_Cube - * @brief : This file implements the USB device descriptors. - ****************************************************************************** - * @attention - * - *

© Copyright (c) 2020 STMicroelectronics. - * All rights reserved.

- * - * This software component is licensed by ST under Ultimate Liberty license - * SLA0044, the "License"; You may not use this file except in compliance with - * the License. You may obtain a copy of the License at: - * www.st.com/SLA0044 - * - ****************************************************************************** - */ -/* USER CODE END Header */ - -/* Includes ------------------------------------------------------------------*/ -#include "usbd_core.h" -#include "usbd_desc.h" -#include "usbd_conf.h" -#include "furi-hal-version.h" -/* USER CODE BEGIN INCLUDE */ - -/* USER CODE END INCLUDE */ - -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -/* Private macro -------------------------------------------------------------*/ - -/* USER CODE BEGIN PV */ -/* Private variables ---------------------------------------------------------*/ - -/* USER CODE END PV */ - -/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY - * @{ - */ - -/** @addtogroup USBD_DESC - * @{ - */ - -/** @defgroup USBD_DESC_Private_TypesDefinitions USBD_DESC_Private_TypesDefinitions - * @brief Private types. - * @{ - */ - -/* USER CODE BEGIN PRIVATE_TYPES */ - -/* USER CODE END PRIVATE_TYPES */ - -/** - * @} - */ - -/** @defgroup USBD_DESC_Private_Defines USBD_DESC_Private_Defines - * @brief Private defines. - * @{ - */ - -#define USBD_VID 1155 -#define USBD_LANGID_STRING 1033 -#define USBD_MANUFACTURER_STRING "Flipper Devices Inc." -#define USBD_PID 22336 -#define USBD_CONFIGURATION_STRING "CDC Config" -#define USBD_INTERFACE_STRING "CDC Interface" -/* USER CODE BEGIN PRIVATE_DEFINES */ - -/* USER CODE END PRIVATE_DEFINES */ - -/** - * @} - */ - -/* USER CODE BEGIN 0 */ -/* USER CODE END 0 */ - -/** @defgroup USBD_DESC_Private_Macros USBD_DESC_Private_Macros - * @brief Private macros. - * @{ - */ - -/* USER CODE BEGIN PRIVATE_MACRO */ - -/* USER CODE END PRIVATE_MACRO */ - -/** - * @} - */ - -/** @defgroup USBD_DESC_Private_FunctionPrototypes USBD_DESC_Private_FunctionPrototypes - * @brief Private functions declaration. - * @{ - */ - -static void Get_SerialNum(void); -static void IntToUnicode(uint32_t value, uint8_t * pbuf, uint8_t len); - -/** - * @} - */ - -/** @defgroup USBD_DESC_Private_FunctionPrototypes USBD_DESC_Private_FunctionPrototypes - * @brief Private functions declaration. - * @{ - */ - -uint8_t * USBD_CDC_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); -uint8_t * USBD_CDC_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); -uint8_t * USBD_CDC_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); -uint8_t * USBD_CDC_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); -uint8_t * USBD_CDC_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); -uint8_t * USBD_CDC_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); -uint8_t * USBD_CDC_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); - -/** - * @} - */ - -/** @defgroup USBD_DESC_Private_Variables USBD_DESC_Private_Variables - * @brief Private variables. - * @{ - */ - -USBD_DescriptorsTypeDef CDC_Desc = -{ - USBD_CDC_DeviceDescriptor, - USBD_CDC_LangIDStrDescriptor, - USBD_CDC_ManufacturerStrDescriptor, - USBD_CDC_ProductStrDescriptor, - USBD_CDC_SerialStrDescriptor, - USBD_CDC_ConfigStrDescriptor, - USBD_CDC_InterfaceStrDescriptor -}; - -#if defined ( __ICCARM__ ) /* IAR Compiler */ - #pragma data_alignment=4 -#endif /* defined ( __ICCARM__ ) */ -/** USB standard device descriptor. */ -__ALIGN_BEGIN uint8_t USBD_CDC_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = -{ - 0x12, /*bLength */ - USB_DESC_TYPE_DEVICE, /*bDescriptorType*/ - 0x00, /*bcdUSB */ - 0x02, - 0x02, /*bDeviceClass*/ - 0x02, /*bDeviceSubClass*/ - 0x00, /*bDeviceProtocol*/ - USB_MAX_EP0_SIZE, /*bMaxPacketSize*/ - LOBYTE(USBD_VID), /*idVendor*/ - HIBYTE(USBD_VID), /*idVendor*/ - LOBYTE(USBD_PID), /*idProduct*/ - HIBYTE(USBD_PID), /*idProduct*/ - 0x00, /*bcdDevice rel. 2.00*/ - 0x02, - USBD_IDX_MFC_STR, /*Index of manufacturer string*/ - USBD_IDX_PRODUCT_STR, /*Index of product string*/ - USBD_IDX_SERIAL_STR, /*Index of serial number string*/ - USBD_MAX_NUM_CONFIGURATION /*bNumConfigurations*/ -}; - -/* USB_DeviceDescriptor */ - -/** - * @} - */ - -/** @defgroup USBD_DESC_Private_Variables USBD_DESC_Private_Variables - * @brief Private variables. - * @{ - */ - -#if defined ( __ICCARM__ ) /* IAR Compiler */ - #pragma data_alignment=4 -#endif /* defined ( __ICCARM__ ) */ - -/** USB lang indentifier descriptor. */ -__ALIGN_BEGIN uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = -{ - USB_LEN_LANGID_STR_DESC, - USB_DESC_TYPE_STRING, - LOBYTE(USBD_LANGID_STRING), - HIBYTE(USBD_LANGID_STRING) -}; - -#if defined ( __ICCARM__ ) /* IAR Compiler */ - #pragma data_alignment=4 -#endif /* defined ( __ICCARM__ ) */ -/* Internal string descriptor. */ -__ALIGN_BEGIN uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END; - -#if defined ( __ICCARM__ ) /*!< IAR Compiler */ - #pragma data_alignment=4 -#endif -__ALIGN_BEGIN uint8_t USBD_StringSerial[USB_SIZ_STRING_SERIAL] __ALIGN_END = { - USB_SIZ_STRING_SERIAL, - USB_DESC_TYPE_STRING, -}; - -/** - * @} - */ - -/** @defgroup USBD_DESC_Private_Functions USBD_DESC_Private_Functions - * @brief Private functions. - * @{ - */ - -/** - * @brief Return the device descriptor - * @param speed : Current device speed - * @param length : Pointer to data length variable - * @retval Pointer to descriptor buffer - */ -uint8_t * USBD_CDC_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) -{ - UNUSED(speed); - *length = sizeof(USBD_CDC_DeviceDesc); - return USBD_CDC_DeviceDesc; -} - -/** - * @brief Return the LangID string descriptor - * @param speed : Current device speed - * @param length : Pointer to data length variable - * @retval Pointer to descriptor buffer - */ -uint8_t * USBD_CDC_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) -{ - UNUSED(speed); - *length = sizeof(USBD_LangIDDesc); - return USBD_LangIDDesc; -} - -/** - * @brief Return the product string descriptor - * @param speed : Current device speed - * @param length : Pointer to data length variable - * @retval Pointer to descriptor buffer - */ -uint8_t * USBD_CDC_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) -{ - USBD_GetString((uint8_t*)furi_hal_version_get_device_name_ptr(), USBD_StrDesc, length); - return USBD_StrDesc; -} - -/** - * @brief Return the manufacturer string descriptor - * @param speed : Current device speed - * @param length : Pointer to data length variable - * @retval Pointer to descriptor buffer - */ -uint8_t * USBD_CDC_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) -{ - UNUSED(speed); - USBD_GetString((uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, length); - return USBD_StrDesc; -} - -/** - * @brief Return the serial number string descriptor - * @param speed : Current device speed - * @param length : Pointer to data length variable - * @retval Pointer to descriptor buffer - */ -uint8_t * USBD_CDC_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) -{ - UNUSED(speed); - *length = USB_SIZ_STRING_SERIAL; - - /* Update the serial number string descriptor with the data from the unique - * ID */ - if(furi_hal_version_get_name_ptr()){ - char buffer[14] = "flip_"; - strncat(buffer, furi_hal_version_get_name_ptr(), 8); - USBD_GetString((uint8_t*) buffer, USBD_StringSerial, length); - } else { - Get_SerialNum(); - } - /* USER CODE BEGIN USBD_CDC_SerialStrDescriptor */ - - /* USER CODE END USBD_CDC_SerialStrDescriptor */ - - return (uint8_t *) USBD_StringSerial; -} - -/** - * @brief Return the configuration string descriptor - * @param speed : Current device speed - * @param length : Pointer to data length variable - * @retval Pointer to descriptor buffer - */ -uint8_t * USBD_CDC_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) -{ - if(speed == USBD_SPEED_HIGH) - { - USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING, USBD_StrDesc, length); - } - else - { - USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING, USBD_StrDesc, length); - } - return USBD_StrDesc; -} - -/** - * @brief Return the interface string descriptor - * @param speed : Current device speed - * @param length : Pointer to data length variable - * @retval Pointer to descriptor buffer - */ -uint8_t * USBD_CDC_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) -{ - if(speed == 0) - { - USBD_GetString((uint8_t *)USBD_INTERFACE_STRING, USBD_StrDesc, length); - } - else - { - USBD_GetString((uint8_t *)USBD_INTERFACE_STRING, USBD_StrDesc, length); - } - return USBD_StrDesc; -} - -/** - * @brief Create the serial number string descriptor - * @param None - * @retval None - */ -static void Get_SerialNum(void) -{ - uint32_t deviceserial0, deviceserial1, deviceserial2; - - deviceserial0 = *(uint32_t *) DEVICE_ID1; - deviceserial1 = *(uint32_t *) DEVICE_ID2; - deviceserial2 = *(uint32_t *) DEVICE_ID3; - - deviceserial0 += deviceserial2; - - if (deviceserial0 != 0) - { - IntToUnicode(deviceserial0, &USBD_StringSerial[2], 8); - IntToUnicode(deviceserial1, &USBD_StringSerial[18], 4); - } -} - -/** - * @brief Convert Hex 32Bits value into char - * @param value: value to convert - * @param pbuf: pointer to the buffer - * @param len: buffer length - * @retval None - */ -static void IntToUnicode(uint32_t value, uint8_t * pbuf, uint8_t len) -{ - uint8_t idx = 0; - - for (idx = 0; idx < len; idx++) - { - if (((value >> 28)) < 0xA) - { - pbuf[2 * idx] = (value >> 28) + '0'; - } - else - { - pbuf[2 * idx] = (value >> 28) + 'A' - 10; - } - - value = value << 4; - - pbuf[2 * idx + 1] = 0; - } -} -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/firmware/targets/f6/ble-glue/app_ble.c b/firmware/targets/f6/ble-glue/app_ble.c index 18ca03ae..042000b5 100644 --- a/firmware/targets/f6/ble-glue/app_ble.c +++ b/firmware/targets/f6/ble-glue/app_ble.c @@ -9,7 +9,6 @@ #include "cmsis_os.h" #include "shci.h" -#include "stm32_lpm.h" #include "otp.h" #include "dis_app.h" #include "hrs_app.h" diff --git a/firmware/targets/f6/ble-glue/app_entry.c b/firmware/targets/f6/ble-glue/app_entry.c index 2a8e35cc..93b528c9 100644 --- a/firmware/targets/f6/ble-glue/app_entry.c +++ b/firmware/targets/f6/ble-glue/app_entry.c @@ -6,7 +6,6 @@ #include "tl.h" #include "cmsis_os.h" #include "shci_tl.h" -#include "stm32_lpm.h" #include "app_debug.h" #include diff --git a/firmware/targets/f6/furi-hal/furi-hal-console.c b/firmware/targets/f6/furi-hal/furi-hal-console.c index 6aee4427..6c67e0c8 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-console.c +++ b/firmware/targets/f6/furi-hal/furi-hal-console.c @@ -66,4 +66,8 @@ void furi_hal_console_printf(const char format[], ...) { va_end(args); furi_hal_console_tx((const uint8_t*)string_get_cstr(string), string_size(string)); string_clear(string); +} + +void furi_hal_console_puts(const char *data) { + furi_hal_console_tx((const uint8_t*)data, strlen(data)); } \ No newline at end of file diff --git a/firmware/targets/f6/furi-hal/furi-hal-console.h b/firmware/targets/f6/furi-hal/furi-hal-console.h index 55ca8791..26ca4540 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-console.h +++ b/firmware/targets/f6/furi-hal/furi-hal-console.h @@ -11,8 +11,16 @@ void furi_hal_console_init(); void furi_hal_console_tx(const uint8_t* buffer, size_t buffer_size); +/** + * Printf-like plain uart interface + * @warning Will not work in ISR context + * @param format + * @param ... + */ void furi_hal_console_printf(const char format[], ...); +void furi_hal_console_puts(const char* data); + #ifdef __cplusplus } #endif diff --git a/firmware/targets/f6/furi-hal/furi-hal-delay.c b/firmware/targets/f6/furi-hal/furi-hal-delay.c index e886e23e..52de8715 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-delay.c +++ b/firmware/targets/f6/furi-hal/furi-hal-delay.c @@ -28,3 +28,7 @@ void delay(float milliseconds) { (void)result; furi_assert(result == osOK); } + +uint32_t millis(void){ + return HAL_GetTick(); +} diff --git a/firmware/targets/f6/furi-hal/furi-hal-irda.c b/firmware/targets/f6/furi-hal/furi-hal-irda.c index 370fea42..7c5d832b 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-irda.c +++ b/firmware/targets/f6/furi-hal/furi-hal-irda.c @@ -411,7 +411,9 @@ static void furi_hal_irda_tx_fill_buffer_last(uint8_t buf_num) { furi_assert(irda_tim_tx.data_callback); IrdaTxBuf* buffer = &irda_tim_tx.buffer[buf_num]; furi_assert(buffer->data != NULL); + (void)buffer->data; furi_assert(buffer->polarity != NULL); + (void)buffer->polarity; irda_tim_tx.buffer[buf_num].data[0] = 0; // 1 pulse irda_tim_tx.buffer[buf_num].polarity[0] = IRDA_TX_CCMR_LOW; @@ -471,8 +473,8 @@ static void furi_hal_irda_tx_fill_buffer(uint8_t buf_num, uint8_t polarity_shift irda_tim_tx.tx_timing_rest_duration = num_of_impulses - 1; irda_tim_tx.tx_timing_rest_status = status; irda_tim_tx.tx_timing_rest_level = level; - buffer->polarity[polarity_counter] = level ? IRDA_TX_CCMR_HIGH : IRDA_TX_CCMR_LOW; - buffer->data[*size] = 0xFFFF; + --(*size); + --polarity_counter; status = FuriHalIrdaTxGetDataStateOk; } else { buffer->polarity[polarity_counter] = level ? IRDA_TX_CCMR_HIGH : IRDA_TX_CCMR_LOW; diff --git a/firmware/targets/f6/furi-hal/furi-hal-resources.c b/firmware/targets/f6/furi-hal/furi-hal-resources.c index f1d2003f..6d7f8a0b 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-resources.c +++ b/firmware/targets/f6/furi-hal/furi-hal-resources.c @@ -3,15 +3,15 @@ #include const InputPin input_pins[] = { - {.port = BUTTON_UP_GPIO_Port, .pin = BUTTON_UP_Pin, .key = InputKeyUp, .inverted = true}, - {.port = BUTTON_DOWN_GPIO_Port, .pin = BUTTON_DOWN_Pin, .key = InputKeyDown, .inverted = true}, + {.port = BUTTON_UP_GPIO_Port, .pin = BUTTON_UP_Pin, .key = InputKeyUp, .inverted = true, .name="Up"}, + {.port = BUTTON_DOWN_GPIO_Port, .pin = BUTTON_DOWN_Pin, .key = InputKeyDown, .inverted = true, .name="Down"}, {.port = BUTTON_RIGHT_GPIO_Port, .pin = BUTTON_RIGHT_Pin, .key = InputKeyRight, - .inverted = true}, - {.port = BUTTON_LEFT_GPIO_Port, .pin = BUTTON_LEFT_Pin, .key = InputKeyLeft, .inverted = true}, - {.port = BUTTON_OK_GPIO_Port, .pin = BUTTON_OK_Pin, .key = InputKeyOk, .inverted = false}, - {.port = BUTTON_BACK_GPIO_Port, .pin = BUTTON_BACK_Pin, .key = InputKeyBack, .inverted = true}, + .inverted = true, .name="Right"}, + {.port = BUTTON_LEFT_GPIO_Port, .pin = BUTTON_LEFT_Pin, .key = InputKeyLeft, .inverted = true, .name="Left"}, + {.port = BUTTON_OK_GPIO_Port, .pin = BUTTON_OK_Pin, .key = InputKeyOk, .inverted = false, .name="Ok"}, + {.port = BUTTON_BACK_GPIO_Port, .pin = BUTTON_BACK_Pin, .key = InputKeyBack, .inverted = true, .name="Back"}, }; const size_t input_pins_count = sizeof(input_pins) / sizeof(InputPin); diff --git a/firmware/targets/f6/furi-hal/furi-hal-resources.h b/firmware/targets/f6/furi-hal/furi-hal-resources.h index e962a232..bec183ef 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-resources.h +++ b/firmware/targets/f6/furi-hal/furi-hal-resources.h @@ -54,6 +54,7 @@ typedef struct { const uint16_t pin; const InputKey key; const bool inverted; + const char* name; } InputPin; extern const InputPin input_pins[]; diff --git a/firmware/targets/f6/furi-hal/furi-hal-rfid.c b/firmware/targets/f6/furi-hal/furi-hal-rfid.c index 514e5f34..4990c5a9 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-rfid.c +++ b/firmware/targets/f6/furi-hal/furi-hal-rfid.c @@ -2,6 +2,8 @@ #include #include +#include + #define LFRFID_READ_TIM htim1 #define LFRFID_READ_CHANNEL TIM_CHANNEL_1 #define LFRFID_EMULATE_TIM htim2 @@ -216,7 +218,11 @@ void furi_hal_rfid_tim_emulate_stop() { void furi_hal_rfid_tim_reset() { HAL_TIM_Base_DeInit(&LFRFID_READ_TIM); + LL_TIM_DeInit(TIM1); + LL_APB2_GRP1_DisableClock(LL_APB2_GRP1_PERIPH_TIM1); HAL_TIM_Base_DeInit(&LFRFID_EMULATE_TIM); + LL_TIM_DeInit(TIM2); + LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_TIM2); } bool furi_hal_rfid_is_tim_emulate(TIM_HandleTypeDef* hw) { @@ -275,4 +281,4 @@ void furi_hal_rfid_change_read_config(float freq, float duty_cycle) { uint32_t period = (uint32_t)((SystemCoreClock) / freq) - 1; furi_hal_rfid_set_read_period(period); furi_hal_rfid_set_read_pulse(period * duty_cycle); -} \ No newline at end of file +} diff --git a/firmware/targets/f6/furi-hal/furi-hal-subghz.c b/firmware/targets/f6/furi-hal/furi-hal-subghz.c index 0b1b7b01..679eea74 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-subghz.c +++ b/firmware/targets/f6/furi-hal/furi-hal-subghz.c @@ -11,14 +11,14 @@ static volatile SubGhzState furi_hal_subghz_state = SubGhzStateInit; -static const uint8_t furi_hal_subghz_preset_ook_async_regs[][2] = { +static const uint8_t furi_hal_subghz_preset_ook_270khz_async_regs[][2] = { // https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz-group/sub-1-ghz/f/sub-1-ghz-forum/382066/cc1101---don-t-know-the-correct-registers-configuration /* GPIO GD0 */ { CC1101_IOCFG0, 0x0D }, // GD0 as async serial data output/input /* FIFO and internals */ - { CC1101_FIFOTHR, 0x47 }, // The only important bit is ADC_RETENTION + { CC1101_FIFOTHR, 0x47 }, // The only important bit is ADC_RETENTION, FIFO Tx=33 Rx=32 /* Packet engine */ { CC1101_PKTCTRL0, 0x32 }, // Async, continious, no whitening @@ -66,6 +66,116 @@ static const uint8_t furi_hal_subghz_preset_ook_async_regs[][2] = { { 0, 0 }, }; +static const uint8_t furi_hal_subghz_preset_ook_650khz_async_regs[][2] = { + // https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz-group/sub-1-ghz/f/sub-1-ghz-forum/382066/cc1101---don-t-know-the-correct-registers-configuration + + /* GPIO GD0 */ + { CC1101_IOCFG0, 0x0D }, // GD0 as async serial data output/input + + /* FIFO and internals */ + { CC1101_FIFOTHR, 0x07 }, // The only important bit is ADC_RETENTION + + /* Packet engine */ + { CC1101_PKTCTRL0, 0x32 }, // Async, continious, no whitening + + /* Frequency Synthesizer Control */ + { CC1101_FSCTRL1, 0x06 }, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz + + // Modem Configuration + { CC1101_MDMCFG0, 0x00 }, // Channel spacing is 25kHz + { CC1101_MDMCFG1, 0x00 }, // Channel spacing is 25kHz + { CC1101_MDMCFG2, 0x30 }, // Format ASK/OOK, No preamble/sync + { CC1101_MDMCFG3, 0x32 }, // Data rate is 3.79372 kBaud + { CC1101_MDMCFG4, 0x17 }, // Rx BW filter is 650.000kHz + + /* Main Radio Control State Machine */ + { CC1101_MCSM0, 0x18 }, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us) + + /* Frequency Offset Compensation Configuration */ + { CC1101_FOCCFG, 0x18 }, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off + + /* Automatic Gain Control */ + { CC1101_AGCTRL0, 0x40 }, // 01 - Low hysteresis, small asymmetric dead zone, medium gain; 00 - 8 samples agc; 00 - Normal AGC, 00 - 4dB boundary + { CC1101_AGCTRL1, 0x00 }, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET + { CC1101_AGCTRL2, 0x03 }, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB + + /* Wake on radio and timeouts control */ + { CC1101_WORCTRL, 0xFB }, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours + + /* Frontend configuration */ + { CC1101_FREND0, 0x11 }, // Adjusts current TX LO buffer + high is PATABLE[1] + { CC1101_FREND1, 0xB6 }, // + + /* Frequency Synthesizer Calibration, valid for 433.92 */ + { CC1101_FSCAL3, 0xE9 }, + { CC1101_FSCAL2, 0x2A }, + { CC1101_FSCAL1, 0x00 }, + { CC1101_FSCAL0, 0x1F }, + + /* Magic f4ckery */ + { CC1101_TEST2, 0x88 }, + { CC1101_TEST1, 0x31 }, + { CC1101_TEST0, 0x09 }, // VCO selection calibration stage is disabled + + /* End */ + { 0, 0 }, +}; +static const uint8_t furi_hal_subghz_preset_2fsk_async_regs[][2] = { + // https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz-group/sub-1-ghz/f/sub-1-ghz-forum/382066/cc1101---don-t-know-the-correct-registers-configuration + + /* GPIO GD0 */ + { CC1101_IOCFG0, 0x0D }, // GD0 as async serial data output/input + + /* FIFO and internals */ + { CC1101_FIFOTHR, 0x47 }, // The only important bit is ADC_RETENTION + + /* Packet engine */ + { CC1101_PKTCTRL0, 0x32 }, // Async, continious, no whitening + + /* Frequency Synthesizer Control */ + { CC1101_FSCTRL1, 0x06 }, // IF = (26*10^6) / (2^10) * 0x06 = 152343.75Hz + + // Modem Configuration + { CC1101_MDMCFG0, 0xF8 }, + { CC1101_MDMCFG1, 0x00 }, // No preamble/sync + { CC1101_MDMCFG2, 0x80 }, // Format 2-FSK/FM, No preamble/sync, Disable (current optimized) + { CC1101_MDMCFG3, 0x83 }, // Data rate is 9.59587 kBaud + { CC1101_MDMCFG4, 0x88 }, // Rx BW filter is 203.125000kHz + + { CC1101_DEVIATN, 0x14}, //Deviation 4.760742 khz + + /* Main Radio Control State Machine */ + { CC1101_MCSM0, 0x18 }, // Autocalibrate on idle-to-rx/tx, PO_TIMEOUT is 64 cycles(149-155us) + + /* Frequency Offset Compensation Configuration */ + { CC1101_FOCCFG, 0x18 }, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off + + /* Automatic Gain Control */ + { CC1101_AGCTRL0, 0x40 }, // 01 - Low hysteresis, small asymmetric dead zone, medium gain; 00 - 8 samples agc; 00 - Normal AGC, 00 - 4dB boundary + { CC1101_AGCTRL1, 0x00 }, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET + { CC1101_AGCTRL2, 0x03 }, // 00 - DVGA all; 000 - MAX LNA+LNA2; 011 - MAIN_TARGET 24 dB + + /* Wake on radio and timeouts control */ + { CC1101_WORCTRL, 0xFB }, // WOR_RES is 2^15 periods (0.91 - 0.94 s) 16.5 - 17.2 hours + + /* Frontend configuration */ + { CC1101_FREND0, 0x10 }, // Adjusts current TX LO buffer + { CC1101_FREND1, 0xB6 }, // + + /* Frequency Synthesizer Calibration, valid for 433.92 */ + { CC1101_FSCAL3, 0xE9 }, + { CC1101_FSCAL2, 0x2A }, + { CC1101_FSCAL1, 0x00 }, + { CC1101_FSCAL0, 0x1F }, + + /* Magic f4ckery */ + { CC1101_TEST2, 0x81 }, // FIFOTHR ADC_RETENTION=1 matched value + { CC1101_TEST1, 0x35 }, // FIFOTHR ADC_RETENTION=1 matched value + { CC1101_TEST0, 0x09 }, // VCO selection calibration stage is disabled + + /* End */ + { 0, 0 }, +}; static const uint8_t furi_hal_subghz_preset_ook_async_patable[8] = { 0x00, 0xC0, // 10dBm 0xC0, 7dBm 0xC8, 5dBm 0x84, 0dBm 0x60, -10dBm 0x34, -15dBm 0x1D, -20dBm 0x0E, -30dBm 0x12 @@ -76,6 +186,16 @@ static const uint8_t furi_hal_subghz_preset_ook_async_patable[8] = { 0x00, 0x00 }; +static const uint8_t furi_hal_subghz_preset_2fsk_async_patable[8] = { + 0xC0, // 10dBm 0xC0, 7dBm 0xC8, 5dBm 0x84, 0dBm 0x60, -10dBm 0x34, -15dBm 0x1D, -20dBm 0x0E, -30dBm 0x12 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 +}; void furi_hal_subghz_init() { furi_assert(furi_hal_subghz_state == SubGhzStateInit); @@ -143,10 +263,16 @@ void furi_hal_subghz_dump_state() { } void furi_hal_subghz_load_preset(FuriHalSubGhzPreset preset) { - if(preset == FuriHalSubGhzPresetOokAsync) { - furi_hal_subghz_load_registers(furi_hal_subghz_preset_ook_async_regs); + if(preset == FuriHalSubGhzPresetOok650Async) { + furi_hal_subghz_load_registers(furi_hal_subghz_preset_ook_650khz_async_regs); furi_hal_subghz_load_patable(furi_hal_subghz_preset_ook_async_patable); - } else { + } else if(preset == FuriHalSubGhzPresetOok270Async){ + furi_hal_subghz_load_registers(furi_hal_subghz_preset_ook_270khz_async_regs); + furi_hal_subghz_load_patable(furi_hal_subghz_preset_ook_async_patable); + } else if(preset == FuriHalSubGhzPreset2FSKAsync){ + furi_hal_subghz_load_registers(furi_hal_subghz_preset_2fsk_async_regs); + furi_hal_subghz_load_patable(furi_hal_subghz_preset_2fsk_async_patable); + }else { furi_check(0); } } @@ -273,6 +399,11 @@ uint32_t furi_hal_subghz_set_frequency(uint32_t value) { uint32_t real_frequency = cc1101_set_frequency(device, value); cc1101_calibrate(device); + while(true) { + CC1101Status status = cc1101_get_status(device); + if (status.STATE == CC1101StateIDLE) break; + } + furi_hal_spi_device_return(device); return real_frequency; diff --git a/firmware/targets/f6/furi-hal/furi-hal-vcp.c b/firmware/targets/f6/furi-hal/furi-hal-vcp.c index 9079a5c8..88de32b5 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-vcp.c +++ b/firmware/targets/f6/furi-hal/furi-hal-vcp.c @@ -1,15 +1,20 @@ -#include -#include +#include + #include +#include #include -#define FURI_HAL_VCP_RX_BUFFER_SIZE 600 +#define FURI_HAL_VCP_RX_BUFFER_SIZE (APP_RX_DATA_SIZE * 5) + +extern USBD_HandleTypeDef hUsbDeviceFS; typedef struct { + volatile bool connected; + StreamBufferHandle_t rx_stream; + volatile bool rx_stream_full; + osSemaphoreId_t tx_semaphore; - volatile bool alive; - volatile bool underrun; } FuriHalVcp; static FuriHalVcp* furi_hal_vcp = NULL; @@ -17,66 +22,31 @@ static FuriHalVcp* furi_hal_vcp = NULL; static const uint8_t ascii_soh = 0x01; static const uint8_t ascii_eot = 0x04; -void _furi_hal_vcp_init(); -void _furi_hal_vcp_deinit(); -void _furi_hal_vcp_control_line(uint8_t state); -void _furi_hal_vcp_rx_callback(const uint8_t* buffer, size_t size); -void _furi_hal_vcp_tx_complete(size_t size); - void furi_hal_vcp_init() { furi_hal_vcp = furi_alloc(sizeof(FuriHalVcp)); + furi_hal_vcp->connected = false; + furi_hal_vcp->rx_stream = xStreamBufferCreate(FURI_HAL_VCP_RX_BUFFER_SIZE, 1); + furi_hal_vcp->rx_stream_full = false; + furi_hal_vcp->tx_semaphore = osSemaphoreNew(1, 1, NULL); - furi_hal_vcp->alive = false; - furi_hal_vcp->underrun = false; + FURI_LOG_I("FuriHalVcp", "Init OK"); } -void _furi_hal_vcp_init() { - osSemaphoreRelease(furi_hal_vcp->tx_semaphore); -} - -void _furi_hal_vcp_deinit() { - furi_hal_vcp->alive = false; - osSemaphoreRelease(furi_hal_vcp->tx_semaphore); -} - -void _furi_hal_vcp_control_line(uint8_t state) { - // bit 0: DTR state, bit 1: RTS state - // bool dtr = state & 0b01; - bool dtr = state & 0b1; - - if (dtr) { - if (!furi_hal_vcp->alive) { - furi_hal_vcp->alive = true; - _furi_hal_vcp_rx_callback(&ascii_soh, 1); // SOH - } - } else { - if (furi_hal_vcp->alive) { - _furi_hal_vcp_rx_callback(&ascii_eot, 1); // EOT - furi_hal_vcp->alive = false; - } - } - - osSemaphoreRelease(furi_hal_vcp->tx_semaphore); -} - -void _furi_hal_vcp_rx_callback(const uint8_t* buffer, size_t size) { - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - size_t ret = xStreamBufferSendFromISR(furi_hal_vcp->rx_stream, buffer, size, &xHigherPriorityTaskWoken); - if (ret != size) { - furi_hal_vcp->underrun = true; - } - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); -} - -void _furi_hal_vcp_tx_complete(size_t size) { - osSemaphoreRelease(furi_hal_vcp->tx_semaphore); -} - size_t furi_hal_vcp_rx(uint8_t* buffer, size_t size) { furi_assert(furi_hal_vcp); - return xStreamBufferReceive(furi_hal_vcp->rx_stream, buffer, size, portMAX_DELAY); + + size_t received = xStreamBufferReceive(furi_hal_vcp->rx_stream, buffer, size, portMAX_DELAY); + + if(furi_hal_vcp->rx_stream_full + &&xStreamBufferSpacesAvailable(furi_hal_vcp->rx_stream) >= APP_RX_DATA_SIZE) { + furi_hal_vcp->rx_stream_full = false; + // data accepted, start waiting for next packet + USBD_CDC_ReceivePacket(&hUsbDeviceFS); + } + + return received; } size_t furi_hal_vcp_rx_with_timeout(uint8_t* buffer, size_t size, uint32_t timeout) { @@ -87,8 +57,10 @@ size_t furi_hal_vcp_rx_with_timeout(uint8_t* buffer, size_t size, uint32_t timeo void furi_hal_vcp_tx(const uint8_t* buffer, size_t size) { furi_assert(furi_hal_vcp); - while (size > 0 && furi_hal_vcp->alive) { + while (size > 0 && furi_hal_vcp->connected) { furi_check(osSemaphoreAcquire(furi_hal_vcp->tx_semaphore, osWaitForever) == osOK); + if (!furi_hal_vcp->connected) + break; size_t batch_size = size; if (batch_size > APP_TX_DATA_SIZE) { @@ -99,8 +71,58 @@ void furi_hal_vcp_tx(const uint8_t* buffer, size_t size) { size -= batch_size; buffer += batch_size; } else { - // Shouldn't be there - osDelay(100); + FURI_LOG_E("FuriHalVcp", "CDC_Transmit_FS failed"); + osDelay(50); } } } + +void furi_hal_vcp_on_usb_resume() { + osSemaphoreRelease(furi_hal_vcp->tx_semaphore); +} + +void furi_hal_vcp_on_usb_suspend() { + if (furi_hal_vcp->connected) { + furi_hal_vcp->connected = false; + osSemaphoreRelease(furi_hal_vcp->tx_semaphore); + } +} + +void furi_hal_vcp_on_cdc_control_line(uint8_t state) { + // bit 0: DTR state, bit 1: RTS state + // bool dtr = state & 0b01; + bool dtr = state & 0b1; + + if (dtr) { + if (!furi_hal_vcp->connected) { + furi_hal_vcp->connected = true; + furi_hal_vcp_on_cdc_rx(&ascii_soh, 1); // SOH + } + } else { + if (furi_hal_vcp->connected) { + furi_hal_vcp_on_cdc_rx(&ascii_eot, 1); // EOT + furi_hal_vcp->connected = false; + } + } + + osSemaphoreRelease(furi_hal_vcp->tx_semaphore); +} + +void furi_hal_vcp_on_cdc_rx(const uint8_t* buffer, size_t size) { + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + size_t ret = xStreamBufferSendFromISR(furi_hal_vcp->rx_stream, buffer, size, &xHigherPriorityTaskWoken); + furi_check(ret == size); + + if (xStreamBufferSpacesAvailable(furi_hal_vcp->rx_stream) >= APP_RX_DATA_SIZE) { + USBD_CDC_ReceivePacket(&hUsbDeviceFS); + } else { + furi_hal_vcp->rx_stream_full = true; + } + + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); +} + +void furi_hal_vcp_on_cdc_tx_complete(size_t size) { + osSemaphoreRelease(furi_hal_vcp->tx_semaphore); +} + diff --git a/firmware/targets/f6/furi-hal/furi-hal-vcp_i.h b/firmware/targets/f6/furi-hal/furi-hal-vcp_i.h new file mode 100644 index 00000000..05ddc6ad --- /dev/null +++ b/firmware/targets/f6/furi-hal/furi-hal-vcp_i.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +void furi_hal_vcp_on_usb_resume(); + +void furi_hal_vcp_on_usb_suspend(); + +void furi_hal_vcp_on_cdc_control_line(uint8_t state); + +void furi_hal_vcp_on_cdc_rx(const uint8_t* buffer, size_t size); + +void furi_hal_vcp_on_cdc_tx_complete(size_t size); diff --git a/firmware/targets/f6/target.mk b/firmware/targets/f6/target.mk index f26d768d..558074c3 100644 --- a/firmware/targets/f6/target.mk +++ b/firmware/targets/f6/target.mk @@ -14,20 +14,6 @@ FLASH_ADDRESS = 0x08000000 CFLAGS += -DNO_BOOTLOADER endif -FURI_HAL_OS_DEBUG ?= 0 -ifeq ($(FURI_HAL_OS_DEBUG), 1) -CFLAGS += -DFURI_HAL_OS_DEBUG -endif - -FURI_HAL_SUBGHZ_TX_GPIO ?= 0 -ifneq ($(FURI_HAL_SUBGHZ_TX_GPIO), 0) -CFLAGS += -DFURI_HAL_SUBGHZ_TX_GPIO=$(FURI_HAL_SUBGHZ_TX_GPIO) -endif - -ifeq ($(INVERT_RFID_IN), 1) -CFLAGS += -DINVERT_RFID_IN -endif - OPENOCD_OPTS = -f interface/stlink.cfg -c "transport select hla_swd" -f ../debug/stm32wbx.cfg -c "stm32wbx.cpu configure -rtos auto" -c "init" BOOT_CFLAGS = -DBOOT_ADDRESS=$(BOOT_ADDRESS) -DFW_ADDRESS=$(FW_ADDRESS) -DOS_OFFSET=$(OS_OFFSET) MCU_FLAGS = -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard @@ -39,10 +25,22 @@ CPPFLAGS += -fno-rtti -fno-use-cxa-atexit -fno-exceptions LDFLAGS += -Wl,--start-group -lstdc++ -lsupc++ -Wl,--end-group MXPROJECT_DIR = $(TARGET_DIR) -FURI_HAL_DIR = $(TARGET_DIR) -CUBE_DIR = ../lib/STM32CubeWB -C_SOURCES += \ +# Entry Point +ASM_SOURCES += $(MXPROJECT_DIR)/startup_stm32wb55xx_cm4.s + +# STM32WB HAL +CUBE_DIR = ../lib/STM32CubeWB +CFLAGS += \ + -DUSE_FULL_LL_DRIVER \ + -DUSE_HAL_DRIVER \ + -DHAVE_FREERTOS +CFLAGS += \ + -I$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Inc \ + -I$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Inc/Legacy \ + -I$(CUBE_DIR)/Drivers/CMSIS/Device/ST/STM32WBxx/Include \ + -I$(CUBE_DIR)/Drivers/CMSIS/Include +C_SOURCES += \ $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal.c \ $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_comp.c \ $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_cortex.c \ @@ -75,7 +73,14 @@ C_SOURCES += \ $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_tim.c \ $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_usart.c \ $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_usb.c \ - $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_utils.c \ + $(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_utils.c + +# FreeRTOS +CFLAGS += \ + -I$(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/include \ + -I$(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2 \ + -I$(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F +C_SOURCES += \ $(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/croutine.c \ $(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/event_groups.c \ $(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/list.c \ @@ -84,46 +89,11 @@ C_SOURCES += \ $(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/tasks.c \ $(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/timers.c \ $(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.c \ - $(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c \ - $(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c \ - $(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c \ - $(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c \ - $(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c \ - $(wildcard $(MXPROJECT_DIR)/Src/*.c) \ - $(wildcard $(MXPROJECT_DIR)/Src/fatfs/*.c) \ - $(wildcard $(FURI_HAL_DIR)/furi-hal/*.c) - -ASM_SOURCES += $(MXPROJECT_DIR)/startup_stm32wb55xx_cm4.s - -# Common -CFLAGS += \ - -DUSE_FULL_LL_DRIVER \ - -DUSE_HAL_DRIVER \ - -DHAVE_FREERTOS - -ifeq ($(NO_BOOTLOADER), 1) -LDFLAGS += -T$(MXPROJECT_DIR)/stm32wb55xx_flash_cm4_no_boot.ld -else -LDFLAGS += -T$(MXPROJECT_DIR)/stm32wb55xx_flash_cm4_boot.ld -endif + $(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c +# BLE glue CFLAGS += \ - -I$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Inc \ - -I$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Inc/Legacy \ - -I$(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/include \ - -I$(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2 \ - -I$(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM4F \ - -I$(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Core/Inc \ - -I$(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc \ - -I$(CUBE_DIR)/Drivers/CMSIS/Device/ST/STM32WBxx/Include \ - -I$(CUBE_DIR)/Drivers/CMSIS/Include \ - -I$(MXPROJECT_DIR)/Inc \ - -I$(MXPROJECT_DIR)/Src/fatfs \ - -I$(FURI_HAL_DIR)/furi-hal \ - -# Ble glue -CFLAGS += -I$(TARGET_DIR)/ble-glue \ - -I$(CUBE_DIR)/Utilities/lpm/tiny_lpm \ + -I$(TARGET_DIR)/ble-glue \ -I$(CUBE_DIR)/Middlewares/ST/STM32_WPAN \ -I$(CUBE_DIR)/Middlewares/ST/STM32_WPAN/ble \ -I$(CUBE_DIR)/Middlewares/ST/STM32_WPAN/ble/core \ @@ -132,8 +102,7 @@ CFLAGS += -I$(TARGET_DIR)/ble-glue \ -I$(CUBE_DIR)/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread \ -I$(CUBE_DIR)/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/tl \ -I$(CUBE_DIR)/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/shci - -C_SOURCES += \ +C_SOURCES += \ $(wildcard $(TARGET_DIR)/ble-glue/*.c) \ $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/utilities/otp.c \ $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/utilities/stm_list.c \ @@ -153,4 +122,50 @@ C_SOURCES += \ $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/tl/shci_tl_if.c \ $(CUBE_DIR)/Middlewares/ST/STM32_WPAN/interface/patterns/ble_thread/shci/shci.c +# USB glue +CFLAGS += \ + -I$(TARGET_DIR)/usb-glue \ + -I$(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Core/Inc \ + -I$(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc +C_SOURCES += \ + $(wildcard $(TARGET_DIR)/usb-glue/*.c) \ + $(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c \ + $(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c \ + $(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c \ + $(CUBE_DIR)/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c + +# Furi HAL +FURI_HAL_OS_DEBUG ?= 0 +ifeq ($(FURI_HAL_OS_DEBUG), 1) +CFLAGS += -DFURI_HAL_OS_DEBUG +endif + +FURI_HAL_SUBGHZ_TX_GPIO ?= 0 +ifneq ($(FURI_HAL_SUBGHZ_TX_GPIO), 0) +CFLAGS += -DFURI_HAL_SUBGHZ_TX_GPIO=$(FURI_HAL_SUBGHZ_TX_GPIO) +endif + +ifeq ($(INVERT_RFID_IN), 1) +CFLAGS += -DINVERT_RFID_IN +endif + +FURI_HAL_DIR = $(TARGET_DIR)/furi-hal +CFLAGS += -I$(FURI_HAL_DIR) +C_SOURCES += $(wildcard $(FURI_HAL_DIR)/*.c) + +# Other +CFLAGS += \ + -I$(MXPROJECT_DIR)/Inc \ + -I$(MXPROJECT_DIR)/Src/fatfs +C_SOURCES += \ + $(wildcard $(MXPROJECT_DIR)/Src/*.c) \ + $(wildcard $(MXPROJECT_DIR)/Src/fatfs/*.c) + +# Linker options +ifeq ($(NO_BOOTLOADER), 1) +LDFLAGS += -T$(MXPROJECT_DIR)/stm32wb55xx_flash_cm4_no_boot.ld +else +LDFLAGS += -T$(MXPROJECT_DIR)/stm32wb55xx_flash_cm4_boot.ld +endif + SVD_FILE = ../debug/STM32WB55_CM4.svd diff --git a/firmware/targets/f6/usb-glue/usb_device.c b/firmware/targets/f6/usb-glue/usb_device.c new file mode 100644 index 00000000..84e9143d --- /dev/null +++ b/firmware/targets/f6/usb-glue/usb_device.c @@ -0,0 +1,34 @@ +#include "usb_device.h" + +#include "stm32wbxx.h" +#include "stm32wbxx_hal.h" + +#include "usbd_def.h" +#include "usbd_core.h" +#include "usbd_desc.h" +#include "usbd_cdc.h" +#include "usbd_cdc_if.h" + +extern void Error_Handler(void); + +/* USB Device Core handle declaration. */ +USBD_HandleTypeDef hUsbDeviceFS; + +extern USBD_DescriptorsTypeDef CDC_Desc; + +/** Init USB device Library, add supported class and start the library */ +void MX_USB_Device_Init(void) { + /* Init Device Library, add supported class and start the library. */ + if (USBD_Init(&hUsbDeviceFS, &CDC_Desc, DEVICE_FS) != USBD_OK) { + Error_Handler(); + } + if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC) != USBD_OK) { + Error_Handler(); + } + if (USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS) != USBD_OK) { + Error_Handler(); + } + if (USBD_Start(&hUsbDeviceFS) != USBD_OK) { + Error_Handler(); + } +} diff --git a/firmware/targets/f6/usb-glue/usb_device.h b/firmware/targets/f6/usb-glue/usb_device.h new file mode 100644 index 00000000..7d80e348 --- /dev/null +++ b/firmware/targets/f6/usb-glue/usb_device.h @@ -0,0 +1,11 @@ +#pragma once + +#ifdef __cplusplus + extern "C" { +#endif + +void MX_USB_Device_Init(); + +#ifdef __cplusplus +} +#endif diff --git a/firmware/targets/f6/usb-glue/usbd_cdc_if.c b/firmware/targets/f6/usb-glue/usbd_cdc_if.c new file mode 100644 index 00000000..6b905c84 --- /dev/null +++ b/firmware/targets/f6/usb-glue/usbd_cdc_if.c @@ -0,0 +1,142 @@ +#include "usbd_cdc_if.h" +#include + +extern USBD_HandleTypeDef hUsbDeviceFS; + +static int8_t CDC_Init_FS(void); +static int8_t CDC_DeInit_FS(void); +static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length); +static int8_t CDC_Receive_FS(uint8_t* pbuf, uint32_t *Len); +static int8_t CDC_TransmitCplt_FS(uint8_t *pbuf, uint32_t *Len, uint8_t epnum); + +USBD_CDC_ItfTypeDef USBD_Interface_fops_FS = +{ + CDC_Init_FS, + CDC_DeInit_FS, + CDC_Control_FS, + CDC_Receive_FS, + CDC_TransmitCplt_FS +}; + +uint8_t UserRxBufferFS[APP_RX_DATA_SIZE]; +uint8_t UserTxBufferFS[APP_TX_DATA_SIZE]; + +/** Initializes the CDC media low layer over the FS USB IP + * @retval USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_Init_FS(void) { + /* Set Application Buffers */ + USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, 0); + USBD_CDC_SetRxBuffer(&hUsbDeviceFS, UserRxBufferFS); + return (USBD_OK); +} + +/** + * @brief DeInitializes the CDC media low layer + * @retval USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_DeInit_FS(void) { + return (USBD_OK); +} + +/** Manage the CDC class requests + * @param cmd: Command code + * @param pbuf: Buffer containing command data (request parameters) + * @param length: Number of data to be sent (in bytes) + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length) { + if (cmd == CDC_SEND_ENCAPSULATED_COMMAND) { + } else if (cmd == CDC_GET_ENCAPSULATED_RESPONSE) { + } else if (cmd == CDC_SET_COMM_FEATURE) { + } else if (cmd == CDC_GET_COMM_FEATURE) { + } else if (cmd == CDC_CLEAR_COMM_FEATURE) { + } else if (cmd == CDC_SET_LINE_CODING) { + /*******************************************************************************/ + /* Line Coding Structure */ + /*-----------------------------------------------------------------------------*/ + /* Offset | Field | Size | Value | Description */ + /* 0 | dwDTERate | 4 | Number |Data terminal rate, in bits per second*/ + /* 4 | bCharFormat | 1 | Number | Stop bits */ + /* 0 - 1 Stop bit */ + /* 1 - 1.5 Stop bits */ + /* 2 - 2 Stop bits */ + /* 5 | bParityType | 1 | Number | Parity */ + /* 0 - None */ + /* 1 - Odd */ + /* 2 - Even */ + /* 3 - Mark */ + /* 4 - Space */ + /* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */ + /*******************************************************************************/ + } else if (cmd == CDC_GET_LINE_CODING) { + } else if (cmd == CDC_SET_CONTROL_LINE_STATE) { + furi_hal_vcp_on_cdc_control_line(((USBD_SetupReqTypedef*)pbuf)->wValue); + } else if (cmd == CDC_SEND_BREAK) { + } else { + } + + return (USBD_OK); +} + +/** Data received over USB OUT endpoint are sent over CDC interface through this function. + * + * @note + * This function will issue a NAK packet on any OUT packet received on + * USB endpoint until exiting this function. If you exit this function + * before transfer is complete on CDC interface (ie. using DMA controller) + * it will result in receiving more data while previous ones are still + * not sent. + * + * @param Buf: Buffer of data to be received + * @param Len: Number of data received (in bytes) + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len) { + if (*Len) { + furi_hal_vcp_on_cdc_rx(Buf, *Len); + } else { + USBD_CDC_ReceivePacket(&hUsbDeviceFS); + } + + return (USBD_OK); +} + +/** CDC_Transmit_FS Data to send over USB IN endpoint are sent over CDC interface + * through this function. + * @param Buf: Buffer of data to be sent + * @param Len: Number of data to be sent (in bytes) + * @retval USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY + */ +uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len) +{ + uint8_t result = USBD_OK; + + USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData; + if (hcdc->TxState != 0){ + return USBD_BUSY; + } + memcpy(UserTxBufferFS, Buf, Len); + USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, Len); + result = USBD_CDC_TransmitPacket(&hUsbDeviceFS); + + return result; +} + +/** CDC_TransmitCplt_FS Data transmited callback + * + * @note + * This function is IN transfer complete callback used to inform user that + * the submitted Data is successfully sent over USB. + * + * @param Buf: Buffer of data to be received + * @param Len: Number of data received (in bytes) + * @retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL + */ +static int8_t CDC_TransmitCplt_FS(uint8_t *Buf, uint32_t *Len, uint8_t epnum) { + uint8_t result = USBD_OK; + + furi_hal_vcp_on_cdc_tx_complete(*Len); + + return result; +} diff --git a/firmware/targets/f6/usb-glue/usbd_cdc_if.h b/firmware/targets/f6/usb-glue/usbd_cdc_if.h new file mode 100644 index 00000000..fc0aefbe --- /dev/null +++ b/firmware/targets/f6/usb-glue/usbd_cdc_if.h @@ -0,0 +1,22 @@ +#pragma once + +#ifdef __cplusplus + extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_cdc.h" + +/* Define size for the receive and transmit buffer over CDC */ +/* It's up to user to redefine and/or remove those define */ +#define APP_RX_DATA_SIZE CDC_DATA_FS_MAX_PACKET_SIZE +#define APP_TX_DATA_SIZE CDC_DATA_FS_MAX_PACKET_SIZE + +/** CDC Interface callback. */ +extern USBD_CDC_ItfTypeDef USBD_Interface_fops_FS; + +uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len); + +#ifdef __cplusplus +} +#endif diff --git a/firmware/targets/f6/usb-glue/usbd_conf.c b/firmware/targets/f6/usb-glue/usbd_conf.c new file mode 100644 index 00000000..cbc137e5 --- /dev/null +++ b/firmware/targets/f6/usb-glue/usbd_conf.c @@ -0,0 +1,506 @@ +#include "stm32wbxx.h" +#include "stm32wbxx_hal.h" + +#include + +#include "usbd_def.h" +#include "usbd_core.h" +#include "usbd_cdc.h" + +PCD_HandleTypeDef hpcd_USB_FS; +void Error_Handler(void); + +static USBD_StatusTypeDef USBD_Get_USB_Status(HAL_StatusTypeDef hal_status); + +static void SystemClockConfig_Resume(void); + +void HAL_PCD_MspInit(PCD_HandleTypeDef* pcdHandle) { + GPIO_InitTypeDef GPIO_InitStruct = {0}; + if(pcdHandle->Instance==USB) { + __HAL_RCC_GPIOA_CLK_ENABLE(); + /**USB GPIO Configuration + PA11 ------> USB_DM + PA12 ------> USB_DP + */ + GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF10_USB; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* Peripheral clock enable */ + __HAL_RCC_USB_CLK_ENABLE(); + + /* Peripheral interrupt init */ + HAL_NVIC_SetPriority(USB_LP_IRQn, 5, 0); + HAL_NVIC_EnableIRQ(USB_LP_IRQn); + } +} + +void HAL_PCD_MspDeInit(PCD_HandleTypeDef* pcdHandle) { + if(pcdHandle->Instance==USB) { + /* Peripheral clock disable */ + __HAL_RCC_USB_CLK_DISABLE(); + + /**USB GPIO Configuration + PA11 ------> USB_DM + PA12 ------> USB_DP + */ + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12); + + /* Peripheral interrupt Deinit*/ + HAL_NVIC_DisableIRQ(USB_LP_IRQn); + } +} + +/** Setup stage callback + * @param hpcd: PCD handle + * @retval None + */ +void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd) { + USBD_LL_SetupStage((USBD_HandleTypeDef*)hpcd->pData, (uint8_t *)hpcd->Setup); +} + +/** Data Out stage callback. + * @param hpcd: PCD handle + * @param epnum: Endpoint number + * @retval None + */ +void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) { + USBD_LL_DataOutStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->OUT_ep[epnum].xfer_buff); +} + +/** Data In stage callback. + * @param hpcd: PCD handle + * @param epnum: Endpoint number + * @retval None + */ +void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) { + USBD_LL_DataInStage((USBD_HandleTypeDef*)hpcd->pData, epnum, hpcd->IN_ep[epnum].xfer_buff); +} + +/** SOF callback. + * @param hpcd: PCD handle + * @retval None + */ +void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) { + USBD_LL_SOF((USBD_HandleTypeDef*)hpcd->pData); +} + +/** Reset callback. + * @param hpcd: PCD handle + * @retval None + */ +void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd) { + USBD_SpeedTypeDef speed = USBD_SPEED_FULL; + + if ( hpcd->Init.speed != PCD_SPEED_FULL) { + Error_Handler(); + } + + /* Set Speed. */ + USBD_LL_SetSpeed((USBD_HandleTypeDef*)hpcd->pData, speed); + + /* Reset Device. */ + USBD_LL_Reset((USBD_HandleTypeDef*)hpcd->pData); +} + +/** Suspend callback. + * When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it) + * @param hpcd: PCD handle + * @retval None + */ +void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd) { + USBD_LL_Suspend((USBD_HandleTypeDef*)hpcd->pData); + + furi_hal_vcp_on_usb_suspend(); + + if (hpcd->Init.low_power_enable) { + /* Set SLEEPDEEP bit and SleepOnExit of Cortex System Control Register. */ + SCB->SCR |= (uint32_t)((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk)); + } +} + +/** Resume callback. + * When Low power mode is enabled the debug cannot be used (IAR, Keil doesn't support it) + * @param hpcd: PCD handle + * @retval None + */ +void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd) { + if (hpcd->Init.low_power_enable) { + /* Reset SLEEPDEEP bit of Cortex System Control Register. */ + SCB->SCR &= (uint32_t)~((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk)); + SystemClockConfig_Resume(); + } + + furi_hal_vcp_on_usb_resume(); + + USBD_LL_Resume((USBD_HandleTypeDef*)hpcd->pData); +} + +/** ISOOUTIncomplete callback. + * @param hpcd: PCD handle + * @param epnum: Endpoint number + * @retval None + */ +void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) { + USBD_LL_IsoOUTIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum); +} + +/** ISOINIncomplete callback. + * @param hpcd: PCD handle + * @param epnum: Endpoint number + * @retval None + */ +void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) { + USBD_LL_IsoINIncomplete((USBD_HandleTypeDef*)hpcd->pData, epnum); +} + +/** Connect callback. + * @param hpcd: PCD handle + * @retval None + */ +void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd) { + USBD_LL_DevConnected((USBD_HandleTypeDef*)hpcd->pData); +} + +/** Disconnect callback. + * @param hpcd: PCD handle + * @retval None + */ +void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd) { + USBD_LL_DevDisconnected((USBD_HandleTypeDef*)hpcd->pData); +} + +/** Initializes the low level portion of the device driver. + * @param pdev: Device handle + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev) { + /* Init USB Ip. */ + hpcd_USB_FS.pData = pdev; + + /* Link the driver to the stack. */ + pdev->pData = &hpcd_USB_FS; + + /* Enable USB power on Pwrctrl CR2 register. */ + HAL_PWREx_EnableVddUSB(); + + hpcd_USB_FS.Instance = USB; + hpcd_USB_FS.Init.dev_endpoints = 8; + hpcd_USB_FS.Init.speed = PCD_SPEED_FULL; + hpcd_USB_FS.Init.phy_itface = PCD_PHY_EMBEDDED; + hpcd_USB_FS.Init.Sof_enable = DISABLE; + hpcd_USB_FS.Init.low_power_enable = DISABLE; + hpcd_USB_FS.Init.lpm_enable = DISABLE; + hpcd_USB_FS.Init.battery_charging_enable = DISABLE; + + if (HAL_PCD_Init(&hpcd_USB_FS) != HAL_OK) { + Error_Handler(); + } + + HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x00 , PCD_SNG_BUF, 0x18); + HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x80 , PCD_SNG_BUF, 0x58); + + HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x81 , PCD_SNG_BUF, 0xC0); + HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x01 , PCD_SNG_BUF, 0x110); + HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x82 , PCD_SNG_BUF, 0x100); + + return USBD_OK; +} + +/** De-Initializes the low level portion of the device driver. + * @param pdev: Device handle + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_DeInit(USBD_HandleTypeDef *pdev) +{ + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_DeInit(pdev->pData); + + usb_status = USBD_Get_USB_Status(hal_status); + + return usb_status; +} + +/** Starts the low level portion of the device driver. + * @param pdev: Device handle + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_Start(USBD_HandleTypeDef *pdev) { + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_Start(pdev->pData); + + usb_status = USBD_Get_USB_Status(hal_status); + + return usb_status; +} + +/** Stops the low level portion of the device driver. + * @param pdev: Device handle + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_Stop(USBD_HandleTypeDef *pdev) { + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_Stop(pdev->pData); + + usb_status = USBD_Get_USB_Status(hal_status); + + return usb_status; +} + +/** Opens an endpoint of the low level driver. + * @param pdev: Device handle + * @param ep_addr: Endpoint number + * @param ep_type: Endpoint type + * @param ep_mps: Endpoint max packet size + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_OpenEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t ep_type, uint16_t ep_mps) { + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_EP_Open(pdev->pData, ep_addr, ep_mps, ep_type); + + usb_status = USBD_Get_USB_Status(hal_status); + + return usb_status; +} + +/** Closes an endpoint of the low level driver. + * @param pdev: Device handle + * @param ep_addr: Endpoint number + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_CloseEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_EP_Close(pdev->pData, ep_addr); + + usb_status = USBD_Get_USB_Status(hal_status); + + return usb_status; +} + +/** + * @brief Flushes an endpoint of the Low Level Driver. + * @param pdev: Device handle + * @param ep_addr: Endpoint number + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_FlushEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_EP_Flush(pdev->pData, ep_addr); + + usb_status = USBD_Get_USB_Status(hal_status); + + return usb_status; +} + +/** Sets a Stall condition on an endpoint of the Low Level Driver. + * @param pdev: Device handle + * @param ep_addr: Endpoint number + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_StallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_EP_SetStall(pdev->pData, ep_addr); + + usb_status = USBD_Get_USB_Status(hal_status); + + return usb_status; +} + +/** Clears a Stall condition on an endpoint of the Low Level Driver. + * @param pdev: Device handle + * @param ep_addr: Endpoint number + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_ClearStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_EP_ClrStall(pdev->pData, ep_addr); + + usb_status = USBD_Get_USB_Status(hal_status); + + return usb_status; +} + +/** Returns Stall condition. + * @param pdev: Device handle + * @param ep_addr: Endpoint number + * @retval Stall (1: Yes, 0: No) + */ +uint8_t USBD_LL_IsStallEP(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { + PCD_HandleTypeDef *hpcd = (PCD_HandleTypeDef*) pdev->pData; + + if((ep_addr & 0x80) == 0x80) + { + return hpcd->IN_ep[ep_addr & 0x7F].is_stall; + } + else + { + return hpcd->OUT_ep[ep_addr & 0x7F].is_stall; + } +} + +/** Assigns a USB address to the device. + * @param pdev: Device handle + * @param dev_addr: Device address + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_SetUSBAddress(USBD_HandleTypeDef *pdev, uint8_t dev_addr) { + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_SetAddress(pdev->pData, dev_addr); + + usb_status = USBD_Get_USB_Status(hal_status); + + return usb_status; +} + +/** Transmits data over an endpoint. + * @param pdev: Device handle + * @param ep_addr: Endpoint number + * @param pbuf: Pointer to data to be sent + * @param size: Data size + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_Transmit(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint32_t size) { + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_EP_Transmit(pdev->pData, ep_addr, pbuf, size); + + usb_status = USBD_Get_USB_Status(hal_status); + + return usb_status; +} + +/** Prepares an endpoint for reception. + * @param pdev: Device handle + * @param ep_addr: Endpoint number + * @param pbuf: Pointer to data to be received + * @param size: Data size + * @retval USBD status + */ +USBD_StatusTypeDef USBD_LL_PrepareReceive(USBD_HandleTypeDef *pdev, uint8_t ep_addr, uint8_t *pbuf, uint32_t size) { + HAL_StatusTypeDef hal_status = HAL_OK; + USBD_StatusTypeDef usb_status = USBD_OK; + + hal_status = HAL_PCD_EP_Receive(pdev->pData, ep_addr, pbuf, size); + + usb_status = USBD_Get_USB_Status(hal_status); + + return usb_status; +} + +/** Returns the last transfered packet size. + * @param pdev: Device handle + * @param ep_addr: Endpoint number + * @retval Recived Data Size + */ +uint32_t USBD_LL_GetRxDataSize(USBD_HandleTypeDef *pdev, uint8_t ep_addr) { + return HAL_PCD_EP_GetRxCount((PCD_HandleTypeDef*) pdev->pData, ep_addr); +} + +/** Send LPM message to user layer + * @param hpcd: PCD handle + * @param msg: LPM message + * @retval None + */ +void HAL_PCDEx_LPM_Callback(PCD_HandleTypeDef *hpcd, PCD_LPM_MsgTypeDef msg) { + switch (msg) { + case PCD_LPM_L0_ACTIVE: + if (hpcd->Init.low_power_enable) { + SystemClockConfig_Resume(); + /* Reset SLEEPDEEP bit of Cortex System Control Register. */ + SCB->SCR &= (uint32_t)~((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk)); + } + USBD_LL_Resume(hpcd->pData); + break; + + case PCD_LPM_L1_ACTIVE: + USBD_LL_Suspend(hpcd->pData); + + /* Enter in STOP mode. */ + if (hpcd->Init.low_power_enable) { + /* Set SLEEPDEEP bit and SleepOnExit of Cortex System Control Register. */ + SCB->SCR |= (uint32_t)((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk)); + } + break; + } +} + +/** Delays routine for the USB Device Library. + * @param Delay: Delay in ms + * @retval None + */ +void USBD_LL_Delay(uint32_t Delay) { + HAL_Delay(Delay); +} + +/** Static single allocation. + * @param size: Size of allocated memory + * @retval None + */ +void *USBD_static_malloc(uint32_t size) { + static uint32_t mem[(sizeof(USBD_CDC_HandleTypeDef)/4)+1];/* On 32-bit boundary */ + return mem; +} + +/** Dummy memory free + * @param p: Pointer to allocated memory address + * @retval None + */ +void USBD_static_free(void *p) { +} + +/** Configures system clock after wake-up from USB resume callBack: + * enable HSI, PLL and select PLL as system clock source. + * @retval None + */ +static void SystemClockConfig_Resume(void) { +} + +/** Retuns the USB status depending on the HAL status: + * @param hal_status: HAL status + * @retval USB status + */ +USBD_StatusTypeDef USBD_Get_USB_Status(HAL_StatusTypeDef hal_status) { + USBD_StatusTypeDef usb_status = USBD_OK; + + switch (hal_status) + { + case HAL_OK : + usb_status = USBD_OK; + break; + case HAL_ERROR : + usb_status = USBD_FAIL; + break; + case HAL_BUSY : + usb_status = USBD_BUSY; + break; + case HAL_TIMEOUT : + usb_status = USBD_FAIL; + break; + default : + usb_status = USBD_FAIL; + break; + } + return usb_status; +} diff --git a/firmware/targets/f6/usb-glue/usbd_conf.h b/firmware/targets/f6/usb-glue/usbd_conf.h new file mode 100644 index 00000000..9e2a86f2 --- /dev/null +++ b/firmware/targets/f6/usb-glue/usbd_conf.h @@ -0,0 +1,73 @@ +#pragma once + +#include +#include +#include +#include "stm32wbxx.h" +#include "stm32wbxx_hal.h" + +#ifdef __cplusplus + extern "C" { +#endif + +#define USBD_MAX_NUM_INTERFACES 1U +#define USBD_MAX_NUM_CONFIGURATION 1U +#define USBD_MAX_STR_DESC_SIZ 512U +#define USBD_DEBUG_LEVEL 0U +#define USBD_LPM_ENABLED 0U +#define USBD_SELF_POWERED 0U + +/****************************************/ +/* #define for FS and HS identification */ +#define DEVICE_FS 0 + +/* Memory management macros */ + +/** Alias for memory allocation. */ +#define USBD_malloc (void *)USBD_static_malloc + +/** Alias for memory release. */ +#define USBD_free USBD_static_free + +/** Alias for memory set. */ +#define USBD_memset memset + +/** Alias for memory copy. */ +#define USBD_memcpy memcpy + +/** Alias for delay. */ +#define USBD_Delay HAL_Delay + +/* DEBUG macros */ + +#if (USBD_DEBUG_LEVEL > 0) +#define USBD_UsrLog(...) printf(__VA_ARGS__);\ + printf("\n"); +#else +#define USBD_UsrLog(...) +#endif + +#if (USBD_DEBUG_LEVEL > 1) + +#define USBD_ErrLog(...) printf("ERROR: ") ;\ + printf(__VA_ARGS__);\ + printf("\n"); +#else +#define USBD_ErrLog(...) +#endif + +#if (USBD_DEBUG_LEVEL > 2) +#define USBD_DbgLog(...) printf("DEBUG : ") ;\ + printf(__VA_ARGS__);\ + printf("\n"); +#else +#define USBD_DbgLog(...) +#endif + +void *USBD_static_malloc(uint32_t size); +void USBD_static_free(void *p); + + +#ifdef __cplusplus +} +#endif diff --git a/firmware/targets/f6/usb-glue/usbd_desc.c b/firmware/targets/f6/usb-glue/usbd_desc.c new file mode 100644 index 00000000..96cc2cda --- /dev/null +++ b/firmware/targets/f6/usb-glue/usbd_desc.c @@ -0,0 +1,206 @@ +#include "usbd_core.h" +#include "usbd_desc.h" +#include "usbd_conf.h" +#include "furi-hal-version.h" + +#define USBD_VID 1155 +#define USBD_LANGID_STRING 1033 +#define USBD_MANUFACTURER_STRING "Flipper Devices Inc." +#define USBD_PID 22336 +#define USBD_CONFIGURATION_STRING "CDC Config" +#define USBD_INTERFACE_STRING "CDC Interface" + +static void Get_SerialNum(void); +static void IntToUnicode(uint32_t value, uint8_t * pbuf, uint8_t len); + +uint8_t* USBD_CDC_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +uint8_t* USBD_CDC_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +uint8_t* USBD_CDC_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +uint8_t* USBD_CDC_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +uint8_t* USBD_CDC_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +uint8_t* USBD_CDC_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +uint8_t* USBD_CDC_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); + +USBD_DescriptorsTypeDef CDC_Desc = { + USBD_CDC_DeviceDescriptor, + USBD_CDC_LangIDStrDescriptor, + USBD_CDC_ManufacturerStrDescriptor, + USBD_CDC_ProductStrDescriptor, + USBD_CDC_SerialStrDescriptor, + USBD_CDC_ConfigStrDescriptor, + USBD_CDC_InterfaceStrDescriptor +}; + +/** USB standard device descriptor. */ +__ALIGN_BEGIN uint8_t USBD_CDC_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = { + 0x12, /*bLength */ + USB_DESC_TYPE_DEVICE, /*bDescriptorType*/ + 0x00, /*bcdUSB */ + 0x02, + 0x02, /*bDeviceClass*/ + 0x02, /*bDeviceSubClass*/ + 0x00, /*bDeviceProtocol*/ + USB_MAX_EP0_SIZE, /*bMaxPacketSize*/ + LOBYTE(USBD_VID), /*idVendor*/ + HIBYTE(USBD_VID), /*idVendor*/ + LOBYTE(USBD_PID), /*idProduct*/ + HIBYTE(USBD_PID), /*idProduct*/ + 0x00, /*bcdDevice rel. 2.00*/ + 0x02, + USBD_IDX_MFC_STR, /*Index of manufacturer string*/ + USBD_IDX_PRODUCT_STR, /*Index of product string*/ + USBD_IDX_SERIAL_STR, /*Index of serial number string*/ + USBD_MAX_NUM_CONFIGURATION /*bNumConfigurations*/ +}; + +/* USB_DeviceDescriptor */ + +/** USB lang indentifier descriptor. */ +__ALIGN_BEGIN uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = { + USB_LEN_LANGID_STR_DESC, + USB_DESC_TYPE_STRING, + LOBYTE(USBD_LANGID_STRING), + HIBYTE(USBD_LANGID_STRING) +}; + +/* Internal string descriptor. */ +__ALIGN_BEGIN uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END; + +__ALIGN_BEGIN uint8_t USBD_StringSerial[USB_SIZ_STRING_SERIAL] __ALIGN_END = { + USB_SIZ_STRING_SERIAL, + USB_DESC_TYPE_STRING, +}; + +/** Return the device descriptor + * @param speed : Current device speed + * @param length : Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t * USBD_CDC_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { + UNUSED(speed); + *length = sizeof(USBD_CDC_DeviceDesc); + return USBD_CDC_DeviceDesc; +} + +/** Return the LangID string descriptor + * @param speed : Current device speed + * @param length : Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t * USBD_CDC_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { + UNUSED(speed); + *length = sizeof(USBD_LangIDDesc); + return USBD_LangIDDesc; +} + +/** Return the product string descriptor + * @param speed : Current device speed + * @param length : Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t * USBD_CDC_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { + USBD_GetString((uint8_t*)furi_hal_version_get_device_name_ptr(), USBD_StrDesc, length); + return USBD_StrDesc; +} + +/** Return the manufacturer string descriptor + * @param speed : Current device speed + * @param length : Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t * USBD_CDC_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { + UNUSED(speed); + USBD_GetString((uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, length); + return USBD_StrDesc; +} + +/** Return the serial number string descriptor + * @param speed : Current device speed + * @param length : Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t * USBD_CDC_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { + UNUSED(speed); + *length = USB_SIZ_STRING_SERIAL; + + /* Update the serial number string descriptor with the data from the unique + * ID */ + if(furi_hal_version_get_name_ptr()){ + char buffer[14] = "flip_"; + strncat(buffer, furi_hal_version_get_name_ptr(), 8); + USBD_GetString((uint8_t*) buffer, USBD_StringSerial, length); + } else { + Get_SerialNum(); + } + + return (uint8_t *) USBD_StringSerial; +} + +/** Return the configuration string descriptor + * @param speed : Current device speed + * @param length : Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t * USBD_CDC_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { + if(speed == USBD_SPEED_HIGH) { + USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING, USBD_StrDesc, length); + } else { + USBD_GetString((uint8_t *)USBD_CONFIGURATION_STRING, USBD_StrDesc, length); + } + return USBD_StrDesc; +} + +/** Return the interface string descriptor + * @param speed : Current device speed + * @param length : Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t * USBD_CDC_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) { + if(speed == 0) { + USBD_GetString((uint8_t *)USBD_INTERFACE_STRING, USBD_StrDesc, length); + } else { + USBD_GetString((uint8_t *)USBD_INTERFACE_STRING, USBD_StrDesc, length); + } + return USBD_StrDesc; +} + +/** Create the serial number string descriptor + * @param None + * @retval None + */ +static void Get_SerialNum(void) { + uint32_t deviceserial0, deviceserial1, deviceserial2; + + deviceserial0 = *(uint32_t *) DEVICE_ID1; + deviceserial1 = *(uint32_t *) DEVICE_ID2; + deviceserial2 = *(uint32_t *) DEVICE_ID3; + + deviceserial0 += deviceserial2; + + if (deviceserial0 != 0) { + IntToUnicode(deviceserial0, &USBD_StringSerial[2], 8); + IntToUnicode(deviceserial1, &USBD_StringSerial[18], 4); + } +} + +/** Convert Hex 32Bits value into char + * @param value: value to convert + * @param pbuf: pointer to the buffer + * @param len: buffer length + * @retval None + */ +static void IntToUnicode(uint32_t value, uint8_t * pbuf, uint8_t len) { + uint8_t idx = 0; + + for (idx = 0; idx < len; idx++) { + if (((value >> 28)) < 0xA) { + pbuf[2 * idx] = (value >> 28) + '0'; + } else { + pbuf[2 * idx] = (value >> 28) + 'A' - 10; + } + + value = value << 4; + + pbuf[2 * idx + 1] = 0; + } +} diff --git a/firmware/targets/f6/usb-glue/usbd_desc.h b/firmware/targets/f6/usb-glue/usbd_desc.h new file mode 100644 index 00000000..795b33e4 --- /dev/null +++ b/firmware/targets/f6/usb-glue/usbd_desc.h @@ -0,0 +1,19 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "usbd_def.h" + +#define DEVICE_ID1 (UID_BASE) +#define DEVICE_ID2 (UID_BASE + 0x4) +#define DEVICE_ID3 (UID_BASE + 0x8) + +#define USB_SIZ_STRING_SERIAL 0x1E + +extern USBD_DescriptorsTypeDef CDC_Desc; + +#ifdef __cplusplus +} +#endif diff --git a/firmware/targets/furi-hal-include/furi-hal-delay.h b/firmware/targets/furi-hal-include/furi-hal-delay.h index 0f6c0a76..3ba2836f 100644 --- a/firmware/targets/furi-hal-include/furi-hal-delay.h +++ b/firmware/targets/furi-hal-include/furi-hal-delay.h @@ -17,6 +17,9 @@ void delay(float milliseconds); /** Delay in microseconds */ void delay_us(float microseconds); +/** Get current millisecond */ +uint32_t millis(void); + #ifdef __cplusplus } #endif diff --git a/firmware/targets/furi-hal-include/furi-hal-subghz.h b/firmware/targets/furi-hal-include/furi-hal-subghz.h index bf80d7e1..653a343c 100644 --- a/firmware/targets/furi-hal-include/furi-hal-subghz.h +++ b/firmware/targets/furi-hal-include/furi-hal-subghz.h @@ -11,7 +11,9 @@ extern "C" { /** Radio Presets */ typedef enum { - FuriHalSubGhzPresetOokAsync, /** OOK, asynchronous */ + FuriHalSubGhzPresetOok270Async, /** OOK, bandwidth 270kHz, asynchronous */ + FuriHalSubGhzPresetOok650Async, /** OOK, bandwidth 650kHz, asynchronous */ + FuriHalSubGhzPreset2FSKAsync, /** FM, asynchronous */ } FuriHalSubGhzPreset; /** Switchable Radio Paths */ diff --git a/lib/ST25RFAL002/source/rfal_nfc.c b/lib/ST25RFAL002/source/rfal_nfc.c index 96d35889..b125f1d8 100755 --- a/lib/ST25RFAL002/source/rfal_nfc.c +++ b/lib/ST25RFAL002/source/rfal_nfc.c @@ -575,7 +575,9 @@ ReturnCode rfalNfcDataExchangeStart( uint8_t *txData, uint16_t txDataLen, uint8_ *rvdLen = (uint16_t*)&gNfcDev.rxLen; *rxData = (uint8_t*)( (gNfcDev.activeDev->rfInterface == RFAL_NFC_INTERFACE_ISODEP) ? gNfcDev.rxBuf.isoDepBuf.apdu : ((gNfcDev.activeDev->rfInterface == RFAL_NFC_INTERFACE_NFCDEP) ? gNfcDev.rxBuf.nfcDepBuf.pdu : gNfcDev.rxBuf.rfBuf)); - gNfcDev.state = RFAL_NFC_STATE_DATAEXCHANGE_DONE; + if(gNfcDev.disc.activate_after_sak) { + gNfcDev.state = RFAL_NFC_STATE_DATAEXCHANGE_DONE; + } return ERR_NONE; } diff --git a/lib/app-scened-template/file-worker-cpp.cpp b/lib/app-scened-template/file-worker-cpp.cpp index 7f7c5d6a..b087a895 100644 --- a/lib/app-scened-template/file-worker-cpp.cpp +++ b/lib/app-scened-template/file-worker-cpp.cpp @@ -71,6 +71,10 @@ bool FileWorkerCpp::read_until_buffered(string_t str_result, char* file_buf, siz return file_worker_read_until_buffered(file_worker, str_result, file_buf, file_buf_cnt, max_length, separator); } +bool FileWorkerCpp::get_value_from_key(string_t key, char delimiter, string_t value) { + return file_worker_get_value_from_key(file_worker, key, delimiter, value); +} + bool FileWorkerCpp::is_file_exist(const char* filename, bool* exist) { return file_worker_is_file_exist(file_worker, filename, exist); } diff --git a/lib/app-scened-template/file-worker-cpp.h b/lib/app-scened-template/file-worker-cpp.h index 6b5b732b..23074307 100644 --- a/lib/app-scened-template/file-worker-cpp.h +++ b/lib/app-scened-template/file-worker-cpp.h @@ -143,6 +143,17 @@ public: */ bool read_until_buffered(string_t str_result, char* file_buf, size_t* file_buf_cnt, size_t max_length, char separator = '\n'); + /** + * @brief Gets value from key + * + * @param file_worker FileWorker instance + * @param key key + * @param delimeter key-value delimeter + * @param value value for given key + * @return true on success + */ + bool get_value_from_key(string_t key, char delimiter, string_t value); + /** * @brief Check whether file exist or not * diff --git a/lib/app-scened-template/file-worker.c b/lib/app-scened-template/file-worker.c index 52427aed..c38c1261 100644 --- a/lib/app-scened-template/file-worker.c +++ b/lib/app-scened-template/file-worker.c @@ -355,6 +355,34 @@ bool file_worker_read_until_buffered( return string_size(str_result) || *file_buf_cnt; } +bool file_worker_get_value_from_key(FileWorker* file_worker, string_t key, char delimiter, string_t value) { + bool found = false; + string_t next_line; + string_t next_key; + string_init(next_line); + string_init(next_key); + size_t delim_pos = 0; + + while(file_worker_read_until(file_worker, next_line, '\n')) { + delim_pos = string_search_char(next_line, delimiter); + if(delim_pos == STRING_FAILURE) { + break; + } + string_set_n(next_key, next_line, 0, delim_pos); + if(string_equal_p(next_key, key)) { + string_right(next_line, delim_pos); + string_strim(next_line); + string_set(value, next_line); + found = true; + break; + } + } + + string_clear(next_line); + string_clear(next_key); + return found; +} + bool file_worker_rename(FileWorker* file_worker, const char* old_path, const char* new_path) { FS_Error fs_result = storage_common_rename(file_worker->api, old_path, new_path); diff --git a/lib/app-scened-template/file-worker.h b/lib/app-scened-template/file-worker.h index 05671301..3a2b83de 100644 --- a/lib/app-scened-template/file-worker.h +++ b/lib/app-scened-template/file-worker.h @@ -185,6 +185,17 @@ bool file_worker_read_until_buffered( size_t max_length, char separator); +/** + * @brief Gets value from key + * + * @param file_worker FileWorker instance + * @param key key + * @param delimeter key-value delimeter + * @param value value for given key + * @return true on success + */ +bool file_worker_get_value_from_key(FileWorker* file_worker, string_t key, char delimiter, string_t value); + /** * @brief Check whether file exist or not * diff --git a/lib/irda/encoder_decoder/irda_common_decoder.c b/lib/irda/encoder_decoder/common/irda_common_decoder.c similarity index 89% rename from lib/irda/encoder_decoder/irda_common_decoder.c rename to lib/irda/encoder_decoder/common/irda_common_decoder.c index a9a29e87..e57844cc 100644 --- a/lib/irda/encoder_decoder/irda_common_decoder.c +++ b/lib/irda/encoder_decoder/common/irda_common_decoder.c @@ -21,6 +21,10 @@ static bool irda_check_preamble(IrdaCommonDecoder* decoder) { } } + if (decoder->protocol->timings.preamble_mark == 0) { + return true; + } + while ((!result) && (decoder->timings_cnt >= 2)) { float preamble_tolerance = decoder->protocol->timings.preamble_tolerance; uint16_t preamble_mark = decoder->protocol->timings.preamble_mark; @@ -94,7 +98,7 @@ IrdaStatus irda_common_decode_pdwm(IrdaCommonDecoder* decoder) { /* level switch detection goes in middle of time-quant */ IrdaStatus irda_common_decode_manchester(IrdaCommonDecoder* decoder) { furi_assert(decoder); - IrdaStatus status = IrdaStatusError; + IrdaStatus status = IrdaStatusOk; uint16_t bit = decoder->protocol->timings.bit1_mark; uint16_t tolerance = decoder->protocol->timings.bit_tolerance; @@ -106,12 +110,22 @@ IrdaStatus irda_common_decode_manchester(IrdaCommonDecoder* decoder) { bool single_timing = MATCH_BIT_TIMING(timing, bit, tolerance); bool double_timing = MATCH_BIT_TIMING(timing, 2*bit, tolerance); - if((!single_timing && !double_timing) || (double_timing && !*switch_detect)) { + if(!single_timing && !double_timing) { status = IrdaStatusError; break; } + if ((decoder->protocol->manchester_start_from_space) && (decoder->databit_cnt == 0)) { + *switch_detect = 1; /* fake as we were previously in the middle of time-quant */ + decoder->data[0] = 0; /* first captured timing should be Mark */ + ++decoder->databit_cnt; + } + if (*switch_detect == 0) { + if (double_timing) { + status = IrdaStatusError; + break; + } /* only single timing - level switch required in the middle of time-quant */ *switch_detect = 1; } else { @@ -123,6 +137,7 @@ IrdaStatus irda_common_decode_manchester(IrdaCommonDecoder* decoder) { --decoder->timings_cnt; shift_left_array(decoder->timings, decoder->timings_cnt, 1); status = IrdaStatusOk; + bool level = (decoder->level + decoder->timings_cnt) % 2; if (decoder->databit_cnt < decoder->protocol->databit_len) { if (*switch_detect) { @@ -130,19 +145,17 @@ IrdaStatus irda_common_decode_manchester(IrdaCommonDecoder* decoder) { uint8_t shift = decoder->databit_cnt % 8; // LSB first if (!shift) decoder->data[index] = 0; - bool inverse_level = decoder->protocol->manchester_inverse_level; - uint8_t logic_value = inverse_level ? !decoder->level : decoder->level; - decoder->data[index] |= (logic_value << shift); + decoder->data[index] |= (level << shift); ++decoder->databit_cnt; } if (decoder->databit_cnt == decoder->protocol->databit_len) { - if (decoder->level) { + if (level) { status = IrdaStatusReady; break; } } } else { - furi_assert(decoder->level); + furi_assert(level); /* cover case: sequence should be stopped after last bit was received */ if (single_timing) { status = IrdaStatusReady; @@ -178,6 +191,7 @@ IrdaMessage* irda_common_decode(IrdaCommonDecoder* decoder, bool level, uint32_t decoder->state = IrdaCommonDecoderStateDecode; decoder->databit_cnt = 0; decoder->switch_detect = false; + continue; } break; case IrdaCommonDecoderStateDecode: @@ -243,6 +257,10 @@ void irda_common_decoder_reset_state(IrdaCommonDecoder* common_decoder) { common_decoder->databit_cnt = 0; common_decoder->switch_detect = false; common_decoder->message.protocol = IrdaProtocolUnknown; + if ((common_decoder->protocol->timings.preamble_mark == 0) && (common_decoder->timings_cnt > 0)) { + --common_decoder->timings_cnt; + shift_left_array(common_decoder->timings, common_decoder->timings_cnt, 1); + } } void irda_common_decoder_reset(void* decoder) { diff --git a/lib/irda/encoder_decoder/irda_common_encoder.c b/lib/irda/encoder_decoder/common/irda_common_encoder.c similarity index 97% rename from lib/irda/encoder_decoder/irda_common_encoder.c rename to lib/irda/encoder_decoder/common/irda_common_encoder.c index 237b3191..6e897233 100644 --- a/lib/irda/encoder_decoder/irda_common_encoder.c +++ b/lib/irda/encoder_decoder/common/irda_common_encoder.c @@ -28,10 +28,9 @@ IrdaStatus irda_common_encode_manchester(IrdaCommonEncoder* encoder, uint32_t* d uint8_t index = encoder->bits_encoded / 8; uint8_t shift = encoder->bits_encoded % 8; // LSB first bool logic_value = !!(encoder->data[index] & (0x01 << shift)); - bool inverse = encoder->protocol->manchester_inverse_level; bool even_timing = !(encoder->timings_encoded % 2); - *level = even_timing ^ logic_value ^ inverse; + *level = even_timing ^ logic_value; *duration = timings->bit1_mark; if (even_timing) /* start encoding from space */ ++encoder->bits_encoded; diff --git a/lib/irda/encoder_decoder/irda_common_i.h b/lib/irda/encoder_decoder/common/irda_common_i.h similarity index 98% rename from lib/irda/encoder_decoder/irda_common_i.h rename to lib/irda/encoder_decoder/common/irda_common_i.h index 56f77790..c73ebee9 100644 --- a/lib/irda/encoder_decoder/irda_common_i.h +++ b/lib/irda/encoder_decoder/common/irda_common_i.h @@ -20,7 +20,7 @@ typedef IrdaStatus (*IrdaCommonEncode)(IrdaCommonEncoder* encoder, uint32_t* out typedef struct { IrdaTimings timings; - bool manchester_inverse_level; + bool manchester_start_from_space; uint32_t databit_len; IrdaCommonDecode decode; IrdaCommonDecode decode_repeat; diff --git a/lib/irda/encoder_decoder/irda_common_protocol_defs.c b/lib/irda/encoder_decoder/common/irda_common_protocol_defs.c similarity index 75% rename from lib/irda/encoder_decoder/irda_common_protocol_defs.c rename to lib/irda/encoder_decoder/common/irda_common_protocol_defs.c index 46327045..e516ab0c 100644 --- a/lib/irda/encoder_decoder/irda_common_protocol_defs.c +++ b/lib/irda/encoder_decoder/common/irda_common_protocol_defs.c @@ -21,26 +21,6 @@ const IrdaCommonProtocolSpec protocol_nec = { .encode_repeat = irda_encoder_nec_encode_repeat, }; -const IrdaCommonProtocolSpec protocol_necext = { - .timings = { - .preamble_mark = IRDA_NEC_PREAMBULE_MARK, - .preamble_space = IRDA_NEC_PREAMBULE_SPACE, - .bit1_mark = IRDA_NEC_BIT1_MARK, - .bit1_space = IRDA_NEC_BIT1_SPACE, - .bit0_mark = IRDA_NEC_BIT0_MARK, - .bit0_space = IRDA_NEC_BIT0_SPACE, - .preamble_tolerance = IRDA_NEC_PREAMBLE_TOLERANCE, - .bit_tolerance = IRDA_NEC_BIT_TOLERANCE, - .silence_time = IRDA_NEC_SILENCE, - }, - .databit_len = 32, - .decode = irda_common_decode_pdwm, - .encode = irda_common_encode_pdwm, - .interpret = irda_decoder_necext_interpret, - .decode_repeat = irda_decoder_nec_decode_repeat, - .encode_repeat = irda_encoder_nec_encode_repeat, -}; - const IrdaCommonProtocolSpec protocol_samsung32 = { .timings = { .preamble_mark = IRDA_SAMSUNG_PREAMBULE_MARK, @@ -71,7 +51,7 @@ const IrdaCommonProtocolSpec protocol_rc6 = { .silence_time = IRDA_RC6_SILENCE, }, .databit_len = 1 + 3 + 1 + 8 + 8, // start_bit + 3 mode bits, + 1 toggle bit (x2 timing) + 8 address + 8 command - .manchester_inverse_level = false, + .manchester_start_from_space = false, .decode = irda_decoder_rc6_decode_manchester, .encode = irda_encoder_rc6_encode_manchester, .interpret = irda_decoder_rc6_interpret, @@ -79,3 +59,21 @@ const IrdaCommonProtocolSpec protocol_rc6 = { .encode_repeat = NULL, }; +const IrdaCommonProtocolSpec protocol_rc5 = { + .timings = { + .preamble_mark = 0, + .preamble_space = 0, + .bit1_mark = IRDA_RC5_BIT, + .preamble_tolerance = 0, + .bit_tolerance = IRDA_RC5_BIT_TOLERANCE, + .silence_time = IRDA_RC5_SILENCE, + }, + .databit_len = 1 + 1 + 1 + 5 + 6, // start_bit + start_bit/command_bit + toggle_bit + 5 address + 6 command + .manchester_start_from_space = true, + .decode = irda_common_decode_manchester, + .encode = irda_common_encode_manchester, + .interpret = irda_decoder_rc5_interpret, + .decode_repeat = NULL, + .encode_repeat = NULL, +}; + diff --git a/lib/irda/encoder_decoder/irda.c b/lib/irda/encoder_decoder/irda.c index 6c7866d1..89552030 100644 --- a/lib/irda/encoder_decoder/irda.c +++ b/lib/irda/encoder_decoder/irda.c @@ -1,6 +1,6 @@ #include "irda.h" #include "furi/check.h" -#include "irda_common_i.h" +#include "common/irda_common_i.h" #include "irda_protocol_defs_i.h" #include #include @@ -9,10 +9,6 @@ #include "irda_i.h" #include -struct IrdaDecoderHandler { - void** ctx; -}; - typedef struct { IrdaAlloc alloc; IrdaDecode decode; @@ -27,27 +23,36 @@ typedef struct { IrdaFree free; } IrdaEncoders; -typedef struct { - IrdaProtocol protocol; - const char* name; - IrdaDecoders decoder; - IrdaEncoders encoder; - uint8_t address_length; - uint8_t command_length; - uint32_t frequency; - float duty_cycle; -} IrdaProtocolImplementation; - -struct IrdaEncoderHandler { - void* encoder; - IrdaProtocol protocol; +struct IrdaDecoderHandler { + void** ctx; }; -// TODO: replace with key-value, Now we refer by enum index, which is dangerous. -static const IrdaProtocolImplementation irda_protocols[] = { - // #0 - { .protocol = IrdaProtocolNEC, - .name = "NEC", +struct IrdaEncoderHandler { + void* handler; + const IrdaEncoders* encoder; +}; + +typedef struct { + IrdaEncoders encoder; + IrdaDecoders decoder; + IrdaGetProtocolSpec get_protocol_spec; +} IrdaEncoderDecoder; + +static const IrdaEncoderDecoder irda_encoder_decoder[] = { + { + .decoder = { + .alloc = irda_decoder_rc5_alloc, + .decode = irda_decoder_rc5_decode, + .reset = irda_decoder_rc5_reset, + .free = irda_decoder_rc5_free}, + .encoder = { + .alloc = irda_encoder_rc5_alloc, + .encode = irda_encoder_rc5_encode, + .reset = irda_encoder_rc5_reset, + .free = irda_encoder_rc5_free}, + .get_protocol_spec = irda_rc5_get_spec, + }, + { .decoder = { .alloc = irda_decoder_nec_alloc, .decode = irda_decoder_nec_decode, @@ -58,32 +63,9 @@ static const IrdaProtocolImplementation irda_protocols[] = { .encode = irda_encoder_nec_encode, .reset = irda_encoder_nec_reset, .free = irda_encoder_nec_free}, - .address_length = 2, - .command_length = 2, - .frequency = IRDA_COMMON_CARRIER_FREQUENCY, - .duty_cycle = IRDA_COMMON_DUTY_CYCLE, + .get_protocol_spec = irda_nec_get_spec, }, - // #1 - have to be after NEC - { .protocol = IrdaProtocolNECext, - .name = "NECext", - .decoder = { - .alloc = irda_decoder_necext_alloc, - .decode = irda_decoder_nec_decode, - .reset = irda_decoder_nec_reset, - .free = irda_decoder_nec_free}, - .encoder = { - .alloc = irda_encoder_necext_alloc, - .encode = irda_encoder_nec_encode, - .reset = irda_encoder_necext_reset, - .free = irda_encoder_nec_free}, - .address_length = 4, - .command_length = 2, - .frequency = IRDA_COMMON_CARRIER_FREQUENCY, - .duty_cycle = IRDA_COMMON_DUTY_CYCLE, - }, - // #2 - { .protocol = IrdaProtocolSamsung32, - .name ="Samsung32", + { .decoder = { .alloc = irda_decoder_samsung32_alloc, .decode = irda_decoder_samsung32_decode, @@ -94,14 +76,9 @@ static const IrdaProtocolImplementation irda_protocols[] = { .encode = irda_encoder_samsung32_encode, .reset = irda_encoder_samsung32_reset, .free = irda_encoder_samsung32_free}, - .address_length = 2, - .command_length = 2, - .frequency = IRDA_COMMON_CARRIER_FREQUENCY, - .duty_cycle = IRDA_COMMON_DUTY_CYCLE, + .get_protocol_spec = irda_samsung32_get_spec, }, - // #3 - { .protocol = IrdaProtocolRC6, - .name = "RC6", + { .decoder = { .alloc = irda_decoder_rc6_alloc, .decode = irda_decoder_rc6_decode, @@ -112,10 +89,7 @@ static const IrdaProtocolImplementation irda_protocols[] = { .encode = irda_encoder_rc6_encode, .reset = irda_encoder_rc6_reset, .free = irda_encoder_rc6_free}, - .address_length = 2, - .command_length = 2, - .frequency = IRDA_COMMON_CARRIER_FREQUENCY, - .duty_cycle = IRDA_COMMON_DUTY_CYCLE, + .get_protocol_spec = irda_rc6_get_spec, }, }; @@ -125,11 +99,10 @@ const IrdaMessage* irda_decode(IrdaDecoderHandler* handler, bool level, uint32_t IrdaMessage* message = NULL; IrdaMessage* result = NULL; - for (int i = 0; i < COUNT_OF(irda_protocols); ++i) { - if (irda_protocols[i].decoder.decode) { - message = irda_protocols[i].decoder.decode(handler->ctx[i], level, duration); + for (int i = 0; i < COUNT_OF(irda_encoder_decoder); ++i) { + if (irda_encoder_decoder[i].decoder.decode) { + message = irda_encoder_decoder[i].decoder.decode(handler->ctx[i], level, duration); if (!result && message) { - message->protocol = irda_protocols[i].protocol; result = message; } } @@ -140,12 +113,12 @@ const IrdaMessage* irda_decode(IrdaDecoderHandler* handler, bool level, uint32_t IrdaDecoderHandler* irda_alloc_decoder(void) { IrdaDecoderHandler* handler = furi_alloc(sizeof(IrdaDecoderHandler)); - handler->ctx = furi_alloc(sizeof(void*) * COUNT_OF(irda_protocols)); + handler->ctx = furi_alloc(sizeof(void*) * COUNT_OF(irda_encoder_decoder)); - for (int i = 0; i < COUNT_OF(irda_protocols); ++i) { + for (int i = 0; i < COUNT_OF(irda_encoder_decoder); ++i) { handler->ctx[i] = 0; - if (irda_protocols[i].decoder.alloc) - handler->ctx[i] = irda_protocols[i].decoder.alloc(); + if (irda_encoder_decoder[i].decoder.alloc) + handler->ctx[i] = irda_encoder_decoder[i].decoder.alloc(); } return handler; @@ -155,9 +128,9 @@ void irda_free_decoder(IrdaDecoderHandler* handler) { furi_assert(handler); furi_assert(handler->ctx); - for (int i = 0; i < COUNT_OF(irda_protocols); ++i) { - if (irda_protocols[i].decoder.free) - irda_protocols[i].decoder.free(handler->ctx[i]); + for (int i = 0; i < COUNT_OF(irda_encoder_decoder); ++i) { + if (irda_encoder_decoder[i].decoder.free) + irda_encoder_decoder[i].decoder.free(handler->ctx[i]); } free(handler->ctx); @@ -165,114 +138,119 @@ void irda_free_decoder(IrdaDecoderHandler* handler) { } void irda_reset_decoder(IrdaDecoderHandler* handler) { - for (int i = 0; i < COUNT_OF(irda_protocols); ++i) { - if (irda_protocols[i].decoder.reset) - irda_protocols[i].decoder.reset(handler->ctx[i]); + for (int i = 0; i < COUNT_OF(irda_encoder_decoder); ++i) { + if (irda_encoder_decoder[i].decoder.reset) + irda_encoder_decoder[i].decoder.reset(handler->ctx[i]); } } IrdaEncoderHandler* irda_alloc_encoder(void) { IrdaEncoderHandler* handler = furi_alloc(sizeof(IrdaEncoderHandler)); + handler->handler = NULL; handler->encoder = NULL; - handler->protocol = IrdaProtocolUnknown; return handler; } void irda_free_encoder(IrdaEncoderHandler* handler) { furi_assert(handler); + const IrdaEncoders* encoder = handler->encoder; - if (handler->encoder) { - furi_assert(irda_is_protocol_valid(handler->protocol)); - furi_assert(irda_protocols[handler->protocol].encoder.free); - irda_protocols[handler->protocol].encoder.free(handler->encoder); + if (encoder || handler->handler) { + furi_assert(encoder); + furi_assert(handler->handler); + furi_assert(encoder->free); + encoder->free(handler->handler); } free(handler); } +static int irda_find_index_by_protocol(IrdaProtocol protocol) { + for (int i = 0; i < COUNT_OF(irda_encoder_decoder); ++i) { + if (irda_encoder_decoder[i].get_protocol_spec(protocol)) { + return i; + } + } + + return -1; +} + void irda_reset_encoder(IrdaEncoderHandler* handler, const IrdaMessage* message) { furi_assert(handler); furi_assert(message); - furi_assert(irda_is_protocol_valid(message->protocol)); - furi_assert(irda_protocols[message->protocol].encoder.reset); - furi_assert(irda_protocols[message->protocol].encoder.alloc); + int index = irda_find_index_by_protocol(message->protocol); + furi_check(index >= 0); + + const IrdaEncoders* required_encoder = &irda_encoder_decoder[index].encoder; + furi_assert(required_encoder); + furi_assert(required_encoder->reset); + furi_assert(required_encoder->alloc); /* Realloc encoder if different protocol set */ - if (message->protocol != handler->protocol) { - if (handler->encoder != NULL) { - furi_assert(handler->protocol != IrdaProtocolUnknown); - irda_protocols[handler->protocol].encoder.free(handler->encoder); + if (required_encoder != handler->encoder) { + if (handler->handler != NULL) { + furi_assert(handler->encoder->free); + handler->encoder->free(handler->handler); } - handler->encoder = irda_protocols[message->protocol].encoder.alloc(); - handler->protocol = message->protocol; + handler->encoder = required_encoder; + handler->handler = handler->encoder->alloc(); } - irda_protocols[handler->protocol].encoder.reset(handler->encoder, message); + handler->encoder->reset(handler->handler, message); } - IrdaStatus irda_encode(IrdaEncoderHandler* handler, uint32_t* duration, bool* level) { furi_assert(handler); - furi_assert(irda_is_protocol_valid(handler->protocol)); - furi_assert(irda_protocols[handler->protocol].encoder.encode); + furi_assert(duration); + furi_assert(level); + const IrdaEncoders* encoder = handler->encoder; + furi_assert(encoder); + furi_assert(encoder->encode); - IrdaStatus status = irda_protocols[handler->protocol].encoder.encode(handler->encoder, duration, level); + IrdaStatus status = encoder->encode(handler->handler, duration, level); furi_assert(status != IrdaStatusError); return status; } - bool irda_is_protocol_valid(IrdaProtocol protocol) { - return (protocol >= 0) && (protocol < COUNT_OF(irda_protocols)); + return irda_find_index_by_protocol(protocol) >= 0; } IrdaProtocol irda_get_protocol_by_name(const char* protocol_name) { - for (int i = 0; i < COUNT_OF(irda_protocols); ++i) { - if (!strcmp(irda_protocols[i].name, protocol_name)) - return i; + for (IrdaProtocol protocol = 0; protocol < IrdaProtocolMAX; ++protocol) { + const char* name = irda_get_protocol_name(protocol); + if (!strcmp(name, protocol_name)) + return protocol; } - furi_assert(0); return IrdaProtocolUnknown; } +static const IrdaProtocolSpecification* irda_get_spec_by_protocol(IrdaProtocol protocol) { + int index = irda_find_index_by_protocol(protocol); + furi_check(index >= 0); + const IrdaProtocolSpecification* spec = irda_encoder_decoder[index].get_protocol_spec(protocol); + furi_assert(spec); + return spec; +} + const char* irda_get_protocol_name(IrdaProtocol protocol) { - furi_assert(irda_is_protocol_valid(protocol)); - if (irda_is_protocol_valid(protocol)) - return irda_protocols[protocol].name; - else - return "Invalid"; + return irda_get_spec_by_protocol(protocol)->name; } uint8_t irda_get_protocol_address_length(IrdaProtocol protocol) { - furi_assert(irda_is_protocol_valid(protocol)); - if (irda_is_protocol_valid(protocol)) - return irda_protocols[protocol].address_length; - else - return 0; + return irda_get_spec_by_protocol(protocol)->address_length; } uint8_t irda_get_protocol_command_length(IrdaProtocol protocol) { - furi_assert(irda_is_protocol_valid(protocol)); - if (irda_is_protocol_valid(protocol)) - return irda_protocols[protocol].command_length; - else - return 0; + return irda_get_spec_by_protocol(protocol)->command_length; } uint32_t irda_get_protocol_frequency(IrdaProtocol protocol) { - furi_assert(irda_is_protocol_valid(protocol)); - if (irda_is_protocol_valid(protocol)) - return irda_protocols[protocol].frequency; - else - return 0; + return irda_get_spec_by_protocol(protocol)->frequency; } float irda_get_protocol_duty_cycle(IrdaProtocol protocol) { - furi_assert(irda_is_protocol_valid(protocol)); - if (irda_is_protocol_valid(protocol)) - return irda_protocols[protocol].duty_cycle; - else - return 0; + return irda_get_spec_by_protocol(protocol)->duty_cycle; } diff --git a/lib/irda/encoder_decoder/irda.h b/lib/irda/encoder_decoder/irda.h index 954be818..d1887e26 100644 --- a/lib/irda/encoder_decoder/irda.h +++ b/lib/irda/encoder_decoder/irda.h @@ -26,6 +26,9 @@ typedef enum { IrdaProtocolNECext = 1, IrdaProtocolSamsung32 = 2, IrdaProtocolRC6 = 3, + IrdaProtocolRC5 = 4, + IrdaProtocolRC5X = 5, + IrdaProtocolMAX, } IrdaProtocol; typedef struct { @@ -58,6 +61,8 @@ IrdaDecoderHandler* irda_alloc_decoder(void); * and decoder resets its state and start decoding from the start. * \param[in] duration - duration of steady high/low input signal. * \return if message is ready, returns pointer to decoded message, returns NULL. + * Note: ownership of returned ptr belongs to handler. So pointer is valid + * up to next irda_free_decoder(), irda_reset_decoder(), irda_decode() calls. */ const IrdaMessage* irda_decode(IrdaDecoderHandler* handler, bool level, uint32_t duration); diff --git a/lib/irda/encoder_decoder/irda_i.h b/lib/irda/encoder_decoder/irda_i.h index 021f1263..4ca194a8 100644 --- a/lib/irda/encoder_decoder/irda_i.h +++ b/lib/irda/encoder_decoder/irda_i.h @@ -14,6 +14,16 @@ typedef struct { uint32_t bit_tolerance; } IrdaTimings; +typedef struct { + const char* name; + uint8_t address_length; + uint8_t command_length; + uint32_t frequency; + float duty_cycle; +} IrdaProtocolSpecification; + +typedef const IrdaProtocolSpecification* (*IrdaGetProtocolSpec) (IrdaProtocol protocol); + typedef void* (*IrdaAlloc) (void); typedef IrdaMessage* (*IrdaDecode) (void* ctx, bool level, uint32_t duration); typedef void (*IrdaReset) (void*); @@ -21,7 +31,6 @@ typedef void (*IrdaFree) (void*); typedef void (*IrdaEncoderReset)(void* encoder, const IrdaMessage* message); typedef IrdaStatus (*IrdaEncode)(void* encoder, uint32_t* out, bool* polarity); -typedef IrdaTimings (*IrdaTimingsGet)(void); static inline uint8_t reverse(uint8_t value) { uint8_t reverse_value = 0; diff --git a/lib/irda/encoder_decoder/irda_protocol_defs_i.h b/lib/irda/encoder_decoder/irda_protocol_defs_i.h index 9c4e5ae9..43703ea9 100644 --- a/lib/irda/encoder_decoder/irda_protocol_defs_i.h +++ b/lib/irda/encoder_decoder/irda_protocol_defs_i.h @@ -4,7 +4,7 @@ #include #include #include "irda.h" -#include "irda_common_i.h" +#include "common/irda_common_i.h" /*************************************************************************************************** * NEC protocol description @@ -40,22 +40,15 @@ void* irda_decoder_nec_alloc(void); void irda_decoder_nec_reset(void* decoder); void irda_decoder_nec_free(void* decoder); IrdaMessage* irda_decoder_nec_decode(void* decoder, bool level, uint32_t duration); - void* irda_encoder_nec_alloc(void); IrdaStatus irda_encoder_nec_encode(void* encoder_ptr, uint32_t* duration, bool* level); void irda_encoder_nec_reset(void* encoder_ptr, const IrdaMessage* message); void irda_encoder_nec_free(void* encoder_ptr); - -void* irda_decoder_necext_alloc(void); -void* irda_encoder_necext_alloc(void); -void irda_encoder_necext_reset(void* encoder_ptr, const IrdaMessage* message); - bool irda_decoder_nec_interpret(IrdaCommonDecoder* decoder); -bool irda_decoder_necext_interpret(IrdaCommonDecoder* decoder); IrdaStatus irda_decoder_nec_decode_repeat(IrdaCommonDecoder* decoder); IrdaStatus irda_encoder_nec_encode_repeat(IrdaCommonEncoder* encoder, uint32_t* duration, bool* level); +const IrdaProtocolSpecification* irda_nec_get_spec(IrdaProtocol protocol); -extern const IrdaCommonProtocolSpec protocol_necext; extern const IrdaCommonProtocolSpec protocol_nec; @@ -98,15 +91,14 @@ void* irda_decoder_samsung32_alloc(void); void irda_decoder_samsung32_reset(void* decoder); void irda_decoder_samsung32_free(void* decoder); IrdaMessage* irda_decoder_samsung32_decode(void* decoder, bool level, uint32_t duration); - IrdaStatus irda_encoder_samsung32_encode(void* encoder_ptr, uint32_t* duration, bool* level); void irda_encoder_samsung32_reset(void* encoder_ptr, const IrdaMessage* message); void* irda_encoder_samsung32_alloc(void); void irda_encoder_samsung32_free(void* encoder_ptr); - bool irda_decoder_samsung32_interpret(IrdaCommonDecoder* decoder); IrdaStatus irda_decoder_samsung32_decode_repeat(IrdaCommonDecoder* decoder); IrdaStatus irda_encoder_samsung32_encode_repeat(IrdaCommonEncoder* encoder, uint32_t* duration, bool* level); +const IrdaProtocolSpecification* irda_samsung32_get_spec(IrdaProtocol protocol); extern const IrdaCommonProtocolSpec protocol_samsung32; @@ -132,6 +124,9 @@ extern const IrdaCommonProtocolSpec protocol_samsung32; * command - 8 bit ***************************************************************************************************/ +#define IRDA_RC6_CARRIER_FREQUENCY 36000 +#define IRDA_RC6_DUTY_CYCLE 0.33 + #define IRDA_RC6_PREAMBULE_MARK 2666 #define IRDA_RC6_PREAMBULE_SPACE 889 #define IRDA_RC6_BIT 444 // half of time-quant for 1 bit @@ -148,10 +143,57 @@ void* irda_encoder_rc6_alloc(void); void irda_encoder_rc6_reset(void* encoder_ptr, const IrdaMessage* message); void irda_encoder_rc6_free(void* decoder); IrdaStatus irda_encoder_rc6_encode(void* encoder_ptr, uint32_t* duration, bool* polarity); - bool irda_decoder_rc6_interpret(IrdaCommonDecoder* decoder); IrdaStatus irda_decoder_rc6_decode_manchester(IrdaCommonDecoder* decoder); IrdaStatus irda_encoder_rc6_encode_manchester(IrdaCommonEncoder* encoder_ptr, uint32_t* duration, bool* polarity); +const IrdaProtocolSpecification* irda_rc6_get_spec(IrdaProtocol protocol); extern const IrdaCommonProtocolSpec protocol_rc6; + +/*************************************************************************************************** +* RC5 protocol description +* https://www.mikrocontroller.net/articles/IRMP_-_english#RC5_.2B_RC5X +**************************************************************************************************** +* Manchester/biphase +* Modulation +* +* 888/1776 - bit (x2 for toggle bit) +* +* __ ____ __ __ __ __ __ __ __ __ +* __ __ ____ __ __ __ __ __ __ __ _ +* | 1 | 1 | 0 | ... | ... | +* s si T address (MSB) command (MSB) +* +* Note: manchester starts from space timing, so it have to be handled properly +* s - start bit (always 1) +* si - RC5: start bit (always 1), RC5X - 7-th bit of address (in our case always 0) +* T - toggle bit, change it's value every button press +* address - 8 bit +* command - 8 bit +***************************************************************************************************/ + +#define IRDA_RC5_CARRIER_FREQUENCY 36000 +#define IRDA_RC5_DUTY_CYCLE 0.33 + +#define IRDA_RC5_PREAMBULE_MARK 0 +#define IRDA_RC5_PREAMBULE_SPACE 0 +#define IRDA_RC5_BIT 888 // half of time-quant for 1 bit +#define IRDA_RC5_PREAMBLE_TOLERANCE 0.07 // percents +#define IRDA_RC5_BIT_TOLERANCE 120 // us +/* protocol allows 2700 silence, but it is hard to send 1 message without repeat */ +#define IRDA_RC5_SILENCE (2700 * 10) + +void* irda_decoder_rc5_alloc(void); +void irda_decoder_rc5_reset(void* decoder); +void irda_decoder_rc5_free(void* decoder); +IrdaMessage* irda_decoder_rc5_decode(void* decoder, bool level, uint32_t duration); +void* irda_encoder_rc5_alloc(void); +void irda_encoder_rc5_reset(void* encoder_ptr, const IrdaMessage* message); +void irda_encoder_rc5_free(void* decoder); +IrdaStatus irda_encoder_rc5_encode(void* encoder_ptr, uint32_t* duration, bool* polarity); +bool irda_decoder_rc5_interpret(IrdaCommonDecoder* decoder); +const IrdaProtocolSpecification* irda_rc5_get_spec(IrdaProtocol protocol); + +extern const IrdaCommonProtocolSpec protocol_rc5; + diff --git a/lib/irda/encoder_decoder/nec/irda_decoder_nec.c b/lib/irda/encoder_decoder/nec/irda_decoder_nec.c index 1abe1b9d..aaea7ec5 100644 --- a/lib/irda/encoder_decoder/nec/irda_decoder_nec.c +++ b/lib/irda/encoder_decoder/nec/irda_decoder_nec.c @@ -1,3 +1,4 @@ +#include "irda.h" #include "irda_protocol_defs_i.h" #include #include @@ -14,27 +15,15 @@ bool irda_decoder_nec_interpret(IrdaCommonDecoder* decoder) { uint8_t command = decoder->data[2]; uint8_t command_inverse = decoder->data[3]; - if ((command == (uint8_t) ~command_inverse) && (address == (uint8_t) ~address_inverse)) { + if (command == (uint8_t) ~command_inverse) { + if (address == (uint8_t) ~address_inverse) { + decoder->message.protocol = IrdaProtocolNEC; + decoder->message.address = address; + } else { + decoder->message.protocol = IrdaProtocolNECext; + decoder->message.address = decoder->data[0] | (decoder->data[1] << 8); + } decoder->message.command = command; - decoder->message.address = address; - decoder->message.repeat = false; - result = true; - } - - return result; -} - -// Some NEC's extensions allow 16 bit address -bool irda_decoder_necext_interpret(IrdaCommonDecoder* decoder) { - furi_assert(decoder); - - bool result = false; - uint8_t command = decoder->data[2]; - uint8_t command_inverse = decoder->data[3]; - - if(command == (uint8_t)~command_inverse) { - decoder->message.command = command; - decoder->message.address = decoder->data[0] | (decoder->data[1] << 8); decoder->message.repeat = false; result = true; } @@ -70,10 +59,6 @@ void* irda_decoder_nec_alloc(void) { return irda_common_decoder_alloc(&protocol_nec); } -void* irda_decoder_necext_alloc(void) { - return irda_common_decoder_alloc(&protocol_necext); -} - IrdaMessage* irda_decoder_nec_decode(void* decoder, bool level, uint32_t duration) { return irda_common_decode(decoder, level, duration); } diff --git a/lib/irda/encoder_decoder/nec/irda_encoder_nec.c b/lib/irda/encoder_decoder/nec/irda_encoder_nec.c index ecd403b3..8bf2dfd5 100644 --- a/lib/irda/encoder_decoder/nec/irda_encoder_nec.c +++ b/lib/irda/encoder_decoder/nec/irda_encoder_nec.c @@ -1,5 +1,6 @@ #include "furi/check.h" -#include "irda_common_i.h" +#include "irda.h" +#include "common/irda_common_i.h" #include #include "../irda_i.h" #include "irda_protocol_defs_i.h" @@ -14,6 +15,7 @@ static const uint32_t repeat_timings[] = { void irda_encoder_nec_reset(void* encoder_ptr, const IrdaMessage* message) { furi_assert(encoder_ptr); + furi_assert(message); IrdaCommonEncoder* encoder = encoder_ptr; irda_common_encoder_reset(encoder); @@ -24,24 +26,11 @@ void irda_encoder_nec_reset(void* encoder_ptr, const IrdaMessage* message) { uint8_t command_inverse = ~command; uint32_t* data = (void*) encoder->data; - *data |= address; - *data |= address_inverse << 8; - *data |= command << 16; - *data |= command_inverse << 24; -} - -void irda_encoder_necext_reset(void* encoder_ptr, const IrdaMessage* message) { - furi_assert(encoder_ptr); - - IrdaCommonEncoder* encoder = encoder_ptr; - irda_common_encoder_reset(encoder); - - uint16_t address = message->address; - uint8_t command = message->command; - uint8_t command_inverse = ~command; - - uint32_t* data = (void*) encoder->data; - *data |= address; + if (message->protocol == IrdaProtocolNEC) { + *data = (address | (address_inverse << 8)); + } else if (message->protocol == IrdaProtocolNECext) { + *data = (uint16_t) message->address; + } *data |= command << 16; *data |= command_inverse << 24; } @@ -67,10 +56,6 @@ IrdaStatus irda_encoder_nec_encode_repeat(IrdaCommonEncoder* encoder, uint32_t* return done ? IrdaStatusDone : IrdaStatusOk; } -void* irda_encoder_necext_alloc(void) { - return irda_common_encoder_alloc(&protocol_necext); -} - void* irda_encoder_nec_alloc(void) { return irda_common_encoder_alloc(&protocol_nec); } diff --git a/lib/irda/encoder_decoder/nec/irda_nec_spec.c b/lib/irda/encoder_decoder/nec/irda_nec_spec.c new file mode 100644 index 00000000..707e3595 --- /dev/null +++ b/lib/irda/encoder_decoder/nec/irda_nec_spec.c @@ -0,0 +1,28 @@ +#include "../irda_i.h" +#include "irda_protocol_defs_i.h" + +static const IrdaProtocolSpecification irda_nec_protocol_specification = { + .name = "NEC", + .address_length = 2, + .command_length = 2, + .frequency = IRDA_COMMON_CARRIER_FREQUENCY, + .duty_cycle = IRDA_COMMON_DUTY_CYCLE, +}; + +static const IrdaProtocolSpecification irda_necext_protocol_specification = { + .name = "NECext", + .address_length = 4, + .command_length = 2, + .frequency = IRDA_COMMON_CARRIER_FREQUENCY, + .duty_cycle = IRDA_COMMON_DUTY_CYCLE, +}; + +const IrdaProtocolSpecification* irda_nec_get_spec(IrdaProtocol protocol) { + if (protocol == IrdaProtocolNEC) + return &irda_nec_protocol_specification; + else if (protocol == IrdaProtocolNECext) + return &irda_necext_protocol_specification; + else + return NULL; +} + diff --git a/lib/irda/encoder_decoder/rc5/irda_decoder_rc5.c b/lib/irda/encoder_decoder/rc5/irda_decoder_rc5.c new file mode 100644 index 00000000..704dc5ae --- /dev/null +++ b/lib/irda/encoder_decoder/rc5/irda_decoder_rc5.c @@ -0,0 +1,79 @@ +#include "irda.h" +#include +#include +#include +#include +#include "../irda_i.h" +#include "../irda_protocol_defs_i.h" + +typedef struct { + IrdaCommonDecoder* common_decoder; + bool toggle; +} IrdaRc5Decoder; + +bool irda_decoder_rc5_interpret(IrdaCommonDecoder* decoder) { + furi_assert(decoder); + + bool result = false; + uint32_t* data = (void*) &decoder->data[0]; + /* Manchester (inverse): + * 0->1 : 1 + * 1->0 : 0 + */ + decoder->data[0] = ~decoder->data[0]; + decoder->data[1] = ~decoder->data[1]; + + // MSB first + uint8_t address = reverse((uint8_t) decoder->data[0]) & 0x1F; + uint8_t command = (reverse((uint8_t) decoder->data[1]) >> 2) & 0x3F; + bool start_bit1 = *data & 0x01; + bool start_bit2 = *data & 0x02; + bool toggle = !!(*data & 0x04); + + if (start_bit1 == 1) { + IrdaProtocol protocol = start_bit2 ? IrdaProtocolRC5 : IrdaProtocolRC5X; + IrdaMessage* message = &decoder->message; + IrdaRc5Decoder *rc5_decoder = decoder->context; + bool *prev_toggle = &rc5_decoder->toggle; + if ((message->address == address) + && (message->command == command) + && (message->protocol == protocol)) { + message->repeat = (toggle == *prev_toggle); + } else { + message->repeat = false; + } + *prev_toggle = toggle; + message->command = command; + message->address = address; + message->protocol = protocol; + + result = true; + } + + return result; +} + +void* irda_decoder_rc5_alloc(void) { + IrdaRc5Decoder* decoder = furi_alloc(sizeof(IrdaRc5Decoder)); + decoder->toggle = false; + decoder->common_decoder = irda_common_decoder_alloc(&protocol_rc5); + irda_common_decoder_set_context(decoder->common_decoder, decoder); + return decoder; +} + +IrdaMessage* irda_decoder_rc5_decode(void* decoder, bool level, uint32_t duration) { + IrdaRc5Decoder* decoder_rc5 = decoder; + return irda_common_decode(decoder_rc5->common_decoder, level, duration); +} + +void irda_decoder_rc5_free(void* decoder) { + IrdaRc5Decoder* decoder_rc5 = decoder; + irda_common_decoder_free(decoder_rc5->common_decoder); + free(decoder_rc5); +} + +void irda_decoder_rc5_reset(void* decoder) { + IrdaRc5Decoder* decoder_rc5 = decoder; + irda_common_decoder_reset(decoder_rc5->common_decoder); +} + diff --git a/lib/irda/encoder_decoder/rc5/irda_encoder_rc5.c b/lib/irda/encoder_decoder/rc5/irda_encoder_rc5.c new file mode 100644 index 00000000..e6fa9f0d --- /dev/null +++ b/lib/irda/encoder_decoder/rc5/irda_encoder_rc5.c @@ -0,0 +1,55 @@ +#include "furi/memmgr.h" +#include "irda.h" +#include "common/irda_common_i.h" +#include "irda_protocol_defs_i.h" +#include +#include "../irda_i.h" + +typedef struct IrdaEncoderRC5 { + IrdaCommonEncoder* common_encoder; + bool toggle_bit; +} IrdaEncoderRC5; + +void irda_encoder_rc5_reset(void* encoder_ptr, const IrdaMessage* message) { + furi_assert(encoder_ptr); + + IrdaEncoderRC5* encoder = encoder_ptr; + IrdaCommonEncoder* common_encoder = encoder->common_encoder; + irda_common_encoder_reset(common_encoder); + + uint32_t* data = (void*) common_encoder->data; + /* RC5 */ + *data |= 0x01; // start bit + if (message->protocol == IrdaProtocolRC5) { + *data |= 0x02; // start bit + } + *data |= encoder->toggle_bit ? 0x04 : 0; + *data |= (reverse(message->address) >> 3) << 3; /* address 5 bit */ + *data |= (reverse(message->command) >> 2) << 8; /* command 6 bit */ + + common_encoder->data[0] = ~common_encoder->data[0]; + common_encoder->data[1] = ~common_encoder->data[1]; + + encoder->toggle_bit ^= 1; +} + +IrdaStatus irda_encoder_rc5_encode(void* encoder_ptr, uint32_t* duration, bool* level) { + IrdaEncoderRC5* encoder = encoder_ptr; + return irda_common_encode(encoder->common_encoder, duration, level); +} + +void* irda_encoder_rc5_alloc(void) { + IrdaEncoderRC5* encoder = furi_alloc(sizeof(IrdaEncoderRC5)); + encoder->common_encoder = irda_common_encoder_alloc(&protocol_rc5); + encoder->toggle_bit = false; + return encoder; +} + +void irda_encoder_rc5_free(void* encoder_ptr) { + furi_assert(encoder_ptr); + + IrdaEncoderRC5* encoder = encoder_ptr; + free(encoder->common_encoder); + free(encoder); +} + diff --git a/lib/irda/encoder_decoder/rc5/irda_rc5_spec.c b/lib/irda/encoder_decoder/rc5/irda_rc5_spec.c new file mode 100644 index 00000000..565b328c --- /dev/null +++ b/lib/irda/encoder_decoder/rc5/irda_rc5_spec.c @@ -0,0 +1,28 @@ +#include "../irda_i.h" +#include "irda_protocol_defs_i.h" + +static const IrdaProtocolSpecification irda_rc5_protocol_specification = { + .name = "RC5", + .address_length = 2, + .command_length = 2, + .frequency = IRDA_RC5_CARRIER_FREQUENCY, + .duty_cycle = IRDA_RC5_DUTY_CYCLE, +}; + +static const IrdaProtocolSpecification irda_rc5x_protocol_specification = { + .name = "RC5X", + .address_length = 2, + .command_length = 2, + .frequency = IRDA_RC5_CARRIER_FREQUENCY, + .duty_cycle = IRDA_RC5_DUTY_CYCLE, +}; + +const IrdaProtocolSpecification* irda_rc5_get_spec(IrdaProtocol protocol) { + if (protocol == IrdaProtocolRC5) + return &irda_rc5_protocol_specification; + else if (protocol == IrdaProtocolRC5X) + return &irda_rc5x_protocol_specification; + else + return NULL; +} + diff --git a/lib/irda/encoder_decoder/rc6/irda_decoder_rc6.c b/lib/irda/encoder_decoder/rc6/irda_decoder_rc6.c index 96246357..d561adad 100644 --- a/lib/irda/encoder_decoder/rc6/irda_decoder_rc6.c +++ b/lib/irda/encoder_decoder/rc6/irda_decoder_rc6.c @@ -37,6 +37,7 @@ bool irda_decoder_rc6_interpret(IrdaCommonDecoder* decoder) { *prev_toggle = toggle; message->command = command; message->address = address; + message->protocol = IrdaProtocolRC6; result = true; } diff --git a/lib/irda/encoder_decoder/rc6/irda_encoder_rc6.c b/lib/irda/encoder_decoder/rc6/irda_encoder_rc6.c index 6b534805..2d099b7d 100644 --- a/lib/irda/encoder_decoder/rc6/irda_encoder_rc6.c +++ b/lib/irda/encoder_decoder/rc6/irda_encoder_rc6.c @@ -1,6 +1,6 @@ #include "furi/memmgr.h" #include "irda.h" -#include "irda_common_i.h" +#include "common/irda_common_i.h" #include "irda_protocol_defs_i.h" #include #include "../irda_i.h" diff --git a/lib/irda/encoder_decoder/rc6/irda_rc6_spec.c b/lib/irda/encoder_decoder/rc6/irda_rc6_spec.c new file mode 100644 index 00000000..bd7977c5 --- /dev/null +++ b/lib/irda/encoder_decoder/rc6/irda_rc6_spec.c @@ -0,0 +1,18 @@ +#include "../irda_i.h" +#include "irda_protocol_defs_i.h" + +static const IrdaProtocolSpecification irda_rc6_protocol_specification = { + .name = "RC6", + .address_length = 2, + .command_length = 2, + .frequency = IRDA_RC6_CARRIER_FREQUENCY, + .duty_cycle = IRDA_RC6_DUTY_CYCLE, +}; + +const IrdaProtocolSpecification* irda_rc6_get_spec(IrdaProtocol protocol) { + if (protocol == IrdaProtocolRC6) + return &irda_rc6_protocol_specification; + else + return NULL; +} + diff --git a/lib/irda/encoder_decoder/samsung/irda_decoder_samsung.c b/lib/irda/encoder_decoder/samsung/irda_decoder_samsung.c index 7311403e..1a92de41 100644 --- a/lib/irda/encoder_decoder/samsung/irda_decoder_samsung.c +++ b/lib/irda/encoder_decoder/samsung/irda_decoder_samsung.c @@ -1,3 +1,4 @@ +#include "irda.h" #include "irda_protocol_defs_i.h" #include #include @@ -17,6 +18,7 @@ bool irda_decoder_samsung32_interpret(IrdaCommonDecoder* decoder) { if ((address1 == address2) && (command == (uint8_t) ~command_inverse)) { decoder->message.command = command; decoder->message.address = address1; + decoder->message.protocol = IrdaProtocolSamsung32; decoder->message.repeat = false; result = true; } diff --git a/lib/irda/encoder_decoder/samsung/irda_encoder_samsung.c b/lib/irda/encoder_decoder/samsung/irda_encoder_samsung.c index 016a1271..5a3c5f50 100644 --- a/lib/irda/encoder_decoder/samsung/irda_encoder_samsung.c +++ b/lib/irda/encoder_decoder/samsung/irda_encoder_samsung.c @@ -1,5 +1,5 @@ #include "furi/check.h" -#include "irda_common_i.h" +#include "common/irda_common_i.h" #include #include "../irda_i.h" #include "irda_protocol_defs_i.h" diff --git a/lib/irda/encoder_decoder/samsung/irda_samsung_spec.c b/lib/irda/encoder_decoder/samsung/irda_samsung_spec.c new file mode 100644 index 00000000..2043ce0a --- /dev/null +++ b/lib/irda/encoder_decoder/samsung/irda_samsung_spec.c @@ -0,0 +1,18 @@ +#include "../irda_i.h" +#include "irda_protocol_defs_i.h" + +static const IrdaProtocolSpecification irda_samsung32_protocol_specification = { + .name = "Samsung32", + .address_length = 2, + .command_length = 2, + .frequency = IRDA_COMMON_CARRIER_FREQUENCY, + .duty_cycle = IRDA_COMMON_DUTY_CYCLE, +}; + +const IrdaProtocolSpecification* irda_samsung32_get_spec(IrdaProtocol protocol) { + if (protocol == IrdaProtocolSamsung32) + return &irda_samsung32_protocol_specification; + else + return NULL; +} + diff --git a/lib/irda/worker/irda_worker.c b/lib/irda/worker/irda_worker.c index 62d4363f..6d4f0f4b 100644 --- a/lib/irda/worker/irda_worker.c +++ b/lib/irda/worker/irda_worker.c @@ -267,10 +267,10 @@ void irda_worker_rx_stop(IrdaWorker* instance) { osEventFlagsSet(instance->events, IRDA_WORKER_EXIT); furi_thread_join(instance->thread); - BaseType_t xReturn = pdFAIL; - xReturn = xStreamBufferReset(instance->stream); + BaseType_t xReturn = xStreamBufferReset(instance->stream); furi_assert(xReturn == pdPASS); - instance->state = IrdaWorkerStateIdle; + (void)xReturn; + instance->state = IrdaWorkerStateIdle; } @@ -424,6 +424,7 @@ static bool irda_worker_tx_fill_buffer(IrdaWorker* instance) { } uint32_t written_size = xStreamBufferSend(instance->stream, &timing, sizeof(IrdaWorkerTiming), 0); furi_assert(sizeof(IrdaWorkerTiming) == written_size); + (void)written_size; } return new_data_available; @@ -528,6 +529,7 @@ void irda_worker_tx_stop(IrdaWorker* instance) { BaseType_t xReturn = pdFAIL; xReturn = xStreamBufferReset(instance->stream); furi_assert(xReturn == pdPASS); + (void)xReturn; instance->state = IrdaWorkerStateIdle; } diff --git a/lib/nfc_protocols/emv_decoder.c b/lib/nfc_protocols/emv_decoder.c index cab0f91a..cf8311a0 100755 --- a/lib/nfc_protocols/emv_decoder.c +++ b/lib/nfc_protocols/emv_decoder.c @@ -63,6 +63,14 @@ static uint16_t emv_parse_TLV(uint8_t* dest, uint8_t* src, uint16_t* idx) { return len; } +static bool emv_decode_search_tag_u16_r(uint16_t tag, uint8_t* buff, uint16_t* idx) { + if((buff[*idx] << 8 | buff[*idx + 1]) == tag) { + *idx = *idx + 3; + return true; + } + return false; +} + uint16_t emv_prepare_select_ppse(uint8_t* dest) { const uint8_t emv_select_ppse[] = { 0x00, 0xA4, // SELECT ppse @@ -219,10 +227,15 @@ bool emv_decode_read_sfi_record(uint8_t* buff, uint16_t len, EmvApplication* app if(buff[i] == EMV_TAG_PAN) { memcpy(app->card_number, &buff[i + 2], 8); pan_parsed = true; - } else if((buff[i] << 8 | buff[i + 1]) == EMV_TAG_EXP_DATE) { - i += 3; + } else if(emv_decode_search_tag_u16_r(EMV_TAG_EXP_DATE, buff, &i)) { app->exp_year = buff[i++]; app->exp_month = buff[i++]; + } else if(emv_decode_search_tag_u16_r(EMV_TAG_CURRENCY_CODE, buff, &i)) { + app->currency_code = (buff[i] << 8) | buff[i + 1]; + i += 2; + } else if(emv_decode_search_tag_u16_r(EMV_TAG_COUNTRY_CODE, buff, &i)) { + app->country_code = (buff[i] << 8) | buff[i + 1]; + i += 2; } } return pan_parsed; diff --git a/lib/nfc_protocols/emv_decoder.h b/lib/nfc_protocols/emv_decoder.h index b01f5325..c1b4e35b 100755 --- a/lib/nfc_protocols/emv_decoder.h +++ b/lib/nfc_protocols/emv_decoder.h @@ -17,6 +17,8 @@ #define EMV_TAG_PAN 0x5A #define EMV_TAG_AFL 0x94 #define EMV_TAG_EXP_DATE 0x5F24 +#define EMV_TAG_COUNTRY_CODE 0x5F28 +#define EMV_TAG_CURRENCY_CODE 0x9F42 #define EMV_TAG_CARDHOLDER_NAME 0x5F20 typedef struct { @@ -39,7 +41,8 @@ typedef struct { uint8_t card_number[8]; uint8_t exp_month; uint8_t exp_year; - char crdholder_name[32]; + uint16_t country_code; + uint16_t currency_code; APDU pdol; APDU afl; } EmvApplication; diff --git a/lib/subghz/protocols/subghz_protocol.c b/lib/subghz/protocols/subghz_protocol.c index f0b93066..c2e3efec 100644 --- a/lib/subghz/protocols/subghz_protocol.c +++ b/lib/subghz/protocols/subghz_protocol.c @@ -31,7 +31,6 @@ typedef enum { SubGhzProtocolTypeMax, } SubGhzProtocolType; - struct SubGhzProtocol { SubGhzKeystore* keystore; @@ -49,7 +48,7 @@ static void subghz_protocol_text_rx_callback(SubGhzProtocolCommon* parser, void* string_t output; string_init(output); subghz_protocol_common_to_str((SubGhzProtocolCommon*)parser, output); - if (instance->text_callback) { + if(instance->text_callback) { instance->text_callback(output, instance->text_callback_context); } else { printf(string_get_cstr(output)); @@ -59,9 +58,9 @@ static void subghz_protocol_text_rx_callback(SubGhzProtocolCommon* parser, void* static void subghz_protocol_parser_rx_callback(SubGhzProtocolCommon* parser, void* context) { SubGhzProtocol* instance = context; - if (instance->parser_callback) { + if(instance->parser_callback) { instance->parser_callback(parser, instance->parser_callback_context); - } + } } SubGhzProtocol* subghz_protocol_alloc() { @@ -69,16 +68,26 @@ SubGhzProtocol* subghz_protocol_alloc() { instance->keystore = subghz_keystore_alloc(); - instance->protocols[SubGhzProtocolTypeCame] =(SubGhzProtocolCommon*)subghz_protocol_came_alloc(); - instance->protocols[SubGhzProtocolTypeKeeloq] = (SubGhzProtocolCommon*)subghz_protocol_keeloq_alloc(instance->keystore); - instance->protocols[SubGhzProtocolTypePrinceton] = (SubGhzProtocolCommon*)subghz_decoder_princeton_alloc(); - instance->protocols[SubGhzProtocolTypeNiceFlo] = (SubGhzProtocolCommon*)subghz_protocol_nice_flo_alloc(); - instance->protocols[SubGhzProtocolTypeNiceFlorS] = (SubGhzProtocolCommon*)subghz_protocol_nice_flor_s_alloc(); - instance->protocols[SubGhzProtocolTypeGateTX] = (SubGhzProtocolCommon*)subghz_protocol_gate_tx_alloc(); - instance->protocols[SubGhzProtocolTypeIDo] = (SubGhzProtocolCommon*)subghz_protocol_ido_alloc(); - instance->protocols[SubGhzProtocolTypeFaacSLH] = (SubGhzProtocolCommon*)subghz_protocol_faac_slh_alloc(); - instance->protocols[SubGhzProtocolTypeNeroSketch] = (SubGhzProtocolCommon*)subghz_protocol_nero_sketch_alloc(); - instance->protocols[SubGhzProtocolTypeStarLine] = (SubGhzProtocolCommon*)subghz_protocol_star_line_alloc(instance->keystore); + instance->protocols[SubGhzProtocolTypeCame] = + (SubGhzProtocolCommon*)subghz_protocol_came_alloc(); + instance->protocols[SubGhzProtocolTypeKeeloq] = + (SubGhzProtocolCommon*)subghz_protocol_keeloq_alloc(instance->keystore); + instance->protocols[SubGhzProtocolTypePrinceton] = + (SubGhzProtocolCommon*)subghz_decoder_princeton_alloc(); + instance->protocols[SubGhzProtocolTypeNiceFlo] = + (SubGhzProtocolCommon*)subghz_protocol_nice_flo_alloc(); + instance->protocols[SubGhzProtocolTypeNiceFlorS] = + (SubGhzProtocolCommon*)subghz_protocol_nice_flor_s_alloc(); + instance->protocols[SubGhzProtocolTypeGateTX] = + (SubGhzProtocolCommon*)subghz_protocol_gate_tx_alloc(); + instance->protocols[SubGhzProtocolTypeIDo] = + (SubGhzProtocolCommon*)subghz_protocol_ido_alloc(); + instance->protocols[SubGhzProtocolTypeFaacSLH] = + (SubGhzProtocolCommon*)subghz_protocol_faac_slh_alloc(); + instance->protocols[SubGhzProtocolTypeNeroSketch] = + (SubGhzProtocolCommon*)subghz_protocol_nero_sketch_alloc(); + instance->protocols[SubGhzProtocolTypeStarLine] = + (SubGhzProtocolCommon*)subghz_protocol_star_line_alloc(instance->keystore); return instance; } @@ -87,15 +96,23 @@ void subghz_protocol_free(SubGhzProtocol* instance) { furi_assert(instance); subghz_protocol_came_free((SubGhzProtocolCame*)instance->protocols[SubGhzProtocolTypeCame]); - subghz_protocol_keeloq_free((SubGhzProtocolKeeloq*)instance->protocols[SubGhzProtocolTypeKeeloq]); - subghz_decoder_princeton_free((SubGhzDecoderPrinceton*)instance->protocols[SubGhzProtocolTypePrinceton]); - subghz_protocol_nice_flo_free((SubGhzProtocolNiceFlo*)instance->protocols[SubGhzProtocolTypeNiceFlo]); - subghz_protocol_nice_flor_s_free((SubGhzProtocolNiceFlorS*)instance->protocols[SubGhzProtocolTypeNiceFlorS]); - subghz_protocol_gate_tx_free((SubGhzProtocolGateTX*)instance->protocols[SubGhzProtocolTypeGateTX]); + subghz_protocol_keeloq_free( + (SubGhzProtocolKeeloq*)instance->protocols[SubGhzProtocolTypeKeeloq]); + subghz_decoder_princeton_free( + (SubGhzDecoderPrinceton*)instance->protocols[SubGhzProtocolTypePrinceton]); + subghz_protocol_nice_flo_free( + (SubGhzProtocolNiceFlo*)instance->protocols[SubGhzProtocolTypeNiceFlo]); + subghz_protocol_nice_flor_s_free( + (SubGhzProtocolNiceFlorS*)instance->protocols[SubGhzProtocolTypeNiceFlorS]); + subghz_protocol_gate_tx_free( + (SubGhzProtocolGateTX*)instance->protocols[SubGhzProtocolTypeGateTX]); subghz_protocol_ido_free((SubGhzProtocolIDo*)instance->protocols[SubGhzProtocolTypeIDo]); - subghz_protocol_faac_slh_free((SubGhzProtocolFaacSLH*)instance->protocols[SubGhzProtocolTypeFaacSLH]); - subghz_protocol_nero_sketch_free((SubGhzProtocolNeroSketch*)instance->protocols[SubGhzProtocolTypeNeroSketch]); - subghz_protocol_star_line_free((SubGhzProtocolStarLine*)instance->protocols[SubGhzProtocolTypeStarLine]); + subghz_protocol_faac_slh_free( + (SubGhzProtocolFaacSLH*)instance->protocols[SubGhzProtocolTypeFaacSLH]); + subghz_protocol_nero_sketch_free( + (SubGhzProtocolNeroSketch*)instance->protocols[SubGhzProtocolTypeNeroSketch]); + subghz_protocol_star_line_free( + (SubGhzProtocolStarLine*)instance->protocols[SubGhzProtocolTypeStarLine]); subghz_keystore_free(instance->keystore); @@ -115,32 +132,40 @@ SubGhzProtocolCommon* subghz_protocol_get_by_name(SubGhzProtocol* instance, cons return result; } -void subghz_protocol_enable_dump_text(SubGhzProtocol* instance, SubGhzProtocolTextCallback callback, void* context) { +void subghz_protocol_enable_dump_text( + SubGhzProtocol* instance, + SubGhzProtocolTextCallback callback, + void* context) { furi_assert(instance); for(size_t i = 0; i < SubGhzProtocolTypeMax; i++) { - subghz_protocol_common_set_callback(instance->protocols[i], subghz_protocol_text_rx_callback, instance); + subghz_protocol_common_set_callback( + instance->protocols[i], subghz_protocol_text_rx_callback, instance); } instance->text_callback = callback; instance->text_callback_context = context; } -void subghz_protocol_enable_dump(SubGhzProtocol* instance, SubGhzProtocolCommonCallbackDump callback, void* context) { +void subghz_protocol_enable_dump( + SubGhzProtocol* instance, + SubGhzProtocolCommonCallbackDump callback, + void* context) { furi_assert(instance); for(size_t i = 0; i < SubGhzProtocolTypeMax; i++) { - subghz_protocol_common_set_callback(instance->protocols[i], subghz_protocol_parser_rx_callback, instance); + subghz_protocol_common_set_callback( + instance->protocols[i], subghz_protocol_parser_rx_callback, instance); } instance->parser_callback = callback; instance->parser_callback_context = context; } - void subghz_protocol_load_nice_flor_s_file(SubGhzProtocol* instance, const char* file_name) { // subghz_protocol_nice_flor_s_name_file(instance->nice_flor_s, file_name); - subghz_protocol_nice_flor_s_name_file((SubGhzProtocolNiceFlorS*) instance->protocols[SubGhzProtocolTypeNiceFlorS], file_name); + subghz_protocol_nice_flor_s_name_file( + (SubGhzProtocolNiceFlorS*)instance->protocols[SubGhzProtocolTypeNiceFlorS], file_name); } void subghz_protocol_load_keeloq_file(SubGhzProtocol* instance, const char* file_name) { @@ -148,29 +173,51 @@ void subghz_protocol_load_keeloq_file(SubGhzProtocol* instance, const char* file } void subghz_protocol_reset(SubGhzProtocol* instance) { - subghz_protocol_came_reset((SubGhzProtocolCame*)instance->protocols[SubGhzProtocolTypeCame]); - subghz_protocol_keeloq_reset((SubGhzProtocolKeeloq*)instance->protocols[SubGhzProtocolTypeKeeloq]); - subghz_decoder_princeton_reset((SubGhzDecoderPrinceton*)instance->protocols[SubGhzProtocolTypePrinceton]); - subghz_protocol_nice_flo_reset((SubGhzProtocolNiceFlo*)instance->protocols[SubGhzProtocolTypeNiceFlo]); - subghz_protocol_nice_flor_s_reset((SubGhzProtocolNiceFlorS*)instance->protocols[SubGhzProtocolTypeNiceFlorS]); - subghz_protocol_gate_tx_reset((SubGhzProtocolGateTX*)instance->protocols[SubGhzProtocolTypeGateTX]); + subghz_protocol_keeloq_reset( + (SubGhzProtocolKeeloq*)instance->protocols[SubGhzProtocolTypeKeeloq]); + subghz_decoder_princeton_reset( + (SubGhzDecoderPrinceton*)instance->protocols[SubGhzProtocolTypePrinceton]); + subghz_protocol_nice_flo_reset( + (SubGhzProtocolNiceFlo*)instance->protocols[SubGhzProtocolTypeNiceFlo]); + subghz_protocol_nice_flor_s_reset( + (SubGhzProtocolNiceFlorS*)instance->protocols[SubGhzProtocolTypeNiceFlorS]); + subghz_protocol_gate_tx_reset( + (SubGhzProtocolGateTX*)instance->protocols[SubGhzProtocolTypeGateTX]); subghz_protocol_ido_reset((SubGhzProtocolIDo*)instance->protocols[SubGhzProtocolTypeIDo]); - subghz_protocol_faac_slh_reset((SubGhzProtocolFaacSLH*)instance->protocols[SubGhzProtocolTypeFaacSLH]); - subghz_protocol_nero_sketch_reset((SubGhzProtocolNeroSketch*)instance->protocols[SubGhzProtocolTypeNeroSketch]); - subghz_protocol_star_line_reset((SubGhzProtocolStarLine*)instance->protocols[SubGhzProtocolTypeStarLine]); + subghz_protocol_faac_slh_reset( + (SubGhzProtocolFaacSLH*)instance->protocols[SubGhzProtocolTypeFaacSLH]); + subghz_protocol_nero_sketch_reset( + (SubGhzProtocolNeroSketch*)instance->protocols[SubGhzProtocolTypeNeroSketch]); + subghz_protocol_star_line_reset( + (SubGhzProtocolStarLine*)instance->protocols[SubGhzProtocolTypeStarLine]); } void subghz_protocol_parse(SubGhzProtocol* instance, bool level, uint32_t duration) { - - subghz_protocol_came_parse((SubGhzProtocolCame*)instance->protocols[SubGhzProtocolTypeCame], level, duration); - subghz_protocol_keeloq_parse((SubGhzProtocolKeeloq*)instance->protocols[SubGhzProtocolTypeKeeloq], level, duration); - subghz_decoder_princeton_parse((SubGhzDecoderPrinceton*)instance->protocols[SubGhzProtocolTypePrinceton], level, duration); - subghz_protocol_nice_flo_parse((SubGhzProtocolNiceFlo*)instance->protocols[SubGhzProtocolTypeNiceFlo], level, duration); - subghz_protocol_nice_flor_s_parse((SubGhzProtocolNiceFlorS*)instance->protocols[SubGhzProtocolTypeNiceFlorS], level, duration); - subghz_protocol_gate_tx_parse((SubGhzProtocolGateTX*)instance->protocols[SubGhzProtocolTypeGateTX], level, duration); - subghz_protocol_ido_parse((SubGhzProtocolIDo*)instance->protocols[SubGhzProtocolTypeIDo], level, duration); - subghz_protocol_faac_slh_parse((SubGhzProtocolFaacSLH*)instance->protocols[SubGhzProtocolTypeFaacSLH], level, duration); - subghz_protocol_nero_sketch_parse((SubGhzProtocolNeroSketch*)instance->protocols[SubGhzProtocolTypeNeroSketch], level, duration); - subghz_protocol_star_line_parse((SubGhzProtocolStarLine*)instance->protocols[SubGhzProtocolTypeStarLine], level, duration); + subghz_protocol_came_parse( + (SubGhzProtocolCame*)instance->protocols[SubGhzProtocolTypeCame], level, duration); + subghz_protocol_keeloq_parse( + (SubGhzProtocolKeeloq*)instance->protocols[SubGhzProtocolTypeKeeloq], level, duration); + subghz_decoder_princeton_parse( + (SubGhzDecoderPrinceton*)instance->protocols[SubGhzProtocolTypePrinceton], + level, + duration); + subghz_protocol_nice_flo_parse( + (SubGhzProtocolNiceFlo*)instance->protocols[SubGhzProtocolTypeNiceFlo], level, duration); + subghz_protocol_nice_flor_s_parse( + (SubGhzProtocolNiceFlorS*)instance->protocols[SubGhzProtocolTypeNiceFlorS], + level, + duration); + subghz_protocol_gate_tx_parse( + (SubGhzProtocolGateTX*)instance->protocols[SubGhzProtocolTypeGateTX], level, duration); + subghz_protocol_ido_parse( + (SubGhzProtocolIDo*)instance->protocols[SubGhzProtocolTypeIDo], level, duration); + subghz_protocol_faac_slh_parse( + (SubGhzProtocolFaacSLH*)instance->protocols[SubGhzProtocolTypeFaacSLH], level, duration); + subghz_protocol_nero_sketch_parse( + (SubGhzProtocolNeroSketch*)instance->protocols[SubGhzProtocolTypeNeroSketch], + level, + duration); + subghz_protocol_star_line_parse( + (SubGhzProtocolStarLine*)instance->protocols[SubGhzProtocolTypeStarLine], level, duration); } diff --git a/lib/subghz/protocols/subghz_protocol_came.c b/lib/subghz/protocols/subghz_protocol_came.c index 330a1509..5d3e5f4c 100644 --- a/lib/subghz/protocols/subghz_protocol_came.c +++ b/lib/subghz/protocols/subghz_protocol_came.c @@ -23,10 +23,12 @@ SubGhzProtocolCame* subghz_protocol_came_alloc() { instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_came_to_str; instance->common.to_save_string = (SubGhzProtocolCommonGetStrSave)subghz_protocol_came_to_save_str; - instance->common.to_load_protocol= - (SubGhzProtocolCommonLoad)subghz_protocol_came_to_load_protocol; + instance->common.to_load_protocol_from_file= + (SubGhzProtocolCommonLoadFromFile)subghz_protocol_came_to_load_protocol_from_file; + instance->common.to_load_protocol = + (SubGhzProtocolCommonLoadFromRAW)subghz_decoder_came_to_load_protocol; instance->common.get_upload_protocol = - (SubGhzProtocolEncoderCommonGetUpLoad)subghz_protocol_came_send_key; + (SubGhzProtocolCommonEncoderGetUpLoad)subghz_protocol_came_send_key; return instance; } @@ -36,7 +38,7 @@ void subghz_protocol_came_free(SubGhzProtocolCame* instance) { free(instance); } -bool subghz_protocol_came_send_key(SubGhzProtocolCame* instance, SubGhzProtocolEncoderCommon* encoder){ +bool subghz_protocol_came_send_key(SubGhzProtocolCame* instance, SubGhzProtocolCommonEncoder* encoder){ furi_assert(instance); furi_assert(encoder); size_t index = 0; @@ -142,9 +144,9 @@ void subghz_protocol_came_to_str(SubGhzProtocolCame* instance, string_t output) string_cat_printf( output, - "%s %d Bit\r\n" - " KEY:0x%08lX\r\n" - " YEK:0x%08lX\r\n", + "%s %dbit\r\n" + "Key:0x%08lX\r\n" + "Yek:0x%08lX\r\n", instance->common.name, instance->common.code_last_count_bit, code_found_lo, @@ -163,7 +165,7 @@ void subghz_protocol_came_to_save_str(SubGhzProtocolCame* instance, string_t out (uint32_t)(instance->common.code_last_found & 0x00000000ffffffff)); } -bool subghz_protocol_came_to_load_protocol(FileWorker* file_worker, SubGhzProtocolCame* instance){ +bool subghz_protocol_came_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolCame* instance){ bool loaded = false; string_t temp_str; string_init(temp_str); @@ -199,3 +201,13 @@ bool subghz_protocol_came_to_load_protocol(FileWorker* file_worker, SubGhzProtoc return loaded; } + +void subghz_decoder_came_to_load_protocol( + SubGhzProtocolCame* instance, + void* context) { + furi_assert(context); + furi_assert(instance); + SubGhzProtocolCommonLoad* data = context; + instance->common.code_last_found = data->code_found; + instance->common.code_last_count_bit = data->code_count_bit; +} diff --git a/lib/subghz/protocols/subghz_protocol_came.h b/lib/subghz/protocols/subghz_protocol_came.h index 24810da4..ffe96835 100644 --- a/lib/subghz/protocols/subghz_protocol_came.h +++ b/lib/subghz/protocols/subghz_protocol_came.h @@ -19,10 +19,12 @@ void subghz_protocol_came_free(SubGhzProtocolCame* instance); /** Get upload protocol * * @param instance - SubGhzProtocolCame instance - * @param encoder - SubGhzProtocolEncoderCommon encoder + * @param encoder - SubGhzProtocolCommonEncoder encoder * @return bool */ -bool subghz_protocol_came_send_key(SubGhzProtocolCame* instance, SubGhzProtocolEncoderCommon* encoder); +bool subghz_protocol_came_send_key( + SubGhzProtocolCame* instance, + SubGhzProtocolCommonEncoder* encoder); /** Reset internal state * @param instance - SubGhzProtocolCame instance @@ -43,5 +45,26 @@ void subghz_protocol_came_parse(SubGhzProtocolCame* instance, bool level, uint32 */ void subghz_protocol_came_to_str(SubGhzProtocolCame* instance, string_t output); +/** Get a string to save the protocol + * + * @param instance - SubGhzProtocolCame instance + * @param output - the resulting string + */ void subghz_protocol_came_to_save_str(SubGhzProtocolCame* instance, string_t output); -bool subghz_protocol_came_to_load_protocol(FileWorker* file_worker, SubGhzProtocolCame* instance); + +/** Loading protocol from file + * + * @param file_worker - FileWorker file_worker + * @param instance - SubGhzProtocolCame instance + * @return bool + */ +bool subghz_protocol_came_to_load_protocol_from_file( + FileWorker* file_worker, + SubGhzProtocolCame* instance); + +/** Loading protocol from bin data + * + * @param instance - SubGhzProtocolCame instance + * @param context - SubGhzProtocolCommonLoad context + */ +void subghz_decoder_came_to_load_protocol(SubGhzProtocolCame* instance, void* context); \ No newline at end of file diff --git a/lib/subghz/protocols/subghz_protocol_common.c b/lib/subghz/protocols/subghz_protocol_common.c index 2c5f4f2e..dc3e4f09 100644 --- a/lib/subghz/protocols/subghz_protocol_common.c +++ b/lib/subghz/protocols/subghz_protocol_common.c @@ -3,27 +3,27 @@ #include -SubGhzProtocolEncoderCommon* subghz_protocol_encoder_common_alloc() { - SubGhzProtocolEncoderCommon* instance = furi_alloc(sizeof(SubGhzProtocolEncoderCommon)); +SubGhzProtocolCommonEncoder* subghz_protocol_encoder_common_alloc() { + SubGhzProtocolCommonEncoder* instance = furi_alloc(sizeof(SubGhzProtocolCommonEncoder)); instance->upload = furi_alloc(SUBGHZ_ENCODER_UPLOAD_MAX_SIZE * sizeof(LevelDuration)); instance->start = true; instance->repeat = 10; //default number of repeat return instance; } -void subghz_protocol_encoder_common_free(SubGhzProtocolEncoderCommon* instance) { +void subghz_protocol_encoder_common_free(SubGhzProtocolCommonEncoder* instance) { furi_assert(instance); free(instance->upload); free(instance); } -size_t subghz_encoder_common_get_repeat_left(SubGhzProtocolEncoderCommon* instance) { +size_t subghz_encoder_common_get_repeat_left(SubGhzProtocolCommonEncoder* instance) { furi_assert(instance); return instance->repeat; } LevelDuration subghz_protocol_encoder_common_yield(void* context) { - SubGhzProtocolEncoderCommon* instance = context; + SubGhzProtocolCommonEncoder* instance = context; if(instance->repeat == 0){ return level_duration_reset(); diff --git a/lib/subghz/protocols/subghz_protocol_common.h b/lib/subghz/protocols/subghz_protocol_common.h index 32a0f923..277f89fa 100644 --- a/lib/subghz/protocols/subghz_protocol_common.h +++ b/lib/subghz/protocols/subghz_protocol_common.h @@ -14,30 +14,37 @@ #define SUBGHZ_TX_PIN_LOW() #define DURATION_DIFF(x, y) ((x < y) ? (y - x) : (x - y)) -//#define SUBGHZ_APP_PATH_FOLDER "/ext/subghz/saved" #define SUBGHZ_APP_FOLDER "/any/subghz" #define SUBGHZ_APP_PATH_FOLDER "/any/subghz/saved" #define SUBGHZ_APP_EXTENSION ".sub" -#define SUBGHZ_ENCODER_UPLOAD_MAX_SIZE 512 +#define SUBGHZ_ENCODER_UPLOAD_MAX_SIZE 512 + +enum { + TYPE_PROTOCOL_UNKNOWN, + TYPE_PROTOCOL_STATIC, + TYPE_PROTOCOL_DYNAMIC, +}; -#define TYPE_PROTOCOL_STATIC 1u -#define TYPE_PROTOCOL_DYNAMIC 2u typedef struct SubGhzProtocolCommon SubGhzProtocolCommon; -typedef struct SubGhzProtocolEncoderCommon SubGhzProtocolEncoderCommon; +typedef struct SubGhzProtocolCommonEncoder SubGhzProtocolCommonEncoder; +typedef struct SubGhzProtocolCommonLoad SubGhzProtocolCommonLoad; typedef void (*SubGhzProtocolCommonCallback)(SubGhzProtocolCommon* parser, void* context); typedef void (*SubGhzProtocolCommonToStr)(SubGhzProtocolCommon* instance, string_t output); -//Save +//Get string to save typedef void (*SubGhzProtocolCommonGetStrSave)(SubGhzProtocolCommon* instance, string_t output); -//Load -typedef bool (*SubGhzProtocolCommonLoad)(FileWorker* file_worker, SubGhzProtocolCommon* instance); - +//Load protocol from file +typedef bool (*SubGhzProtocolCommonLoadFromFile)(FileWorker* file_worker, SubGhzProtocolCommon* instance); +//Load protocol +typedef void (*SubGhzProtocolCommonLoadFromRAW)(SubGhzProtocolCommon* instance, void* context); //Get upload encoder protocol -typedef bool (*SubGhzProtocolEncoderCommonGetUpLoad)(SubGhzProtocolCommon* instance, SubGhzProtocolEncoderCommon* encoder); +typedef bool (*SubGhzProtocolCommonEncoderGetUpLoad)( + SubGhzProtocolCommon* instance, + SubGhzProtocolCommonEncoder* encoder); struct SubGhzProtocolCommon { const char* name; @@ -65,13 +72,15 @@ struct SubGhzProtocolCommon { SubGhzProtocolCommonToStr to_string; /* Get string to save */ SubGhzProtocolCommonGetStrSave to_save_string; - /*Load protocol by file*/ - SubGhzProtocolCommonLoad to_load_protocol; - /*Get upload encoder protocol*/ - SubGhzProtocolEncoderCommonGetUpLoad get_upload_protocol; + /* Load protocol from file */ + SubGhzProtocolCommonLoadFromFile to_load_protocol_from_file; + /* Load protocol from RAW data */ + SubGhzProtocolCommonLoadFromRAW to_load_protocol; + /* Get upload encoder protocol */ + SubGhzProtocolCommonEncoderGetUpLoad get_upload_protocol; }; -struct SubGhzProtocolEncoderCommon { +struct SubGhzProtocolCommonEncoder { bool start; size_t repeat; size_t front; @@ -79,9 +88,38 @@ struct SubGhzProtocolEncoderCommon { LevelDuration* upload; }; -SubGhzProtocolEncoderCommon* subghz_protocol_encoder_common_alloc(); -void subghz_protocol_encoder_common_free(SubGhzProtocolEncoderCommon* instance); -size_t subghz_encoder_common_get_repeat_left(SubGhzProtocolEncoderCommon* instance); +struct SubGhzProtocolCommonLoad{ + uint64_t code_found; + uint8_t code_count_bit; + uint32_t param1; + uint32_t param2; + uint32_t param3; +}; + +/** Allocate SubGhzProtocolCommonEncoder + * + * @return SubGhzProtocolCommonEncoder* + */ +SubGhzProtocolCommonEncoder* subghz_protocol_encoder_common_alloc(); + +/** Free SubGhzProtocolCommonEncoder + * + * @param instance + */ +void subghz_protocol_encoder_common_free(SubGhzProtocolCommonEncoder* instance); + +/** Get count repeat left + * + * @param instance - SubGhzProtocolCommonEncoder instance + * @return count repeat left + */ +size_t subghz_encoder_common_get_repeat_left(SubGhzProtocolCommonEncoder* instance); + +/** Get LevelDuration this encoder step + * + * @param context - SubGhzProtocolCommonEncoder context + * @return LevelDuration this step + */ LevelDuration subghz_protocol_encoder_common_yield(void* context); /** Add data bit to code_found @@ -129,4 +167,11 @@ void subghz_protocol_common_set_callback( */ void subghz_protocol_common_to_str(SubGhzProtocolCommon* instance, string_t output); +/** Converting a string to a HEX array + * + * @param str - string data + * @param buff - uint8_t* buff + * @param len - size buff + * @return bool + */ bool subghz_protocol_common_read_hex(string_t str, uint8_t* buff, uint16_t len); diff --git a/lib/subghz/protocols/subghz_protocol_faac_slh.c b/lib/subghz/protocols/subghz_protocol_faac_slh.c index dff5b4fd..ee44ec76 100644 --- a/lib/subghz/protocols/subghz_protocol_faac_slh.c +++ b/lib/subghz/protocols/subghz_protocol_faac_slh.c @@ -15,6 +15,8 @@ SubGhzProtocolFaacSLH* subghz_protocol_faac_slh_alloc(void) { instance->common.te_delta = 100; instance->common.type_protocol = TYPE_PROTOCOL_DYNAMIC; instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_faac_slh_to_str; + instance->common.to_load_protocol = + (SubGhzProtocolCommonLoadFromRAW)subghz_decoder_faac_slh_to_load_protocol; return instance; } @@ -145,11 +147,11 @@ void subghz_protocol_faac_slh_to_str(SubGhzProtocolFaacSLH* instance, string_t o uint32_t code_hop = (code_found_reverse >>32) & 0xFFFFFFFF; string_cat_printf(output, - "%s, %d Bit\r\n" - " KEY:0x%lX%08lX\r\n" - " FIX:%08lX \r\n" - " HOP:%08lX \r\n" - " SN:%07lX BTN:%lX\r\n", + "%s %dbit\r\n" + "Key:0x%lX%08lX\r\n" + "Fix:%08lX \r\n" + "Hop:%08lX \r\n" + "Sn:%07lX Btn:%lX\r\n", instance->common.name, instance->common.code_last_count_bit, (uint32_t)(instance->common.code_last_found >> 32), @@ -157,4 +159,15 @@ void subghz_protocol_faac_slh_to_str(SubGhzProtocolFaacSLH* instance, string_t o code_fix, code_hop, instance->common.serial, instance->common.btn); +} + +void subghz_decoder_faac_slh_to_load_protocol( + SubGhzProtocolFaacSLH* instance, + void* context) { + furi_assert(context); + furi_assert(instance); + SubGhzProtocolCommonLoad* data = context; + instance->common.code_last_found = data->code_found; + instance->common.code_last_count_bit = data->code_count_bit; + subghz_protocol_faac_slh_check_remote_controller(instance); } \ No newline at end of file diff --git a/lib/subghz/protocols/subghz_protocol_faac_slh.h b/lib/subghz/protocols/subghz_protocol_faac_slh.h index 26b4ac08..cfd46061 100644 --- a/lib/subghz/protocols/subghz_protocol_faac_slh.h +++ b/lib/subghz/protocols/subghz_protocol_faac_slh.h @@ -49,3 +49,10 @@ void subghz_protocol_faac_slh_parse(SubGhzProtocolFaacSLH* instance, bool level, * @param output - output string */ void subghz_protocol_faac_slh_to_str(SubGhzProtocolFaacSLH* instance, string_t output); + +/** Loading protocol from bin data + * + * @param instance - SubGhzProtocolFaacSLH instance + * @param context - SubGhzProtocolCommonLoad context + */ +void subghz_decoder_faac_slh_to_load_protocol(SubGhzProtocolFaacSLH* instance, void* context); diff --git a/lib/subghz/protocols/subghz_protocol_gate_tx.c b/lib/subghz/protocols/subghz_protocol_gate_tx.c index d850d741..8e10d5f8 100644 --- a/lib/subghz/protocols/subghz_protocol_gate_tx.c +++ b/lib/subghz/protocols/subghz_protocol_gate_tx.c @@ -17,10 +17,12 @@ SubGhzProtocolGateTX* subghz_protocol_gate_tx_alloc(void) { instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_gate_tx_to_str; instance->common.to_save_string = (SubGhzProtocolCommonGetStrSave)subghz_protocol_gate_tx_to_save_str; - instance->common.to_load_protocol= - (SubGhzProtocolCommonLoad)subghz_protocol_gate_tx_to_load_protocol; + instance->common.to_load_protocol_from_file= + (SubGhzProtocolCommonLoadFromFile)subghz_protocol_gate_tx_to_load_protocol_from_file; + instance->common.to_load_protocol = + (SubGhzProtocolCommonLoadFromRAW)subghz_decoder_gate_tx_to_load_protocol; instance->common.get_upload_protocol = - (SubGhzProtocolEncoderCommonGetUpLoad)subghz_protocol_gate_tx_send_key; + (SubGhzProtocolCommonEncoderGetUpLoad)subghz_protocol_gate_tx_send_key; return instance; } @@ -29,7 +31,7 @@ void subghz_protocol_gate_tx_free(SubGhzProtocolGateTX* instance) { free(instance); } -bool subghz_protocol_gate_tx_send_key(SubGhzProtocolGateTX* instance, SubGhzProtocolEncoderCommon* encoder){ +bool subghz_protocol_gate_tx_send_key(SubGhzProtocolGateTX* instance, SubGhzProtocolCommonEncoder* encoder){ furi_assert(instance); furi_assert(encoder); size_t index = 0; @@ -133,9 +135,9 @@ void subghz_protocol_gate_tx_parse(SubGhzProtocolGateTX* instance, bool level, u void subghz_protocol_gate_tx_to_str(SubGhzProtocolGateTX* instance, string_t output) { subghz_protocol_gate_tx_check_remote_controller(instance); string_cat_printf(output, - "%s, %d Bit\r\n" - " KEY:%06lX\r\n" - " SN:%05lX BTN:%lX\r\n", + "%s %dbit\r\n" + "Key:%06lX\r\n" + "Sn:%05lX Btn:%lX\r\n", instance->common.name, instance->common.code_last_count_bit, (uint32_t)(instance->common.code_last_found & 0xFFFFFF), @@ -155,7 +157,7 @@ void subghz_protocol_gate_tx_to_save_str(SubGhzProtocolGateTX* instance, string_ (uint32_t)(instance->common.code_last_found & 0x00000000ffffffff)); } -bool subghz_protocol_gate_tx_to_load_protocol(FileWorker* file_worker, SubGhzProtocolGateTX* instance){ +bool subghz_protocol_gate_tx_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolGateTX* instance){ bool loaded = false; string_t temp_str; string_init(temp_str); @@ -192,3 +194,14 @@ bool subghz_protocol_gate_tx_to_load_protocol(FileWorker* file_worker, SubGhzPro return loaded; } + +void subghz_decoder_gate_tx_to_load_protocol( + SubGhzProtocolGateTX* instance, + void* context) { + furi_assert(context); + furi_assert(instance); + SubGhzProtocolCommonLoad* data = context; + instance->common.code_last_found = data->code_found; + instance->common.code_last_count_bit = data->code_count_bit; + subghz_protocol_gate_tx_check_remote_controller(instance); +} \ No newline at end of file diff --git a/lib/subghz/protocols/subghz_protocol_gate_tx.h b/lib/subghz/protocols/subghz_protocol_gate_tx.h index b5682d7d..79f3b9db 100644 --- a/lib/subghz/protocols/subghz_protocol_gate_tx.h +++ b/lib/subghz/protocols/subghz_protocol_gate_tx.h @@ -19,10 +19,10 @@ void subghz_protocol_gate_tx_free(SubGhzProtocolGateTX* instance); /** Get upload protocol * * @param instance - SubGhzProtocolCame instance - * @param encoder - SubGhzProtocolEncoderCommon encoder + * @param encoder - SubGhzProtocolCommonEncoder encoder * @return bool */ -bool subghz_protocol_gate_tx_send_key(SubGhzProtocolGateTX* instance, SubGhzProtocolEncoderCommon* encoder); +bool subghz_protocol_gate_tx_send_key(SubGhzProtocolGateTX* instance, SubGhzProtocolCommonEncoder* encoder); /** Reset internal state * @param instance - SubGhzProtocolGateTX instance @@ -43,5 +43,24 @@ void subghz_protocol_gate_tx_parse(SubGhzProtocolGateTX* instance, bool level, u */ void subghz_protocol_gate_tx_to_str(SubGhzProtocolGateTX* instance, string_t output); +/** Get a string to save the protocol + * + * @param instance - SubGhzProtocolGateTX instance + * @param output - the resulting string + */ void subghz_protocol_gate_tx_to_save_str(SubGhzProtocolGateTX* instance, string_t output); -bool subghz_protocol_gate_tx_to_load_protocol(FileWorker* file_worker, SubGhzProtocolGateTX* instance); + +/** Loading protocol from file + * + * @param file_worker - FileWorker file_worker + * @param instance - SubGhzProtocolGateTX instance + * @return bool + */ +bool subghz_protocol_gate_tx_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolGateTX* instance); + +/** Loading protocol from bin data + * + * @param instance - SubGhzProtocolGateTX instance + * @param context - SubGhzProtocolCommonLoad context + */ +void subghz_decoder_gate_tx_to_load_protocol(SubGhzProtocolGateTX* instance, void* context); diff --git a/lib/subghz/protocols/subghz_protocol_ido.c b/lib/subghz/protocols/subghz_protocol_ido.c index 95e571e3..a5d33f32 100644 --- a/lib/subghz/protocols/subghz_protocol_ido.c +++ b/lib/subghz/protocols/subghz_protocol_ido.c @@ -1,6 +1,5 @@ #include "subghz_protocol_ido.h" - struct SubGhzProtocolIDo { SubGhzProtocolCommon common; }; @@ -15,6 +14,8 @@ SubGhzProtocolIDo* subghz_protocol_ido_alloc(void) { instance->common.te_delta = 150; instance->common.type_protocol = TYPE_PROTOCOL_DYNAMIC; instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_ido_to_str; + instance->common.to_load_protocol = + (SubGhzProtocolCommonLoadFromRAW)subghz_decoder_ido_to_load_protocol; return instance; } @@ -30,7 +31,7 @@ void subghz_protocol_ido_free(SubGhzProtocolIDo* instance) { * @param bit - bit */ void subghz_protocol_ido_send_bit(SubGhzProtocolIDo* instance, uint8_t bit) { - if (bit) { + if(bit) { //send bit 1 SUBGHZ_TX_PIN_HIGH(); delay_us(instance->common.te_short); @@ -45,15 +46,19 @@ void subghz_protocol_ido_send_bit(SubGhzProtocolIDo* instance, uint8_t bit) { } } -void subghz_protocol_ido_send_key(SubGhzProtocolIDo* instance, uint64_t key, uint8_t bit,uint8_t repeat) { - while (repeat--) { +void subghz_protocol_ido_send_key( + SubGhzProtocolIDo* instance, + uint64_t key, + uint8_t bit, + uint8_t repeat) { + while(repeat--) { SUBGHZ_TX_PIN_HIGH(); //Send header delay_us(instance->common.te_short * 10); SUBGHZ_TX_PIN_LOW(); - delay_us(instance->common.te_short * 10); + delay_us(instance->common.te_short * 10); //Send key data - for (uint8_t i = bit; i > 0; i--) { + for(uint8_t i = bit; i > 0; i--) { subghz_protocol_ido_send_bit(instance, bit_read(key, i - 1)); } } @@ -68,7 +73,8 @@ void subghz_protocol_ido_reset(SubGhzProtocolIDo* instance) { * @param instance SubGhzProtocolIDo instance */ void subghz_protocol_ido_check_remote_controller(SubGhzProtocolIDo* instance) { - uint64_t code_found_reverse = subghz_protocol_common_reverse_key(instance->common.code_last_found, instance->common.code_last_count_bit); + uint64_t code_found_reverse = subghz_protocol_common_reverse_key( + instance->common.code_last_found, instance->common.code_last_count_bit); uint32_t code_fix = code_found_reverse & 0xFFFFFF; instance->common.serial = code_fix & 0xFFFFF; @@ -76,18 +82,18 @@ void subghz_protocol_ido_check_remote_controller(SubGhzProtocolIDo* instance) { } void subghz_protocol_ido_parse(SubGhzProtocolIDo* instance, bool level, uint32_t duration) { - switch (instance->common.parser_step) { + switch(instance->common.parser_step) { case 0: - if ((level) - && (DURATION_DIFF(duration,instance->common.te_short * 10)< instance->common.te_delta * 5)) { + if((level) && (DURATION_DIFF(duration, instance->common.te_short * 10) < + instance->common.te_delta * 5)) { instance->common.parser_step = 1; } else { instance->common.parser_step = 0; } break; case 1: - if ((!level) - && (DURATION_DIFF(duration,instance->common.te_short * 10)< instance->common.te_delta * 5)) { + if((!level) && (DURATION_DIFF(duration, instance->common.te_short * 10) < + instance->common.te_delta * 5)) { //Found Preambula instance->common.parser_step = 2; instance->common.code_found = 0; @@ -97,13 +103,16 @@ void subghz_protocol_ido_parse(SubGhzProtocolIDo* instance, bool level, uint32_t } break; case 2: - if (level) { - if (duration >= (instance->common.te_short * 5 + instance->common.te_delta)) { + if(level) { + if(duration >= (instance->common.te_short * 5 + instance->common.te_delta)) { instance->common.parser_step = 1; - if (instance->common.code_count_bit>= instance->common.code_min_count_bit_for_found) { + if(instance->common.code_count_bit >= + instance->common.code_min_count_bit_for_found) { instance->common.code_last_found = instance->common.code_found; instance->common.code_last_count_bit = instance->common.code_count_bit; - if (instance->common.callback) instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context); + if(instance->common.callback) + instance->common.callback( + (SubGhzProtocolCommon*)instance, instance->common.context); } instance->common.code_found = 0; instance->common.code_count_bit = 0; @@ -113,18 +122,22 @@ void subghz_protocol_ido_parse(SubGhzProtocolIDo* instance, bool level, uint32_t instance->common.parser_step = 3; } - }else{ + } else { instance->common.parser_step = 0; } break; case 3: - if(!level){ - if ((DURATION_DIFF(instance->common.te_last,instance->common.te_short)< instance->common.te_delta) - && (DURATION_DIFF(duration,instance->common.te_long)< instance->common.te_delta*3)) { + if(!level) { + if((DURATION_DIFF(instance->common.te_last, instance->common.te_short) < + instance->common.te_delta) && + (DURATION_DIFF(duration, instance->common.te_long) < + instance->common.te_delta * 3)) { subghz_protocol_common_add_bit(&instance->common, 0); instance->common.parser_step = 2; - } else if ((DURATION_DIFF(instance->common.te_last,instance->common.te_short )< instance->common.te_delta*3) - && (DURATION_DIFF(duration,instance->common.te_short)< instance->common.te_delta)) { + } else if( + (DURATION_DIFF(instance->common.te_last, instance->common.te_short) < + instance->common.te_delta * 3) && + (DURATION_DIFF(duration, instance->common.te_short) < instance->common.te_delta)) { subghz_protocol_common_add_bit(&instance->common, 1); instance->common.parser_step = 2; } else { @@ -139,21 +152,35 @@ void subghz_protocol_ido_parse(SubGhzProtocolIDo* instance, bool level, uint32_t void subghz_protocol_ido_to_str(SubGhzProtocolIDo* instance, string_t output) { subghz_protocol_ido_check_remote_controller(instance); - uint64_t code_found_reverse = subghz_protocol_common_reverse_key(instance->common.code_last_found, instance->common.code_last_count_bit); + uint64_t code_found_reverse = subghz_protocol_common_reverse_key( + instance->common.code_last_found, instance->common.code_last_count_bit); uint32_t code_fix = code_found_reverse & 0xFFFFFF; - uint32_t code_hop = (code_found_reverse >>24) & 0xFFFFFF; + uint32_t code_hop = (code_found_reverse >> 24) & 0xFFFFFF; - string_cat_printf(output, - "%s, %d Bit\r\n" - " KEY:0x%lX%08lX\r\n" - " FIX:%06lX \r\n" - " HOP:%06lX \r\n" - " SN:%05lX BTN:%lX\r\n", - instance->common.name, - instance->common.code_last_count_bit, - (uint32_t)(instance->common.code_last_found >> 32), - (uint32_t)instance->common.code_last_found, - code_fix, code_hop, - instance->common.serial, - instance->common.btn); + string_cat_printf( + output, + "%s %dbit\r\n" + "Key:0x%lX%08lX\r\n" + "Fix:%06lX \r\n" + "Hop:%06lX \r\n" + "Sn:%05lX Btn:%lX\r\n", + instance->common.name, + instance->common.code_last_count_bit, + (uint32_t)(instance->common.code_last_found >> 32), + (uint32_t)instance->common.code_last_found, + code_fix, + code_hop, + instance->common.serial, + instance->common.btn); +} + +void subghz_decoder_ido_to_load_protocol( + SubGhzProtocolIDo* instance, + void* context) { + furi_assert(context); + furi_assert(instance); + SubGhzProtocolCommonLoad* data = context; + instance->common.code_last_found = data->code_found; + instance->common.code_last_count_bit = data->code_count_bit; + subghz_protocol_ido_check_remote_controller(instance); } \ No newline at end of file diff --git a/lib/subghz/protocols/subghz_protocol_ido.h b/lib/subghz/protocols/subghz_protocol_ido.h index 35d26967..10b1ddb0 100644 --- a/lib/subghz/protocols/subghz_protocol_ido.h +++ b/lib/subghz/protocols/subghz_protocol_ido.h @@ -49,3 +49,10 @@ void subghz_protocol_ido_parse(SubGhzProtocolIDo* instance, bool level, uint32_t * @param output - output string */ void subghz_protocol_ido_to_str(SubGhzProtocolIDo* instance, string_t output); + +/** Loading protocol from bin data + * + * @param instance - SubGhzProtocolIDo instance + * @param context - SubGhzProtocolCommonLoad context + */ +void subghz_decoder_ido_to_load_protocol(SubGhzProtocolIDo* instance, void* context); diff --git a/lib/subghz/protocols/subghz_protocol_keeloq.c b/lib/subghz/protocols/subghz_protocol_keeloq.c index 6bbc9c80..875e6002 100644 --- a/lib/subghz/protocols/subghz_protocol_keeloq.c +++ b/lib/subghz/protocols/subghz_protocol_keeloq.c @@ -27,10 +27,12 @@ SubGhzProtocolKeeloq* subghz_protocol_keeloq_alloc(SubGhzKeystore* keystore) { instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_keeloq_to_str; instance->common.to_save_string = (SubGhzProtocolCommonGetStrSave)subghz_protocol_keeloq_to_save_str; + instance->common.to_load_protocol_from_file = + (SubGhzProtocolCommonLoadFromFile)subghz_protocol_keeloq_to_load_protocol_from_file; instance->common.to_load_protocol = - (SubGhzProtocolCommonLoad)subghz_protocol_keeloq_to_load_protocol; + (SubGhzProtocolCommonLoadFromRAW)subghz_decoder_keeloq_to_load_protocol; instance->common.get_upload_protocol = - (SubGhzProtocolEncoderCommonGetUpLoad)subghz_protocol_keeloq_send_key; + (SubGhzProtocolCommonEncoderGetUpLoad)subghz_protocol_keeloq_send_key; return instance; } @@ -63,7 +65,8 @@ uint8_t subghz_protocol_keeloq_check_remote_controller_selector( //Simple Learning decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key); if((decrypt >> 28 == btn) && - ((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial)) { + (((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial) || + ((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0))) { instance->manufacture_name = string_get_cstr(manufacture_code->name); instance->common.cnt = decrypt & 0x0000FFFF; return 1; @@ -76,7 +79,8 @@ uint8_t subghz_protocol_keeloq_check_remote_controller_selector( subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key); decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning); if((decrypt >> 28 == btn) && - ((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial)) { + (((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial) || + ((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0))) { instance->manufacture_name = string_get_cstr(manufacture_code->name); instance->common.cnt = decrypt & 0x0000FFFF; return 1; @@ -86,7 +90,8 @@ uint8_t subghz_protocol_keeloq_check_remote_controller_selector( // Simple Learning decrypt = subghz_protocol_keeloq_common_decrypt(hop, manufacture_code->key); if((decrypt >> 28 == btn) && - ((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial)) { + (((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial) || + ((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0))) { instance->manufacture_name = string_get_cstr(manufacture_code->name); instance->common.cnt = decrypt & 0x0000FFFF; return 1; @@ -100,7 +105,8 @@ uint8_t subghz_protocol_keeloq_check_remote_controller_selector( } decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_rev); if((decrypt >> 28 == btn) && - ((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial)) { + (((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial) || + ((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0))) { instance->manufacture_name = string_get_cstr(manufacture_code->name); instance->common.cnt = decrypt & 0x0000FFFF; return 1; @@ -112,7 +118,8 @@ uint8_t subghz_protocol_keeloq_check_remote_controller_selector( subghz_protocol_keeloq_common_normal_learning(fix, manufacture_code->key); decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning); if((decrypt >> 28 == btn) && - ((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial)) { + (((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial) || + ((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0))) { instance->manufacture_name = string_get_cstr(manufacture_code->name); instance->common.cnt = decrypt & 0x0000FFFF; return 1; @@ -127,7 +134,8 @@ uint8_t subghz_protocol_keeloq_check_remote_controller_selector( man_normal_learning = subghz_protocol_keeloq_common_normal_learning(fix, man_rev); decrypt = subghz_protocol_keeloq_common_decrypt(hop, man_normal_learning); if((decrypt >> 28 == btn) && - ((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial)) { + (((((uint16_t)(decrypt >> 16)) & 0x3FF) == end_serial) || + ((((uint16_t)(decrypt >> 16)) & 0x3FF) == 0))) { instance->manufacture_name = string_get_cstr(manufacture_code->name); instance->common.cnt = decrypt & 0x0000FFFF; return 1; @@ -165,9 +173,32 @@ void subghz_protocol_keeloq_check_remote_controller(SubGhzProtocolKeeloq* instan instance->common.serial = key_fix & 0x0FFFFFFF; instance->common.btn = key_fix >> 28; } -void subghz_protocol_keeloq_set_manufacture_name (void* context, const char* manufacture_name){ + +const char* subghz_protocol_keeloq_find_and_get_manufacture_name(void* context) { + SubGhzProtocolKeeloq* instance = context; + subghz_protocol_keeloq_check_remote_controller(instance); + return instance->manufacture_name; +} + +const char* subghz_protocol_keeloq_get_manufacture_name(void* context) { + SubGhzProtocolKeeloq* instance = context; + return instance->manufacture_name; +} + +bool subghz_protocol_keeloq_set_manufacture_name(void* context, const char* manufacture_name) { SubGhzProtocolKeeloq* instance = context; instance->manufacture_name = manufacture_name; + int res = 0; + for + M_EACH( + manufacture_code, + *subghz_keystore_get_data(instance->keystore), + SubGhzKeyArray_t) { + res = strcmp(string_get_cstr(manufacture_code->name), instance->manufacture_name); + if(res == 0) return true; + } + instance->manufacture_name = "Unknown"; + return false; } uint64_t subghz_protocol_keeloq_gen_key(void* context) { @@ -205,17 +236,24 @@ uint64_t subghz_protocol_keeloq_gen_key(void* context) { return subghz_protocol_common_reverse_key(yek, instance->common.code_last_count_bit); } -bool subghz_protocol_keeloq_send_key(SubGhzProtocolKeeloq* instance, SubGhzProtocolEncoderCommon* encoder){ +bool subghz_protocol_keeloq_send_key( + SubGhzProtocolKeeloq* instance, + SubGhzProtocolCommonEncoder* encoder) { furi_assert(instance); furi_assert(encoder); //gen new key instance->common.cnt++; instance->common.code_last_found = subghz_protocol_keeloq_gen_key(instance); - if(instance->common.callback)instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context); - + if(instance->common.callback) + instance->common.callback((SubGhzProtocolCommon*)instance, instance->common.context); + + if(!strcmp(instance->manufacture_name, "Unknown")) { + return false; + } + size_t index = 0; - encoder->size_upload =11*2+2+(instance->common.code_last_count_bit * 2) + 4; + encoder->size_upload = 11 * 2 + 2 + (instance->common.code_last_count_bit * 2) + 4; if(encoder->size_upload > SUBGHZ_ENCODER_UPLOAD_MAX_SIZE) return false; //Send header @@ -224,18 +262,23 @@ bool subghz_protocol_keeloq_send_key(SubGhzProtocolKeeloq* instance, SubGhzProto encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_short); } encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short); - encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_short*10); + encoder->upload[index++] = + level_duration_make(false, (uint32_t)instance->common.te_short * 10); //Send key data - for (uint8_t i = instance->common.code_last_count_bit; i > 0; i--) { - if(bit_read(instance->common.code_last_found, i - 1)){ + for(uint8_t i = instance->common.code_last_count_bit; i > 0; i--) { + if(bit_read(instance->common.code_last_found, i - 1)) { //send bit 1 - encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short); - encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_long); - }else{ + encoder->upload[index++] = + level_duration_make(true, (uint32_t)instance->common.te_short); + encoder->upload[index++] = + level_duration_make(false, (uint32_t)instance->common.te_long); + } else { //send bit 0 - encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_long); - encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_short); + encoder->upload[index++] = + level_duration_make(true, (uint32_t)instance->common.te_long); + encoder->upload[index++] = + level_duration_make(false, (uint32_t)instance->common.te_short); } } // +send 2 status bit @@ -247,7 +290,8 @@ bool subghz_protocol_keeloq_send_key(SubGhzProtocolKeeloq* instance, SubGhzProto // send end encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->common.te_short); - encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->common.te_short*40); + encoder->upload[index++] = + level_duration_make(false, (uint32_t)instance->common.te_short * 40); return true; } @@ -353,25 +397,26 @@ void subghz_protocol_keeloq_to_str(SubGhzProtocolKeeloq* instance, string_t outp uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff; string_cat_printf( output, - "%s, %d Bit\r\n" - "KEY:0x%lX%lX\r\n" - "FIX:%08lX MF:%s \r\n" - "HOP:%08lX \r\n" - "SN:%07lX CNT:%04X B:%02lX\r\n", + "%s %dbit\r\n" + "Key:0x%lX%lX\r\n" + "Fix:0x%08lX Cnt:%04X\r\n" + "Hop:0x%08lX Btn:%02lX\r\n" + "MF:%s\r\n" + "Sn:0x%07lX \r\n", instance->common.name, instance->common.code_last_count_bit, code_found_hi, code_found_lo, code_found_reverse_hi, - instance->manufacture_name, - code_found_reverse_lo, - instance->common.serial, instance->common.cnt, - instance->common.btn); + code_found_reverse_lo, + instance->common.btn, + instance->manufacture_name, + instance->common.serial); } void subghz_protocol_keeloq_to_save_str(SubGhzProtocolKeeloq* instance, string_t output) { - string_printf( + string_printf( output, "Protocol: %s\n" "Bit: %d\n" @@ -379,11 +424,10 @@ void subghz_protocol_keeloq_to_save_str(SubGhzProtocolKeeloq* instance, string_t instance->common.name, instance->common.code_last_count_bit, (uint32_t)(instance->common.code_last_found >> 32), - (uint32_t)(instance->common.code_last_found & 0xFFFFFFFF) - ); + (uint32_t)(instance->common.code_last_found & 0xFFFFFFFF)); } -bool subghz_protocol_keeloq_to_load_protocol( +bool subghz_protocol_keeloq_to_load_protocol_from_file( FileWorker* file_worker, SubGhzProtocolKeeloq* instance) { bool loaded = false; @@ -410,12 +454,12 @@ bool subghz_protocol_keeloq_to_load_protocol( // strlen("Key: ") = 5 string_right(temp_str, 5); - uint8_t buf_key[8]={0}; - if(!subghz_protocol_common_read_hex(temp_str, buf_key, 8)){ + uint8_t buf_key[8] = {0}; + if(!subghz_protocol_common_read_hex(temp_str, buf_key, 8)) { break; } - for(uint8_t i = 0; i < 8; i++){ + for(uint8_t i = 0; i < 8; i++) { instance->common.code_last_found = instance->common.code_last_found << 8 | buf_key[i]; } loaded = true; @@ -424,3 +468,12 @@ bool subghz_protocol_keeloq_to_load_protocol( return loaded; } + +void subghz_decoder_keeloq_to_load_protocol(SubGhzProtocolKeeloq* instance, void* context) { + furi_assert(context); + furi_assert(instance); + SubGhzProtocolCommonLoad* data = context; + instance->common.code_last_found = data->code_found; + instance->common.code_last_count_bit = data->code_count_bit; + subghz_protocol_keeloq_check_remote_controller(instance); +} diff --git a/lib/subghz/protocols/subghz_protocol_keeloq.h b/lib/subghz/protocols/subghz_protocol_keeloq.h index cd591980..1cbacd8c 100644 --- a/lib/subghz/protocols/subghz_protocol_keeloq.h +++ b/lib/subghz/protocols/subghz_protocol_keeloq.h @@ -18,12 +18,27 @@ SubGhzProtocolKeeloq* subghz_protocol_keeloq_alloc(SubGhzKeystore* keystore); */ void subghz_protocol_keeloq_free(SubGhzProtocolKeeloq* instance); +/** Find and get manufacture name + * + * @param context - SubGhzProtocolKeeloq context + * @return name - char* manufacture name + */ +const char* subghz_protocol_keeloq_find_and_get_manufacture_name(void* context); + +/** Get manufacture name + * + * @param context - SubGhzProtocolKeeloq context + * @return name - char* manufacture name + */ +const char* subghz_protocol_keeloq_get_manufacture_name(void* context); + /** Set manufacture name * * @param manufacture_name - manufacture name * @param context - SubGhzProtocolKeeloq context + * @return bool */ -void subghz_protocol_keeloq_set_manufacture_name(void* context, const char* manufacture_name); +bool subghz_protocol_keeloq_set_manufacture_name(void* context, const char* manufacture_name); /** Get key keeloq * @@ -35,10 +50,10 @@ uint64_t subghz_protocol_keeloq_gen_key(void* context); /** Get upload protocol * * @param instance - SubGhzProtocolCame instance - * @param encoder - SubGhzProtocolEncoderCommon encoder + * @param encoder - SubGhzProtocolCommonEncoder encoder * @return bool */ -bool subghz_protocol_keeloq_send_key(SubGhzProtocolKeeloq* instance, SubGhzProtocolEncoderCommon* encoder); +bool subghz_protocol_keeloq_send_key(SubGhzProtocolKeeloq* instance, SubGhzProtocolCommonEncoder* encoder); /** Reset internal state * @param instance - SubGhzProtocolKeeloq instance @@ -59,5 +74,24 @@ void subghz_protocol_keeloq_parse(SubGhzProtocolKeeloq* instance, bool level, ui */ void subghz_protocol_keeloq_to_str(SubGhzProtocolKeeloq* instance, string_t output); +/** Get a string to save the protocol + * + * @param instance - SubGhzProtocolKeeloq instance + * @param output - the resulting string + */ void subghz_protocol_keeloq_to_save_str(SubGhzProtocolKeeloq* instance, string_t output); -bool subghz_protocol_keeloq_to_load_protocol(FileWorker* file_worker, SubGhzProtocolKeeloq* instance); + +/** Loading protocol from file + * + * @param file_worker - FileWorker file_worker + * @param instance - SubGhzProtocolKeeloq instance + * @return bool + */ +bool subghz_protocol_keeloq_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolKeeloq* instance); + +/** Loading protocol from bin data + * + * @param instance - SubGhzProtocolKeeloq instance + * @param context - SubGhzProtocolCommonLoad context + */ +void subghz_decoder_keeloq_to_load_protocol(SubGhzProtocolKeeloq* instance, void* context); diff --git a/lib/subghz/protocols/subghz_protocol_nero_sketch.c b/lib/subghz/protocols/subghz_protocol_nero_sketch.c index 4b20b4cb..4663bc05 100644 --- a/lib/subghz/protocols/subghz_protocol_nero_sketch.c +++ b/lib/subghz/protocols/subghz_protocol_nero_sketch.c @@ -17,10 +17,12 @@ SubGhzProtocolNeroSketch* subghz_protocol_nero_sketch_alloc(void) { instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_nero_sketch_to_str; instance->common.to_save_string = (SubGhzProtocolCommonGetStrSave)subghz_protocol_nero_sketch_to_save_str; - instance->common.to_load_protocol= - (SubGhzProtocolCommonLoad)subghz_protocol_nero_sketch_to_load_protocol; + instance->common.to_load_protocol_from_file= + (SubGhzProtocolCommonLoadFromFile)subghz_protocol_nero_sketch_to_load_protocol_from_file; + instance->common.to_load_protocol = + (SubGhzProtocolCommonLoadFromRAW)subghz_decoder_nero_sketch_to_load_protocol; instance->common.get_upload_protocol = - (SubGhzProtocolEncoderCommonGetUpLoad)subghz_protocol_nero_sketch_send_key; + (SubGhzProtocolCommonEncoderGetUpLoad)subghz_protocol_nero_sketch_send_key; return instance; } @@ -30,7 +32,7 @@ void subghz_protocol_nero_sketch_free(SubGhzProtocolNeroSketch* instance) { free(instance); } -bool subghz_protocol_nero_sketch_send_key(SubGhzProtocolNeroSketch* instance, SubGhzProtocolEncoderCommon* encoder){ +bool subghz_protocol_nero_sketch_send_key(SubGhzProtocolNeroSketch* instance, SubGhzProtocolCommonEncoder* encoder){ furi_assert(instance); furi_assert(encoder); size_t index = 0; @@ -184,9 +186,9 @@ void subghz_protocol_nero_sketch_to_str(SubGhzProtocolNeroSketch* instance, stri uint32_t code_found_reverse_lo = code_found_reverse&0x00000000ffffffff; string_cat_printf(output, - "%s, %d Bit\r\n" - " KEY:0x%lX%08lX\r\n" - " YEK:0x%lX%08lX\r\n", + "%s %dbit\r\n" + "Key:0x%lX%08lX\r\n" + "Yek:0x%lX%08lX\r\n", instance->common.name, instance->common.code_last_count_bit, code_found_hi, @@ -212,7 +214,7 @@ void subghz_protocol_nero_sketch_to_save_str(SubGhzProtocolNeroSketch* instance, ); } -bool subghz_protocol_nero_sketch_to_load_protocol(FileWorker* file_worker, SubGhzProtocolNeroSketch* instance){ +bool subghz_protocol_nero_sketch_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolNeroSketch* instance){ bool loaded = false; string_t temp_str; string_init(temp_str); @@ -249,3 +251,13 @@ bool subghz_protocol_nero_sketch_to_load_protocol(FileWorker* file_worker, SubGh return loaded; } + +void subghz_decoder_nero_sketch_to_load_protocol( + SubGhzProtocolNeroSketch* instance, + void* context) { + furi_assert(context); + furi_assert(instance); + SubGhzProtocolCommonLoad* data = context; + instance->common.code_last_found = data->code_found; + instance->common.code_last_count_bit = data->code_count_bit; +} \ No newline at end of file diff --git a/lib/subghz/protocols/subghz_protocol_nero_sketch.h b/lib/subghz/protocols/subghz_protocol_nero_sketch.h index 170895c4..e8a19a50 100644 --- a/lib/subghz/protocols/subghz_protocol_nero_sketch.h +++ b/lib/subghz/protocols/subghz_protocol_nero_sketch.h @@ -19,10 +19,10 @@ void subghz_protocol_nero_sketch_free(SubGhzProtocolNeroSketch* instance); /** Get upload protocol * * @param instance - SubGhzProtocolCame instance - * @param encoder - SubGhzProtocolEncoderCommon encoder + * @param encoder - SubGhzProtocolCommonEncoder encoder * @return bool */ -bool subghz_protocol_nero_sketch_send_key(SubGhzProtocolNeroSketch* instance, SubGhzProtocolEncoderCommon* encoder); +bool subghz_protocol_nero_sketch_send_key(SubGhzProtocolNeroSketch* instance, SubGhzProtocolCommonEncoder* encoder); /** Reset internal state * @param instance - SubGhzProtocolNeroSketch instance @@ -49,5 +49,24 @@ void subghz_protocol_nero_sketch_parse(SubGhzProtocolNeroSketch* instance, bool */ void subghz_protocol_nero_sketch_to_str(SubGhzProtocolNeroSketch* instance, string_t output); +/** Get a string to save the protocol + * + * @param instance - SubGhzProtocolNeroSketch instance + * @param output - the resulting string + */ void subghz_protocol_nero_sketch_to_save_str(SubGhzProtocolNeroSketch* instance, string_t output); -bool subghz_protocol_nero_sketch_to_load_protocol(FileWorker* file_worker, SubGhzProtocolNeroSketch* instance); + +/** Loading protocol from file + * + * @param file_worker - FileWorker file_worker + * @param instance - SubGhzProtocolNeroSketch instance + * @return bool + */ +bool subghz_protocol_nero_sketch_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolNeroSketch* instance); + +/** Loading protocol from bin data + * + * @param instance - SubGhzProtocolNeroSketch instance + * @param context - SubGhzProtocolCommonLoad context + */ +void subghz_decoder_nero_sketch_to_load_protocol(SubGhzProtocolNeroSketch* instance, void* context); \ No newline at end of file diff --git a/lib/subghz/protocols/subghz_protocol_nice_flo.c b/lib/subghz/protocols/subghz_protocol_nice_flo.c index b53160b8..af778543 100644 --- a/lib/subghz/protocols/subghz_protocol_nice_flo.c +++ b/lib/subghz/protocols/subghz_protocol_nice_flo.c @@ -22,10 +22,12 @@ SubGhzProtocolNiceFlo* subghz_protocol_nice_flo_alloc() { instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_nice_flo_to_str; instance->common.to_save_string = (SubGhzProtocolCommonGetStrSave)subghz_protocol_nice_flo_to_save_str; - instance->common.to_load_protocol= - (SubGhzProtocolCommonLoad)subghz_protocol_nice_flo_to_load_protocol; + instance->common.to_load_protocol_from_file= + (SubGhzProtocolCommonLoadFromFile)subghz_protocol_nice_flo_to_load_protocol_from_file; + instance->common.to_load_protocol = + (SubGhzProtocolCommonLoadFromRAW)subghz_decoder_nice_flo_to_load_protocol; instance->common.get_upload_protocol = - (SubGhzProtocolEncoderCommonGetUpLoad)subghz_protocol_nice_flo_send_key; + (SubGhzProtocolCommonEncoderGetUpLoad)subghz_protocol_nice_flo_send_key; return instance; } @@ -34,7 +36,7 @@ void subghz_protocol_nice_flo_free(SubGhzProtocolNiceFlo* instance) { free(instance); } -bool subghz_protocol_nice_flo_send_key(SubGhzProtocolNiceFlo* instance, SubGhzProtocolEncoderCommon* encoder){ +bool subghz_protocol_nice_flo_send_key(SubGhzProtocolNiceFlo* instance, SubGhzProtocolCommonEncoder* encoder){ furi_assert(instance); furi_assert(encoder); size_t index = 0; @@ -137,9 +139,9 @@ void subghz_protocol_nice_flo_to_str(SubGhzProtocolNiceFlo* instance, string_t o string_cat_printf( output, - "%s %d Bit\r\n" - " KEY:0x%08lX\r\n" - " YEK:0x%08lX\r\n", + "%s %dbit\r\n" + "Key:0x%08lX\r\n" + "Yek:0x%08lX\r\n", instance->common.name, instance->common.code_last_count_bit, code_found_lo, @@ -159,7 +161,7 @@ void subghz_protocol_nice_flo_to_save_str(SubGhzProtocolNiceFlo* instance, strin (uint32_t)(instance->common.code_last_found & 0x00000000ffffffff)); } -bool subghz_protocol_nice_flo_to_load_protocol(FileWorker* file_worker, SubGhzProtocolNiceFlo* instance){ +bool subghz_protocol_nice_flo_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolNiceFlo* instance){ bool loaded = false; string_t temp_str; string_init(temp_str); @@ -195,3 +197,15 @@ bool subghz_protocol_nice_flo_to_load_protocol(FileWorker* file_worker, SubGhzPr return loaded; } + +void subghz_decoder_nice_flo_to_load_protocol( + SubGhzProtocolNiceFlo* instance, + void* context) { + furi_assert(context); + furi_assert(instance); + SubGhzProtocolCommonLoad* data = context; + instance->common.code_last_found = data->code_found; + instance->common.code_last_count_bit = data->code_count_bit; + instance->common.serial = 0x0; + instance->common.btn = 0x0; +} \ No newline at end of file diff --git a/lib/subghz/protocols/subghz_protocol_nice_flo.h b/lib/subghz/protocols/subghz_protocol_nice_flo.h index fc80f02a..0f88636d 100644 --- a/lib/subghz/protocols/subghz_protocol_nice_flo.h +++ b/lib/subghz/protocols/subghz_protocol_nice_flo.h @@ -19,10 +19,10 @@ void subghz_protocol_nice_flo_free(SubGhzProtocolNiceFlo* instance); /** Get upload protocol * * @param instance - SubGhzProtocolCame instance - * @param encoder - SubGhzProtocolEncoderCommon encoder + * @param encoder - SubGhzProtocolCommonEncoder encoder * @return bool */ -bool subghz_protocol_nice_flo_send_key(SubGhzProtocolNiceFlo* instance, SubGhzProtocolEncoderCommon* encoder); +bool subghz_protocol_nice_flo_send_key(SubGhzProtocolNiceFlo* instance, SubGhzProtocolCommonEncoder* encoder); /** Reset internal state * @param instance - SubGhzProtocolNiceFlo instance @@ -43,5 +43,24 @@ void subghz_protocol_nice_flo_parse(SubGhzProtocolNiceFlo* instance, bool level, */ void subghz_protocol_nice_flo_to_str(SubGhzProtocolNiceFlo* instance, string_t output); +/** Get a string to save the protocol + * + * @param instance - SubGhzProtocolNiceFlo instance + * @param output - the resulting string + */ void subghz_protocol_nice_flo_to_save_str(SubGhzProtocolNiceFlo* instance, string_t output); -bool subghz_protocol_nice_flo_to_load_protocol(FileWorker* file_worker, SubGhzProtocolNiceFlo* instance); + +/** Loading protocol from file + * + * @param file_worker - FileWorker file_worker + * @param instance - SubGhzProtocolNiceFlo instance + * @return bool + */ +bool subghz_protocol_nice_flo_to_load_protocol_from_file(FileWorker* file_worker, SubGhzProtocolNiceFlo* instance); + +/** Loading protocol from bin data + * + * @param instance - SubGhzProtocolNiceFlo instance + * @param context - SubGhzProtocolCommonLoad context + */ +void subghz_decoder_nice_flo_to_load_protocol(SubGhzProtocolNiceFlo* instance, void* context); diff --git a/lib/subghz/protocols/subghz_protocol_nice_flor_s.c b/lib/subghz/protocols/subghz_protocol_nice_flor_s.c index ab6b83ea..84b81334 100644 --- a/lib/subghz/protocols/subghz_protocol_nice_flor_s.c +++ b/lib/subghz/protocols/subghz_protocol_nice_flor_s.c @@ -23,6 +23,8 @@ SubGhzProtocolNiceFlorS* subghz_protocol_nice_flor_s_alloc() { instance->common.te_delta = 300; instance->common.type_protocol = TYPE_PROTOCOL_DYNAMIC; instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_nice_flor_s_to_str; + instance->common.to_load_protocol = + (SubGhzProtocolCommonLoadFromRAW)subghz_decoder_nice_flor_s_to_load_protocol; return instance; } @@ -224,10 +226,10 @@ void subghz_protocol_nice_flor_s_to_str(SubGhzProtocolNiceFlorS* instance, strin string_cat_printf( output, - "%s, %d Bit\r\n" - " KEY:0x%lX%08lX\r\n" - " SN:%05lX\r\n" - " CNT:%04X BTN:%02lX\r\n", + "%s %dbit\r\n" + "Key:0x%lX%08lX\r\n" + "Sn:%05lX\r\n" + "Cnt:%04X Btn:%02lX\r\n", instance->common.name, instance->common.code_last_count_bit, code_found_hi, @@ -236,4 +238,15 @@ void subghz_protocol_nice_flor_s_to_str(SubGhzProtocolNiceFlorS* instance, strin instance->common.cnt, instance->common.btn ); +} + +void subghz_decoder_nice_flor_s_to_load_protocol( + SubGhzProtocolNiceFlorS* instance, + void* context) { + furi_assert(context); + furi_assert(instance); + SubGhzProtocolCommonLoad* data = context; + instance->common.code_last_found = data->code_found; + instance->common.code_last_count_bit = data->code_count_bit; + subghz_nice_flor_s_decoder_decrypt(instance); } \ No newline at end of file diff --git a/lib/subghz/protocols/subghz_protocol_nice_flor_s.h b/lib/subghz/protocols/subghz_protocol_nice_flor_s.h index 32ae54fa..60f7431d 100644 --- a/lib/subghz/protocols/subghz_protocol_nice_flor_s.h +++ b/lib/subghz/protocols/subghz_protocol_nice_flor_s.h @@ -50,3 +50,10 @@ void subghz_protocol_nice_flor_s_parse(SubGhzProtocolNiceFlorS* instance, bool l * @param output - output string */ void subghz_protocol_nice_flor_s_to_str(SubGhzProtocolNiceFlorS* instance, string_t output); + +/** Loading protocol from bin data + * + * @param instance - SubGhzProtocolNiceFlorS instance + * @param context - SubGhzProtocolCommonLoad context + */ +void subghz_decoder_nice_flor_s_to_load_protocol(SubGhzProtocolNiceFlorS* instance, void* context); \ No newline at end of file diff --git a/lib/subghz/protocols/subghz_protocol_princeton.c b/lib/subghz/protocols/subghz_protocol_princeton.c index c05f297b..201f07d0 100644 --- a/lib/subghz/protocols/subghz_protocol_princeton.c +++ b/lib/subghz/protocols/subghz_protocol_princeton.c @@ -5,7 +5,7 @@ * */ -#define SUBGHZ_PT_SHORT 450 +#define SUBGHZ_PT_SHORT 400 #define SUBGHZ_PT_LONG (SUBGHZ_PT_SHORT * 3) #define SUBGHZ_PT_GUARD (SUBGHZ_PT_SHORT * 30) @@ -16,7 +16,6 @@ struct SubGhzEncoderPrinceton { size_t front; }; - SubGhzEncoderPrinceton* subghz_encoder_princeton_alloc() { SubGhzEncoderPrinceton* instance = furi_alloc(sizeof(SubGhzEncoderPrinceton)); return instance; @@ -27,16 +26,15 @@ void subghz_encoder_princeton_free(SubGhzEncoderPrinceton* instance) { free(instance); } -void subghz_encoder_princeton_set_te(SubGhzEncoderPrinceton* instance, void* decoder){ - SubGhzDecoderPrinceton* pricenton = decoder; - if((pricenton->te) !=0){ +void subghz_encoder_princeton_set_te(SubGhzEncoderPrinceton* instance, void* decoder) { + SubGhzDecoderPrinceton* pricenton = decoder; + if((pricenton->te) != 0) { instance->te = pricenton->te; - }else{ + } else { instance->te = SUBGHZ_PT_SHORT; } } - void subghz_encoder_princeton_set(SubGhzEncoderPrinceton* instance, uint32_t key, size_t repeat) { furi_assert(instance); instance->te = SUBGHZ_PT_SHORT; @@ -88,16 +86,18 @@ SubGhzDecoderPrinceton* subghz_decoder_princeton_alloc(void) { instance->common.code_min_count_bit_for_found = 24; instance->common.te_short = SUBGHZ_PT_SHORT; //150; instance->common.te_long = SUBGHZ_PT_LONG; //450; - instance->common.te_delta = 200; //50; + instance->common.te_delta = 250; //50; instance->common.type_protocol = TYPE_PROTOCOL_STATIC; instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_decoder_princeton_to_str; instance->common.to_save_string = (SubGhzProtocolCommonGetStrSave)subghz_decoder_princeton_to_save_str; - instance->common.to_load_protocol= - (SubGhzProtocolCommonLoad)subghz_decoder_princeton_to_load_protocol; + instance->common.to_load_protocol_from_file = + (SubGhzProtocolCommonLoadFromFile)subghz_decoder_princeton_to_load_protocol_from_file; + instance->common.to_load_protocol = + (SubGhzProtocolCommonLoadFromRAW)subghz_decoder_princeton_to_load_protocol; instance->common.get_upload_protocol = - (SubGhzProtocolEncoderCommonGetUpLoad)subghz_protocol_princeton_send_key; - + (SubGhzProtocolCommonEncoderGetUpLoad)subghz_protocol_princeton_send_key; + return instance; } @@ -106,30 +106,37 @@ void subghz_decoder_princeton_free(SubGhzDecoderPrinceton* instance) { free(instance); } -bool subghz_protocol_princeton_send_key(SubGhzDecoderPrinceton* instance, SubGhzProtocolEncoderCommon* encoder){ +uint16_t subghz_protocol_princeton_get_te(void* context) { + SubGhzDecoderPrinceton* instance = context; + return instance->te; +} + +bool subghz_protocol_princeton_send_key( + SubGhzDecoderPrinceton* instance, + SubGhzProtocolCommonEncoder* encoder) { furi_assert(instance); furi_assert(encoder); size_t index = 0; - encoder->size_upload =(instance->common.code_last_count_bit * 2) + 2; + encoder->size_upload = (instance->common.code_last_count_bit * 2) + 2; if(encoder->size_upload > SUBGHZ_ENCODER_UPLOAD_MAX_SIZE) return false; - + //Send key data - for (uint8_t i = instance->common.code_last_count_bit; i > 0; i--) { - if(bit_read(instance->common.code_last_found, i - 1)){ + for(uint8_t i = instance->common.code_last_count_bit; i > 0; i--) { + if(bit_read(instance->common.code_last_found, i - 1)) { //send bit 1 - encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->te*3); + encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->te * 3); encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->te); - }else{ + } else { //send bit 0 encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->te); - encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->te*3); + encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->te * 3); } } //Send Stop bit encoder->upload[index++] = level_duration_make(true, (uint32_t)instance->te); //Send PT_GUARD - encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->te*30); + encoder->upload[index++] = level_duration_make(false, (uint32_t)instance->te * 30); return true; } @@ -221,17 +228,18 @@ void subghz_decoder_princeton_to_str(SubGhzDecoderPrinceton* instance, string_t string_cat_printf( output, - "%s %d Bit te %dus\r\n" - " KEY:0x%08lX\r\n" - " YEK:0x%08lX\r\n" - " SN:0x%05lX BTN:%02X\r\n", + "%s %dbit\r\n" + "Key:0x%08lX\r\n" + "Yek:0x%08lX\r\n" + "Sn:0x%05lX BTN:%02X\r\n" + "Te:%dus\r\n", instance->common.name, instance->common.code_last_count_bit, - instance->te, code_found_lo, code_found_reverse_lo, instance->common.serial, - instance->common.btn); + instance->common.btn, + instance->te); } void subghz_decoder_princeton_to_save_str(SubGhzDecoderPrinceton* instance, string_t output) { @@ -247,7 +255,9 @@ void subghz_decoder_princeton_to_save_str(SubGhzDecoderPrinceton* instance, stri (uint32_t)(instance->common.code_last_found & 0x00000000ffffffff)); } -bool subghz_decoder_princeton_to_load_protocol(FileWorker* file_worker, SubGhzDecoderPrinceton* instance){ +bool subghz_decoder_princeton_to_load_protocol_from_file( + FileWorker* file_worker, + SubGhzDecoderPrinceton* instance) { bool loaded = false; string_t temp_str; string_init(temp_str); @@ -295,3 +305,16 @@ bool subghz_decoder_princeton_to_load_protocol(FileWorker* file_worker, SubGhzDe return loaded; } + +void subghz_decoder_princeton_to_load_protocol( + SubGhzDecoderPrinceton* instance, + void* context) { + furi_assert(context); + furi_assert(instance); + SubGhzProtocolCommonLoad* data = context; + instance->common.code_last_found = data->code_found; + instance->common.code_last_count_bit = data->code_count_bit; + instance->te = data->param1; + instance->common.serial = instance->common.code_last_found >> 4; + instance->common.btn = (uint8_t)instance->common.code_last_found & 0x00000F; +} diff --git a/lib/subghz/protocols/subghz_protocol_princeton.h b/lib/subghz/protocols/subghz_protocol_princeton.h index a414b6a2..fdc37a43 100644 --- a/lib/subghz/protocols/subghz_protocol_princeton.h +++ b/lib/subghz/protocols/subghz_protocol_princeton.h @@ -20,7 +20,6 @@ SubGhzEncoderPrinceton* subghz_encoder_princeton_alloc(); */ void subghz_encoder_princeton_free(SubGhzEncoderPrinceton* instance); - /** Set new encoder params * @param instance - SubGhzEncoderPrinceton instance * @param key - 24bit key @@ -40,14 +39,10 @@ size_t subghz_encoder_princeton_get_repeat_left(SubGhzEncoderPrinceton* instance */ LevelDuration subghz_encoder_princeton_yield(void* context); - /** SubGhzDecoderPrinceton anonymous type */ typedef struct SubGhzDecoderPrinceton SubGhzDecoderPrinceton; - -void subghz_encoder_princeton_set_te( - SubGhzEncoderPrinceton* instance, - void* decoder); +void subghz_encoder_princeton_set_te(SubGhzEncoderPrinceton* instance, void* decoder); /** Allocate SubGhzDecoderPrinceton * @@ -61,13 +56,22 @@ SubGhzDecoderPrinceton* subghz_decoder_princeton_alloc(); */ void subghz_decoder_princeton_free(SubGhzDecoderPrinceton* instance); +/** Get Te interval protocol + * + * @param context - SubGhzDecoderPrinceton context + * @return Te interval (us) + */ +uint16_t subghz_protocol_princeton_get_te(void* context); + /** Get upload protocol * * @param instance - SubGhzDecoderPrinceton instance - * @param encoder - SubGhzProtocolEncoderCommon encoder + * @param encoder - SubGhzProtocolCommonEncoder encoder * @return bool */ -bool subghz_protocol_princeton_send_key(SubGhzDecoderPrinceton* instance, SubGhzProtocolEncoderCommon* encoder); +bool subghz_protocol_princeton_send_key( + SubGhzDecoderPrinceton* instance, + SubGhzProtocolCommonEncoder* encoder); /** Reset internal state * @param instance - SubGhzDecoderPrinceton instance @@ -79,7 +83,10 @@ void subghz_decoder_princeton_reset(SubGhzDecoderPrinceton* instance); * @param instance - SubGhzDecoderPrinceton instance * @param data - LevelDuration level_duration */ -void subghz_decoder_princeton_parse(SubGhzDecoderPrinceton* instance, bool level, uint32_t duration); +void subghz_decoder_princeton_parse( + SubGhzDecoderPrinceton* instance, + bool level, + uint32_t duration); /** Outputting information from the parser * @@ -88,7 +95,26 @@ void subghz_decoder_princeton_parse(SubGhzDecoderPrinceton* instance, bool level */ void subghz_decoder_princeton_to_str(SubGhzDecoderPrinceton* instance, string_t output); +/** Get a string to save the protocol + * + * @param instance - SubGhzDecoderPrinceton instance + * @param output - the resulting string + */ void subghz_decoder_princeton_to_save_str(SubGhzDecoderPrinceton* instance, string_t output); -bool subghz_decoder_princeton_to_load_protocol(FileWorker* file_worker, SubGhzDecoderPrinceton* instance); +/** Loading protocol from file + * + * @param file_worker - FileWorker file_worker + * @param instance - SubGhzDecoderPrinceton instance + * @return bool + */ +bool subghz_decoder_princeton_to_load_protocol_from_file(FileWorker* file_worker, SubGhzDecoderPrinceton* instance); +/** Loading protocol from bin data + * + * @param instance - SubGhzDecoderPrinceton instance + * @param context - SubGhzProtocolCommonLoad context + */ +void subghz_decoder_princeton_to_load_protocol( + SubGhzDecoderPrinceton* instance, + void* context) ; diff --git a/lib/subghz/protocols/subghz_protocol_star_line.c b/lib/subghz/protocols/subghz_protocol_star_line.c index 1890b5e6..f8207348 100644 --- a/lib/subghz/protocols/subghz_protocol_star_line.c +++ b/lib/subghz/protocols/subghz_protocol_star_line.c @@ -27,6 +27,8 @@ SubGhzProtocolStarLine* subghz_protocol_star_line_alloc(SubGhzKeystore* keystore instance->common.te_delta = 120; instance->common.type_protocol = TYPE_PROTOCOL_DYNAMIC; instance->common.to_string = (SubGhzProtocolCommonToStr)subghz_protocol_star_line_to_str; + instance->common.to_load_protocol = + (SubGhzProtocolCommonLoadFromRAW)subghz_decoder_star_line_to_load_protocol; return instance; } @@ -36,6 +38,17 @@ void subghz_protocol_star_line_free(SubGhzProtocolStarLine* instance) { free(instance); } +const char* subghz_protocol_star_line_find_and_get_manufacture_name (void* context){ + SubGhzProtocolStarLine* instance = context; + subghz_protocol_star_line_check_remote_controller(instance); + return instance->manufacture_name; +} + +const char* subghz_protocol_star_line_get_manufacture_name (void* context){ + SubGhzProtocolStarLine* instance = context; + return instance->manufacture_name; +} + /** Send bit * * @param instance - SubGhzProtocolStarLine instance @@ -268,20 +281,32 @@ void subghz_protocol_star_line_to_str(SubGhzProtocolStarLine* instance, string_t uint32_t code_found_reverse_lo = code_found_reverse&0x00000000ffffffff; string_cat_printf( output, - "%s, %d Bit\r\n" - "KEY:0x%lX%lX\r\n" - "FIX:%08lX MF:%s \r\n" - "HOP:%08lX \r\n" - "SN:%06lX CNT:%04X B:%02lX\r\n", + "%s %dbit\r\n" + "Key:0x%lX%lX\r\n" + "Fix:0x%08lX Cnt:%04X\r\n" + "Hop:0x%08lX Btn:%02lX\r\n" + "MF:%s\r\n" + "Sn:0x%07lX \r\n", instance->common.name, instance->common.code_last_count_bit, code_found_hi, code_found_lo, code_found_reverse_hi, - instance->manufacture_name, + instance->common.cnt, code_found_reverse_lo, - instance->common.serial, - instance->common.cnt, - instance->common.btn + instance->common.btn, + instance->manufacture_name, + instance->common.serial ); } + +void subghz_decoder_star_line_to_load_protocol( + SubGhzProtocolStarLine* instance, + void* context) { + furi_assert(context); + furi_assert(instance); + SubGhzProtocolCommonLoad* data = context; + instance->common.code_last_found = data->code_found; + instance->common.code_last_count_bit = data->code_count_bit; + subghz_protocol_star_line_check_remote_controller(instance); +} \ No newline at end of file diff --git a/lib/subghz/protocols/subghz_protocol_star_line.h b/lib/subghz/protocols/subghz_protocol_star_line.h index e39cbbc6..b1c28dc5 100644 --- a/lib/subghz/protocols/subghz_protocol_star_line.h +++ b/lib/subghz/protocols/subghz_protocol_star_line.h @@ -18,6 +18,20 @@ SubGhzProtocolStarLine* subghz_protocol_star_line_alloc(SubGhzKeystore* keystore */ void subghz_protocol_star_line_free(SubGhzProtocolStarLine* instance); +/** Find and get manufacture name + * + * @param context - SubGhzProtocolStarLine context + * @return name - char* manufacture name + */ +const char* subghz_protocol_star_line_find_and_get_manufacture_name(void* context); + +/** Get manufacture name + * + * @param context - SubGhzProtocolStarLine context + * @return name - char* manufacture name + */ +const char* subghz_protocol_star_line_get_manufacture_name(void* context); + /** Sends the key on the air * * @param instance - SubGhzProtocolStarLine instance @@ -51,3 +65,10 @@ void subghz_protocol_star_line_parse(SubGhzProtocolStarLine* instance, bool leve * @param output - output string */ void subghz_protocol_star_line_to_str(SubGhzProtocolStarLine* instance, string_t output); + +/** Loading protocol from bin data + * + * @param instance - SubGhzDecoderPrinceton instance + * @param context - SubGhzProtocolCommonLoad context + */ +void subghz_decoder_star_line_to_load_protocol(SubGhzProtocolStarLine* instance, void* context); diff --git a/lib/subghz/subghz_keystore.h b/lib/subghz/subghz_keystore.h index 4b10730b..4cd388f5 100644 --- a/lib/subghz/subghz_keystore.h +++ b/lib/subghz/subghz_keystore.h @@ -16,10 +16,28 @@ ARRAY_DEF(SubGhzKeyArray, SubGhzKey, M_POD_OPLIST) typedef struct SubGhzKeystore SubGhzKeystore; +/** Allocate SubGhzKeystore + * + * @return SubGhzKeystore* + */ SubGhzKeystore* subghz_keystore_alloc(); +/** Free SubGhzKeystore + * + * @param instance + */ void subghz_keystore_free(SubGhzKeystore* instance); +/** Loading manufacture key from file + * + * @param instance - SubGhzKeystore instance + * @param filename - const char* full path to the file + */ void subghz_keystore_load(SubGhzKeystore* instance, const char* filename); +/** Get array of keys and names manufacture + * + * @param instance - SubGhzKeystore instance + * @return SubGhzKeyArray_t* + */ SubGhzKeyArray_t* subghz_keystore_get_data(SubGhzKeystore* instance); diff --git a/lib/subghz/subghz_worker.c b/lib/subghz/subghz_worker.c index 8cab5e01..626ec77f 100644 --- a/lib/subghz/subghz_worker.c +++ b/lib/subghz/subghz_worker.c @@ -117,3 +117,8 @@ void subghz_worker_stop(SubGhzWorker* instance) { furi_thread_join(instance->thread); } + +bool subghz_worker_is_running(SubGhzWorker* instance) { + furi_assert(instance); + return instance->running; +} diff --git a/lib/subghz/subghz_worker.h b/lib/subghz/subghz_worker.h index 6ef10190..4516352a 100644 --- a/lib/subghz/subghz_worker.h +++ b/lib/subghz/subghz_worker.h @@ -54,3 +54,9 @@ void subghz_worker_start(SubGhzWorker* instance); * @param instance SubGhzWorker instance */ void subghz_worker_stop(SubGhzWorker* instance); + +/** Check if worker is running + * @param instance SubGhzWorker instance + * @return bool - true if running + */ +bool subghz_worker_is_running(SubGhzWorker* instance); diff --git a/make/git.mk b/make/git.mk index 7e871756..cc03c56c 100644 --- a/make/git.mk +++ b/make/git.mk @@ -1,9 +1,13 @@ -GIT_COMMIT = $(shell git describe --always --exclude '*' || echo 'unknown') -GIT_BRANCH = $(shell git rev-parse --abbrev-ref HEAD || echo 'unknown') -GIT_BRANCH_NUM = $(shell git rev-list --count $(GIT_BRANCH) || echo 'nan') -BUILD_DATE = $(shell date '+%d-%m-%Y' || echo 'unknown') -VERSION = $(shell git describe --tags --abbrev=0 || echo 'unknown') - -CFLAGS += -DGIT_COMMIT="\"$(GIT_COMMIT)\"" -DGIT_BRANCH="\"$(GIT_BRANCH)\"" -DGIT_BRANCH_NUM="\"$(GIT_BRANCH_NUM)\"" -CFLAGS += -DBUILD_DATE="\"$(BUILD_DATE)\"" -DTARGET="\"$(TARGET)\"" -DVERSION="\"$(VERSION)\"" +GIT_COMMIT := $(shell git rev-parse --short HEAD || echo 'unknown') +GIT_BRANCH := $(shell echo $${WORKFLOW_BRANCH_OR_TAG-$$(git rev-parse --abbrev-ref HEAD || echo 'unknown')}) +GIT_BRANCH_NUM := $(shell git rev-list --count HEAD || echo 'nan') +BUILD_DATE := $(shell date '+%d-%m-%Y' || echo 'unknown') +VERSION := $(shell git describe --tags --abbrev=0 --exact-match || echo 'unknown') +CFLAGS += \ + -DGIT_COMMIT="\"$(GIT_COMMIT)\"" \ + -DGIT_BRANCH="\"$(GIT_BRANCH)\"" \ + -DGIT_BRANCH_NUM="\"$(GIT_BRANCH_NUM)\"" \ + -DBUILD_DATE="\"$(BUILD_DATE)\"" \ + -DTARGET="\"$(TARGET)\"" \ + -DVERSION="\"$(VERSION)\"" diff --git a/make/rules.mk b/make/rules.mk index 48454638..fd50375a 100644 --- a/make/rules.mk +++ b/make/rules.mk @@ -19,7 +19,7 @@ $(shell test -d $(OBJ_DIR) || mkdir -p $(OBJ_DIR)) BUILD_FLAGS_SHELL=\ echo "$(CFLAGS)" > $(OBJ_DIR)/BUILD_FLAGS.tmp; \ - diff $(OBJ_DIR)/BUILD_FLAGS $(OBJ_DIR)/BUILD_FLAGS.tmp 2>/dev/null \ + diff -u $(OBJ_DIR)/BUILD_FLAGS $(OBJ_DIR)/BUILD_FLAGS.tmp 2>&1 > /dev/null \ && ( echo "CFLAGS ok"; rm $(OBJ_DIR)/BUILD_FLAGS.tmp) \ || ( echo "CFLAGS has been changed"; mv $(OBJ_DIR)/BUILD_FLAGS.tmp $(OBJ_DIR)/BUILD_FLAGS ) $(info $(shell $(BUILD_FLAGS_SHELL))) @@ -127,4 +127,6 @@ generate_cscope_db: @rm -rf $(OBJ_DIR)/source.list $(OBJ_DIR)/source.list.p +ifneq ("$(wildcard $(OBJ_DIR)/*.d)","") -include $(DEPS) +endif diff --git a/scripts/ReadMe.md b/scripts/ReadMe.md index 6517e87e..935a58e7 100644 --- a/scripts/ReadMe.md +++ b/scripts/ReadMe.md @@ -53,3 +53,11 @@ Setting option bytes: ```bash ob.py set ``` + +# Assets delivery + +Run in the root folder of the repo: + +```bash +python scripts/storage.py -p send assets/resources /ext +``` \ No newline at end of file