Merge branch 'dev' into release-candidate
This commit is contained in:
		
						commit
						3d9efa98d4
					
				
							
								
								
									
										48
									
								
								.github/workflows/amap_analyse.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										48
									
								
								.github/workflows/amap_analyse.yml
									
									
									
									
										vendored
									
									
								
							| @ -14,6 +14,7 @@ env: | ||||
| 
 | ||||
| jobs: | ||||
|   amap_analyse: | ||||
|     if: ${{ !github.event.pull_request.head.repo.fork }} | ||||
|     runs-on: [self-hosted,FlipperZeroMacShell] | ||||
|     timeout-minutes: 15 | ||||
|     steps: | ||||
| @ -34,8 +35,7 @@ jobs: | ||||
|       - name: 'Decontaminate previous build leftovers' | ||||
|         run: | | ||||
|           if [ -d .git ]; then | ||||
|             git submodule status \ | ||||
|               || git checkout `git rev-list --max-parents=0 HEAD | tail -n 1` | ||||
|             git submodule status || git checkout "$(git rev-list --max-parents=0 HEAD | tail -n 1)" | ||||
|           fi | ||||
| 
 | ||||
|       - name: 'Checkout code' | ||||
| @ -44,32 +44,14 @@ jobs: | ||||
|           fetch-depth: 0 | ||||
|           ref: ${{ github.event.pull_request.head.sha }} | ||||
| 
 | ||||
|       - name: 'Generate prefixes by commit' | ||||
|         id: names | ||||
|       - name: 'Get commit details' | ||||
|         run: | | ||||
|           REF="${{github.ref}}" | ||||
|           COMMIT_HASH="$(git rev-parse HEAD)" | ||||
|           SHA="$(git rev-parse --short HEAD)" | ||||
|           COMMIT_MSG="${{github.event.head_commit.message}}" | ||||
|           FBT_TOOLCHAIN_PATH=/opt source scripts/toolchain/fbtenv.sh | ||||
|           if [[ ${{ github.event_name }} == 'pull_request' ]]; then | ||||
|             REF="${{github.head_ref}}" | ||||
|             COMMIT_HASH="$(git log -1 --pretty=oneline | awk '{print $1}')" | ||||
|             SHA="$(cut -c -8 <<< "$COMMIT_HASH")" | ||||
|             COMMIT_MSG="$(git log -1 --pretty=format:"%s")" | ||||
|             PULL_ID="${{github.event.pull_request.number}}" | ||||
|             PULL_NAME="${{github.event.pull_request.title}}" | ||||
|             python3 scripts/get_env.py "--event_file=${{ github.event_path }}" "--is_pull" | ||||
|           else | ||||
|             python3 scripts/get_env.py "--event_file=${{ github.event_path }}" | ||||
|           fi | ||||
|           BRANCH_NAME=${REF#refs/*/} | ||||
|           SUFFIX=${BRANCH_NAME//\//_}-$(date +'%d%m%Y')-${SHA} | ||||
|           if [[ "${{ github.ref }}" == "refs/tags/"* ]]; then | ||||
|             SUFFIX=${BRANCH_NAME//\//_} | ||||
|           fi | ||||
|           echo "::set-output name=commit-hash::${COMMIT_HASH}" | ||||
|           echo "::set-output name=commit-msg::${COMMIT_MSG}" | ||||
|           echo "::set-output name=pull-id::${PULL_ID}" | ||||
|           echo "::set-output name=pull-name::${PULL_NAME}" | ||||
|           echo "::set-output name=branch-name::${BRANCH_NAME}" | ||||
|           echo "::set-output name=suffix::${SUFFIX}" | ||||
| 
 | ||||
|       - name: 'Make artifacts directory' | ||||
|         run: | | ||||
| @ -77,19 +59,18 @@ jobs: | ||||
|           mkdir artifacts | ||||
| 
 | ||||
|       - name: 'Download build artifacts' | ||||
|         if: ${{ !github.event.pull_request.head.repo.fork }} | ||||
|         run: | | ||||
|           echo "${{ secrets.RSYNC_DEPLOY_KEY }}" > deploy_key; | ||||
|           chmod 600 ./deploy_key; | ||||
|           rsync -avzP \ | ||||
|               -e 'ssh -p ${{ secrets.RSYNC_DEPLOY_PORT }} -i ./deploy_key' \ | ||||
|               ${{ secrets.RSYNC_DEPLOY_USER }}@${{ secrets.RSYNC_DEPLOY_HOST }}:"${{ secrets.RSYNC_DEPLOY_BASE_PATH }}${{steps.names.outputs.branch-name}}/" artifacts/; | ||||
|               ${{ secrets.RSYNC_DEPLOY_USER }}@${{ secrets.RSYNC_DEPLOY_HOST }}:"${{ secrets.RSYNC_DEPLOY_BASE_PATH }}${BRANCH_NAME}/" artifacts/; | ||||
|           rm ./deploy_key; | ||||
| 
 | ||||
|       - name: 'Make .map file analyze' | ||||
|         run: | | ||||
|           cd artifacts/ | ||||
|           /Applications/amap/Contents/MacOS/amap -f flipper-z-f7-firmware-${{steps.names.outputs.suffix}}.elf.map | ||||
|           /Applications/amap/Contents/MacOS/amap -f "flipper-z-f7-firmware-${SUFFIX}.elf.map" | ||||
| 
 | ||||
|       - name: 'Upload report to DB' | ||||
|         run: | | ||||
| @ -98,21 +79,14 @@ jobs: | ||||
|           { | ||||
|             SECTION="$1"; | ||||
|             arm-none-eabi-size \ | ||||
|               -A artifacts/flipper-z-f7-firmware-${{steps.names.outputs.suffix}}.elf \ | ||||
|               -A artifacts/flipper-z-f7-firmware-$SUFFIX.elf \ | ||||
|               | grep "^$SECTION" | awk '{print $2}' | ||||
|           } | ||||
|           export COMMIT_HASH="${{steps.names.outputs.commit-hash}}" | ||||
|           export COMMIT_MSG="${{steps.names.outputs.commit-msg}}" | ||||
|           export BRANCH_NAME="${{steps.names.outputs.branch-name}}" | ||||
|           export BSS_SIZE="$(get_size ".bss")" | ||||
|           export TEXT_SIZE="$(get_size ".text")" | ||||
|           export RODATA_SIZE="$(get_size ".rodata")" | ||||
|           export DATA_SIZE="$(get_size ".data")" | ||||
|           export FREE_FLASH_SIZE="$(get_size ".free_flash")" | ||||
|           if [[ ${{ github.event_name }} == 'pull_request' ]]; then | ||||
|             export PULL_ID="${{steps.names.outputs.pull-id}}" | ||||
|             export PULL_NAME="${{steps.names.outputs.pull-name}}" | ||||
|           fi | ||||
|           python3 -m pip install mariadb | ||||
|           python3 scripts/amap_mariadb_insert.py \ | ||||
|             ${{ secrets.AMAP_MARIADB_USER }} \ | ||||
| @ -120,4 +94,4 @@ jobs: | ||||
|             ${{ secrets.AMAP_MARIADB_HOST }} \ | ||||
|             ${{ secrets.AMAP_MARIADB_PORT }} \ | ||||
|             ${{ secrets.AMAP_MARIADB_DATABASE }} \ | ||||
|             artifacts/flipper-z-f7-firmware-${{steps.names.outputs.suffix}}.elf.map.all | ||||
|             artifacts/flipper-z-f7-firmware-$SUFFIX.elf.map.all | ||||
|  | ||||
							
								
								
									
										104
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										104
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							| @ -19,10 +19,8 @@ jobs: | ||||
|     steps: | ||||
|       - name: 'Decontaminate previous build leftovers' | ||||
|         run: | | ||||
|           if [ -d .git ] | ||||
|           then | ||||
|             git submodule status \ | ||||
|               || git checkout `git rev-list --max-parents=0 HEAD | tail -n 1` | ||||
|           if [ -d .git ]; then | ||||
|             git submodule status || git checkout "$(git rev-list --max-parents=0 HEAD | tail -n 1)" | ||||
|           fi | ||||
| 
 | ||||
|       - name: 'Checkout code' | ||||
| @ -33,51 +31,44 @@ jobs: | ||||
| 
 | ||||
|       - name: 'Make artifacts directory' | ||||
|         run: | | ||||
|           test -d artifacts && rm -rf artifacts || true | ||||
|           rm -rf artifacts | ||||
|           mkdir artifacts | ||||
| 
 | ||||
|       - name: 'Generate suffix and folder name' | ||||
|       - name: 'Get commit details' | ||||
|         run: | | ||||
|           FBT_TOOLCHAIN_PATH=/opt source scripts/toolchain/fbtenv.sh | ||||
|           if [[ ${{ github.event_name }} == 'pull_request' ]]; then | ||||
|             python3 scripts/get_env.py "--event_file=${{ github.event_path }}" "--is_pull" | ||||
|           else | ||||
|             python3 scripts/get_env.py "--event_file=${{ github.event_path }}" | ||||
|           fi | ||||
| 
 | ||||
|       - name: 'Generate suffixes for comment' | ||||
|         id: names | ||||
|         run: | | ||||
|           REF=${{ github.ref }} | ||||
|           if [[ ${{ github.event_name }} == 'pull_request' ]]; then | ||||
|             REF=${{ github.head_ref }} | ||||
|           fi | ||||
|           BRANCH_OR_TAG=${REF#refs/*/} | ||||
|           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 "DIST_SUFFIX=${SUFFIX}" >> $GITHUB_ENV | ||||
|           echo "::set-output name=artifacts-path::${BRANCH_OR_TAG}" | ||||
|           echo "::set-output name=branch_name::${BRANCH_NAME}" | ||||
|           echo "::set-output name=commit_sha::${COMMIT_SHA}" | ||||
|           echo "::set-output name=default_target::${DEFAULT_TARGET}" | ||||
|           echo "::set-output name=suffix::${SUFFIX}" | ||||
|           echo "::set-output name=short-hash::${SHA}" | ||||
|           echo "::set-output name=default-target::${DEFAULT_TARGET}" | ||||
| 
 | ||||
|       - name: 'Bundle scripts' | ||||
|         if: ${{ !github.event.pull_request.head.repo.fork }} | ||||
|         run: | | ||||
|           tar czpf artifacts/flipper-z-any-scripts-${{steps.names.outputs.suffix}}.tgz scripts | ||||
|           tar czpf artifacts/flipper-z-any-scripts-${SUFFIX}.tgz scripts | ||||
| 
 | ||||
|       - name: 'Build the firmware' | ||||
|         run: | | ||||
|           set -e | ||||
|           for TARGET in ${TARGETS} | ||||
|           do | ||||
|             FBT_TOOLCHAIN_PATH=/opt ./fbt TARGET_HW=`echo ${TARGET} | sed 's/f//'` updater_package ${{ startsWith(github.ref, 'refs/tags') && 'DEBUG=0 COMPACT=1' || '' }} | ||||
|           for TARGET in ${TARGETS}; do | ||||
|             FBT_TOOLCHAIN_PATH=/opt ./fbt TARGET_HW="$(echo "${TARGET}" | sed 's/f//')" \ | ||||
|                 updater_package ${{ startsWith(github.ref, 'refs/tags') && 'DEBUG=0 COMPACT=1' || '' }} | ||||
|           done | ||||
| 
 | ||||
|       - name: 'Move upload files' | ||||
|         if: ${{ !github.event.pull_request.head.repo.fork }} | ||||
|         run: | | ||||
|           set -e | ||||
|           for TARGET in ${TARGETS} | ||||
|           do | ||||
|           for TARGET in ${TARGETS}; do | ||||
|             mv dist/${TARGET}-*/* artifacts/ | ||||
|           done | ||||
| 
 | ||||
| @ -85,12 +76,11 @@ jobs: | ||||
|         if: ${{ !github.event.pull_request.head.repo.fork }} | ||||
|         run: | | ||||
|           set -e | ||||
|           for UPDATEBUNDLE in artifacts/*/ | ||||
|           do | ||||
|             BUNDLE_NAME=`echo $UPDATEBUNDLE | cut -d'/' -f2` | ||||
|             echo Packaging ${BUNDLE_NAME} | ||||
|             tar czpf artifacts/flipper-z-${BUNDLE_NAME}.tgz -C artifacts ${BUNDLE_NAME} | ||||
|             rm -rf artifacts/${BUNDLE_NAME} | ||||
|           for UPDATEBUNDLE in artifacts/*/; do | ||||
|             BUNDLE_NAME="$(echo "$UPDATEBUNDLE" | cut -d'/' -f2)" | ||||
|             echo Packaging "${BUNDLE_NAME}" | ||||
|             tar czpf "artifacts/flipper-z-${BUNDLE_NAME}.tgz" -C artifacts "${BUNDLE_NAME}" | ||||
|             rm -rf "artifacts/${BUNDLE_NAME}" | ||||
|           done | ||||
| 
 | ||||
|       - name: "Check for uncommitted changes" | ||||
| @ -100,17 +90,17 @@ jobs: | ||||
|       - name: 'Bundle resources' | ||||
|         if: ${{ !github.event.pull_request.head.repo.fork }} | ||||
|         run: | | ||||
|           tar czpf artifacts/flipper-z-any-resources-${{steps.names.outputs.suffix}}.tgz -C assets resources | ||||
|           tar czpf "artifacts/flipper-z-any-resources-${SUFFIX}.tgz" -C assets resources | ||||
| 
 | ||||
|       - name: 'Bundle core2 firmware' | ||||
|         if: ${{ !github.event.pull_request.head.repo.fork }} | ||||
|         run: | | ||||
|           FBT_TOOLCHAIN_PATH=/opt ./fbt copro_dist | ||||
|           tar czpf artifacts/flipper-z-any-core2_firmware-${{steps.names.outputs.suffix}}.tgz -C assets core2_firmware | ||||
|           tar czpf "artifacts/flipper-z-any-core2_firmware-${SUFFIX}.tgz" -C assets core2_firmware | ||||
| 
 | ||||
|       - name: 'Copy .map file' | ||||
|         run: | | ||||
|           cp build/f7-firmware-*/firmware.elf.map artifacts/flipper-z-f7-firmware-${{steps.names.outputs.suffix}}.elf.map | ||||
|           cp build/f7-firmware-*/firmware.elf.map "artifacts/flipper-z-f7-firmware-${SUFFIX}.elf.map" | ||||
| 
 | ||||
|       - name: 'Upload artifacts to update server' | ||||
|         if: ${{ !github.event.pull_request.head.repo.fork }} | ||||
| @ -119,7 +109,7 @@ jobs: | ||||
|           chmod 600 ./deploy_key; | ||||
|           rsync -avzP --delete --mkpath \ | ||||
|               -e 'ssh -p ${{ secrets.RSYNC_DEPLOY_PORT }} -i ./deploy_key' \ | ||||
|               artifacts/ ${{ secrets.RSYNC_DEPLOY_USER }}@${{ secrets.RSYNC_DEPLOY_HOST }}:"${{ secrets.RSYNC_DEPLOY_BASE_PATH }}${{steps.names.outputs.artifacts-path}}/"; | ||||
|               artifacts/ ${{ secrets.RSYNC_DEPLOY_USER }}@${{ secrets.RSYNC_DEPLOY_HOST }}:"${{ secrets.RSYNC_DEPLOY_BASE_PATH }}${BRANCH_NAME}/"; | ||||
|           rm ./deploy_key; | ||||
| 
 | ||||
|       - name: 'Trigger update server reindex' | ||||
| @ -142,10 +132,10 @@ jobs: | ||||
|           comment-id: ${{ steps.fc.outputs.comment-id }} | ||||
|           issue-number: ${{ github.event.pull_request.number }} | ||||
|           body: | | ||||
|             **Compiled firmware for commit `${{steps.names.outputs.short-hash}}`:** | ||||
|             - [📦 Update package](https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.artifacts-path}}/flipper-z-${{steps.names.outputs.default-target}}-update-${{steps.names.outputs.suffix}}.tgz) | ||||
|             - [📥 DFU file](https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.artifacts-path}}/flipper-z-${{steps.names.outputs.default-target}}-full-${{steps.names.outputs.suffix}}.dfu) | ||||
|             - [☁️ Web updater](https://my.flipp.dev/?url=https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.artifacts-path}}/flipper-z-${{steps.names.outputs.default-target}}-update-${{steps.names.outputs.suffix}}.tgz&channel=${{steps.names.outputs.artifacts-path}}&version=${{steps.names.outputs.short-hash}}) | ||||
|             **Compiled firmware for commit `${{steps.names.outputs.commit_sha}}`:** | ||||
|             - [📦 Update package](https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.branch_name}}/flipper-z-${{steps.names.outputs.default_target}}-update-${{steps.names.outputs.suffix}}.tgz) | ||||
|             - [📥 DFU file](https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.branch_name}}/flipper-z-${{steps.names.outputs.default_target}}-full-${{steps.names.outputs.suffix}}.dfu) | ||||
|             - [☁️ Web updater](https://my.flipp.dev/?url=https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.branch_name}}/flipper-z-${{steps.names.outputs.default_target}}-update-${{steps.names.outputs.suffix}}.tgz&channel=${{steps.names.outputs.branch_name}}&version=${{steps.names.outputs.commit_sha}}) | ||||
|           edit-mode: replace | ||||
| 
 | ||||
|   compact: | ||||
| @ -157,7 +147,7 @@ jobs: | ||||
|           if [ -d .git ] | ||||
|           then | ||||
|             git submodule status \ | ||||
|               || git checkout `git rev-list --max-parents=0 HEAD | tail -n 1` | ||||
|               || git checkout "$(git rev-list --max-parents=0 HEAD | tail -n 1)" | ||||
|           fi | ||||
| 
 | ||||
|       - name: 'Checkout code' | ||||
| @ -167,29 +157,21 @@ jobs: | ||||
|           submodules: true | ||||
|           ref: ${{ github.event.pull_request.head.sha }} | ||||
| 
 | ||||
|       - name: 'Generate suffix and folder name' | ||||
|         id: names | ||||
|       - name: 'Get commit details' | ||||
|         run: | | ||||
|           REF=${{ github.ref }} | ||||
|           FBT_TOOLCHAIN_PATH=/opt source scripts/toolchain/fbtenv.sh | ||||
|           if [[ ${{ github.event_name }} == 'pull_request' ]]; then | ||||
|             REF=${{ github.head_ref }} | ||||
|           fi | ||||
|           BRANCH_OR_TAG=${REF#refs/*/} | ||||
|           SHA=$(git rev-parse --short HEAD) | ||||
| 
 | ||||
|           if [[ "${{ github.ref }}" == "refs/tags/"* ]]; then | ||||
|             SUFFIX=${BRANCH_OR_TAG//\//_} | ||||
|             python3 scripts/get_env.py "--event_file=${{ github.event_path }}" "--is_pull" | ||||
|           else | ||||
|             SUFFIX=${BRANCH_OR_TAG//\//_}-$(date +'%d%m%Y')-${SHA} | ||||
|             python3 scripts/get_env.py "--event_file=${{ github.event_path }}" | ||||
|           fi | ||||
| 
 | ||||
|           echo "WORKFLOW_BRANCH_OR_TAG=${BRANCH_OR_TAG}" >> $GITHUB_ENV | ||||
|           echo "WORKFLOW_BRANCH_OR_TAG=${BRANCH_NAME}" >> $GITHUB_ENV | ||||
|           echo "DIST_SUFFIX=${SUFFIX}" >> $GITHUB_ENV | ||||
| 
 | ||||
|       - name: 'Build the firmware' | ||||
|         run: | | ||||
|           set -e | ||||
|           for TARGET in ${TARGETS} | ||||
|           do | ||||
|             FBT_TOOLCHAIN_PATH=/opt ./fbt TARGET_HW=`echo ${TARGET} | sed 's/f//'` updater_package DEBUG=0 COMPACT=1 | ||||
|           for TARGET in ${TARGETS}; do | ||||
|             FBT_TOOLCHAIN_PATH=/opt ./fbt TARGET_HW="$(echo "${TARGET}" | sed 's/f//')" \ | ||||
|                 updater_package DEBUG=0 COMPACT=1 | ||||
|           done | ||||
|  | ||||
							
								
								
									
										6
									
								
								.github/workflows/check_submodules.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.github/workflows/check_submodules.yml
									
									
									
									
										vendored
									
									
								
							| @ -15,10 +15,8 @@ jobs: | ||||
|     steps: | ||||
|       - name: 'Decontaminate previous build leftovers' | ||||
|         run: | | ||||
|           if [ -d .git ] | ||||
|           then | ||||
|             git submodule status \ | ||||
|               || git checkout `git rev-list --max-parents=0 HEAD | tail -n 1` | ||||
|           if [ -d .git ]; then | ||||
|             git submodule status || git checkout "$(git rev-list --max-parents=0 HEAD | tail -n 1)" | ||||
|           fi | ||||
| 
 | ||||
|       - name: 'Checkout code' | ||||
|  | ||||
							
								
								
									
										6
									
								
								.github/workflows/lint_c.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.github/workflows/lint_c.yml
									
									
									
									
										vendored
									
									
								
							| @ -18,10 +18,8 @@ jobs: | ||||
|     steps: | ||||
|       - name: 'Decontaminate previous build leftovers' | ||||
|         run: | | ||||
|           if [ -d .git ] | ||||
|           then | ||||
|             git submodule status \ | ||||
|               || git checkout `git rev-list --max-parents=0 HEAD | tail -n 1` | ||||
|           if [ -d .git ]; then | ||||
|             git submodule status || git checkout "$(git rev-list --max-parents=0 HEAD | tail -n 1)" | ||||
|           fi | ||||
| 
 | ||||
|       - name: 'Checkout code' | ||||
|  | ||||
							
								
								
									
										6
									
								
								.github/workflows/lint_python.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.github/workflows/lint_python.yml
									
									
									
									
										vendored
									
									
								
							| @ -15,10 +15,8 @@ jobs: | ||||
|     steps: | ||||
|       - name: 'Decontaminate previous build leftovers' | ||||
|         run: | | ||||
|           if [ -d .git ] | ||||
|           then | ||||
|             git submodule status \ | ||||
|               || git checkout `git rev-list --max-parents=0 HEAD | tail -n 1` | ||||
|           if [ -d .git ]; then | ||||
|             git submodule status || git checkout "$(git rev-list --max-parents=0 HEAD | tail -n 1)" | ||||
|           fi | ||||
| 
 | ||||
|       - name: 'Checkout code' | ||||
|  | ||||
							
								
								
									
										48
									
								
								.github/workflows/pvs_studio.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										48
									
								
								.github/workflows/pvs_studio.yml
									
									
									
									
										vendored
									
									
								
							| @ -15,14 +15,13 @@ env: | ||||
| 
 | ||||
| jobs: | ||||
|   analyse_c_cpp: | ||||
|     if: ${{ !github.event.pull_request.head.repo.fork }} | ||||
|     runs-on: [self-hosted, FlipperZeroShell] | ||||
|     steps: | ||||
|       - name: 'Decontaminate previous build leftovers' | ||||
|         run: | | ||||
|           if [ -d .git ] | ||||
|           then | ||||
|             git submodule status \ | ||||
|               || git checkout `git rev-list --max-parents=0 HEAD | tail -n 1` | ||||
|           if [ -d .git ]; then | ||||
|             git submodule status || git checkout "$(git rev-list --max-parents=0 HEAD | tail -n 1)" | ||||
|           fi | ||||
| 
 | ||||
|       - name: 'Checkout code' | ||||
| @ -31,28 +30,23 @@ jobs: | ||||
|           fetch-depth: 0 | ||||
|           ref: ${{ github.event.pull_request.head.sha }} | ||||
| 
 | ||||
|       - name: 'Generate suffix and folder name' | ||||
|       - name: 'Get commit details' | ||||
|         run: | | ||||
|           FBT_TOOLCHAIN_PATH=/opt source scripts/toolchain/fbtenv.sh | ||||
|           if [[ ${{ github.event_name }} == 'pull_request' ]]; then | ||||
|             python3 scripts/get_env.py "--event_file=${{ github.event_path }}" "--is_pull" | ||||
|           else | ||||
|             python3 scripts/get_env.py "--event_file=${{ github.event_path }}" | ||||
|           fi | ||||
| 
 | ||||
|       - name: 'Generate suffixes for comment' | ||||
|         if: ${{ !github.event.pull_request.head.repo.fork && github.event.pull_request }} | ||||
|         id: names | ||||
|         run: | | ||||
|           REF=${{ github.ref }} | ||||
|           if [[ ${{ github.event_name }} == 'pull_request' ]]; then | ||||
|             REF=${{ github.head_ref }} | ||||
|           fi | ||||
|           BRANCH_OR_TAG=${REF#refs/*/} | ||||
|           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 "DIST_SUFFIX=${SUFFIX}" >> $GITHUB_ENV | ||||
|           echo "::set-output name=artifacts-path::${BRANCH_OR_TAG}" | ||||
|           echo "::set-output name=branch_name::${BRANCH_NAME}" | ||||
|           echo "::set-output name=commit_sha::${COMMIT_SHA}" | ||||
|           echo "::set-output name=default_target::${DEFAULT_TARGET}" | ||||
|           echo "::set-output name=suffix::${SUFFIX}" | ||||
|           echo "::set-output name=short-hash::${SHA}" | ||||
|           echo "::set-output name=default-target::${DEFAULT_TARGET}" | ||||
| 
 | ||||
|       - name: 'Make reports directory' | ||||
|         run: | | ||||
| @ -74,7 +68,7 @@ jobs: | ||||
|               -o PVS-Studio.log | ||||
| 
 | ||||
|       - name: 'Convert PVS-Studio output to html page' | ||||
|         run: plog-converter -a GA:1,2,3 -t fullhtml PVS-Studio.log -o reports/${{steps.names.outputs.default-target}}-${{steps.names.outputs.suffix}} | ||||
|         run: plog-converter -a GA:1,2,3 -t fullhtml PVS-Studio.log -o reports/${DEFAULT_TARGET}-${SUFFIX} | ||||
| 
 | ||||
|       - name: 'Upload artifacts to update server' | ||||
|         if: ${{ !github.event.pull_request.head.repo.fork }} | ||||
| @ -83,7 +77,7 @@ jobs: | ||||
|           chmod 600 ./deploy_key; | ||||
|           rsync -avrzP --mkpath \ | ||||
|               -e 'ssh -p ${{ secrets.RSYNC_DEPLOY_PORT }} -i ./deploy_key' \ | ||||
|               reports/ ${{ secrets.RSYNC_DEPLOY_USER }}@${{ secrets.RSYNC_DEPLOY_HOST }}:/home/data/firmware-pvs-studio-report/"${{steps.names.outputs.artifacts-path}}/"; | ||||
|               reports/ ${{ secrets.RSYNC_DEPLOY_USER }}@${{ secrets.RSYNC_DEPLOY_HOST }}:/home/data/firmware-pvs-studio-report/"${BRANCH_NAME}/"; | ||||
|           rm ./deploy_key; | ||||
| 
 | ||||
|       - name: 'Find Previous Comment' | ||||
| @ -102,6 +96,6 @@ jobs: | ||||
|           comment-id: ${{ steps.fc.outputs.comment-id }} | ||||
|           issue-number: ${{ github.event.pull_request.number }} | ||||
|           body: | | ||||
|             **PVS-Studio report for commit `${{steps.names.outputs.short-hash}}`:** | ||||
|             - [Report](https://update.flipperzero.one/builds/firmware-pvs-studio-report/${{steps.names.outputs.artifacts-path}}/${{steps.names.outputs.default-target}}-${{steps.names.outputs.suffix}}/index.html) | ||||
|             **PVS-Studio report for commit `${{steps.names.outputs.commit_sha}}`:** | ||||
|             - [Report](https://update.flipperzero.one/builds/firmware-pvs-studio-report/${{steps.names.outputs.branch_name}}/${{steps.names.outputs.default_target}}-${{steps.names.outputs.suffix}}/index.html) | ||||
|           edit-mode: replace | ||||
|  | ||||
							
								
								
									
										14
									
								
								ReadMe.md
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								ReadMe.md
									
									
									
									
									
								
							| @ -74,19 +74,7 @@ brew bundle --verbose | ||||
| 
 | ||||
| ## Linux Prerequisites | ||||
| 
 | ||||
| ### gcc-arm-none-eabi | ||||
| 
 | ||||
| ```sh | ||||
| toolchain="gcc-arm-none-eabi-10.3-2021.10" | ||||
| toolchain_package="$toolchain-$(uname -m)-linux" | ||||
| 
 | ||||
| wget -P /opt "https://developer.arm.com/-/media/Files/downloads/gnu-rm/10.3-2021.10/$toolchain_package.tar.bz2" | ||||
| 
 | ||||
| tar xjf /opt/$toolchain_package.tar.bz2 -C /opt | ||||
| rm /opt/$toolchain_package.tar.bz2 | ||||
| 
 | ||||
| for file in /opt/$toolchain/bin/* ; do ln -s "${file}" "/usr/bin/$(basename ${file})" ; done | ||||
| ``` | ||||
| The FBT tool handles everything, only `git` is required. | ||||
| 
 | ||||
| ### Optional dependencies | ||||
| 
 | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| # | ||||
| # Main Fipper Build System entry point | ||||
| # Main Flipper Build System entry point | ||||
| # | ||||
| # This file is evaluated by scons (the build system) every time fbt is invoked. | ||||
| # Scons constructs all referenced environments & their targets' dependency | ||||
| @ -15,7 +15,7 @@ DefaultEnvironment(tools=[]) | ||||
| # Progress(["OwO\r", "owo\r", "uwu\r", "owo\r"], interval=15) | ||||
| 
 | ||||
| 
 | ||||
| # This environment is created only for loading options & validating file/dir existance | ||||
| # This environment is created only for loading options & validating file/dir existence | ||||
| fbt_variables = SConscript("site_scons/commandline.scons") | ||||
| cmd_environment = Environment(tools=[], variables=fbt_variables) | ||||
| Help(fbt_variables.GenerateHelpText(cmd_environment)) | ||||
|  | ||||
							
								
								
									
										0
									
								
								applications/bad_usb/views/bad_usb_view.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/bad_usb/views/bad_usb_view.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/bt/bt_debug_app/views/bt_carrier_test.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/bt/bt_debug_app/views/bt_carrier_test.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/bt/bt_debug_app/views/bt_test.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/bt/bt_debug_app/views/bt_test.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/bt/bt_debug_app/views/bt_test.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/bt/bt_debug_app/views/bt_test.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/bt/bt_hid_app/views/bt_hid_keynote.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/bt/bt_hid_app/views/bt_hid_keynote.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/bt/bt_hid_app/views/bt_hid_media.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/bt/bt_hid_app/views/bt_hid_media.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/bt/bt_settings_app/bt_settings_app.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/bt/bt_settings_app/bt_settings_app.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/bt/bt_settings_app/bt_settings_app.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/bt/bt_settings_app/bt_settings_app.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/bt/bt_settings_app/scenes/bt_settings_scene_config.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/bt/bt_settings_app/scenes/bt_settings_scene_config.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/bt/bt_settings_app/scenes/bt_settings_scene_forget_dev_confirm.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/bt/bt_settings_app/scenes/bt_settings_scene_forget_dev_confirm.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/bt/bt_settings_app/scenes/bt_settings_scene_forget_dev_success.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/bt/bt_settings_app/scenes/bt_settings_scene_forget_dev_success.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/bt/bt_settings_app/scenes/bt_settings_scene_start.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/bt/bt_settings_app/scenes/bt_settings_scene_start.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							| @ -281,6 +281,9 @@ void cli_command_free(Cli* cli, string_t args, void* context) { | ||||
|     printf("Total heap size: %d\r\n", memmgr_get_total_heap()); | ||||
|     printf("Minimum heap size: %d\r\n", memmgr_get_minimum_free_heap()); | ||||
|     printf("Maximum heap block: %d\r\n", memmgr_heap_get_max_free_block()); | ||||
| 
 | ||||
|     printf("Pool free: %d\r\n", memmgr_pool_get_free()); | ||||
|     printf("Maximum pool block: %d\r\n", memmgr_pool_get_max_block()); | ||||
| } | ||||
| 
 | ||||
| void cli_command_free_blocks(Cli* cli, string_t args, void* context) { | ||||
|  | ||||
							
								
								
									
										0
									
								
								applications/cli/cli_i.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/cli/cli_i.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/gpio/views/gpio_test.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/gpio/views/gpio_test.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/gpio/views/gpio_test.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/gpio/views/gpio_test.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/gpio/views/gpio_usb_uart.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/gpio/views/gpio_usb_uart.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/gui/canvas.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/gui/canvas.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/gui/modules/dialog_ex.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/gui/modules/dialog_ex.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/gui/modules/menu.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/gui/modules/menu.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/gui/modules/text_box.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/gui/modules/text_box.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/gui/modules/text_box.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/gui/modules/text_box.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/gui/modules/variable_item_list.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/gui/modules/variable_item_list.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/gui/modules/widget.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/gui/modules/widget.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/gui/modules/widget_elements/widget_element_frame.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/gui/modules/widget_elements/widget_element_frame.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/gui/modules/widget_elements/widget_element_i.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/gui/modules/widget_elements/widget_element_i.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/gui/modules/widget_elements/widget_element_string.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/gui/modules/widget_elements/widget_element_string.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/gui/scene_manager.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/gui/scene_manager.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/gui/scene_manager.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/gui/scene_manager.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/gui/scene_manager_i.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/gui/scene_manager_i.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/gui/view_dispatcher.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/gui/view_dispatcher.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							| @ -3,6 +3,8 @@ | ||||
| #include <infrared.h> | ||||
| #include <infrared_worker.h> | ||||
| #include <furi_hal_infrared.h> | ||||
| #include <flipper_format.h> | ||||
| #include <toolbox/args.h> | ||||
| 
 | ||||
| #include "infrared_signal.h" | ||||
| 
 | ||||
| @ -10,6 +12,7 @@ | ||||
| 
 | ||||
| static void infrared_cli_start_ir_rx(Cli* cli, string_t args); | ||||
| static void infrared_cli_start_ir_tx(Cli* cli, string_t args); | ||||
| static void infrared_cli_process_decode(Cli* cli, string_t args); | ||||
| 
 | ||||
| static const struct { | ||||
|     const char* cmd; | ||||
| @ -17,6 +20,7 @@ static const struct { | ||||
| } infrared_cli_commands[] = { | ||||
|     {.cmd = "rx", .process_function = infrared_cli_start_ir_rx}, | ||||
|     {.cmd = "tx", .process_function = infrared_cli_start_ir_tx}, | ||||
|     {.cmd = "decode", .process_function = infrared_cli_process_decode}, | ||||
| }; | ||||
| 
 | ||||
| static void signal_received_callback(void* context, InfraredWorkerSignal* received_signal) { | ||||
| @ -86,6 +90,7 @@ static void infrared_cli_print_usage(void) { | ||||
|         "\tFrequency (%d - %d), Duty cycle (0 - 100), max 512 samples\r\n", | ||||
|         INFRARED_MIN_FREQUENCY, | ||||
|         INFRARED_MAX_FREQUENCY); | ||||
|     printf("\tir decode <input_file> [<output_file>]\r\n"); | ||||
| } | ||||
| 
 | ||||
| static bool infrared_cli_parse_message(const char* str, InfraredSignal* signal) { | ||||
| @ -162,6 +167,160 @@ static void infrared_cli_start_ir_tx(Cli* cli, string_t args) { | ||||
|     infrared_signal_free(signal); | ||||
| } | ||||
| 
 | ||||
| static bool | ||||
|     infrared_cli_save_signal(InfraredSignal* signal, FlipperFormat* file, const char* name) { | ||||
|     bool ret = infrared_signal_save(signal, file, name); | ||||
|     if(!ret) { | ||||
|         printf("Failed to save signal: \"%s\"\r\n", name); | ||||
|     } | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static bool infrared_cli_decode_raw_signal( | ||||
|     InfraredRawSignal* raw_signal, | ||||
|     InfraredDecoderHandler* decoder, | ||||
|     FlipperFormat* output_file, | ||||
|     const char* signal_name) { | ||||
|     InfraredSignal* signal = infrared_signal_alloc(); | ||||
|     bool ret = false, level = true, is_decoded = false; | ||||
| 
 | ||||
|     size_t i; | ||||
|     for(i = 0; i < raw_signal->timings_size; ++i) { | ||||
|         // TODO: Any infrared_check_decoder_ready() magic?
 | ||||
|         const InfraredMessage* message = infrared_decode(decoder, level, raw_signal->timings[i]); | ||||
| 
 | ||||
|         if(message) { | ||||
|             is_decoded = true; | ||||
|             printf( | ||||
|                 "Protocol: %s address: 0x%lX command: 0x%lX %s\r\n", | ||||
|                 infrared_get_protocol_name(message->protocol), | ||||
|                 message->address, | ||||
|                 message->command, | ||||
|                 (message->repeat ? "R" : "")); | ||||
|             if(output_file && !message->repeat) { | ||||
|                 infrared_signal_set_message(signal, message); | ||||
|                 if(!infrared_cli_save_signal(signal, output_file, signal_name)) break; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         level = !level; | ||||
|     } | ||||
| 
 | ||||
|     if(i == raw_signal->timings_size) { | ||||
|         if(!is_decoded && output_file) { | ||||
|             infrared_signal_set_raw_signal( | ||||
|                 signal, | ||||
|                 raw_signal->timings, | ||||
|                 raw_signal->timings_size, | ||||
|                 raw_signal->frequency, | ||||
|                 raw_signal->duty_cycle); | ||||
|             ret = infrared_cli_save_signal(signal, output_file, signal_name); | ||||
|         } else { | ||||
|             ret = true; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     infrared_reset_decoder(decoder); | ||||
|     infrared_signal_free(signal); | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static bool infrared_cli_decode_file(FlipperFormat* input_file, FlipperFormat* output_file) { | ||||
|     bool ret = false; | ||||
| 
 | ||||
|     InfraredSignal* signal = infrared_signal_alloc(); | ||||
|     InfraredDecoderHandler* decoder = infrared_alloc_decoder(); | ||||
| 
 | ||||
|     string_t tmp; | ||||
|     string_init(tmp); | ||||
| 
 | ||||
|     while(infrared_signal_read(signal, input_file, tmp)) { | ||||
|         ret = false; | ||||
|         if(!infrared_signal_is_valid(signal)) { | ||||
|             printf("Invalid signal\r\n"); | ||||
|             break; | ||||
|         } | ||||
|         if(!infrared_signal_is_raw(signal)) { | ||||
|             if(output_file && | ||||
|                !infrared_cli_save_signal(signal, output_file, string_get_cstr(tmp))) { | ||||
|                 break; | ||||
|             } else { | ||||
|                 printf("Skipping decoded signal\r\n"); | ||||
|                 continue; | ||||
|             } | ||||
|         } | ||||
|         InfraredRawSignal* raw_signal = infrared_signal_get_raw_signal(signal); | ||||
|         printf("Raw signal: %s, %u samples\r\n", string_get_cstr(tmp), raw_signal->timings_size); | ||||
|         if(!infrared_cli_decode_raw_signal(raw_signal, decoder, output_file, string_get_cstr(tmp))) | ||||
|             break; | ||||
|         ret = true; | ||||
|     } | ||||
| 
 | ||||
|     infrared_free_decoder(decoder); | ||||
|     infrared_signal_free(signal); | ||||
|     string_clear(tmp); | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static void infrared_cli_process_decode(Cli* cli, string_t args) { | ||||
|     UNUSED(cli); | ||||
|     Storage* storage = furi_record_open(RECORD_STORAGE); | ||||
|     FlipperFormat* input_file = flipper_format_buffered_file_alloc(storage); | ||||
|     FlipperFormat* output_file = NULL; | ||||
| 
 | ||||
|     uint32_t version; | ||||
|     string_t tmp, header, input_path, output_path; | ||||
|     string_init(tmp); | ||||
|     string_init(header); | ||||
|     string_init(input_path); | ||||
|     string_init(output_path); | ||||
| 
 | ||||
|     do { | ||||
|         if(!args_read_probably_quoted_string_and_trim(args, input_path)) { | ||||
|             printf("Wrong arguments.\r\n"); | ||||
|             infrared_cli_print_usage(); | ||||
|             break; | ||||
|         } | ||||
|         args_read_probably_quoted_string_and_trim(args, output_path); | ||||
|         if(!flipper_format_buffered_file_open_existing(input_file, string_get_cstr(input_path))) { | ||||
|             printf("Failed to open file for reading: \"%s\"\r\n", string_get_cstr(input_path)); | ||||
|             break; | ||||
|         } | ||||
|         if(!flipper_format_read_header(input_file, header, &version) || | ||||
|            (!string_start_with_str_p(header, "IR")) || version != 1) { | ||||
|             printf("Invalid or corrupted input file: \"%s\"\r\n", string_get_cstr(input_path)); | ||||
|             break; | ||||
|         } | ||||
|         if(!string_empty_p(output_path)) { | ||||
|             printf("Writing output to file: \"%s\"\r\n", string_get_cstr(output_path)); | ||||
|             output_file = flipper_format_file_alloc(storage); | ||||
|         } | ||||
|         if(output_file && | ||||
|            !flipper_format_file_open_always(output_file, string_get_cstr(output_path))) { | ||||
|             printf("Failed to open file for writing: \"%s\"\r\n", string_get_cstr(output_path)); | ||||
|             break; | ||||
|         } | ||||
|         if(output_file && !flipper_format_write_header(output_file, header, version)) { | ||||
|             printf("Failed to write to the output file: \"%s\"\r\n", string_get_cstr(output_path)); | ||||
|             break; | ||||
|         } | ||||
|         if(!infrared_cli_decode_file(input_file, output_file)) { | ||||
|             break; | ||||
|         } | ||||
|         printf("File successfully decoded.\r\n"); | ||||
|     } while(false); | ||||
| 
 | ||||
|     string_clear(tmp); | ||||
|     string_clear(header); | ||||
|     string_clear(input_path); | ||||
|     string_clear(output_path); | ||||
| 
 | ||||
|     flipper_format_free(input_file); | ||||
|     if(output_file) flipper_format_free(output_file); | ||||
|     furi_record_close(RECORD_STORAGE); | ||||
| } | ||||
| 
 | ||||
| static void infrared_cli_start_ir(Cli* cli, string_t args, void* context) { | ||||
|     UNUSED(context); | ||||
|     if(furi_hal_infrared_is_busy()) { | ||||
| @ -169,18 +328,15 @@ static void infrared_cli_start_ir(Cli* cli, string_t args, void* context) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     string_t command; | ||||
|     string_init(command); | ||||
|     args_read_string_and_trim(args, command); | ||||
| 
 | ||||
|     size_t i = 0; | ||||
|     for(; i < COUNT_OF(infrared_cli_commands); ++i) { | ||||
|         size_t size = strlen(infrared_cli_commands[i].cmd); | ||||
|         bool cmd_found = !strncmp(string_get_cstr(args), infrared_cli_commands[i].cmd, size); | ||||
|         if(cmd_found) { | ||||
|             if(string_size(args) == size) { | ||||
|                 break; | ||||
|             } | ||||
|             if(string_get_cstr(args)[size] == ' ') { | ||||
|                 string_right(args, size + 1); | ||||
|                 break; | ||||
|             } | ||||
|         size_t cmd_len = strlen(infrared_cli_commands[i].cmd); | ||||
|         if(!strncmp(string_get_cstr(command), infrared_cli_commands[i].cmd, cmd_len)) { | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -189,6 +345,8 @@ static void infrared_cli_start_ir(Cli* cli, string_t args, void* context) { | ||||
|     } else { | ||||
|         infrared_cli_print_usage(); | ||||
|     } | ||||
| 
 | ||||
|     string_clear(command); | ||||
| } | ||||
| void infrared_on_system_start() { | ||||
| #ifdef SRV_CLI | ||||
|  | ||||
| @ -25,7 +25,6 @@ bool infrared_scene_learn_on_event(void* context, SceneManagerEvent event) { | ||||
| 
 | ||||
|     if(event.type == SceneManagerEventTypeCustom) { | ||||
|         if(event.event == InfraredCustomEventTypeSignalReceived) { | ||||
|             infrared_worker_rx_set_received_signal_callback(infrared->worker, NULL, NULL); | ||||
|             infrared_play_notification_message(infrared, InfraredNotificationMessageSuccess); | ||||
|             scene_manager_next_scene(infrared->scene_manager, InfraredSceneLearnSuccess); | ||||
|             consumed = true; | ||||
| @ -38,6 +37,7 @@ bool infrared_scene_learn_on_event(void* context, SceneManagerEvent event) { | ||||
| void infrared_scene_learn_on_exit(void* context) { | ||||
|     Infrared* infrared = context; | ||||
|     Popup* popup = infrared->popup; | ||||
|     infrared_worker_rx_set_received_signal_callback(infrared->worker, NULL, NULL); | ||||
|     infrared_worker_rx_stop(infrared->worker); | ||||
|     infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop); | ||||
|     popup_set_icon(popup, 0, 0, NULL); | ||||
|  | ||||
| @ -3,7 +3,7 @@ App( | ||||
|     name="Basic services", | ||||
|     apptype=FlipperAppType.METAPACKAGE, | ||||
|     provides=[ | ||||
|         "rpc", | ||||
|         "rpc_start", | ||||
|         "bt", | ||||
|         "desktop", | ||||
|         "loader", | ||||
|  | ||||
							
								
								
									
										0
									
								
								applications/nfc/helpers/nfc_emv_parser.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/nfc/helpers/nfc_emv_parser.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/nfc/helpers/nfc_emv_parser.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/nfc/helpers/nfc_emv_parser.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							| @ -254,7 +254,7 @@ static void | ||||
|         session_register_page = 234; | ||||
|         break; | ||||
|     default: | ||||
|         furi_assert(false); | ||||
|         furi_crash("Unknown MFUL"); | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -94,6 +94,11 @@ Nfc* nfc_alloc() { | ||||
|     view_dispatcher_add_view( | ||||
|         nfc->view_dispatcher, NfcViewDictAttack, dict_attack_get_view(nfc->dict_attack)); | ||||
| 
 | ||||
|     // Detect Reader
 | ||||
|     nfc->detect_reader = detect_reader_alloc(); | ||||
|     view_dispatcher_add_view( | ||||
|         nfc->view_dispatcher, NfcViewDetectReader, detect_reader_get_view(nfc->detect_reader)); | ||||
| 
 | ||||
|     // Generator
 | ||||
|     nfc->generator = NULL; | ||||
| 
 | ||||
| @ -158,6 +163,10 @@ void nfc_free(Nfc* nfc) { | ||||
|     view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewDictAttack); | ||||
|     dict_attack_free(nfc->dict_attack); | ||||
| 
 | ||||
|     // Detect Reader
 | ||||
|     view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewDetectReader); | ||||
|     detect_reader_free(nfc->detect_reader); | ||||
| 
 | ||||
|     // Worker
 | ||||
|     nfc_worker_stop(nfc->worker); | ||||
|     nfc_worker_free(nfc->worker); | ||||
|  | ||||
							
								
								
									
										0
									
								
								applications/nfc/nfc_cli.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/nfc/nfc_cli.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							| @ -28,6 +28,7 @@ | ||||
| #include <lib/nfc/parsers/nfc_supported_card.h> | ||||
| 
 | ||||
| #include "views/dict_attack.h" | ||||
| #include "views/detect_reader.h" | ||||
| 
 | ||||
| #include <nfc/scenes/nfc_scene.h> | ||||
| #include <nfc/helpers/nfc_custom_event.h> | ||||
| @ -71,6 +72,7 @@ struct Nfc { | ||||
|     TextBox* text_box; | ||||
|     Widget* widget; | ||||
|     DictAttack* dict_attack; | ||||
|     DetectReader* detect_reader; | ||||
| 
 | ||||
|     const NfcGenerator* generator; | ||||
| }; | ||||
| @ -85,6 +87,7 @@ typedef enum { | ||||
|     NfcViewTextBox, | ||||
|     NfcViewWidget, | ||||
|     NfcViewDictAttack, | ||||
|     NfcViewDetectReader, | ||||
| } NfcView; | ||||
| 
 | ||||
| Nfc* nfc_alloc(); | ||||
|  | ||||
							
								
								
									
										0
									
								
								applications/nfc/scenes/nfc_scene.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/nfc/scenes/nfc_scene.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										2
									
								
								applications/nfc/scenes/nfc_scene_config.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										2
									
								
								applications/nfc/scenes/nfc_scene_config.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							| @ -48,4 +48,6 @@ ADD_SCENE(nfc, rpc, Rpc) | ||||
| ADD_SCENE(nfc, exit_confirm, ExitConfirm) | ||||
| ADD_SCENE(nfc, retry_confirm, RetryConfirm) | ||||
| ADD_SCENE(nfc, detect_reader, DetectReader) | ||||
| ADD_SCENE(nfc, mfkey_nonces_info, MfkeyNoncesInfo) | ||||
| ADD_SCENE(nfc, mfkey_complete, MfkeyComplete) | ||||
| ADD_SCENE(nfc, nfc_data_info, NfcDataInfo) | ||||
|  | ||||
							
								
								
									
										0
									
								
								applications/nfc/scenes/nfc_scene_delete.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/nfc/scenes/nfc_scene_delete.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/nfc/scenes/nfc_scene_delete_success.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/nfc/scenes/nfc_scene_delete_success.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							| @ -1,126 +1,48 @@ | ||||
| #include "../nfc_i.h" | ||||
| #include <dolphin/dolphin.h> | ||||
| 
 | ||||
| #define NFC_SCENE_DETECT_READER_LOG_SIZE_MAX (200) | ||||
| 
 | ||||
| enum { | ||||
|     NfcSceneDetectReaderStateWidget, | ||||
|     NfcSceneDetectReaderStateTextBox, | ||||
| }; | ||||
| 
 | ||||
| bool nfc_detect_reader_worker_callback(NfcWorkerEvent event, void* context) { | ||||
|     UNUSED(event); | ||||
|     furi_assert(context); | ||||
|     Nfc* nfc = context; | ||||
|     view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit); | ||||
|     view_dispatcher_send_custom_event(nfc->view_dispatcher, event); | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| void nfc_scene_detect_reader_widget_callback(GuiButtonType result, InputType type, void* context) { | ||||
|     furi_assert(context); | ||||
|     Nfc* nfc = context; | ||||
|     if(type == InputTypeShort) { | ||||
|         view_dispatcher_send_custom_event(nfc->view_dispatcher, result); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void nfc_detect_reader_textbox_callback(void* context) { | ||||
| void nfc_scene_detect_reader_callback(void* context) { | ||||
|     furi_assert(context); | ||||
|     Nfc* nfc = context; | ||||
|     view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); | ||||
| } | ||||
| 
 | ||||
| // Add widget with device name or inform that data received
 | ||||
| static void nfc_scene_detect_reader_widget_config(Nfc* nfc, bool data_received) { | ||||
|     Widget* widget = nfc->widget; | ||||
|     widget_reset(widget); | ||||
| 
 | ||||
|     widget_add_icon_element(widget, 0, 14, &I_Reader_detect); | ||||
|     widget_add_string_element( | ||||
|         widget, 64, 3, AlignCenter, AlignTop, FontSecondary, "Hold Near Reader"); | ||||
|     widget_add_string_element(widget, 55, 22, AlignLeft, AlignTop, FontPrimary, "Emulating..."); | ||||
| 
 | ||||
|     if(data_received) { | ||||
|         widget_add_button_element( | ||||
|             widget, GuiButtonTypeCenter, "Log", nfc_scene_detect_reader_widget_callback, nfc); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void nfc_scene_detect_reader_on_enter(void* context) { | ||||
|     Nfc* nfc = context; | ||||
|     DOLPHIN_DEED(DolphinDeedNfcEmulate); | ||||
|     FuriHalNfcDevData nfc_params = { | ||||
|         .uid = {0x36, 0x9C, 0xe7, 0xb1, 0x0A, 0xC1, 0x34}, | ||||
|         .uid_len = 7, | ||||
|         .atqa = {0x44, 0x00}, | ||||
|         .sak = 0x08, | ||||
|         .type = FuriHalNfcTypeA, | ||||
|     }; | ||||
|     nfc->dev->dev_data.nfc_data = nfc_params; | ||||
| 
 | ||||
|     // Setup Widget
 | ||||
|     nfc_scene_detect_reader_widget_config(nfc, false); | ||||
|     // Setup TextBox
 | ||||
|     TextBox* text_box = nfc->text_box; | ||||
|     text_box_set_font(text_box, TextBoxFontHex); | ||||
|     text_box_set_focus(text_box, TextBoxFocusEnd); | ||||
|     string_reset(nfc->text_box_store); | ||||
| 
 | ||||
|     // Set Widget state and view
 | ||||
|     scene_manager_set_scene_state( | ||||
|         nfc->scene_manager, NfcSceneDetectReader, NfcSceneDetectReaderStateWidget); | ||||
|     view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); | ||||
|     // Start worker
 | ||||
|     memset(&nfc->dev->dev_data.reader_data, 0, sizeof(NfcReaderRequestData)); | ||||
|     detect_reader_set_callback(nfc->detect_reader, nfc_scene_detect_reader_callback, nfc); | ||||
|     nfc_worker_start( | ||||
|         nfc->worker, | ||||
|         NfcWorkerStateUidEmulate, | ||||
|         NfcWorkerStateAnalyzeReader, | ||||
|         &nfc->dev->dev_data, | ||||
|         nfc_detect_reader_worker_callback, | ||||
|         nfc); | ||||
| 
 | ||||
|     view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDetectReader); | ||||
| 
 | ||||
|     nfc_blink_start(nfc); | ||||
| } | ||||
| 
 | ||||
| bool nfc_scene_detect_reader_on_event(void* context, SceneManagerEvent event) { | ||||
|     Nfc* nfc = context; | ||||
|     NfcReaderRequestData* reader_data = &nfc->dev->dev_data.reader_data; | ||||
|     uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneDetectReader); | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event.type == SceneManagerEventTypeCustom) { | ||||
|         if(event.event == NfcCustomEventWorkerExit) { | ||||
|             // Add data button to widget if data is received for the first time
 | ||||
|             if(!string_size(nfc->text_box_store)) { | ||||
|                 nfc_scene_detect_reader_widget_config(nfc, true); | ||||
|             } | ||||
|             // Update TextBox data
 | ||||
|             if(string_size(nfc->text_box_store) < NFC_SCENE_DETECT_READER_LOG_SIZE_MAX) { | ||||
|                 string_cat_printf(nfc->text_box_store, "R:"); | ||||
|                 for(uint16_t i = 0; i < reader_data->size; i++) { | ||||
|                     string_cat_printf(nfc->text_box_store, " %02X", reader_data->data[i]); | ||||
|                 } | ||||
|                 string_push_back(nfc->text_box_store, '\n'); | ||||
|                 text_box_set_text(nfc->text_box, string_get_cstr(nfc->text_box_store)); | ||||
|             } | ||||
|             memset(reader_data, 0, sizeof(NfcReaderRequestData)); | ||||
|         if(event.event == NfcCustomEventViewExit) { | ||||
|             nfc_worker_stop(nfc->worker); | ||||
|             scene_manager_next_scene(nfc->scene_manager, NfcSceneMfkeyNoncesInfo); | ||||
|             consumed = true; | ||||
|         } else if(event.event == GuiButtonTypeCenter && state == NfcSceneDetectReaderStateWidget) { | ||||
|             view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox); | ||||
|             scene_manager_set_scene_state( | ||||
|                 nfc->scene_manager, NfcSceneDetectReader, NfcSceneDetectReaderStateTextBox); | ||||
|             consumed = true; | ||||
|         } else if(event.event == NfcCustomEventViewExit && state == NfcSceneDetectReaderStateTextBox) { | ||||
|             view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); | ||||
|             scene_manager_set_scene_state( | ||||
|                 nfc->scene_manager, NfcSceneDetectReader, NfcSceneDetectReaderStateWidget); | ||||
|             consumed = true; | ||||
|         } | ||||
|     } else if(event.type == SceneManagerEventTypeBack) { | ||||
|         if(state == NfcSceneDetectReaderStateTextBox) { | ||||
|             view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); | ||||
|             scene_manager_set_scene_state( | ||||
|                 nfc->scene_manager, NfcSceneDetectReader, NfcSceneDetectReaderStateWidget); | ||||
|         } else if(event.event == NfcWorkerEventDetectReaderMfkeyCollected) { | ||||
|             detect_reader_inc_nonce_cnt(nfc->detect_reader); | ||||
|             consumed = true; | ||||
|         } | ||||
|     } | ||||
| @ -135,9 +57,7 @@ void nfc_scene_detect_reader_on_exit(void* context) { | ||||
|     nfc_worker_stop(nfc->worker); | ||||
| 
 | ||||
|     // Clear view
 | ||||
|     widget_reset(nfc->widget); | ||||
|     text_box_reset(nfc->text_box); | ||||
|     string_reset(nfc->text_box_store); | ||||
|     detect_reader_reset(nfc->detect_reader); | ||||
| 
 | ||||
|     nfc_blink_stop(nfc); | ||||
| } | ||||
|  | ||||
							
								
								
									
										0
									
								
								applications/nfc/scenes/nfc_scene_emulate_uid.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/nfc/scenes/nfc_scene_emulate_uid.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/nfc/scenes/nfc_scene_file_select.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/nfc/scenes/nfc_scene_file_select.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/nfc/scenes/nfc_scene_mf_ultralight_emulate.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/nfc/scenes/nfc_scene_mf_ultralight_emulate.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										49
									
								
								applications/nfc/scenes/nfc_scene_mfkey_complete.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								applications/nfc/scenes/nfc_scene_mfkey_complete.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,49 @@ | ||||
| #include "../nfc_i.h" | ||||
| 
 | ||||
| void nfc_scene_mfkey_complete_callback(GuiButtonType result, InputType type, void* context) { | ||||
|     Nfc* nfc = context; | ||||
|     if(type == InputTypeShort) { | ||||
|         view_dispatcher_send_custom_event(nfc->view_dispatcher, result); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void nfc_scene_mfkey_complete_on_enter(void* context) { | ||||
|     Nfc* nfc = context; | ||||
| 
 | ||||
|     widget_add_string_element(nfc->widget, 64, 0, AlignCenter, AlignTop, FontPrimary, "Complete!"); | ||||
|     widget_add_string_multiline_element( | ||||
|         nfc->widget, | ||||
|         64, | ||||
|         32, | ||||
|         AlignCenter, | ||||
|         AlignCenter, | ||||
|         FontSecondary, | ||||
|         "Now use mfkey32v2\nto extract keys"); | ||||
|     widget_add_button_element( | ||||
|         nfc->widget, GuiButtonTypeCenter, "OK", nfc_scene_mfkey_complete_callback, nfc); | ||||
| 
 | ||||
|     view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); | ||||
| } | ||||
| 
 | ||||
| bool nfc_scene_mfkey_complete_on_event(void* context, SceneManagerEvent event) { | ||||
|     Nfc* nfc = context; | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event.type == SceneManagerEventTypeCustom) { | ||||
|         if(event.event == GuiButtonTypeCenter) { | ||||
|             consumed = scene_manager_search_and_switch_to_previous_scene( | ||||
|                 nfc->scene_manager, NfcSceneStart); | ||||
|         } | ||||
|     } else if(event.event == SceneManagerEventTypeBack) { | ||||
|         consumed = | ||||
|             scene_manager_search_and_switch_to_previous_scene(nfc->scene_manager, NfcSceneStart); | ||||
|     } | ||||
| 
 | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void nfc_scene_mfkey_complete_on_exit(void* context) { | ||||
|     Nfc* nfc = context; | ||||
| 
 | ||||
|     widget_reset(nfc->widget); | ||||
| } | ||||
							
								
								
									
										55
									
								
								applications/nfc/scenes/nfc_scene_mfkey_nonces_info.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								applications/nfc/scenes/nfc_scene_mfkey_nonces_info.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,55 @@ | ||||
| #include "../nfc_i.h" | ||||
| #include <lib/nfc/helpers/mfkey32.h> | ||||
| 
 | ||||
| void nfc_scene_mfkey_nonces_info_callback(GuiButtonType result, InputType type, void* context) { | ||||
|     Nfc* nfc = context; | ||||
|     if(type == InputTypeShort) { | ||||
|         view_dispatcher_send_custom_event(nfc->view_dispatcher, result); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void nfc_scene_mfkey_nonces_info_on_enter(void* context) { | ||||
|     Nfc* nfc = context; | ||||
| 
 | ||||
|     string_t temp_str; | ||||
|     string_init(temp_str); | ||||
| 
 | ||||
|     uint16_t nonces_saved = mfkey32_get_auth_sectors(temp_str); | ||||
|     widget_add_text_scroll_element(nfc->widget, 0, 22, 128, 42, string_get_cstr(temp_str)); | ||||
|     string_printf(temp_str, "Nonces saved %d", nonces_saved); | ||||
|     widget_add_string_element( | ||||
|         nfc->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, string_get_cstr(temp_str)); | ||||
|     widget_add_string_element( | ||||
|         nfc->widget, 0, 12, AlignLeft, AlignTop, FontSecondary, "Authenticated sectors:"); | ||||
| 
 | ||||
|     widget_add_button_element( | ||||
|         nfc->widget, GuiButtonTypeRight, "Next", nfc_scene_mfkey_nonces_info_callback, nfc); | ||||
| 
 | ||||
|     string_clear(temp_str); | ||||
| 
 | ||||
|     view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); | ||||
| } | ||||
| 
 | ||||
| bool nfc_scene_mfkey_nonces_info_on_event(void* context, SceneManagerEvent event) { | ||||
|     Nfc* nfc = context; | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event.type == SceneManagerEventTypeCustom) { | ||||
|         if(event.event == GuiButtonTypeRight) { | ||||
|             scene_manager_next_scene(nfc->scene_manager, NfcSceneMfkeyComplete); | ||||
|             consumed = true; | ||||
|         } | ||||
|     } else if(event.type == SceneManagerEventTypeBack) { | ||||
|         consumed = | ||||
|             scene_manager_search_and_switch_to_previous_scene(nfc->scene_manager, NfcSceneStart); | ||||
|     } | ||||
| 
 | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void nfc_scene_mfkey_nonces_info_on_exit(void* context) { | ||||
|     Nfc* nfc = context; | ||||
| 
 | ||||
|     // Clear view
 | ||||
|     widget_reset(nfc->widget); | ||||
| } | ||||
							
								
								
									
										0
									
								
								applications/nfc/scenes/nfc_scene_read_card_success.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/nfc/scenes/nfc_scene_read_card_success.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/nfc/scenes/nfc_scene_set_atqa.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/nfc/scenes/nfc_scene_set_atqa.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/nfc/scenes/nfc_scene_set_sak.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/nfc/scenes/nfc_scene_set_sak.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/nfc/scenes/nfc_scene_set_uid.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/nfc/scenes/nfc_scene_set_uid.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							| @ -49,7 +49,12 @@ bool nfc_scene_start_on_event(void* context, SceneManagerEvent event) { | ||||
|             scene_manager_next_scene(nfc->scene_manager, NfcSceneRead); | ||||
|             consumed = true; | ||||
|         } else if(event.event == SubmenuIndexDetectReader) { | ||||
|             scene_manager_next_scene(nfc->scene_manager, NfcSceneDetectReader); | ||||
|             bool sd_exist = storage_sd_status(nfc->dev->storage) == FSE_OK; | ||||
|             if(sd_exist) { | ||||
|                 scene_manager_next_scene(nfc->scene_manager, NfcSceneDetectReader); | ||||
|             } else { | ||||
|                 scene_manager_next_scene(nfc->scene_manager, NfcSceneDictNotFound); | ||||
|             } | ||||
|             consumed = true; | ||||
|         } else if(event.event == SubmenuIndexSaved) { | ||||
|             scene_manager_next_scene(nfc->scene_manager, NfcSceneFileSelect); | ||||
| @ -61,7 +66,6 @@ bool nfc_scene_start_on_event(void* context, SceneManagerEvent event) { | ||||
|             scene_manager_next_scene(nfc->scene_manager, NfcSceneSetType); | ||||
|             consumed = true; | ||||
|         } else if(event.event == SubmenuIndexDebug) { | ||||
|             scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, SubmenuIndexDebug); | ||||
|             scene_manager_next_scene(nfc->scene_manager, NfcSceneDebug); | ||||
|             consumed = true; | ||||
|         } | ||||
|  | ||||
							
								
								
									
										115
									
								
								applications/nfc/views/detect_reader.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								applications/nfc/views/detect_reader.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,115 @@ | ||||
| #include "detect_reader.h" | ||||
| 
 | ||||
| #include <gui/elements.h> | ||||
| 
 | ||||
| struct DetectReader { | ||||
|     View* view; | ||||
|     DetectReaderDoneCallback callback; | ||||
|     void* context; | ||||
| }; | ||||
| 
 | ||||
| typedef struct { | ||||
|     uint16_t nonces; | ||||
| } DetectReaderViewModel; | ||||
| 
 | ||||
| static void detect_reader_draw_callback(Canvas* canvas, void* model) { | ||||
|     DetectReaderViewModel* m = model; | ||||
|     char text[32] = {}; | ||||
| 
 | ||||
|     snprintf(text, sizeof(text), "Tap the reader several times"); | ||||
|     canvas_draw_str_aligned(canvas, 64, 0, AlignCenter, AlignTop, "Tap the reader several times"); | ||||
| 
 | ||||
|     if(m->nonces == 0) { | ||||
|         canvas_set_font(canvas, FontPrimary); | ||||
|         canvas_draw_str_aligned(canvas, 52, 22, AlignLeft, AlignTop, "Emulating..."); | ||||
|         canvas_set_font(canvas, FontSecondary); | ||||
|         canvas_draw_str_aligned(canvas, 52, 35, AlignLeft, AlignTop, "MIFARE Classic"); | ||||
|         canvas_draw_icon(canvas, 0, 13, &I_Tap_reader_36x38); | ||||
|     } else { | ||||
|         canvas_set_font(canvas, FontPrimary); | ||||
|         canvas_draw_str_aligned(canvas, 54, 22, AlignLeft, AlignTop, "Collecting..."); | ||||
|         canvas_set_font(canvas, FontSecondary); | ||||
|         snprintf(text, sizeof(text), "Nonces: %d", m->nonces); | ||||
|         canvas_draw_str_aligned(canvas, 54, 35, AlignLeft, AlignTop, text); | ||||
|         elements_button_right(canvas, "Next"); | ||||
|         canvas_draw_icon(canvas, 6, 15, &I_ArrowC_1_36x36); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static bool detect_reader_input_callback(InputEvent* event, void* context) { | ||||
|     DetectReader* detect_reader = context; | ||||
|     furi_assert(detect_reader->callback); | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     uint8_t nonces = 0; | ||||
|     with_view_model( | ||||
|         detect_reader->view, (DetectReaderViewModel * model) { | ||||
|             nonces = model->nonces; | ||||
|             return false; | ||||
|         }); | ||||
| 
 | ||||
|     if(event->type == InputTypeShort) { | ||||
|         if(event->key == InputKeyRight) { | ||||
|             if(nonces > 0) { | ||||
|                 detect_reader->callback(detect_reader->context); | ||||
|                 consumed = true; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| DetectReader* detect_reader_alloc() { | ||||
|     DetectReader* detect_reader = malloc(sizeof(DetectReader)); | ||||
|     detect_reader->view = view_alloc(); | ||||
|     view_allocate_model(detect_reader->view, ViewModelTypeLocking, sizeof(DetectReaderViewModel)); | ||||
|     view_set_draw_callback(detect_reader->view, detect_reader_draw_callback); | ||||
|     view_set_input_callback(detect_reader->view, detect_reader_input_callback); | ||||
|     view_set_context(detect_reader->view, detect_reader); | ||||
| 
 | ||||
|     return detect_reader; | ||||
| } | ||||
| 
 | ||||
| void detect_reader_free(DetectReader* detect_reader) { | ||||
|     furi_assert(detect_reader); | ||||
| 
 | ||||
|     view_free(detect_reader->view); | ||||
|     free(detect_reader); | ||||
| } | ||||
| 
 | ||||
| void detect_reader_reset(DetectReader* detect_reader) { | ||||
|     furi_assert(detect_reader); | ||||
| 
 | ||||
|     with_view_model( | ||||
|         detect_reader->view, (DetectReaderViewModel * model) { | ||||
|             model->nonces = 0; | ||||
|             return false; | ||||
|         }); | ||||
| } | ||||
| 
 | ||||
| View* detect_reader_get_view(DetectReader* detect_reader) { | ||||
|     furi_assert(detect_reader); | ||||
| 
 | ||||
|     return detect_reader->view; | ||||
| } | ||||
| 
 | ||||
| void detect_reader_set_callback( | ||||
|     DetectReader* detect_reader, | ||||
|     DetectReaderDoneCallback callback, | ||||
|     void* context) { | ||||
|     furi_assert(detect_reader); | ||||
|     furi_assert(callback); | ||||
| 
 | ||||
|     detect_reader->callback = callback; | ||||
|     detect_reader->context = context; | ||||
| } | ||||
| 
 | ||||
| void detect_reader_inc_nonce_cnt(DetectReader* detect_reader) { | ||||
|     furi_assert(detect_reader); | ||||
|     with_view_model( | ||||
|         detect_reader->view, (DetectReaderViewModel * model) { | ||||
|             model->nonces++; | ||||
|             return false; | ||||
|         }); | ||||
| } | ||||
							
								
								
									
										23
									
								
								applications/nfc/views/detect_reader.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								applications/nfc/views/detect_reader.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | ||||
| #pragma once | ||||
| #include <stdint.h> | ||||
| #include <gui/view.h> | ||||
| #include <gui/modules/widget.h> | ||||
| 
 | ||||
| typedef struct DetectReader DetectReader; | ||||
| 
 | ||||
| typedef void (*DetectReaderDoneCallback)(void* context); | ||||
| 
 | ||||
| DetectReader* detect_reader_alloc(); | ||||
| 
 | ||||
| void detect_reader_free(DetectReader* detect_reader); | ||||
| 
 | ||||
| void detect_reader_reset(DetectReader* detect_reader); | ||||
| 
 | ||||
| View* detect_reader_get_view(DetectReader* detect_reader); | ||||
| 
 | ||||
| void detect_reader_set_callback( | ||||
|     DetectReader* detect_reader, | ||||
|     DetectReaderDoneCallback callback, | ||||
|     void* context); | ||||
| 
 | ||||
| void detect_reader_inc_nonce_cnt(DetectReader* detect_reader); | ||||
| @ -190,12 +190,87 @@ ReturnCode picopass_read_card(PicopassBlock* AA1) { | ||||
|     return ERR_NONE; | ||||
| } | ||||
| 
 | ||||
| ReturnCode picopass_write_card(PicopassBlock* AA1) { | ||||
|     rfalPicoPassIdentifyRes idRes; | ||||
|     rfalPicoPassSelectRes selRes; | ||||
|     rfalPicoPassReadCheckRes rcRes; | ||||
|     rfalPicoPassCheckRes chkRes; | ||||
| 
 | ||||
|     ReturnCode err; | ||||
| 
 | ||||
|     uint8_t div_key[8] = {0}; | ||||
|     uint8_t mac[4] = {0}; | ||||
|     uint8_t ccnr[12] = {0}; | ||||
| 
 | ||||
|     err = rfalPicoPassPollerIdentify(&idRes); | ||||
|     if(err != ERR_NONE) { | ||||
|         FURI_LOG_E(TAG, "rfalPicoPassPollerIdentify error %d", err); | ||||
|         return err; | ||||
|     } | ||||
| 
 | ||||
|     err = rfalPicoPassPollerSelect(idRes.CSN, &selRes); | ||||
|     if(err != ERR_NONE) { | ||||
|         FURI_LOG_E(TAG, "rfalPicoPassPollerSelect error %d", err); | ||||
|         return err; | ||||
|     } | ||||
| 
 | ||||
|     err = rfalPicoPassPollerReadCheck(&rcRes); | ||||
|     if(err != ERR_NONE) { | ||||
|         FURI_LOG_E(TAG, "rfalPicoPassPollerReadCheck error %d", err); | ||||
|         return err; | ||||
|     } | ||||
|     memcpy(ccnr, rcRes.CCNR, sizeof(rcRes.CCNR)); // last 4 bytes left 0
 | ||||
| 
 | ||||
|     loclass_diversifyKey(selRes.CSN, picopass_iclass_key, div_key); | ||||
|     loclass_opt_doReaderMAC(ccnr, div_key, mac); | ||||
| 
 | ||||
|     err = rfalPicoPassPollerCheck(mac, &chkRes); | ||||
|     if(err != ERR_NONE) { | ||||
|         FURI_LOG_E(TAG, "rfalPicoPassPollerCheck error %d", err); | ||||
|         return err; | ||||
|     } | ||||
| 
 | ||||
|     for(size_t i = 6; i < 10; i++) { | ||||
|         FURI_LOG_D(TAG, "rfalPicoPassPollerWriteBlock %d", i); | ||||
|         uint8_t data[9] = {0}; | ||||
|         data[0] = i; | ||||
|         memcpy(data + 1, AA1[i].data, RFAL_PICOPASS_MAX_BLOCK_LEN); | ||||
|         loclass_doMAC_N(data, sizeof(data), div_key, mac); | ||||
|         FURI_LOG_D( | ||||
|             TAG, | ||||
|             "loclass_doMAC_N %d %02x%02x%02x%02x%02x%02x%02x%02x %02x%02x%02x%02x", | ||||
|             i, | ||||
|             data[1], | ||||
|             data[2], | ||||
|             data[3], | ||||
|             data[4], | ||||
|             data[5], | ||||
|             data[6], | ||||
|             data[7], | ||||
|             data[8], | ||||
|             mac[0], | ||||
|             mac[1], | ||||
|             mac[2], | ||||
|             mac[3]); | ||||
| 
 | ||||
|         err = rfalPicoPassPollerWriteBlock(i, AA1[i].data, mac); | ||||
|         if(err != ERR_NONE) { | ||||
|             FURI_LOG_E(TAG, "rfalPicoPassPollerWriteBlock error %d", err); | ||||
|             return err; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return ERR_NONE; | ||||
| } | ||||
| 
 | ||||
| int32_t picopass_worker_task(void* context) { | ||||
|     PicopassWorker* picopass_worker = context; | ||||
| 
 | ||||
|     picopass_worker_enable_field(); | ||||
|     if(picopass_worker->state == PicopassWorkerStateDetect) { | ||||
|         picopass_worker_detect(picopass_worker); | ||||
|     } else if(picopass_worker->state == PicopassWorkerStateWrite) { | ||||
|         picopass_worker_write(picopass_worker); | ||||
|     } | ||||
|     picopass_worker_disable_field(ERR_NONE); | ||||
| 
 | ||||
| @ -212,27 +287,60 @@ void picopass_worker_detect(PicopassWorker* picopass_worker) { | ||||
|     PicopassPacs* pacs = &dev_data->pacs; | ||||
|     ReturnCode err; | ||||
| 
 | ||||
|     PicopassWorkerEvent nextState = PicopassWorkerEventSuccess; | ||||
| 
 | ||||
|     while(picopass_worker->state == PicopassWorkerStateDetect) { | ||||
|         if(picopass_detect_card(1000) == ERR_NONE) { | ||||
|             // Process first found device
 | ||||
|             err = picopass_read_card(AA1); | ||||
|             if(err != ERR_NONE) { | ||||
|                 FURI_LOG_E(TAG, "picopass_read_card error %d", err); | ||||
|                 nextState = PicopassWorkerEventFail; | ||||
|             } | ||||
| 
 | ||||
|             err = picopass_device_parse_credential(AA1, pacs); | ||||
|             if(nextState == PicopassWorkerEventSuccess) { | ||||
|                 err = picopass_device_parse_credential(AA1, pacs); | ||||
|             } | ||||
|             if(err != ERR_NONE) { | ||||
|                 FURI_LOG_E(TAG, "picopass_device_parse_credential error %d", err); | ||||
|                 nextState = PicopassWorkerEventFail; | ||||
|             } | ||||
| 
 | ||||
|             err = picopass_device_parse_wiegand(pacs->credential, &pacs->record); | ||||
|             if(nextState == PicopassWorkerEventSuccess) { | ||||
|                 err = picopass_device_parse_wiegand(pacs->credential, &pacs->record); | ||||
|             } | ||||
|             if(err != ERR_NONE) { | ||||
|                 FURI_LOG_E(TAG, "picopass_device_parse_wiegand error %d", err); | ||||
|                 nextState = PicopassWorkerEventFail; | ||||
|             } | ||||
| 
 | ||||
|             // Notify caller and exit
 | ||||
|             if(picopass_worker->callback) { | ||||
|                 picopass_worker->callback(PicopassWorkerEventSuccess, picopass_worker->context); | ||||
|                 picopass_worker->callback(nextState, picopass_worker->context); | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
|         furi_delay_ms(100); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void picopass_worker_write(PicopassWorker* picopass_worker) { | ||||
|     PicopassDeviceData* dev_data = picopass_worker->dev_data; | ||||
|     PicopassBlock* AA1 = dev_data->AA1; | ||||
|     ReturnCode err; | ||||
|     PicopassWorkerEvent nextState = PicopassWorkerEventSuccess; | ||||
| 
 | ||||
|     while(picopass_worker->state == PicopassWorkerStateWrite) { | ||||
|         if(picopass_detect_card(1000) == ERR_NONE) { | ||||
|             err = picopass_write_card(AA1); | ||||
|             if(err != ERR_NONE) { | ||||
|                 FURI_LOG_E(TAG, "picopass_write_card error %d", err); | ||||
|                 nextState = PicopassWorkerEventFail; | ||||
|             } | ||||
| 
 | ||||
|             // Notify caller and exit
 | ||||
|             if(picopass_worker->callback) { | ||||
|                 picopass_worker->callback(nextState, picopass_worker->context); | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
|  | ||||
							
								
								
									
										1
									
								
								applications/picopass/picopass_worker.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										1
									
								
								applications/picopass/picopass_worker.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							| @ -11,6 +11,7 @@ typedef enum { | ||||
|     PicopassWorkerStateReady, | ||||
|     // Main worker states
 | ||||
|     PicopassWorkerStateDetect, | ||||
|     PicopassWorkerStateWrite, | ||||
|     // Transition
 | ||||
|     PicopassWorkerStateStop, | ||||
| } PicopassWorkerState; | ||||
|  | ||||
| @ -31,3 +31,4 @@ void picopass_worker_change_state(PicopassWorker* picopass_worker, PicopassWorke | ||||
| int32_t picopass_worker_task(void* context); | ||||
| 
 | ||||
| void picopass_worker_detect(PicopassWorker* picopass_worker); | ||||
| void picopass_worker_write(PicopassWorker* picopass_worker); | ||||
|  | ||||
							
								
								
									
										0
									
								
								applications/picopass/scenes/picopass_scene.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/picopass/scenes/picopass_scene.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										2
									
								
								applications/picopass/scenes/picopass_scene_config.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										2
									
								
								applications/picopass/scenes/picopass_scene_config.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							| @ -9,3 +9,5 @@ ADD_SCENE(picopass, file_select, FileSelect) | ||||
| ADD_SCENE(picopass, device_info, DeviceInfo) | ||||
| ADD_SCENE(picopass, delete, Delete) | ||||
| ADD_SCENE(picopass, delete_success, DeleteSuccess) | ||||
| ADD_SCENE(picopass, write_card, WriteCard) | ||||
| ADD_SCENE(picopass, write_card_success, WriteCardSuccess) | ||||
|  | ||||
							
								
								
									
										0
									
								
								applications/picopass/scenes/picopass_scene_delete_success.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/picopass/scenes/picopass_scene_delete_success.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							| @ -37,8 +37,6 @@ bool picopass_scene_read_card_on_event(void* context, SceneManagerEvent event) { | ||||
|             scene_manager_next_scene(picopass->scene_manager, PicopassSceneReadCardSuccess); | ||||
|             consumed = true; | ||||
|         } | ||||
|     } else if(event.type == SceneManagerEventTypeTick) { | ||||
|         consumed = true; | ||||
|     } | ||||
|     return consumed; | ||||
| } | ||||
|  | ||||
| @ -29,38 +29,57 @@ void picopass_scene_read_card_success_on_enter(void* context) { | ||||
|     PicopassPacs* pacs = &picopass->dev->dev_data.pacs; | ||||
|     Widget* widget = picopass->widget; | ||||
| 
 | ||||
|     size_t bytesLength = 1 + pacs->record.bitLength / 8; | ||||
|     string_set_str(credential_str, ""); | ||||
|     for(uint8_t i = PICOPASS_BLOCK_LEN - bytesLength; i < PICOPASS_BLOCK_LEN; i++) { | ||||
|         string_cat_printf(credential_str, " %02X", pacs->credential[i]); | ||||
|     } | ||||
|     if(pacs->record.bitLength == 0) { | ||||
|         string_cat_printf(wiegand_str, "Read Failed"); | ||||
| 
 | ||||
|     if(pacs->record.valid) { | ||||
|         string_cat_printf( | ||||
|             wiegand_str, "FC: %u CN: %u", pacs->record.FacilityCode, pacs->record.CardNumber); | ||||
|         widget_add_button_element( | ||||
|             widget, | ||||
|             GuiButtonTypeLeft, | ||||
|             "Retry", | ||||
|             picopass_scene_read_card_success_widget_callback, | ||||
|             picopass); | ||||
| 
 | ||||
|         widget_add_string_element( | ||||
|             widget, 64, 12, AlignCenter, AlignCenter, FontPrimary, string_get_cstr(wiegand_str)); | ||||
|     } else { | ||||
|         string_cat_printf(wiegand_str, "%d bits", pacs->record.bitLength); | ||||
|         size_t bytesLength = 1 + pacs->record.bitLength / 8; | ||||
|         string_set_str(credential_str, ""); | ||||
|         for(uint8_t i = PICOPASS_BLOCK_LEN - bytesLength; i < PICOPASS_BLOCK_LEN; i++) { | ||||
|             string_cat_printf(credential_str, " %02X", pacs->credential[i]); | ||||
|         } | ||||
| 
 | ||||
|         if(pacs->record.valid) { | ||||
|             string_cat_printf( | ||||
|                 wiegand_str, "FC: %u CN: %u", pacs->record.FacilityCode, pacs->record.CardNumber); | ||||
|         } else { | ||||
|             string_cat_printf(wiegand_str, "%d bits", pacs->record.bitLength); | ||||
|         } | ||||
| 
 | ||||
|         widget_add_button_element( | ||||
|             widget, | ||||
|             GuiButtonTypeLeft, | ||||
|             "Retry", | ||||
|             picopass_scene_read_card_success_widget_callback, | ||||
|             picopass); | ||||
| 
 | ||||
|         widget_add_button_element( | ||||
|             widget, | ||||
|             GuiButtonTypeRight, | ||||
|             "More", | ||||
|             picopass_scene_read_card_success_widget_callback, | ||||
|             picopass); | ||||
| 
 | ||||
|         widget_add_string_element( | ||||
|             widget, 64, 12, AlignCenter, AlignCenter, FontPrimary, string_get_cstr(wiegand_str)); | ||||
|         widget_add_string_element( | ||||
|             widget, | ||||
|             64, | ||||
|             32, | ||||
|             AlignCenter, | ||||
|             AlignCenter, | ||||
|             FontSecondary, | ||||
|             string_get_cstr(credential_str)); | ||||
|     } | ||||
| 
 | ||||
|     widget_add_button_element( | ||||
|         widget, | ||||
|         GuiButtonTypeLeft, | ||||
|         "Retry", | ||||
|         picopass_scene_read_card_success_widget_callback, | ||||
|         picopass); | ||||
| 
 | ||||
|     widget_add_button_element( | ||||
|         widget, | ||||
|         GuiButtonTypeRight, | ||||
|         "More", | ||||
|         picopass_scene_read_card_success_widget_callback, | ||||
|         picopass); | ||||
| 
 | ||||
|     widget_add_string_element( | ||||
|         widget, 64, 12, AlignCenter, AlignCenter, FontPrimary, string_get_cstr(wiegand_str)); | ||||
|     widget_add_string_element( | ||||
|         widget, 64, 32, AlignCenter, AlignCenter, FontSecondary, string_get_cstr(credential_str)); | ||||
| 
 | ||||
|     string_clear(credential_str); | ||||
|     string_clear(wiegand_str); | ||||
| 
 | ||||
|  | ||||
| @ -24,6 +24,8 @@ void picopass_scene_saved_menu_on_enter(void* context) { | ||||
|         picopass); | ||||
|     submenu_add_item( | ||||
|         submenu, "Info", SubmenuIndexInfo, picopass_scene_saved_menu_submenu_callback, picopass); | ||||
|     submenu_add_item( | ||||
|         submenu, "Write", SubmenuIndexWrite, picopass_scene_saved_menu_submenu_callback, picopass); | ||||
| 
 | ||||
|     submenu_set_selected_item( | ||||
|         picopass->submenu, | ||||
| @ -46,6 +48,9 @@ bool picopass_scene_saved_menu_on_event(void* context, SceneManagerEvent event) | ||||
|         } else if(event.event == SubmenuIndexInfo) { | ||||
|             scene_manager_next_scene(picopass->scene_manager, PicopassSceneDeviceInfo); | ||||
|             consumed = true; | ||||
|         } else if(event.event == SubmenuIndexWrite) { | ||||
|             scene_manager_next_scene(picopass->scene_manager, PicopassSceneWriteCard); | ||||
|             consumed = true; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										53
									
								
								applications/picopass/scenes/picopass_scene_write_card.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								applications/picopass/scenes/picopass_scene_write_card.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,53 @@ | ||||
| #include "../picopass_i.h" | ||||
| #include <dolphin/dolphin.h> | ||||
| 
 | ||||
| void picopass_write_card_worker_callback(PicopassWorkerEvent event, void* context) { | ||||
|     UNUSED(event); | ||||
|     Picopass* picopass = context; | ||||
|     view_dispatcher_send_custom_event(picopass->view_dispatcher, PicopassCustomEventWorkerExit); | ||||
| } | ||||
| 
 | ||||
| void picopass_scene_write_card_on_enter(void* context) { | ||||
|     Picopass* picopass = context; | ||||
|     DOLPHIN_DEED(DolphinDeedNfcSave); | ||||
| 
 | ||||
|     // Setup view
 | ||||
|     Popup* popup = picopass->popup; | ||||
|     popup_set_header(popup, "Writing\npicopass\ncard", 68, 30, AlignLeft, AlignTop); | ||||
|     popup_set_icon(popup, 0, 3, &I_RFIDDolphinSend_97x61); | ||||
| 
 | ||||
|     // Start worker
 | ||||
|     view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewPopup); | ||||
|     picopass_worker_start( | ||||
|         picopass->worker, | ||||
|         PicopassWorkerStateWrite, | ||||
|         &picopass->dev->dev_data, | ||||
|         picopass_write_card_worker_callback, | ||||
|         picopass); | ||||
| 
 | ||||
|     picopass_blink_start(picopass); | ||||
| } | ||||
| 
 | ||||
| bool picopass_scene_write_card_on_event(void* context, SceneManagerEvent event) { | ||||
|     Picopass* picopass = context; | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event.type == SceneManagerEventTypeCustom) { | ||||
|         if(event.event == PicopassCustomEventWorkerExit) { | ||||
|             scene_manager_next_scene(picopass->scene_manager, PicopassSceneWriteCardSuccess); | ||||
|             consumed = true; | ||||
|         } | ||||
|     } | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void picopass_scene_write_card_on_exit(void* context) { | ||||
|     Picopass* picopass = context; | ||||
| 
 | ||||
|     // Stop worker
 | ||||
|     picopass_worker_stop(picopass->worker); | ||||
|     // Clear view
 | ||||
|     popup_reset(picopass->popup); | ||||
| 
 | ||||
|     picopass_blink_stop(picopass); | ||||
| } | ||||
| @ -0,0 +1,57 @@ | ||||
| #include "../picopass_i.h" | ||||
| #include <dolphin/dolphin.h> | ||||
| 
 | ||||
| void picopass_scene_write_card_success_widget_callback( | ||||
|     GuiButtonType result, | ||||
|     InputType type, | ||||
|     void* context) { | ||||
|     furi_assert(context); | ||||
|     Picopass* picopass = context; | ||||
| 
 | ||||
|     if(type == InputTypeShort) { | ||||
|         view_dispatcher_send_custom_event(picopass->view_dispatcher, result); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void picopass_scene_write_card_success_on_enter(void* context) { | ||||
|     Picopass* picopass = context; | ||||
|     Widget* widget = picopass->widget; | ||||
| 
 | ||||
|     DOLPHIN_DEED(DolphinDeedNfcReadSuccess); | ||||
| 
 | ||||
|     // Send notification
 | ||||
|     notification_message(picopass->notifications, &sequence_success); | ||||
| 
 | ||||
|     widget_add_button_element( | ||||
|         widget, | ||||
|         GuiButtonTypeLeft, | ||||
|         "Retry", | ||||
|         picopass_scene_write_card_success_widget_callback, | ||||
|         picopass); | ||||
| 
 | ||||
|     view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewWidget); | ||||
| } | ||||
| 
 | ||||
| bool picopass_scene_write_card_success_on_event(void* context, SceneManagerEvent event) { | ||||
|     Picopass* picopass = context; | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event.type == SceneManagerEventTypeCustom) { | ||||
|         if(event.event == GuiButtonTypeLeft) { | ||||
|             consumed = scene_manager_previous_scene(picopass->scene_manager); | ||||
|         } else if(event.event == GuiButtonTypeRight) { | ||||
|             // Clear device name
 | ||||
|             picopass_device_set_name(picopass->dev, ""); | ||||
|             scene_manager_next_scene(picopass->scene_manager, PicopassSceneCardMenu); | ||||
|             consumed = true; | ||||
|         } | ||||
|     } | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void picopass_scene_write_card_success_on_exit(void* context) { | ||||
|     Picopass* picopass = context; | ||||
| 
 | ||||
|     // Clear view
 | ||||
|     widget_reset(picopass->widget); | ||||
| } | ||||
							
								
								
									
										0
									
								
								applications/power/battery_test_app/battery_test_app.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/power/battery_test_app/battery_test_app.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/power/power_service/power_i.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/power/power_service/power_i.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/power/power_settings_app/scenes/power_settings_scene_battery_info.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/power/power_settings_app/scenes/power_settings_scene_battery_info.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/power/power_settings_app/scenes/power_settings_scene_config.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/power/power_settings_app/scenes/power_settings_scene_config.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/power/power_settings_app/scenes/power_settings_scene_reboot.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/power/power_settings_app/scenes/power_settings_scene_reboot.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
								
								
									
										0
									
								
								applications/power/power_settings_app/scenes/power_settings_scene_start.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/power/power_settings_app/scenes/power_settings_scene_start.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							| @ -1,12 +1,8 @@ | ||||
| App( | ||||
|     appid="rpc", | ||||
|     name="RpcSrv", | ||||
|     apptype=FlipperAppType.SERVICE, | ||||
|     entry_point="rpc_srv", | ||||
|     appid="rpc_start", | ||||
|     apptype=FlipperAppType.STARTUP, | ||||
|     entry_point="rpc_on_system_start", | ||||
|     cdefines=["SRV_RPC"], | ||||
|     requires=[ | ||||
|         "cli", | ||||
|     ], | ||||
|     stack_size=4 * 1024, | ||||
|     requires=["cli"], | ||||
|     order=10, | ||||
| ) | ||||
|  | ||||
| @ -395,7 +395,7 @@ void rpc_session_close(RpcSession* session) { | ||||
|     furi_thread_flags_set(furi_thread_get_id(session->thread), RpcEvtDisconnect); | ||||
| } | ||||
| 
 | ||||
| int32_t rpc_srv(void* p) { | ||||
| void rpc_on_system_start(void* p) { | ||||
|     UNUSED(p); | ||||
|     Rpc* rpc = malloc(sizeof(Rpc)); | ||||
| 
 | ||||
| @ -406,8 +406,6 @@ int32_t rpc_srv(void* p) { | ||||
|         cli, "start_rpc_session", CliCommandFlagParallelSafe, rpc_cli_command_start_session, rpc); | ||||
| 
 | ||||
|     furi_record_create(RECORD_RPC, rpc); | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| void rpc_add_handler(RpcSession* session, pb_size_t message_tag, RpcHandler* handler) { | ||||
|  | ||||
							
								
								
									
										0
									
								
								applications/storage_settings/scenes/storage_settings_scene_formatting.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/storage_settings/scenes/storage_settings_scene_formatting.c
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							| @ -114,19 +114,21 @@ void subghz_cli_command_tx(Cli* cli, string_t args, void* context) { | ||||
|     uint32_t frequency = 433920000; | ||||
|     uint32_t key = 0x0074BADE; | ||||
|     uint32_t repeat = 10; | ||||
|     uint32_t te = 403; | ||||
| 
 | ||||
|     if(string_size(args)) { | ||||
|         int ret = sscanf(string_get_cstr(args), "%lx %lu %lu", &key, &frequency, &repeat); | ||||
|         if(ret != 3) { | ||||
|         int ret = sscanf(string_get_cstr(args), "%lx %lu %lu %lu", &key, &frequency, &te, &repeat); | ||||
|         if(ret != 4) { | ||||
|             printf( | ||||
|                 "sscanf returned %d, key: %lx, frequency: %lu, repeat: %lu\r\n", | ||||
|                 "sscanf returned %d, key: %lx, frequency: %lu, te:%lu, repeat: %lu\r\n", | ||||
|                 ret, | ||||
|                 key, | ||||
|                 frequency, | ||||
|                 te, | ||||
|                 repeat); | ||||
|             cli_print_usage( | ||||
|                 "subghz tx", | ||||
|                 "<3 Byte Key: in hex> <Frequency: in Hz> <Repeat count>", | ||||
|                 "<3 Byte Key: in hex> <Frequency: in Hz> <Te us> <Repeat count>", | ||||
|                 string_get_cstr(args)); | ||||
|             return; | ||||
|         } | ||||
| @ -139,9 +141,10 @@ void subghz_cli_command_tx(Cli* cli, string_t args, void* context) { | ||||
|     } | ||||
| 
 | ||||
|     printf( | ||||
|         "Transmitting at %lu, key %lx, repeat %lu. Press CTRL+C to stop\r\n", | ||||
|         "Transmitting at %lu, key %lx, te %lu, repeat %lu. Press CTRL+C to stop\r\n", | ||||
|         frequency, | ||||
|         key, | ||||
|         te, | ||||
|         repeat); | ||||
| 
 | ||||
|     string_t flipper_format_string; | ||||
| @ -149,12 +152,13 @@ void subghz_cli_command_tx(Cli* cli, string_t args, void* context) { | ||||
|         flipper_format_string, | ||||
|         "Protocol: Princeton\n" | ||||
|         "Bit: 24\n" | ||||
|         "Key: 00 00 00 00 00 %X %X %X\n" | ||||
|         "TE: 403\n" | ||||
|         "Key: 00 00 00 00 00 %02X %02X %02X\n" | ||||
|         "TE: %d\n" | ||||
|         "Repeat: %d\n", | ||||
|         (uint8_t)((key >> 16) & 0xFF), | ||||
|         (uint8_t)((key >> 8) & 0xFF), | ||||
|         (uint8_t)(key & 0xFF), | ||||
|         te, | ||||
|         repeat); | ||||
|     FlipperFormat* flipper_format = flipper_format_string_alloc(); | ||||
|     Stream* stream = flipper_format_get_raw_stream(flipper_format); | ||||
| @ -425,7 +429,7 @@ static void subghz_cli_command_print_usage() { | ||||
| 
 | ||||
|     printf("\tchat <frequency:in Hz>\t - Chat with other Flippers\r\n"); | ||||
|     printf( | ||||
|         "\ttx <3 byte Key: in hex> <frequency: in Hz> <repeat: count>\t - Transmitting key\r\n"); | ||||
|         "\ttx <3 byte Key: in hex> <frequency: in Hz> <te: us> <repeat: count>\t - Transmitting key\r\n"); | ||||
|     printf("\trx <frequency:in Hz>\t - Reception key\r\n"); | ||||
|     printf("\tdecode_raw <file_name: path_RAW_file>\t - Testing\r\n"); | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										0
									
								
								applications/system/system_settings.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							
							
						
						
									
										0
									
								
								applications/system/system_settings.h
									
									
									
									
									
										
										
										Executable file → Normal file
									
								
							| @ -13,7 +13,7 @@ | ||||
| #define CAME_ATOMO_DIR_NAME EXT_PATH("subghz/assets/came_atomo") | ||||
| #define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s") | ||||
| #define TEST_RANDOM_DIR_NAME EXT_PATH("unit_tests/subghz/test_random_raw.sub") | ||||
| #define TEST_RANDOM_COUNT_PARSE 196 | ||||
| #define TEST_RANDOM_COUNT_PARSE 232 | ||||
| #define TEST_TIMEOUT 10000 | ||||
| 
 | ||||
| static SubGhzEnvironment* environment_handler; | ||||
| @ -127,7 +127,7 @@ static bool subghz_decode_random_test(const char* path) { | ||||
|         } | ||||
|         subghz_file_encoder_worker_free(file_worker_encoder_handler); | ||||
|     } | ||||
|     FURI_LOG_T(TAG, "\r\n Decoder count parse \033[0;33m%d\033[0m ", subghz_test_decoder_count); | ||||
|     FURI_LOG_D(TAG, "\r\n Decoder count parse \033[0;33m%d\033[0m ", subghz_test_decoder_count); | ||||
|     if(furi_get_tick() - test_start > TEST_TIMEOUT * 10) { | ||||
|         printf("\033[0;31mRandom test ERROR TimeOut\033[0m\r\n"); | ||||
|         return false; | ||||
| @ -419,6 +419,21 @@ MU_TEST(subghz_decoder_magellen_test) { | ||||
|         "Test decoder " SUBGHZ_PROTOCOL_MAGELLEN_NAME " error\r\n"); | ||||
| } | ||||
| 
 | ||||
| MU_TEST(subghz_decoder_intertechno_v3_test) { | ||||
|     mu_assert( | ||||
|         subghz_decoder_test( | ||||
|             EXT_PATH("unit_tests/subghz/intertechno_v3_raw.sub"), | ||||
|             SUBGHZ_PROTOCOL_INTERTECHNO_V3_NAME), | ||||
|         "Test decoder " SUBGHZ_PROTOCOL_INTERTECHNO_V3_NAME " error\r\n"); | ||||
| } | ||||
| 
 | ||||
| MU_TEST(subghz_decoder_clemsa_test) { | ||||
|     mu_assert( | ||||
|         subghz_decoder_test( | ||||
|             EXT_PATH("unit_tests/subghz/clemsa_raw.sub"), SUBGHZ_PROTOCOL_CLEMSA_NAME), | ||||
|         "Test decoder " SUBGHZ_PROTOCOL_CLEMSA_NAME " error\r\n"); | ||||
| } | ||||
| 
 | ||||
| //test encoders
 | ||||
| MU_TEST(subghz_encoder_princeton_test) { | ||||
|     mu_assert( | ||||
| @ -528,6 +543,18 @@ MU_TEST(subghz_encoder_magellen_test) { | ||||
|         "Test encoder " SUBGHZ_PROTOCOL_MAGELLEN_NAME " error\r\n"); | ||||
| } | ||||
| 
 | ||||
| MU_TEST(subghz_encoder_intertechno_v3_test) { | ||||
|     mu_assert( | ||||
|         subghz_encoder_test(EXT_PATH("unit_tests/subghz/intertechno_v3.sub")), | ||||
|         "Test encoder " SUBGHZ_PROTOCOL_INTERTECHNO_V3_NAME " error\r\n"); | ||||
| } | ||||
| 
 | ||||
| MU_TEST(subghz_encoder_clemsa_test) { | ||||
|     mu_assert( | ||||
|         subghz_encoder_test(EXT_PATH("unit_tests/subghz/clemsa.sub")), | ||||
|         "Test encoder " SUBGHZ_PROTOCOL_CLEMSA_NAME " error\r\n"); | ||||
| } | ||||
| 
 | ||||
| MU_TEST(subghz_random_test) { | ||||
|     mu_assert(subghz_decode_random_test(TEST_RANDOM_DIR_NAME), "Random test error\r\n"); | ||||
| } | ||||
| @ -566,6 +593,8 @@ MU_TEST_SUITE(subghz) { | ||||
|     MU_RUN_TEST(subghz_decoder_phoenix_v2_test); | ||||
|     MU_RUN_TEST(subghz_decoder_honeywell_wdb_test); | ||||
|     MU_RUN_TEST(subghz_decoder_magellen_test); | ||||
|     MU_RUN_TEST(subghz_decoder_intertechno_v3_test); | ||||
|     MU_RUN_TEST(subghz_decoder_clemsa_test); | ||||
| 
 | ||||
|     MU_RUN_TEST(subghz_encoder_princeton_test); | ||||
|     MU_RUN_TEST(subghz_encoder_came_test); | ||||
| @ -585,6 +614,8 @@ MU_TEST_SUITE(subghz) { | ||||
|     MU_RUN_TEST(subghz_encoder_phoenix_v2_test); | ||||
|     MU_RUN_TEST(subghz_encoder_honeywell_wdb_test); | ||||
|     MU_RUN_TEST(subghz_encoder_magellen_test); | ||||
|     MU_RUN_TEST(subghz_encoder_intertechno_v3_test); | ||||
|     MU_RUN_TEST(subghz_encoder_clemsa_test); | ||||
| 
 | ||||
|     MU_RUN_TEST(subghz_random_test); | ||||
|     subghz_test_deinit(); | ||||
|  | ||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.6 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/NFC/Tap_reader_36x38.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/icons/NFC/Tap_reader_36x38.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 3.7 KiB | 
							
								
								
									
										7
									
								
								assets/unit_tests/subghz/clemsa.sub
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								assets/unit_tests/subghz/clemsa.sub
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| Filetype: Flipper SubGhz Key File | ||||
| Version: 1 | ||||
| Frequency: 433920000 | ||||
| Preset: FuriHalSubGhzPresetOok650Async | ||||
| Protocol: Clemsa | ||||
| Bit: 18 | ||||
| Key: 00 00 00 00 00 02 FC AA | ||||
							
								
								
									
										14
									
								
								assets/unit_tests/subghz/clemsa_raw.sub
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								assets/unit_tests/subghz/clemsa_raw.sub
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | ||||
| Filetype: Flipper SubGhz RAW File | ||||
| Version: 1 | ||||
| Frequency: 433920000 | ||||
| Preset: FuriHalSubGhzPresetOok650Async | ||||
| Protocol: RAW | ||||
| RAW_Data: -334 10811 -4320 65 -100 65 -698 10157 -7550 65 -200 165 -166 133 -66 531 -66 331 -102 197 -132 133 -298 99 -132 263 -200 261 -988 99 -262 131 -296 97 -132 229 -100 459 -100 131 -132 393 -100 1119 -100 8325 -6376 133 -366 131 -562 65 -1034 131 -198 563 -168 365 -66 229 -332 297 -100 231 -166 429 -132 295 -166 97 -100 195 -724 97 -132 97 -1088 163 -200 1651 -100 2885 -8520 365 -166 97 -1558 163 -198 163 -132 465 -134 131 -66 267 -198 65 -232 299 -66 165 -166 65 -498 165 -100 233 -200 133 -166 131 -68 821 -100 263 -66 7633 -7610 1259 -200 99 -98 165 -1196 99 -132 263 -266 99 -200 463 -66 627 -66 1981 -98 7801 -4004 97 -628 65 -264 133 -1088 163 -134 131 -928 297 -166 133 -134 131 -266 297 -596 229 -164 427 -564 197 -166 265 -198 65 -100 559 -6708 131 -132 131 -430 527 -200 367 -66 263 -198 233 -98 299 -68 365 -296 465 -132 855 -66 857 -98 4741 -8312 99 -364 163 -200 133 -1428 529 -132 65 -166 595 -1392 97 -100 97 -132 99 -264 199 -828 99 -398 297 -66 233 -98 861 -100 663 -100 2357 -100 5075 -4640 131 -3312 231 -100 363 -132 99 -296 99 -132 165 -132 363 -98 165 -130 65 -98 165 -132 163 -130 63 -164 297 -198 9769 -3852 133 -98 67 -1226 329 -526 99 -164 295 -496 1713 -196 1681 -130 131 -132 5497 -7230 65 -1150 133 -330 259 -66 329 -100 97 -988 165 -134 197 -166 67 -100 361 -68 461 -100 231 -132 165 -66 365 -264 231 -100 99 -98 265 -696 99 -166 199 -100 101 -962 7101 -6484 363 -760 363 -132 265 -134 431 -264 329 -66 427 -330 263 -164 593 -130 231 -130 627 -66 399 -432 329 -526 131 -100 591 -166 9305 -4044 65 -3532 361 -98 163 -66 461 -264 197 -98 391 -66 329 -132 165 -136 463 -66 529 -166 131 -100 199 -264 133 -66 361 -98 689 -66 229 -198 627 -66 297 -100 261 -66 1685 -134 7883 -3932 229 -728 133 -98 133 -862 65 -132 99 -498 297 -166 133 -332 197 -132 693 -198 97 -656 1087 -64 6209 -6164 131 -266 99 -496 165 -432 67 -100 97 -330 821 -98 361 -100 493 -164 133 -66 197 -200 431 -66 65 -66 399 -66 331 -200 199 -402 131 -664 10955 -5314 65 -262 97 -198 97 -724 99 -196 65 -592 327 -66 625 -262 131 -66 197 -64 427 -132 65 -628 265 -332 329 -368 789 -66 8809 -6238 129 -328 295 -232 363 -98 431 -100 199 -98 261 -530 561 -592 263 -132 1645 -5358 65 -764 65 -330 165 -1158 197 -432 265 -98 397 -166 463 -498 561 -398 199 -66 199 -66 3479 | ||||
| RAW_Data: -12124 165 -626 65 -890 229 -362 1329 -66 2187 -98 2081 -66 725 -134 3309 -9856 165 -166 263 -198 65 -960 653 -66 261 -66 821 -66 12463 -4032 97 -166 97 -924 65 -464 97 -68 163 -198 165 -100 263 -232 97 -366 633 -12244 65 -332 231 -200 197 -134 197 -234 2457 -134 399 -132 923 -198 197 -64 331 -132 295 -66 11377 -3896 163 -98 65 -194 131 -132 231 -366 131 -132 65 -1050 197 -200 299 -66 3007 -100 11685 -6172 133 -1154 491 -100 293 -200 65 -98 429 -266 463 -64 797 -98 265 -266 397 -132 1227 -66 8485 -4224 97 -166 65 -100 199 -2706 65 -66 263 -98 299 -298 231 -100 499 -66 97 -134 295 -66 431 -198 565 -66 2093 -100 533 -4056 65 -1482 229 -1160 165 -168 299 -166 459 -66 165 -134 99 -100 497 -166 397 -200 431 -200 65 -66 661 -164 529 -66 4671 -8442 131 -100 65 -66 165 -530 131 -132 597 -66 963 -488 275 -2806 2641 -438 2639 -420 2691 -412 2677 -404 2669 -416 2693 -416 361 -2730 367 -2724 2665 -422 355 -2726 2687 -394 399 -2698 2697 -390 375 -2732 2701 -388 355 -21244 2697 -416 377 -2722 2675 -416 2689 -388 2707 -396 2679 -414 2689 -392 2717 -388 375 -2706 383 -2732 2673 -396 365 -2734 2695 -386 377 -2728 2689 -384 389 -2730 2671 -386 379 -21252 2693 -416 347 -2748 2687 -396 2707 -384 2701 -388 2679 -412 2701 -418 2669 -404 363 -2726 385 -2698 2699 -416 355 -2706 2689 -416 365 -2736 2673 -386 415 -2692 2709 -378 361 -21270 2685 -452 311 -2774 2637 -442 2665 -418 2661 -448 2653 -408 2703 -384 2687 -410 365 -2738 355 -2742 2689 -382 371 -2738 2677 -384 415 -2700 2673 -410 363 -2730 2701 -386 357 -21270 2705 -398 361 -2740 2689 -386 2679 -414 2687 -410 2673 -418 2697 -386 2681 -412 383 -2702 395 -2706 2703 -380 385 -2696 2709 -418 355 -2702 2699 -418 361 -2700 2717 -386 375 -21242 2697 -418 355 -2748 2695 -382 2683 -410 2703 -380 2707 -384 2705 -404 2675 -416 383 -2700 359 -2728 2695 -382 385 -2728 2687 -416 357 -2708 2705 -386 389 -2700 2717 -388 373 -21234 2721 -418 353 -2724 2667 -416 2705 -380 2693 -386 2711 -384 2691 -422 2699 -398 365 -2726 385 -2700 2703 -378 361 -2728 2697 -420 357 -2704 2711 -388 377 -2734 2667 -406 363 -21260 2699 -418 361 -2702 2711 -380 2695 -416 2689 -402 2687 -384 2695 -416 2677 -408 361 -2732 385 -2704 2707 -414 325 -2730 2695 -418 361 -2728 2669 -414 385 -2702 2701 -414 355 -21246 2705 -378 379 -2728 2693 -384 2715 -380 2717 -386 2695 -390 2709 -388 2683 -420 355 -2730 385 -2700 2685 -416 347 -2748 2683 -396 365 -2740 2667 -416 385 -2696 2693 -414 349 -21260 2689 -452 319 -2762 2631 -476 2627 -430 2689 | ||||
| RAW_Data: -416 2667 -412 2671 -416 2689 -424 347 -2732 353 -2738 2669 -410 363 -2728 2689 -410 349 -2742 2677 -386 415 -2696 2705 -380 361 -21254 2717 -386 413 -2700 2693 -380 2695 -416 2691 -398 2679 -416 2699 -384 2709 -382 367 -2726 361 -2730 2707 -382 377 -2728 2675 -386 411 -2684 2713 -414 357 -2704 2707 -388 357 -21276 2699 -382 385 -2724 2689 -416 2661 -416 2685 -384 2723 -388 2703 -400 2677 -416 385 -2696 357 -2724 2713 -384 375 -2726 2673 -420 355 -2728 2685 -396 397 -2688 2697 -408 363 -21252 2667 -484 311 -2766 2635 -476 2637 -420 2665 -448 2651 -408 2701 -384 2697 -406 355 -2758 327 -2736 2685 -420 361 -2728 2683 -384 385 -2726 2685 -414 357 -2708 2711 -388 375 -21246 2689 -448 323 -2750 2695 -378 2715 -386 2687 -392 2711 -384 2683 -416 2705 -412 327 -2732 387 -2728 2679 -416 357 -2738 2659 -418 363 -2732 2677 -386 413 -2700 2695 -380 391 -21258 2679 -406 383 -2706 2695 -384 2703 -418 2679 -404 2705 -380 2687 -418 2669 -410 359 -2726 387 -2696 2707 -416 357 -2710 2693 -418 361 -2730 2691 -380 385 -2730 2677 -414 357 -21254 2711 -382 385 -2700 2713 -414 2667 -384 2705 -418 2675 -406 2699 -382 2689 -418 365 -2726 377 -2708 2701 -384 389 -2698 2709 -398 361 -2738 2669 -416 385 -2692 2687 -418 357 -77456 131 -398 197 -132 295 -330 97 -132 229 -164 459 -164 295 -264 393 -264 719 -64 427 -98 855 -134 395 -98 297 -164 263 -262 65 -100 63 -132 197 -328 1185 -66 9359 -6420 261 -664 131 -100 299 -134 301 -232 363 -232 299 -200 165 -166 427 -230 299 -164 361 -394 1025 -100 225 -820 165 -1248 491 -100 293 -66 261 -264 131 -98 589 -164 655 -132 427 -132 295 -164 129 -132 163 -328 263 -196 627 -566 129 -100 131 -98 2377 -130 1255 -3878 297 -232 195 -132 65 -98 165 -596 397 -266 99 -198 363 -98 923 -100 431 -66 1383 -3724 297 -166 165 -66 99 -398 265 -266 463 -232 133 -232 65 -230 65 -266 959 -200 99 -298 231 -68 65 -100 97 -398 363 -132 199 -134 133 -134 133 -266 593 -66 363 -66 827 -2374 65 -1724 399 -166 265 -100 331 -198 165 -398 233 -98 233 -66 165 -266 97 -66 231 -132 165 -298 395 -234 99 -132 65 -100 99 -132 131 -66 297 -264 197 -194 229 -530 2189 -166 9577 -3702 199 -98 465 -398 97 -134 395 -132 429 -100 529 -68 263 -132 265 -368 263 -860 97 -100 163 -196 427 -98 163 -166 327 -98 493 -166 327 -98 233 -5094 99 -198 97 -100 65 -1250 131 -560 855 -66 855 -262 859 -164 10219 -7528 761 -66 1121 -100 429 -298 331 -232 263 -166 261 -166 265 -100 1427 -98 9787 -6682 131 -564 429 | ||||
| RAW_Data: -66 529 -66 2519 -66 265 -68 10101 -1794 65 -1890 393 -562 97 -132 197 -98 493 -330 97 -164 97 -230 327 -326 99 -100 97 -164 65 -132 293 -98 297 -166 161 -130 297 -230 1391 -68 11185 -3800 229 -230 297 -66 65 -198 65 -466 99 -464 99 -430 67 -698 295 -132 165 -164 1095 -66 299 -66 1321 -264 12675 -66 99 -166 229 -134 65 -330 165 -164 65 -890 131 -830 67 -66 1157 -100 167 -168 265 -66 827 -66 2047 -100 261 -594 2279 -134 10701 -3890 163 -1384 67 -98 99 -1322 99 -98 65 -398 823 -66 65 -68 927 -100 495 -132 593 -100 165 -198 1387 -1022 131 -728 99 -662 97 -462 495 -200 829 -330 563 -100 297 -330 65 -598 165 -592 295 -166 131 -764 165 -164 565 -66 131 -166 165 -66 9675 -5052 165 -2878 199 -66 265 -432 265 -66 267 -898 163 -132 231 -198 229 -164 97 -100 4445 -66 7853 -636 199 -662 265 -298 233 -1428 331 -134 1791 -66 1649 -66 297 -100 361 -198 559 -98 363 -200 1315 -66 265 -98 1049 -132 1647 -66 265 -822 295 -526 131 -1712 199 -166 231 -200 165 -66 265 -166 97 -132 163 -164 395 -630 495 -168 297 -298 229 -266 629 -200 133 -132 133 -166 65 -132 99 -100 131 -66 67 -98 133 -496 1391 -98 1751 -164 359 -132 97 -164 263 -64 691 -66 199 -66 293 -98 589 -198 11299 -3968 65 -68 65 -2702 65 -1186 927 -166 65 -66 429 -134 197 -134 529 -200 67 -66 231 -100 2151 -4014 97 -1486 99 -464 65 -330 129 -330 331 -134 599 -66 497 -200 165 -66 661 -166 6881 -8830 295 -100 197 -232 725 -134 299 -166 229 -166 525 -198 295 -66 459 -66 329 -230 595 -98 299 -132 329 -66 99 -98 163 -134 229 -100 8345 -6726 131 -132 295 -66 1579 -66 329 -98 501 -132 231 -66 491 -298 331 -266 363 -132 1193 -168 8847 -4194 199 -828 65 -100 195 -262 197 -298 65 -898 65 -132 629 -66 229 -100 291 -100 623 -66 295 -66 461 -132 529 -632 597 -132 65 -100 97 -134 297 -100 297 -166 397 -168 527 -134 9603 -3850 99 -200 67 -896 959 -198 165 -100 229 -266 531 -64 165 -132 163 -296 3715 -11994 165 -1492 429 -68 263 -100 265 -330 199 -64 495 -132 363 -66 63 -166 297 -398 65 -100 231 -332 199 -100 7683 -4916 65 -1294 297 -1022 1325 -166 393 -132 165 -498 1255 -134 197 -198 427 -164 329 -132 631 -594 199 -196 99 -100 265 -134 1457 -100 3649 -8592 67 -268 131 -332 99 -100 65 -760 101 -198 297 -168 199 -132 369 -100 97 -132 99 -232 397 -198 99 -134 97 -100 231 -332 131 -796 329 -266 263 | ||||
| RAW_Data: -100 10841 -4030 163 -164 197 -398 195 -592 65 -132 63 -430 295 -298 263 -200 3517 -132 3763 -12296 99 -330 361 -98 99 -200 65 -430 165 -166 2327 -100 4051 -66 9653 -3478 197 -66 163 -198 167 -66 65 -598 165 -298 131 -666 199 -198 299 -298 165 -200 565 -66 797 -98 1125 -98 825 -100 4113 -6956 65 -5536 165 -266 99 -232 461 -198 65 -200 1989 -66 295 -66 723 -66 65 -98 329 -98 955 -66 559 -232 331 -66 10851 -1048 65 -3748 65 -498 99 -1392 99 -794 529 -98 331 -98 397 -164 363 -394 331 -266 299 -230 165 -66 3001 -568 197 -2872 2579 -468 2637 -472 2599 -488 2647 -426 2653 -448 2665 -392 379 -2734 381 -2700 2691 -388 377 -2732 2669 -420 355 -2726 2687 -394 403 -2706 2687 -388 377 -21248 2717 -388 377 -2738 2659 -408 2703 -382 2689 -416 2679 -408 2701 -382 2687 -418 365 -2736 365 -2722 2689 -384 391 -2696 2707 -386 379 -2734 2665 -410 361 -2726 2703 -418 357 -21246 2679 -466 297 -2768 2657 -448 2627 -434 2669 -450 2653 -416 2673 -408 2697 -386 383 -2728 369 -2706 2701 -382 387 -2726 2687 -418 357 -2708 2693 -418 361 -2702 2709 -396 401 -21232 2689 -406 361 -2736 2695 -386 2695 -406 2695 -382 2687 -418 2675 -410 2693 -414 375 -2692 389 -2706 2701 -404 363 -2724 2695 -388 389 -2702 2719 -358 405 -2704 2701 -402 363 -21262 2677 -414 367 -2738 2677 -386 2693 -420 2701 -400 2677 -386 2695 -420 2669 -430 369 -2718 353 -2730 2673 -412 361 -2734 2691 -420 357 -2698 2701 -394 401 -2702 2687 -424 347 -21244 2701 -418 365 -2726 2703 -382 2697 -420 2675 -400 2685 -384 2721 -398 2667 -418 355 -2744 343 -2722 2703 -420 353 -2724 2689 -396 363 -2736 2687 -390 377 -2730 2697 -386 357 -21274 2683 -414 375 -2726 2667 -420 2703 -398 2677 -388 2695 -420 2699 -398 2671 -384 415 -2698 357 -2738 2695 -382 383 -2724 2685 -416 357 -2706 2707 -384 391 -2726 2671 -384 415 -21238 2651 -476 293 -2776 2653 -462 2641 -446 2661 -422 2663 -418 2689 -412 2683 -414 357 -2706 385 -2698 2715 -378 379 -2710 2719 -388 377 -2708 2695 -406 361 -2724 2689 -416 361 -21244 2703 -386 413 -2698 2697 -414 2689 -384 2685 -386 2719 -378 2701 -416 2689 -386 377 -2728 387 -2700 2673 -410 361 -2730 2695 -420 357 -2732 2679 -386 377 -2734 2699 -378 361 -21262 2697 -392 405 -2702 2687 -406 2703 -382 2703 -418 2671 -406 2677 -416 2695 -386 387 -2700 381 -2704 2695 -418 357 -2712 2721 -388 375 -2702 2693 -408 363 -2730 2693 -420 355 -21248 2653 -494 289 -91206 131 -132 97 -232 559 -132 591 -98 691 -66 131 -130 297 -66 231 -66 331 -66 433 -100 499 -132 231 -166 197 -134 593 -100 11707 -4456 133 -200 131 | ||||
| RAW_Data: -66 133 -66 97 -166 561 -100 895 -132 1323 -66 10873 -3752 99 -722 229 -394 97 -66 99 -98 99 -328 297 -328 265 -298 3089 -132 10573 -1460 133 -432 99 -232 99 -132 333 -232 731 -164 65 -166 165 -132 131 -330 65 -98 131 -596 65 -198 133 -98 397 -568 65 -132 1157 -166 195 -130 131 -64 99 -66 63 -198 265 -98 297 -66 63 -166 295 -100 1747 -232 6099 -11348 199 -528 297 -266 97 -598 99 -198 231 -64 4433 -334 65 -298 65 -3284 67 -530 97 -432 133 -2356 493 -68 231 -168 297 -266 427 -100 559 -98 229 -460 197 -66 261 -132 65 -98 565 -132 231 -66 497 -100 3491 -12356 65 -660 197 -198 165 -132 331 -134 65 -98 2651 -134 4531 -10850 65 -1322 263 -68 431 -232 165 -134 165 -202 231 -300 5625 -66 6951 -8162 65 -398 99 -596 65 -132 461 -598 429 -132 97 -132 463 -232 229 -98 329 -100 397 -100 363 -100 231 -200 163 -200 961 -66 693 -100 397 -134 10601 -3872 263 -100 165 -100 131 -198 99 -696 233 -1524 331 -132 131 -164 229 -132 493 -98 631 -134 231 -100 595 -66 295 -66 5965 -8248 99 -296 99 -98 397 -66 65 -924 229 -398 299 -98 1425 -130 565 -198 827 -262 429 -598 725 -704 729 -12290 131 -98 99 -98 65 -100 163 -164 65 -494 231 -100 97 -100 863 -66 1751 -3948 165 -100 195 -66 165 -296 65 -2042 99 -200 495 -132 557 -100 827 -98 167 -66 433 -100 661 -164 689 -98 10803 -3906 231 -296 295 -232 99 -234 131 -332 395 -266 1283 -164 755 -466 397 -164 335 -66 1355 -14376 557 -66 331 -68 431 -134 599 -364 229 -100 763 -98 265 -132 525 -166 99 -396 495 -98 3867 -134 595 -168 865 -166 503 -200 467 -134 8145 -458 235 -794 599 -458 265 -436 231 -426 333 -368 299 -730 689 -360 327 -370 363 -326 367 -668 733 -328 363 -302 397 -328 371 -296 393 -666 725 -622 795 -634 433 -264 1023 -228 5041 -762 585 -466 233 -826 235 -470 631 -368 299 -402 299 -726 361 -328 331 -370 363 -332 701 -298 401 -692 369 -302 759 -268 461 -236 435 -622 423 -260 465 -266 719 -13608 65 -624 197 -558 921 -164 1315 -134 465 -134 263 -100 295 -132 293 -66 329 -98 197 -132 9977 -5036 197 -798 333 -828 295 -100 197 -100 165 -66 665 -100 763 -300 297 -166 165 -98 823 -8348 229 -100 427 -196 263 -624 197 -134 797 -100 263 -68 529 -132 233 -134 165 -264 131 -132 559 -66 263 -228 927 -132 731 -102 1061 -66 863 -8206 131 -332 299 -166 461 -100 99 -66 429 -66 3271 -98 465 -100 401 -232 331 -66 397 -430 10341 | ||||
| RAW_Data: -5434 65 -298 133 -132 131 -68 231 -200 661 -132 9517 -424 97 -1456 99 -1694 393 -100 131 -560 131 -196 197 -298 65 -428 229 -196 297 -266 131 -166 2435 -66 10161 -11230 65 -1320 131 -298 265 -532 231 -200 1291 -68 631 -66 12645 -4048 133 -66 67 -132 167 -266 163 -66 397 -132 197 -132 299 -98 197 -198 2903 -66 2361 -66 9627 -3588 197 -332 165 -68 331 -68 197 -132 99 -100 663 -66 363 -230 231 -166 131 -100 201 -298 163 -132 133 -202 363 -300 397 -102 263 -100 165 -66 1221 -66 1479 -132 165 -98 229 -12976 263 -66 363 -134 231 -66 629 -132 327 -100 97 -130 99 -164 227 -64 297 -132 397 -164 425 -198 97 -198 99 -66 365 -164 199 -102 97 -66 1817 -13524 231 -134 16907 -4086 233 -630 65 -396 201 -66 165 -198 67 -198 99 -664 2117 -166 12473 -446 2649 -440 2661 -420 2651 -422 2681 -418 2703 -400 365 -2724 387 -2696 2695 -414 357 -2704 2707 -386 389 -2700 2687 -392 405 -2706 2695 -402 363 -21268 2707 -388 377 -2706 2691 -404 2699 -382 2717 -382 2707 -378 2693 -416 2687 -396 363 -2736 355 -2748 2659 -416 365 -2708 2715 -388 377 -2708 2697 -404 363 -2730 2673 -420 355 -21268 2655 -460 319 -2766 2663 -448 2631 -436 2665 -418 2683 -410 2681 -416 2701 -386 383 -2700 375 -2744 2669 -416 353 -2730 2685 -416 357 -2708 2721 -380 369 -2724 2697 -382 385 -21260 2701 -418 353 -2720 2673 -418 2675 -408 2693 -384 2715 -386 2717 -386 2691 -404 363 -2732 387 -2702 2669 -412 359 -2736 2699 -380 381 -2728 2675 -416 381 -2720 2675 -414 347 -21280 2685 -390 377 -2724 2689 -416 2673 -408 2705 -382 2695 -410 2689 -414 2661 -418 385 -2704 369 -2704 2693 -416 375 -2726 2661 -420 355 -2728 2711 -388 375 -2702 2691 -410 363 -21252 2659 -488 287 -2794 2651 -448 2629 -436 2671 -416 2695 -416 2663 -406 2699 -384 383 -2730 367 -2702 2695 -418 385 -2702 2685 -412 349 -2744 2693 -366 389 -2714 2693 -394 381 -21266 2685 -418 363 -2730 2683 -382 2693 -418 2675 -410 2699 -384 2719 -382 2707 -380 359 -2734 387 -2704 2709 -380 361 -2732 2699 -418 357 -2728 2667 -416 383 -2696 2709 -380 391 -21228 2685 -458 307 -2800 2647 -412 2659 -432 2667 -416 2695 -416 2675 -406 2675 -416 383 -2700 361 -2730 2687 -414 375 -2696 2701 -420 353 -2720 2711 -382 367 -2728 2675 -416 385 -21222 2735 -386 355 -2744 2687 -396 2679 -418 2701 -386 2705 -382 2681 -410 2697 -384 385 -2736 365 -2704 2715 -384 377 -2696 2697 -416 349 -2722 2707 -386 379 -2732 2671 -410 361 -21258 2681 -464 297 -2796 2629 -456 2655 -420 2661 -448 2663 -404 2695 -382 2715 -380 371 -2740 355 -2744 2679 -384 391 -2728 2675 -388 379 | ||||
| RAW_Data: -2728 2695 -414 357 -2704 2705 -418 357 -21262 2673 -416 383 -2696 2709 -380 2703 -384 2699 -418 2671 -408 2695 -382 2713 -386 379 -2730 357 -2732 2695 -384 383 -2730 2679 -416 357 -2708 2701 -410 349 -2736 2697 -382 385 -21252 2669 -478 289 -2790 2647 -426 2651 -444 2653 -430 2659 -418 2695 -414 2681 -402 349 -2738 383 -2722 2677 -414 347 -2744 2691 -382 369 -2730 2691 -384 383 -2734 2679 -414 347 -21264 2705 -386 379 -2736 2667 -410 2695 -382 2715 -380 2709 -420 2665 -392 2713 -382 383 -2730 365 -2728 2665 -418 383 -2696 2693 -418 357 -2710 2711 -380 375 -2718 2701 -416 357 -21238 2677 -484 311 -2766 2635 -444 2657 -420 2663 -422 2695 -416 2667 -428 2675 -396 363 -73890 133 -98 131 -132 129 -658 99 -66 853 -100 63 -100 361 -98 1589 -66 1231 -132 65 -100 297 -198 65 -132 265 -66 9857 -4672 165 -1030 97 -1394 65 -200 2687 -68 6873 -8336 99 -1156 97 -66 163 -232 163 -262 197 -132 295 -132 263 -166 953 -100 263 -130 393 -164 295 -64 329 -66 393 -164 823 -130 165 -66 6133 -8436 165 -164 265 -266 65 -362 197 -696 3181 -132 363 -98 65 -166 131 -66 399 -132 663 -396 329 -66 7335 -7578 497 -230 627 -264 99 -366 99 -132 131 -134 265 -498 163 -100 1323 -66 265 -66 1129 -100 399 -132 365 -100 795 -68 397 -98 597 -364 297 -132 361 -132 265 -132 8591 -4740 65 -100 131 -166 199 -1088 97 -296 99 -528 131 -98 661 -66 401 -198 1157 -166 361 -164 495 -100 165 -66 297 -100 1423 -66 3067 -5658 67 -6406 197 -1092 65 -530 659 -68 265 -100 991 -68 231 -230 297 -66 327 -66 131 -132 659 -134 131 -100 1183 -132 263 -98 621 -66 2075 -6976 65 -5138 67 -132 129 -664 67 -132 165 -100 331 -466 231 -68 467 -98 563 -66 231 -100 531 -66 465 -66 1023 -166 297 -134 3409 -12290 67 -164 99 -532 133 -166 263 -66 231 -66 721 -64 131 -68 959 -134 495 -100 299 -98 497 -98 365 -100 397 -232 297 -98 531 -66 3029 -12216 265 -132 99 -364 199 -234 131 -66 431 -166 333 -166 397 -132 327 -100 395 -66 197 -132 395 -66 527 -98 295 -100 97 -98 789 -132 363 -132 297 -200 2815 -4914 65 -6620 65 -462 65 -134 297 -66 497 -264 231 -198 2773 -134 365 -100 831 -166 131 -100 297 -132 861 -132 299 -100 561 -66 1381 -6946 65 -5516 231 -266 97 -1362 1093 -68 1621 -134 165 -332 297 -98 361 -228 97 -132 797 -98 3487 -13224 229 -164 65 -132 913 -66 1123 -98 527 -134 929 -98 723 -100 12259 -270 165 -132 67 -132 165 -1326 99 -98 65 -1194 431 -66 695 -66 733 -134 197 | ||||
| RAW_Data: -134 10801 -166 67 -6130 133 -198 231 -334 365 -98 229 -132 165 -68 231 -166 14501 -524 65 -328 131 -498 129 -1288 65 -494 163 -64 165 -66 527 -132 131 -132 1019 -198 129 -166 393 -198 65 -164 6411 -66 3255 -10642 65 -1320 165 -164 493 -492 559 -264 2555 -66 695 -66 1657 -164 855 -66 4001 -10526 97 -596 133 -298 67 -264 65 -300 65 -100 263 -166 231 -134 99 -100 2703 -68 13643 -4922 297 -100 65 -232 133 -198 331 -300 231 -66 331 -100 12047 -3872 97 -196 65 -494 329 -66 65 -890 97 -98 229 -164 195 -596 797 -66 861 -132 65 -66 231 -100 565 -66 65 -66 1297 -132 265 -66 363 -134 265 -364 297 -164 299 -134 297 -134 495 -98 11309 -3790 131 -1380 65 -758 65 -164 129 -460 65 -360 199 -100 563 -68 497 -198 363 -266 263 -100 165 -66 697 -66 1933 -13594 65 -762 1223 -132 1119 -196 361 -134 131 -100 793 -166 695 -68 231 -68 463 -66 11727 -4204 363 -264 131 -132 133 -1124 97 -100 163 -100 327 -100 331 -198 397 -66 397 -100 395 -100 163 -66 197 -564 1059 -7962 65 -100 65 -198 129 -362 99 -394 197 -296 495 -100 1357 -68 459 -66 593 -66 265 -68 301 -132 465 -66 231 -200 397 -66 397 -232 199 -298 12077 -4350 231 -796 363 -198 133 -264 65 -1132 597 -332 3295 -100 755 -98 231 -164 97 -264 459 -166 759 -164 3265 -12138 99 -232 99 -1228 1025 -100 393 -66 531 -132 693 -132 1063 -66 427 -64 297 -294 229 -98 9723 -5404 67 -466 99 -796 267 -98 201 -100 167 -264 461 -98 1415 -66 861 -66 267 -66 331 -134 1663 -66 2089 -7012 65 -100 101 -4804 431 -728 99 -100 65 -100 995 -134 165 -66 929 -100 65 -66 927 -100 1093 -168 99 -100 497 -66 665 -200 6517 -8312 165 -66 129 -66 559 -166 99 -430 65 -398 67 -66 593 -198 459 -132 261 -132 263 -130 723 -66 459 -100 325 -166 67 -198 559 -66 493 -66 11475 -3896 99 -266 99 -66 197 -1092 129 -198 361 -166 163 -98 263 -196 759 -100 265 -100 365 -630 4635 -12748 65 -1712 461 -100 497 -66 395 -98 265 -98 229 -164 529 -132 297 -66 565 -132 987 -132 8665 -2820 2265 -450 313 -2774 2643 -442 325 -2772 2665 -416 359 -2734 2667 -386 379 -21274 2657 -474 293 -2810 2619 -466 2613 -476 2629 -452 2663 -388 2683 -418 2705 -400 365 -2722 387 -2700 2697 -380 361 -2732 2691 -418 361 -2732 2667 -416 383 -2698 2697 -416 357 -21238 2715 -384 383 -2732 2685 -416 2667 -416 2695 -398 2671 -418 2687 -390 2713 -382 383 -2730 365 -2728 2661 -416 379 -2716 2685 -384 379 -2720 2703 -378 401 -2718 2671 | ||||
							
								
								
									
										7
									
								
								assets/unit_tests/subghz/intertechno_v3.sub
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								assets/unit_tests/subghz/intertechno_v3.sub
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| Filetype: Flipper SubGhz Key File | ||||
| Version: 1 | ||||
| Frequency: 433920000 | ||||
| Preset: FuriHalSubGhzPresetOok650Async | ||||
| Protocol: Intertechno_V3 | ||||
| Bit: 32 | ||||
| Key: 00 00 00 00 3F 86 C5 9F | ||||
							
								
								
									
										13
									
								
								assets/unit_tests/subghz/intertechno_v3_raw.sub
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								assets/unit_tests/subghz/intertechno_v3_raw.sub
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | ||||
| Filetype: Flipper SubGhz RAW File | ||||
| Version: 1 | ||||
| Frequency: 433920000 | ||||
| Preset: FuriHalSubGhzPresetOok650Async | ||||
| Protocol: RAW | ||||
| RAW_Data: 15041 -66 15883 -66 12643 -66 12681 -66 3413 -68 2713 -68 33389 -66 1445 -66 1279 -68 1027 -66 6911 -98 25229 -66 3967 -100 3019 -100 6131 -66 955 -66 3605 -66 12411 -98 1419 -66 3593 -68 2753 -66 2457 -66 6007 -66 627 -100 1597 -66 3071 -98 22749 -66 333 -66 12829 -66 4313 -132 855 -66 44097 -64 20391 -98 29999 -66 3539 -98 557 -66 1489 -100 4081 -100 3857 -64 2895 -132 2261 -166 3089 -66 2429 -68 34467 -66 3585 -66 3087 -66 3329 -132 5287 -66 1063 -98 15259 -100 2535 -66 995 -66 13057 -100 24233 -68 531 -100 26415 -66 1761 -100 2717 -66 4071 -100 12191 -66 23367 -68 2323 -66 19809 -248 245 -1388 255 -242 275 -1358 273 -1370 277 -246 277 -1368 275 -246 275 -1362 275 -244 275 -1364 275 -244 275 -1362 275 -244 275 -1328 273 -278 273 -1358 275 -246 275 -238 263 -1384 275 -246 273 -1358 275 -244 273 -1358 275 -246 275 -1360 275 -1344 277 -246 275 -1358 275 -244 275 -234 263 -1382 277 -1344 277 -246 279 -1362 275 -246 271 -234 261 -1380 275 -246 273 -1360 275 -246 275 -1366 277 -1340 277 -248 279 -238 263 -1382 275 -1344 277 -246 279 -1364 277 -244 275 -234 263 -1382 277 -244 273 -1358 275 -1344 277 -248 279 -1368 275 -244 273 -1360 239 -280 271 -1358 275 -244 275 -1358 275 -174 269 -10298 289 -2660 267 -238 299 -1356 275 -244 275 -1356 275 -1344 277 -248 277 -1360 275 -246 275 -1328 309 -244 273 -1358 277 -244 275 -1356 275 -246 273 -1326 309 -244 275 -1356 275 -246 273 -234 263 -1380 277 -246 273 -1326 309 -244 273 -1356 277 -246 277 -1358 275 -1338 279 -248 279 -1364 275 -246 273 -234 261 -1380 277 -1344 279 -250 277 -1330 309 -244 273 -232 261 -1384 275 -246 273 -1356 275 -248 275 -1360 275 -1340 279 -248 277 -236 263 -1380 277 -1342 279 -248 279 -1366 275 -246 273 -234 263 -1380 275 -246 275 -1358 275 -1340 279 -248 281 -1336 309 -244 273 -1358 275 -246 273 -1360 275 -244 273 -1358 275 -176 267 -10306 257 -2646 299 -234 301 -1354 277 -246 275 -1356 277 -1340 279 -250 279 -1332 309 -244 275 -1358 275 -248 273 -1326 309 -246 273 -1326 309 -244 275 -1356 277 -248 275 -1328 309 -246 273 -234 261 -1382 277 -246 277 -1326 309 -244 275 -1358 277 -246 277 -1356 277 -1346 277 -250 277 -1358 277 -246 275 -234 263 -1382 279 -1346 279 -248 281 -1330 307 -246 273 -236 261 -1380 277 -246 277 -1360 277 -246 277 -1360 275 -1344 279 -248 279 -236 263 -1384 277 -1340 279 -250 281 -1338 307 -246 271 -234 261 -1384 277 -246 275 -1356 277 -1340 279 -250 283 -1336 309 -246 273 -1356 277 -246 273 -1360 277 -246 | ||||
| RAW_Data: 275 -1328 309 -174 269 -10296 289 -2648 267 -238 299 -1356 277 -246 275 -1324 307 -1342 279 -250 277 -1330 309 -244 275 -1362 277 -244 275 -1356 275 -248 273 -1328 309 -244 273 -1328 309 -244 275 -1360 277 -246 275 -234 259 -1384 277 -246 275 -1360 275 -246 273 -1358 277 -248 277 -1362 275 -1344 277 -248 277 -1328 307 -246 273 -236 261 -1384 277 -1348 279 -248 279 -1360 277 -246 273 -234 263 -1388 275 -246 275 -1360 277 -248 279 -1368 277 -1344 279 -248 279 -240 265 -1386 275 -1342 279 -286 247 -1372 275 -248 275 -238 265 -1386 277 -248 275 -1360 275 -1344 277 -286 247 -1374 275 -246 275 -1362 277 -246 275 -1360 277 -248 275 -1326 307 -174 269 -10290 287 -2654 269 -236 301 -1352 275 -248 273 -1326 311 -1340 277 -248 277 -1328 309 -244 273 -1358 275 -244 275 -1326 309 -244 273 -1356 277 -244 273 -1356 275 -246 275 -1358 275 -244 275 -234 261 -1382 277 -246 273 -1358 275 -246 273 -1360 277 -246 273 -1324 309 -1340 277 -248 277 -1328 307 -246 271 -234 259 -1382 277 -1346 279 -248 277 -1330 309 -244 271 -232 259 -1382 277 -244 275 -1356 277 -248 273 -1354 277 -1342 277 -248 275 -236 261 -1380 277 -1344 277 -248 279 -1330 307 -246 273 -234 261 -1378 277 -246 273 -1356 277 -1342 277 -248 277 -1330 309 -244 273 -1322 307 -246 273 -1326 309 -244 273 -1322 309 -176 267 -10298 257 -2682 265 -236 299 -1324 309 -248 273 -1324 311 -1342 277 -246 279 -1360 277 -244 275 -1362 275 -244 275 -1358 275 -244 275 -1360 275 -246 273 -1360 275 -244 277 -1360 275 -246 273 -234 263 -1384 275 -246 273 -1358 275 -246 275 -1360 277 -246 277 -1356 277 -1342 279 -248 277 -1364 275 -244 275 -234 261 -1384 275 -1344 277 -250 279 -1366 275 -246 273 -236 263 -1384 277 -246 275 -1358 277 -246 277 -1362 277 -1342 279 -248 279 -236 265 -1382 277 -1346 277 -248 281 -1366 275 -246 275 -234 265 -1384 275 -246 273 -1358 277 -1344 279 -248 279 -1364 275 -244 275 -1324 309 -246 273 -1324 307 -246 273 -1326 309 -174 267 -118796 133 -100 131 -892 329 -166 199 -132 131 -166 99 -100 265 -264 4663 -134 4889 -100 365 -98 5921 -100 5903 -68 4877 -98 2953 -98 1645 -64 1687 -66 981 -98 10769 -66 18319 -66 4831 -66 13301 -66 893 -132 5967 -100 15949 -66 3749 -66 497 -100 625 -66 1147 -66 469 -66 1261 -66 3651 -100 265 -100 26741 -68 6873 -66 4485 -100 2667 -68 3159 -68 2857 -132 2655 -66 12903 -66 1277 -66 1711 -66 787 -100 1327 -198 727 -64 1677 -100 1187 -66 1019 -66 891 -66 4303 -100 11297 -66 3923 -254 253 -1380 247 -292 253 -1344 | ||||
| RAW_Data: 277 -1346 277 -250 279 -1364 275 -244 275 -1362 275 -244 275 -1356 275 -246 273 -1358 241 -278 273 -1356 275 -246 273 -1360 275 -246 273 -234 263 -1382 275 -244 273 -1358 275 -246 273 -1360 275 -246 273 -1358 275 -1340 277 -248 277 -1362 275 -246 273 -234 261 -1380 277 -1344 277 -248 279 -1362 275 -244 273 -236 261 -1380 275 -244 275 -1360 275 -246 275 -1358 275 -1346 277 -246 275 -236 263 -1384 275 -1342 277 -248 277 -1364 277 -244 273 -234 261 -1378 277 -246 273 -1356 277 -1340 277 -248 281 -1334 307 -246 271 -1356 275 -246 273 -1358 275 -244 273 -1326 309 -174 267 -10296 257 -2650 297 -232 263 -1384 277 -244 273 -1358 275 -1340 279 -248 279 -1328 309 -244 275 -1328 307 -244 273 -1356 275 -244 275 -1358 275 -246 273 -1324 309 -244 275 -1328 307 -244 273 -234 261 -1382 275 -246 273 -1326 309 -244 273 -1358 275 -246 273 -1358 275 -1338 279 -248 279 -1330 309 -244 273 -232 261 -1380 277 -1344 279 -248 279 -1330 309 -244 271 -234 261 -1382 275 -246 273 -1358 277 -244 275 -1330 309 -1338 277 -246 277 -236 263 -1380 277 -1342 277 -248 279 -1364 275 -246 273 -232 261 -1380 275 -248 275 -1328 307 -1338 277 -248 279 -1334 309 -244 271 -1358 275 -244 275 -1324 307 -246 271 -1328 309 -174 265 -10270 291 -2640 297 -232 297 -1350 277 -248 275 -1326 309 -1340 277 -248 277 -1328 309 -244 273 -1358 275 -246 273 -1326 309 -244 273 -1354 275 -246 273 -1330 307 -244 273 -1358 275 -246 273 -234 263 -1380 275 -246 273 -1358 275 -246 273 -1360 275 -244 273 -1358 275 -1340 277 -248 279 -1364 275 -244 273 -232 261 -1380 277 -1342 279 -250 279 -1332 307 -244 271 -234 261 -1378 277 -246 273 -1358 275 -248 275 -1360 275 -1340 277 -248 275 -236 263 -1382 277 -1344 277 -246 277 -1364 275 -246 273 -234 259 -1380 275 -246 273 -1362 275 -1342 275 -248 277 -1334 309 -244 271 -1356 275 -244 275 -1326 307 -244 273 -1356 275 -176 267 -10290 289 -2644 267 -238 301 -1320 309 -246 273 -1324 309 -1340 277 -248 277 -1328 307 -246 273 -1326 307 -246 273 -1324 309 -246 273 -1322 309 -246 273 -1322 307 -246 275 -1326 309 -246 273 -234 259 -1382 275 -246 275 -1322 309 -246 273 -1326 309 -246 273 -1326 309 -1340 277 -248 275 -1326 309 -246 273 -232 261 -1380 279 -1346 277 -250 277 -1328 309 -244 271 -232 261 -1380 277 -246 273 -1358 275 -248 273 -1328 307 -1340 277 -248 277 -236 261 -1380 277 -1344 277 -248 279 -1328 309 -244 275 -232 261 -1378 277 -248 273 -1326 309 -1344 277 -248 277 -1358 277 -246 273 -1328 307 -244 271 -1324 309 -244 | ||||
| RAW_Data: 273 -1324 309 -174 267 -10270 289 -2638 297 -234 297 -1352 275 -248 275 -1328 307 -1340 277 -248 275 -1330 309 -244 273 -1358 275 -244 275 -1326 309 -244 271 -1356 275 -244 275 -1326 307 -246 273 -1326 309 -244 273 -234 261 -1378 275 -248 275 -1326 309 -244 271 -1356 277 -248 273 -1328 309 -1338 277 -248 277 -1328 309 -244 271 -232 261 -1380 277 -1348 279 -248 277 -1328 307 -246 271 -234 259 -1384 275 -244 275 -1356 277 -246 275 -1326 309 -1344 275 -248 275 -236 261 -1378 277 -1342 277 -250 279 -1334 309 -244 271 -232 261 -1380 277 -246 273 -1326 307 -1344 277 -248 277 -1328 309 -246 273 -1326 309 -244 271 -1324 309 -244 273 -1324 307 -176 267 -10288 287 -2618 299 -236 299 -1354 277 -244 273 -1326 307 -1340 279 -248 275 -1328 309 -244 275 -1326 309 -246 273 -1324 307 -246 273 -1322 309 -244 273 -1322 309 -244 275 -1328 309 -246 273 -232 261 -1380 277 -246 275 -1324 309 -244 273 -1356 277 -246 275 -1324 309 -1340 279 -246 277 -1328 309 -244 273 -232 261 -1382 277 -1344 279 -250 277 -1324 309 -246 273 -234 261 -1380 277 -246 273 -1358 277 -246 273 -1328 309 -1340 277 -248 275 -236 261 -1380 275 -1344 279 -248 279 -1360 277 -244 273 -234 261 -1380 277 -246 275 -1354 277 -1344 277 -248 277 -1328 311 -246 273 -1324 307 -244 273 -1324 309 -244 273 -1320 309 -176 269 -118210 761 -168 267 -66 563 -132 99 -132 3543 -66 5345 -100 4355 -66 4617 -68 20503 -166 2379 -132 293 -98 4117 -66 1151 -98 3353 -66 3485 -66 2491 -66 6133 -66 233 -68 16307 -68 16959 -98 357 -66 5419 -134 799 -100 327 -100 791 -66 2481 -66 963 -100 3481 -98 1679 -134 2473 -100 227 -68 3087 -66 11527 -130 4305 -98 435 -66 563 -100 2887 -100 267 -66 1787 -66 9655 -66 4793 -100 2119 -66 359 -98 1313 -132 3393 -234 995 -66 2681 -98 99 -130 1379 -100 3757 -100 21695 -132 5135 -100 693 -98 4631 -100 2325 -68 4937 -66 10409 -98 897 -100 1287 -66 2565 -66 3753 -66 4055 -66 2023 -68 1961 -68 629 -66 431 -66 5039 -66 2155 -100 2673 -66 1163 -98 6539 -100 825 -66 1197 -100 3053 -66 13973 -68 15515 -100 1861 -66 1027 -66 797 -98 959 -98 787 -132 787 -64 3811 -132 1747 -66 6683 -66 1033 -68 24927 -66 1259 -100 1125 -68 663 -66 1687 -66 4357 -132 4567 -66 3969 -98 3317 -132 433 -134 6043 -66 3249 -100 431 -98 2367 -100 11265 -66 5085 -68 2355 -64 1815 -66 1395 -274 241 -1366 275 -244 275 -1362 275 -1338 277 -284 243 -1368 239 -278 275 -1362 275 -244 275 -1360 241 -278 273 -1356 275 -246 275 -1360 239 -280 275 -1360 | ||||
| RAW_Data: 275 -244 275 -234 263 -1386 239 -280 273 -1356 275 -244 273 -1360 275 -244 277 -1364 275 -1336 277 -248 277 -1366 275 -244 273 -234 263 -1386 275 -1340 277 -248 279 -1364 275 -244 275 -234 263 -1384 273 -244 275 -1358 275 -244 275 -1364 275 -1342 275 -248 277 -236 265 -1384 275 -1340 277 -282 243 -1366 275 -246 273 -236 263 -1382 277 -244 275 -1358 275 -1342 277 -248 277 -1364 275 -246 275 -1360 239 -280 273 -1358 241 -278 275 -1356 275 -210 233 -10302 257 -2652 297 -232 297 -1354 277 -244 275 -1358 275 -1340 279 -248 279 -1360 275 -246 275 -1360 275 -246 273 -1360 275 -244 275 -1328 309 -242 273 -1324 309 -244 275 -1360 275 -246 273 -234 261 -1384 275 -246 273 -1358 275 -244 275 -1358 277 -248 273 -1358 275 -1340 279 -248 277 -1334 307 -242 273 -232 261 -1380 277 -1348 277 -250 277 -1364 275 -244 275 -234 261 -1380 277 -244 275 -1358 277 -246 277 -1360 277 -1342 275 -248 275 -236 263 -1380 277 -1344 277 -248 279 -1368 275 -244 275 -232 261 -1382 277 -244 275 -1356 275 -1344 277 -248 279 -1362 275 -246 275 -1360 275 -246 273 -1356 275 -246 273 -1356 275 -176 267 -10302 257 -2648 299 -234 297 -1352 277 -246 275 -1326 309 -1340 279 -248 277 -1330 309 -244 275 -1328 309 -244 273 -1324 309 -244 275 -1324 309 -246 273 -1324 307 -246 275 -1328 309 -244 273 -234 261 -1378 277 -248 275 -1328 309 -244 273 -1356 277 -248 275 -1326 309 -1344 277 -248 275 -1326 309 -246 273 -234 259 -1380 277 -1348 281 -248 279 -1328 307 -246 273 -234 259 -1382 277 -246 275 -1360 275 -248 275 -1324 309 -1340 279 -248 277 -238 261 -1382 277 -1344 277 -248 279 -1330 311 -244 273 -234 259 -1378 277 -248 275 -1326 309 -1340 279 -248 279 -1336 307 -246 271 -1324 309 -244 275 -1324 307 -246 273 -1326 309 -174 269 -10296 257 -2648 299 -234 297 -1352 277 -248 273 -1326 309 -1342 277 -248 277 -1328 309 -246 275 -1328 309 -244 273 -1326 309 -244 273 -1322 309 -244 273 -1328 307 -244 275 -1328 309 -246 273 -234 261 -1382 277 -246 275 -1326 309 -244 273 -1352 277 -248 275 -1330 309 -1340 277 -248 277 -1328 309 -244 275 -232 261 -1384 277 -1342 279 -250 279 -1328 309 -244 273 -234 263 -1380 277 -246 273 -1360 277 -246 275 -1326 309 -1340 277 -250 277 -236 263 -1382 277 -1342 277 -248 279 -1362 277 -246 273 -234 263 -1382 277 -244 275 -1356 277 -1340 279 -248 279 -1362 275 -246 275 -1328 307 -246 273 -1356 275 -246 273 -1356 275 -174 269 -10292 287 -2650 269 -236 301 -1354 275 -248 273 -1358 275 -1340 279 -248 277 -1332 307 -246 275 -1328 | ||||
| RAW_Data: 309 -244 273 -1324 309 -244 273 -1356 275 -246 273 -1358 275 -244 277 -1330 309 -244 273 -234 261 -1382 277 -244 275 -1358 275 -246 273 -1356 277 -248 275 -1360 275 -1340 277 -248 277 -1360 275 -246 273 -236 261 -1382 279 -1344 279 -248 279 -1360 277 -244 273 -234 261 -1380 277 -246 275 -1360 277 -246 273 -1360 275 -1342 279 -248 275 -236 263 -1382 275 -1344 279 -248 279 -1362 277 -246 273 -234 263 -1380 277 -246 275 -1356 275 -1342 277 -248 281 -1336 307 -246 271 -1354 277 -246 275 -1328 307 -244 273 -1352 277 -176 269 -10300 257 -2650 299 -232 297 -1354 277 -246 275 -1356 277 -1342 277 -248 279 -1328 309 -244 275 -1360 275 -246 273 -1328 307 -246 273 -1356 277 -246 277 -1326 309 -244 277 -1360 277 -246 273 -234 263 -1384 277 -246 275 -1324 309 -246 275 -1358 277 -246 277 -1360 277 -1344 277 -248 277 -1326 309 -246 273 -236 261 -1382 277 -1348 279 -250 281 -1330 307 -246 273 -234 263 -1386 277 -244 275 -1356 277 -248 277 -1362 277 -1342 277 -250 277 -238 263 -1384 277 -1342 277 -250 281 -1332 309 -246 273 -234 263 -1380 277 -246 275 -1360 277 -1342 279 -248 281 -1334 307 -246 273 -1356 275 -248 275 -1328 309 -244 275 -1324 309 -176 269 -115034 163 -362 67 -894 529 -166 14663 -98 4135 -66 3681 -100 299 -68 9829 -66 3517 -64 21569 -66 3251 -66 2209 -64 23701 -66 3359 -68 1057 -66 723 -66 299 -134 765 -66 589 -98 1687 -134 2153 -66 3081 -68 10447 -66 11643 -66 2451 -66 2277 -66 2897 -66 755 -100 5539 -64 5117 -132 4867 -134 3931 -64 625 -66 1317 -98 11597 -66 2255 -66 1165 -66 1123 -66 6371 -100 699 -68 1811 -66 621 -68 2191 -64 1291 -134 3003 -66 2423 -64 1463 -66 663 -100 1127 -100 6169 -100 489 -100 6087 -100 2027 -66 1195 -66 13195 -66 557 -66 40423 -98 1919 -100 1061 -132 201 -66 2553 -132 12549 -66 1789 -100 921 -134 1067 -66 729 -66 10029 -66 3909 -100 265 -100 16017 -134 21177 -68 2461 -66 2215 -68 1197 -66 5911 -66 2645 -66 3419 -132 16275 -64 5091 -68 2123 -66 2677 -64 10305 -66 12381 -100 427 -166 25331 -66 2457 -66 11859 -248 279 -1368 275 -246 275 -1360 275 -1340 277 -246 279 -1364 239 -278 275 -1358 275 -244 275 -1362 239 -278 273 -1358 239 -280 271 -1360 241 -278 273 -1360 275 -244 275 -234 261 -1384 239 -280 273 -1356 275 -244 273 -1360 275 -244 275 -1358 275 -1344 277 -248 275 -1358 275 -244 273 -236 261 -1384 275 -1342 279 -246 279 -1360 275 -244 275 -234 263 -1384 239 -278 273 -1358 275 -244 275 -1362 275 -1342 275 -248 275 -238 263 -1382 275 -1344 275 -248 | ||||
| RAW_Data: 277 -1364 275 -244 273 -234 263 -1380 275 -246 273 -1358 275 -1342 277 -246 279 -1366 275 -244 273 -1362 239 -278 239 -1386 275 -246 273 -1360 241 -208 269 -10290 257 -2686 265 -232 265 -1384 275 -246 275 -1358 275 -1344 277 -248 275 -1358 275 -246 275 -1360 277 -244 273 -1326 309 -244 271 -1354 275 -244 275 -1358 275 -246 273 -1358 275 -246 273 -234 263 -1378 275 -246 275 -1360 275 -244 273 -1356 275 -246 275 -1360 275 -1342 277 -246 277 -1360 275 -246 273 -232 261 -1382 277 -1342 279 -248 279 -1360 275 -244 275 -232 261 -1380 277 -244 275 -1356 277 -246 277 -1360 275 -1342 277 -246 275 -236 263 -1384 275 -1342 277 -248 277 -1362 275 -246 273 -234 261 -1378 277 -246 275 -1328 307 -1340 277 -246 279 -1366 275 -244 273 -1326 307 -244 273 -1324 309 -244 273 -1356 275 -174 267 -10304 255 -2648 297 -230 263 -1382 277 -244 275 -1330 307 -1338 277 -248 277 -1330 309 -244 273 -1356 275 -246 273 -1362 275 -244 273 -1356 275 -244 273 -1326 307 -244 273 -1360 273 -246 273 -236 261 -1380 275 -244 275 -1328 307 -244 273 -1358 275 -244 275 -1360 275 -1342 277 -246 277 -1364 275 -244 271 -232 261 -1384 277 -1340 279 -248 279 -1360 275 -246 273 -234 261 -1380 275 -244 275 -1360 277 -244 275 -1356 275 -1342 279 -246 277 -236 263 -1382 275 -1340 277 -248 279 -1366 275 -246 271 -234 261 -1382 277 -244 275 -1354 275 -1342 277 -248 277 -1364 273 -246 273 -1362 275 -244 271 -1360 275 -244 273 -1358 275 -174 267 -10272 289 -2646 265 -262 261 -1382 277 -244 275 -1356 275 -1342 277 -248 277 -1364 275 -244 275 -1360 275 -244 273 -1358 275 -244 273 -1358 275 -244 273 -1326 307 -244 275 -1358 275 -246 273 -234 261 -1382 275 -246 273 -1358 275 -244 273 -1358 275 -246 275 -1360 275 -1338 277 -248 277 -1362 277 -244 271 -234 261 -1380 277 -1344 279 -248 277 -1332 273 -278 271 -234 261 -1382 275 -244 275 -1356 277 -246 275 -1360 277 -1340 277 -246 277 -234 263 -1384 275 -1342 277 -248 277 -1366 275 -244 273 -234 261 -1380 275 -246 273 -1360 275 -1340 277 -246 279 -1334 307 -244 273 -1356 275 -246 273 -1360 275 -244 271 -1354 277 -174 269 -10300 257 -2648 297 -230 263 -1384 277 -244 273 -1356 277 -1342 277 -248 277 -1362 275 -244 275 -1330 307 -244 273 -1324 309 -244 273 -1324 307 -246 273 -1326 307 -244 273 -1358 275 -246 273 -234 261 -1380 277 -246 273 -1358 275 -244 275 -1354 277 -248 275 -1360 275 -1338 279 -246 277 -1360 275 -244 273 -234 261 -1378 279 -1344 279 -248 279 -1330 309 -244 271 -232 261 -1380 277 -246 273 -1360 | ||||
| RAW_Data: 277 -244 275 -1360 275 -1340 277 -246 277 -236 261 -1380 275 -1346 277 -248 277 -1362 275 -246 273 -234 263 -1380 275 -244 275 -1358 275 -1340 277 -248 279 -1334 309 -244 273 -1324 307 -246 273 -1356 275 -244 273 -1356 275 -174 269 -10302 257 -2644 297 -232 263 -1384 277 -246 275 -1354 275 -1344 277 -248 275 -1360 275 -246 275 -1358 275 -246 273 -1326 307 -246 273 -1324 307 -244 273 -1328 307 -244 273 -1358 275 -244 273 -236 261 -1380 275 -246 273 -1358 275 -244 273 -1358 275 -246 273 -1360 275 -1344 275 -248 275 -1360 275 -244 273 -234 261 -1378 277 -1344 279 -248 277 -1362 275 -246 273 -234 261 -1378 275 -244 275 -1360 275 -246 275 -1358 275 -1344 277 -246 277 -234 263 -1380 275 -1338 279 -246 281 -1368 275 -244 271 -234 261 -1386 275 -244 271 -1358 275 -1342 277 -246 279 -1362 275 -244 275 -1326 273 -278 273 -1358 239 -278 273 -1358 275 -174 267 -127478 195 -964 2317 -66 763 -98 1455 -100 16109 -66 5683 -98 11469 -66 34413 -66 5443 -66 11613 -66 2737 -66 12191 -66 2951 -68 1851 -68 1895 -68 2643  | ||||
| @ -139,3 +139,9 @@ RAW_Data: 277 -244 275 -1360 275 -1340 277 -246 277 -236 261 -1380 275 -1346 277 | ||||
| RAW_Data: 29262 361 -68 2635 -66 24113 -66 1131 -100 4157 -66 26253 -130 621 -18438 99 -298 231 -66 197 -496 753 -230 7503 -16526 65 -396 65 -296 99 -196 293 -64 429 -132 397 -66 329 -66 37701 -66 13475 -100 54967 -64 18209 -18340 97 -462 197 -98 587 -232 97 -100 259 -98 197 -262 297 -64 557 -100 599 -100 333 -234 42493 -13212 6449 -206 173 -214 217 -176 195 -218 181 -218 181 -182 217 -182 217 -176 187 -214 215 -180 217 -182 217 -182 217 -178 185 -424 1177 -388 387 -240 381 -214 181 -398 211 -380 419 -176 217 -394 203 -394 205 -380 189 -402 421 -168 219 -398 393 -190 191 -398 205 -406 185 -402 381 -212 215 -362 241 -378 421 -176 377 -218 197 -378 427 -210 393 -172 429 -172 397 -212 217 -362 389 -228 197 -372 417 -204 395 -210 181 -398 391 -192 201 -216888 761 -200 299 -166 695 -132 15435 -66 5611 -66 21049 -66 4947 -66 2355 -66 1921 -100 2223 -100 2107 -100 397 -98 3643 -66 5301 -98 14205 -66 37371 -246 175 -216 179 -216 177 -224 149 -246 159 -228 181 -212 201 -204 159 -244 151 -254 169 -214 181 -210 197 -182 181 -454 1141 -444 357 -228 361 -246 177 -396 209 -412 367 -188 187 -434 201 -394 185 -406 193 -402 377 -238 181 -386 381 -234 153 -424 205 -412 157 -412 383 -240 181 -398 203 -392 385 -236 371 -212 179 -400 383 -240 359 -210 375 -220 381 -246 175 -394 383 -240 181 -398 363 -222 379 -246 175 -394 383 -204 217 -182856 99 -66 99 -300 133 -402 65 -198 99 -328 65 -100 491 -164 593 -100 3547 -64 361 -66 789 -68 2521 -66 22883 -66 2659 -98 3309 -130 3789 -100 9689 -17178 99 -1388 65 -266 197 -100 131 -134 99 -232 627 -130 233 -66 1949 -100 14567 -198 165 -256 181 -208 159 -214 183 -220 163 -244 149 -246 159 -236 181 -254 141 -226 151 -246 157 -228 181 -212 201 -400 1163 -428 379 -230 355 -244 177 -396 207 -412 367 -222 157 -418 189 -410 207 -412 171 -430 357 -226 165 -404 413 -204 181 -428 173 -428 169 -426 353 -236 173 -414 173 -408 381 -244 337 -222 201 -408 397 -208 393 -204 395 -208 359 -246 177 -394 387 -200 205 -380 415 -202 395 -208 181 -432 357 -226 169 -195084 65 -300 763 -66 297 -364 593 -68 2883 -66 1357 -68 363 -98 3841 -66 3119 -66 5153 -66 4023 -268 143 -246 133 -290 141 -250 139 -254 141 -226 181 -248 137 -254 143 -252 139 -252 143 -230 181 -250 139 -254 145 -436 1135 -448 349 -240 347 -254 157 -434 167 -426 377 -226 157 -434 167 -426 155 -440 163 -434 375 -206 215 -380 381 -234 153 | ||||
| RAW_Data: -424 205 -412 159 -412 381 -240 181 -398 203 -392 387 -236 369 -212 179 -400 383 -240 359 -244 339 -222 381 -246 175 -394 383 -240 181 -398 363 -222 381 -244 175 -392 383 -240 181 -184002 99 -360 63 -330 65 -132 129 -232 97 -198 295 -328 6031 -66 831 -132 3417 -66 2187 -64 2183 -100 6535 -66 1127 -66 2569 -66 2031 -66 2271 -66 2183 -66 3815 -66 3803 -66 493 -66 1909 -66 1627 -98 4805 -17512 67 -2164 131 -498 265 -430 163 -98 97 -64 99 -230 99 -100 229 -230 165 -196 63 -132 99 -66 927 -66 14955 -66 19621 -68 2627 -66 14305 -68 23247 -66 2891 -66 3941 -66 3021 -212 173 -242 181 -218 181 -214 181 -208 157 -250 141 -248 181 -218 179 -214 179 -210 159 -250 179 -214 181 -218 181 -404 1153 -404 389 -244 375 -192 181 -436 161 -414 383 -240 181 -398 205 -392 201 -394 205 -394 365 -246 177 -396 383 -204 217 -398 171 -426 167 -428 353 -242 173 -420 173 -408 373 -220 403 -208 175 -422 381 -194 399 -228 357 -246 355 -210 215 -400 387 -208 181 -398 391 -226 353 -246 177 -398 383 -204 217 -185098 163 -166 525 -98 293 -100 63 -66 229 -66 1183 -66 1507 -66 3089 -98 30187 -66 2847 -19112 133 -364 131 -394 97 -166 295 -66 229 -164 227 -66 263 -130 623 -98 2071 -66 493 -66 787 -98 691 -64 10249 -132 3879 -66 1949 -66 3453 -198 23157 -66 2845 -100 1193 -66 1587 -100 3797 -98 3187 -100 3319 -66 22119 -98 5513 -226 155 -244 153 -256 131 -248 151 -246 159 -262 121 -274 133 -272 127 -244 153 -254 167 -248 145 -244 133 -252 177 -398 1169 -418 381 -238 359 -242 141 -430 169 -426 357 -274 139 -422 171 -442 173 -428 167 -426 353 -236 171 -416 379 -226 149 -436 161 -438 173 -406 381 -234 153 -424 205 -380 389 -244 359 -206 215 -384 381 -246 335 -224 383 -246 355 -244 179 -404 385 -206 181 -432 359 -226 355 -246 175 -398 383 -240 181 -179760 97 -168 727 -66 97 -332 1389 -66 2793 -66 4955 -100 12453 -100 2425 -66 21965 -66 3809 -68 1683 -66 3095 -66 2153 -64 999 -208 173 -220 181 -214 191 -196 181 -212 183 -220 191 -212 181 -214 191 -198 181 -212 181 -222 191 -212 181 -214 191 -416 1167 -424 369 -220 373 -210 209 -390 207 -376 403 -190 187 -418 189 -408 209 -412 173 -428 357 -226 169 -404 399 -208 179 -412 209 -396 169 -428 355 -230 201 -378 205 -406 381 -244 339 -222 193 -400 413 -204 393 -208 347 -220 401 -210 175 -422 383 -202 217 -398 365 -222 377 -246 175 -390 385 -204 217 -179890 165 -1552 131 -164 65 | ||||
| RAW_Data: -1448 361 -17056 131 -134 233 -1462 131 -166 953 -100 261 -164 5077 -272 137 -268 143 -252 141 -248 143 -246 159 -252 141 -244 143 -290 107 -276 145 -244 131 -250 179 -248 143 -252 141 -414 1165 -424 373 -236 359 -242 145 -434 169 -428 355 -230 169 -442 173 -434 157 -406 193 -402 379 -238 181 -422 335 -252 157 -434 167 -428 185 -406 381 -208 211 -390 207 -410 381 -200 373 -236 171 -414 383 -202 393 -210 379 -220 373 -208 211 -390 383 -204 217 -398 365 -220 379 -244 175 -394 381 -240 181 -161030 97 -166 167 -930 593 -2670 1091 -132 229 -98 461 -164 1649 -66 6311 -100 44723 -16832 67 -2656 131 -132 99 -132 263 -100 399 -68 893 -18950 99 -164 165 -198 525 -998 335 -66 565 -66 1057 -17880 97 -360 195 -262 131 -332 625 -98 197 -230 455 -98 9343 -16498 67 -368 131 -598 65 -1066 333 -300 789 -130 757 -66 87207 -16554 97 -3520 97 -786 591 -64 461 -98 21495 -66 24811 -18448 131 -296 491 -134 163 -760 1091 -230 893 -66 927 -68 4581 -68 32965 -64 45217 -17292 131 -1684 231 -132 327 -64 163 -330 263 -230 25751 | ||||
| RAW_Data: -66 529 -66 2519 -66 265 -68 10101 -1794 65 -1890 393 -562 97 -132 197 -98 493 -330 97 -164 97 -230 327 -326 99 -100 97 -164 65 -132 293 -98 297 -166 161 -130 297 -230 1391 -68 11185 -3800 229 -230 297 -66 65 -198 65 -466 99 -464 99 -430 67 -698 295 -132 165 -164 1095 -66 299 -66 1321 -264 12675 -66 99 -166 229 -134 65 -330 165 -164 65 -890 131 -830 67 -66 1157 -100 167 -168 265 -66 827 -66 2047 -100 261 -594 2279 -134 10701 -3890 163 -1384 67 -98 99 -1322 99 -98 65 -398 823 -66 65 -68 927 -100 495 -132 593 -100 165 -198 1387 -1022 131 -728 99 -662 97 -462 495 -200 829 -330 563 -100 297 -330 65 -598 165 -592 295 -166 131 -764 165 -164 565 -66 131 -166 165 -66 9675 -5052 165 -2878 199 -66 265 -432 265 -66 267 -898 163 -132 231 -198 229 -164 97 -100 4445 -66 7853 -636 199 -662 265 -298 233 -1428 331 -134 1791 -66 1649 -66 297 -100 361 -198 559 -98 363 -200 1315 -66 265 -98 1049 -132 1647 -66 265 -822 295 -526 131 -1712 199 -166 231 -200 165 -66 265 -166 97 -132 163 -164 395 -630 495 -168 297 -298 229 -266 629 -200 133 -132 133 -166 65 -132 99 -100 131 -66 67 -98 133 -496 1391 -98 1751 -164 359 -132 97 -164 263 -64 691 -66 199 -66 293 -98 589 -198 11299 -3968 65 -68 65 -2702 65 -1186 927 -166 65 -66 429 -134 197 -134 529 -200 67 -66 231 -100 2151 -4014 97 -1486 99 -464 65 -330 129 -330 331 -134 599 -66 497 -200 165 -66 661 -166 6881 -8830 295 -100 197 -232 725 -134 299 -166 229 -166 525 -198 295 -66 459 -66 329 -230 595 -98 299 -132 329 -66 99 -98 163 -134 229 -100 8345 -6726 131 -132 295 -66 1579 -66 329 -98 501 -132 231 -66 491 -298 331 -266 363 -132 1193 -168 8847 -4194 199 -828 65 -100 195 -262 197 -298 65 -898 65 -132 629 -66 229 -100 291 -100 623 -66 295 -66 461 -132 529 -632 597 -132 65 -100 97 -134 297 -100 297 -166 397 -168 527 -134 9603 -3850 99 -200 67 -896 959 -198 165 -100 229 -266 531 -64 165 -132 163 -296 3715 -11994 165 -1492 429 -68 263 -100 265 -330 199 -64 495 -132 363 -66 63 -166 297 -398 65 -100 231 -332 199 -100 7683 -4916 65 -1294 297 -1022 1325 -166 393 -132 165 -498 1255 -134 197 -198 427 -164 329 -132 631 -594 199 -196 99 -100 265 -134 1457 -100 3649 -8592 67 -268 131 -332 99 -100 65 -760 101 -198 297 -168 199 -132 369 -100 97 -132 99 -232 397 -198 99 -134 97 -100 231 -332 131 -796 329 -266 263 | ||||
| RAW_Data: -100 10841 -4030 163 -164 197 -398 195 -592 65 -132 63 -430 295 -298 263 -200 3517 -132 3763 -12296 99 -330 361 -98 99 -200 65 -430 165 -166 2327 -100 4051 -66 9653 -3478 197 -66 163 -198 167 -66 65 -598 165 -298 131 -666 199 -198 299 -298 165 -200 565 -66 797 -98 1125 -98 825 -100 4113 -6956 65 -5536 165 -266 99 -232 461 -198 65 -200 1989 -66 295 -66 723 -66 65 -98 329 -98 955 -66 559 -232 331 -66 10851 -1048 65 -3748 65 -498 99 -1392 99 -794 529 -98 331 -98 397 -164 363 -394 331 -266 299 -230 165 -66 3001 -568 197 -2872 2579 -468 2637 -472 2599 -488 2647 -426 2653 -448 2665 -392 379 -2734 381 -2700 2691 -388 377 -2732 2669 -420 355 -2726 2687 -394 403 -2706 2687 -388 377 -21248 2717 -388 377 -2738 2659 -408 2703 -382 2689 -416 2679 -408 2701 -382 2687 -418 365 -2736 365 -2722 2689 -384 391 -2696 2707 -386 379 -2734 2665 -410 361 -2726 2703 -418 357 -21246 2679 -466 297 -2768 2657 -448 2627 -434 2669 -450 2653 -416 2673 -408 2697 -386 383 -2728 369 -2706 2701 -382 387 -2726 2687 -418 357 -2708 2693 -418 361 -2702 2709 -396 401 -21232 2689 -406 361 -2736 2695 -386 2695 -406 2695 -382 2687 -418 2675 -410 2693 -414 375 -2692 389 -2706 2701 -404 363 -2724 2695 -388 389 -2702 2719 -358 405 -2704 2701 -402 363 -21262 2677 -414 367 -2738 2677 -386 2693 -420 2701 -400 2677 -386 2695 -420 2669 -430 369 -2718 353 -2730 2673 -412 361 -2734 2691 -420 357 -2698 2701 -394 401 -2702 2687 -424 347 -21244 2701 -418 365 -2726 2703 -382 2697 -420 2675 -400 2685 -384 2721 -398 2667 -418 355 -2744 343 -2722 2703 -420 353 -2724 2689 -396 363 -2736 2687 -390 377 -2730 2697 -386 357 -21274 2683 -414 375 -2726 2667 -420 2703 -398 2677 -388 2695 -420 2699 -398 2671 -384 415 -2698 357 -2738 2695 -382 383 -2724 2685 -416 357 -2706 2707 -384 391 -2726 2671 -384 415 -21238 2651 -476 293 -2776 2653 -462 2641 -446 2661 -422 2663 -418 2689 -412 2683 -414 357 -2706 385 -2698 2715 -378 379 -2710 2719 -388 377 -2708 2695 -406 361 -2724 2689 -416 361 -21244 2703 -386 413 -2698 2697 -414 2689 -384 2685 -386 2719 -378 2701 -416 2689 -386 377 -2728 387 -2700 2673 -410 361 -2730 2695 -420 357 -2732 2679 -386 377 -2734 2699 -378 361 -21262 2697 -392 405 -2702 2687 -406 2703 -382 2703 -418 2671 -406 2677 -416 2695 -386 387 -2700 381 -2704 2695 -418 357 -2712 2721 -388 375 -2702 2693 -408 363 -2730 2693 -420 355 -21248 2653 -494 289 -91206 131 -132 97 -232 559 -132 591 -98 691 -66 131 -130 297 -66 231 -66 331 -66 433 -100 499 -132 231 -166 197 -134 593 -100 11707 -4456 133 -200 131 | ||||
| RAW_Data: -66 133 -66 97 -166 561 -100 895 -132 1323 -66 10873 -3752 99 -722 229 -394 97 -66 99 -98 99 -328 297 -328 265 -298 3089 -132 10573 -1460 133 -432 99 -232 99 -132 333 -232 731 -164 65 -166 165 -132 131 -330 65 -98 131 -596 65 -198 133 -98 397 -568 65 -132 1157 -166 195 -130 131 -64 99 -66 63 -198 265 -98 297 -66 63 -166 295 -100 1747 -232 6099 -11348 199 -528 297 -266 97 -598 99 -198 231 -64 4433 -334 65 -298 65 -3284 67 -530 97 -432 133 -2356 493 -68 231 -168 297 -266 427 -100 559 -98 229 -460 197 -66 261 -132 65 -98 565 -132 231 -66 497 -100 3491 -12356 65 -660 197 -198 165 -132 331 -134 65 -98 2651 -134 4531 -10850 65 -1322 263 -68 431 -232 165 -134 165 -202 231 -300 5625 -66 6951 -8162 65 -398 99 -596 65 -132 461 -598 429 -132 97 -132 463 -232 229 -98 329 -100 397 -100 363 -100 231 -200 163 -200 961 -66 693 -100 397 -134 10601 -3872 263 -100 165 -100 131 -198 99 -696 233 -1524 331 -132 131 -164 229 -132 493 -98 631 -134 231 -100 595 -66 295 -66 5965 -8248 99 -296 99 -98 397 -66 65 -924 229 -398 299 -98 1425 -130 565 -198 827 -262 429 -598 725 -704 729 -12290 131 -98 99 -98 65 -100 163 -164 65 -494 231 -100 97 -100 863 -66 1751 -3948 165 -100 195 -66 165 -296 65 -2042 99 -200 495 -132 557 -100 827 -98 167 -66 433 -100 661 -164 689 -98 10803 -3906 231 -296 295 -232 99 -234 131 -332 395 -266 1283 -164 755 -466 397 -164 335 -66 1355 -14376 557 -66 331 -68 431 -134 599 -364 229 -100 763 -98 265 -132 525 -166 99 -396 495 -98 3867 -134 595 -168 865 -166 503 -200 467 -134 8145 -458 235 -794 599 -458 265 -436 231 -426 333 -368 299 -730 689 -360 327 -370 363 -326 367 -668 733 -328 363 -302 397 -328 371 -296 393 -666 725 -622 795 -634 433 -264 1023 -228 5041 -762 585 -466 233 -826 235 -470 631 -368 299 -402 299 -726 361 -328 331 -370 363 -332 701 -298 401 -692 369 -302 759 -268 461 -236 435 -622 423 -260 465 -266 719 -13608 65 -624 197 -558 921 -164 1315 -134 465 -134 263 -100 295 -132 293 -66 329 -98 197 -132 9977 -5036 197 -798 333 -828 295 -100 197 -100 165 -66 665 -100 763 -300 297 -166 165 -98 823 -8348 229 -100 427 -196 263 -624 197 -134 797 -100 263 -68 529 -132 233 -134 165 -264 131 -132 559 -66 263 -228 927 -132 731 -102 1061 -66 863 -8206 131 -332 299 -166 461 -100 99 -66 429 -66 3271 -98 465 -100 401 -232 331 -66 397 -430 10341 | ||||
| RAW_Data: -5434 65 -298 133 -132 131 -68 231 -200 661 -132 9517 -424 97 -1456 99 -1694 393 -100 131 -560 131 -196 197 -298 65 -428 229 -196 297 -266 131 -166 2435 -66 10161 -11230 65 -1320 131 -298 265 -532 231 -200 1291 -68 631 -66 12645 -4048 133 -66 67 -132 167 -266 163 -66 397 -132 197 -132 299 -98 197 -198 2903 -66 2361 -66 9627 -3588 197 -332 165 -68 331 -68 197 -132 99 -100 663 -66 363 -230 231 -166 131 -100 201 -298 163 -132 133 -202 363 -300 397 -102 263 -100 165 -66 1221 -66 1479 -132 165 -98 229 -12976 263 -66 363 -134 231 -66 629 -132 327 -100 97 -130 99 -164 227 -64 297 -132 397 -164 425 -198 97 -198 99 -66 365 -164 199 -102 97 -66 1817 -13524 231 -134 16907 -4086 233 -630 65 -396 201 -66 165 -198 67 -198 99 -664 2117 -166 12473 -446 2649 -440 2661 -420 2651 -422 2681 -418 2703 -400 365 -2724 387 -2696 2695 -414 357 -2704 2707 -386 389 -2700 2687 -392 405 -2706 2695 -402 363 -21268 2707 -388 377 -2706 2691 -404 2699 -382 2717 -382 2707 -378 2693 -416 2687 -396 363 -2736 355 -2748 2659 -416 365 -2708 2715 -388 377 -2708 2697 -404 363 -2730 2673 -420 355 -21268 2655 -460 319 -2766 2663 -448 2631 -436 2665 -418 2683 -410 2681 -416 2701 -386 383 -2700 375 -2744 2669 -416 353 -2730 2685 -416 357 -2708 2721 -380 369 -2724 2697 -382 385 -21260 2701 -418 353 -2720 2673 -418 2675 -408 2693 -384 2715 -386 2717 -386 2691 -404 363 -2732 387 -2702 2669 -412 359 -2736 2699 -380 381 -2728 2675 -416 381 -2720 2675 -414 347 -21280 2685 -390 377 -2724 2689 -416 2673 -408 2705 -382 2695 -410 2689 -414 2661 -418 385 -2704 369 -2704 2693 -416 375 -2726 2661 -420 355 -2728 2711 -388 375 -2702 2691 -410 363 -21252 2659 -488 287 -2794 2651 -448 2629 -436 2671 -416 2695 -416 2663 -406 2699 -384 383 -2730 367 -2702 2695 -418 385 -2702 2685 -412 349 -2744 2693 -366 389 -2714 2693 -394 381 -21266 2685 -418 363 -2730 2683 -382 2693 -418 2675 -410 2699 -384 2719 -382 2707 -380 359 -2734 387 -2704 2709 -380 361 -2732 2699 -418 357 -2728 2667 -416 383 -2696 2709 -380 391 -21228 2685 -458 307 -2800 2647 -412 2659 -432 2667 -416 2695 -416 2675 -406 2675 -416 383 -2700 361 -2730 2687 -414 375 -2696 2701 -420 353 -2720 2711 -382 367 -2728 2675 -416 385 -21222 2735 -386 355 -2744 2687 -396 2679 -418 2701 -386 2705 -382 2681 -410 2697 -384 385 -2736 365 -2704 2715 -384 377 -2696 2697 -416 349 -2722 2707 -386 379 -2732 2671 -410 361 -21258 2681 -464 297 -2796 2629 -456 2655 -420 2661 -448 2663 -404 2695 -382 2715 -380 371 -2740 355 -2744 2679 -384 391 -2728 2675 -388 379 | ||||
| RAW_Data: -2728 2695 -414 357 -2704 2705 -418 357 -21262 2673 -416 383 -2696 2709 -380 2703 -384 2699 -418 2671 -408 2695 -382 2713 -386 379 -2730 357 -2732 2695 -384 383 -2730 2679 -416 357 -2708 2701 -410 349 -2736 2697 -382 385 -21252 2669 -478 289 -2790 2647 -426 2651 -444 2653 -430 2659 -418 2695 -414 2681 -402 349 -2738 383 -2722 2677 -414 347 -2744 2691 -382 369 -2730 2691 -384 383 -2734 2679 -414 347 -21264 2705 -386 379 -2736 2667 -410 2695 -382 2715 -380 2709 -420 2665 -392 2713 -382 383 -2730 365 -2728 2665 -418 383 -2696 2693 -418 357 -2710 2711 -380 375 -2718 2701 -416 357 -21238 2677 -484 311 -2766 2635 -444 2657 -420 2663 -422 2695 -416 2667 -428 2675 -396 363 -73890 133 -98 131 -132 129 -658 99 -66 853 -100 63 -100 361 -98 1589 -66 1231 -132 65 -100 297 -198 65 -132 265 -66 9857 -4672 165 -1030 97 -1394 65 -200 2687 -68 6873 -8336 99 -1156 97 -66 163 -232 163 -262 197 -132 295 -132 263 -166 953 -100 263 -130 393 -164 295 -64 329 -66 393 -164 823 -130 165 -66 6133 -8436 165 -164 265 -266 65 -362 197 -696 3181 -132 363 -98 65 -166 131 -66 399 -132 663 -396 329 -66 7335 -7578 497 -230 627 -264 99 -366 99 -132 131 -134 265 -498 163 -100 1323 -66 265 -66 1129 -100 399 -132 365 -100 795 -68 397 -98 597 -364 297 -132 361 -132 265 -132 8591 -4740 65 -100 131 -166 199 -1088 97 -296 99 -528 131 -98 661 -66 401 -198 1157 -166 361 -164 495 -100 165 -66 297 -100 1423 -66 3067 -5658 67 -6406 197 -1092 65 -530 659 -68 265 -100 991 -68 231 -230 297 -66 327 -66 131 -132 659 -134 131 -100 1183 -132 263 -98 621 -66 2075 -6976 65 -5138 67 -132 129 -664 67 -132 165 -100 331 -466 231 -68 467 -98 563 -66 231 -100 531 -66 465 -66 1023 -166 297 -134 3409 -12290 67 -164 99 -532 133 -166 263 -66 231 -66 721 -64 131 -68 959 -134 495 -100 299 -98 497 -98 365 -100 397 -232 297 -98 531 -66 3029 -12216 265 -132 99 -364 199 -234 131 -66 431 -166 333 -166 397 -132 327 -100 395 -66 197 -132 395 -66 527 -98 295 -100 97 -98 789 -132 363 -132 297 -200 2815 -4914 65 -6620 65 -462 65 -134 297 -66 497 -264 231 -198 2773 -134 365 -100 831 -166 131 -100 297 -132 861 -132 299 -100 561 -66 1381 -6946 65 -5516 231 -266 97 -1362 1093 -68 1621 -134 165 -332 297 -98 361 -228 97 -132 797 -98 3487 -13224 229 -164 65 -132 913 -66 1123 -98 527 -134 929 -98 723 -100 12259 -270 165 -132 67 -132 165 -1326 99 -98 65 -1194 431 -66 695 -66 733 -134 197 | ||||
| RAW_Data: -134 10801 -166 67 -6130 133 -198 231 -334 365 -98 229 -132 165 -68 231 -166 14501 -524 65 -328 131 -498 129 -1288 65 -494 163 -64 165 -66 527 -132 131 -132 1019 -198 129 -166 393 -198 65 -164 6411 -66 3255 -10642 65 -1320 165 -164 493 -492 559 -264 2555 -66 695 -66 1657 -164 855 -66 4001 -10526 97 -596 133 -298 67 -264 65 -300 65 -100 263 -166 231 -134 99 -100 2703 -68 13643 -4922 297 -100 65 -232 133 -198 331 -300 231 -66 331 -100 12047 -3872 97 -196 65 -494 329 -66 65 -890 97 -98 229 -164 195 -596 797 -66 861 -132 65 -66 231 -100 565 -66 65 -66 1297 -132 265 -66 363 -134 265 -364 297 -164 299 -134 297 -134 495 -98 11309 -3790 131 -1380 65 -758 65 -164 129 -460 65 -360 199 -100 563 -68 497 -198 363 -266 263 -100 165 -66 697 -66 1933 -13594 65 -762 1223 -132 1119 -196 361 -134 131 -100 793 -166 695 -68 231 -68 463 -66 11727 -4204 363 -264 131 -132 133 -1124 97 -100 163 -100 327 -100 331 -198 397 -66 397 -100 395 -100 163 -66 197 -564 1059 -7962 65 -100 65 -198 129 -362 99 -394 197 -296 495 -100 1357 -68 459 -66 593 -66 265 -68 301 -132 465 -66 231 -200 397 -66 397 -232 199 -298 12077 -4350 231 -796 363 -198 133 -264 65 -1132 597 -332 3295 -100 755 -98 231 -164 97 -264 459 -166 759 -164 3265 -12138 99 -232 99 -1228 1025 -100 393 -66 531 -132 693 -132 1063 -66 427 -64 297 -294 229 -98 9723 -5404 67 -466 99 -796 267 -98 201 -100 167 -264 461 -98 1415 -66 861 -66 267 -66 331 -134 1663 -66 2089 -7012 65 -100 101 -4804 431 -728 99 -100 65 -100 995 -134 165 -66 929 -100 65 -66 927 -100 1093 -168 99 -100 497 -66 665 -200 6517 -8312 165 -66 129 -66 559 -166 99 -430 65 -398 67 -66 593 -198 459 -132 261 -132 263 -130 723 -66 459 -100 325 -166 67 -198 559 -66 493 -66 11475 -3896 99 -266 99 -66 197 -1092 129 -198 361 -166 163 -98 263 -196 759 -100 265 -100 365 -630 4635 -12748 65 -1712 461 -100 497 -66 395 -98 265 -98 229 -164 529 -132 297 -66 565 -132 987 -132 8665 -2820 2265 -450 313 -2774 2643 -442 325 -2772 2665 -416 359 -2734 2667 -386 379 -21274 2657 -474 293 -2810 2619 -466 2613 -476 2629 -452 2663 -388 2683 -418 2705 -400 365 -2722 387 -2700 2697 -380 361 -2732 2691 -418 361 -2732 2667 -416 383 -2698 2697 -416 357 -21238 2715 -384 383 -2732 2685 -416 2667 -416 2695 -398 2671 -418 2687 -390 2713 -382 383 -2730 365 -2728 2661 -416 379 -2716 2685 -384 379 -2720 2703 -378 401 -2718 2671 | ||||
|  | ||||
| @ -6,7 +6,6 @@ It is invoked by `./fbt` in the firmware project root directory. Internally, it | ||||
| ## Requirements | ||||
| 
 | ||||
| Please install Python packages required by assets build scripts: `pip3 install -r scripts/requirements.txt` | ||||
| Make sure that `gcc-arm-none-eabi` toolchain & OpenOCD executables are in system's PATH. | ||||
| 
 | ||||
| ## NB | ||||
| 
 | ||||
|  | ||||
| @ -14,7 +14,7 @@ extern uint32_t SystemCoreClock; | ||||
| #define configENABLE_MPU 0 | ||||
| 
 | ||||
| #define configUSE_PREEMPTION 1 | ||||
| #define configSUPPORT_STATIC_ALLOCATION 0 | ||||
| #define configSUPPORT_STATIC_ALLOCATION 1 | ||||
| #define configSUPPORT_DYNAMIC_ALLOCATION 1 | ||||
| #define configUSE_IDLE_HOOK 0 | ||||
| #define configUSE_TICK_HOOK 0 | ||||
|  | ||||
							
								
								
									
										59
									
								
								firmware/targets/f7/fatfs/sector_cache.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								firmware/targets/f7/fatfs/sector_cache.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,59 @@ | ||||
| #include "sector_cache.h" | ||||
| 
 | ||||
| #include <stddef.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <furi.h> | ||||
| #include <furi_hal_memory.h> | ||||
| 
 | ||||
| #define SECTOR_SIZE 512 | ||||
| #define N_SECTORS 8 | ||||
| 
 | ||||
| typedef struct { | ||||
|     uint32_t itr; | ||||
|     uint32_t sectors[N_SECTORS]; | ||||
|     uint8_t sector_data[N_SECTORS][SECTOR_SIZE]; | ||||
| } SectorCache; | ||||
| 
 | ||||
| static SectorCache* cache = NULL; | ||||
| 
 | ||||
| void sector_cache_init() { | ||||
|     if(cache == NULL) { | ||||
|         cache = furi_hal_memory_alloc(sizeof(SectorCache)); | ||||
|     } | ||||
| 
 | ||||
|     if(cache != NULL) { | ||||
|         FURI_LOG_I("SectorCache", "Initializing sector cache"); | ||||
|         memset(cache, 0, sizeof(SectorCache)); | ||||
|     } else { | ||||
|         FURI_LOG_E("SectorCache", "Cannot enable sector cache"); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| uint8_t* sector_cache_get(uint32_t n_sector) { | ||||
|     if(cache != NULL && n_sector != 0) { | ||||
|         for(int sector_i = 0; sector_i < N_SECTORS; ++sector_i) { | ||||
|             if(cache->sectors[sector_i] == n_sector) { | ||||
|                 return cache->sector_data[sector_i]; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| void sector_cache_put(uint32_t n_sector, uint8_t* data) { | ||||
|     if(cache == NULL) return; | ||||
|     cache->sectors[cache->itr % N_SECTORS] = n_sector; | ||||
|     memcpy(cache->sector_data[cache->itr % N_SECTORS], data, SECTOR_SIZE); | ||||
|     cache->itr++; | ||||
| } | ||||
| 
 | ||||
| void sector_cache_invalidate_range(uint32_t start_sector, uint32_t end_sector) { | ||||
|     if(cache == NULL) return; | ||||
|     for(int sector_i = 0; sector_i < N_SECTORS; ++sector_i) { | ||||
|         if((cache->sectors[sector_i] >= start_sector) && | ||||
|            (cache->sectors[sector_i] <= end_sector)) { | ||||
|             cache->sectors[sector_i] = 0; | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										36
									
								
								firmware/targets/f7/fatfs/sector_cache.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								firmware/targets/f7/fatfs/sector_cache.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| #pragma once | ||||
| #include <stdint.h> | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief Init sector cache system | ||||
|  */ | ||||
| void sector_cache_init(); | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief Get sector data from cache | ||||
|  * @param n_sector Sector number | ||||
|  * @return Pointer to sector data or NULL if not found | ||||
|  */ | ||||
| uint8_t* sector_cache_get(uint32_t n_sector); | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief Put sector data to cache | ||||
|  * @param n_sector Sector number | ||||
|  * @param data Pointer to sector data | ||||
|  */ | ||||
| void sector_cache_put(uint32_t n_sector, uint8_t* data); | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief Invalidate sector cache for given range | ||||
|  * @param start_sector Start sector number | ||||
|  * @param end_sector End sector number | ||||
|  */ | ||||
| void sector_cache_invalidate_range(uint32_t start_sector, uint32_t end_sector); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| @ -92,6 +92,7 @@ | ||||
| #include "string.h" | ||||
| #include "stdio.h" | ||||
| #include <furi_hal.h> | ||||
| #include "sector_cache.h" | ||||
| 
 | ||||
| /** @addtogroup BSP
 | ||||
|   * @{ | ||||
| @ -377,6 +378,8 @@ uint8_t BSP_SD_Init(bool reset_card) { | ||||
|     furi_hal_sd_spi_handle = NULL; | ||||
|     furi_hal_spi_release(&furi_hal_spi_bus_handle_sd_slow); | ||||
| 
 | ||||
|     sector_cache_init(); | ||||
| 
 | ||||
|     /* SD initialized and set to SPI mode properly */ | ||||
|     return res; | ||||
| } | ||||
| @ -427,9 +430,15 @@ uint8_t | ||||
|     uint32_t offset = 0; | ||||
|     uint32_t addr; | ||||
|     uint8_t retr = BSP_SD_ERROR; | ||||
|     uint8_t* ptr = NULL; | ||||
|     SD_CmdAnswer_typedef response; | ||||
|     uint16_t BlockSize = 512; | ||||
|     uint8_t* cached_data; | ||||
| 
 | ||||
|     bool single_sector_read = (NumOfBlocks == 1); | ||||
|     if(single_sector_read && (cached_data = sector_cache_get(ReadAddr))) { | ||||
|         memcpy(pData, cached_data, BlockSize); | ||||
|         return BSP_SD_OK; | ||||
|     } | ||||
| 
 | ||||
|     /* Send CMD16 (SD_CMD_SET_BLOCKLEN) to set the size of the block and 
 | ||||
|      Check if the SD acknowledged the set block length command: R1 response (0x00: no errors) */ | ||||
| @ -440,12 +449,6 @@ uint8_t | ||||
|         goto error; | ||||
|     } | ||||
| 
 | ||||
|     ptr = malloc(sizeof(uint8_t) * BlockSize); | ||||
|     if(ptr == NULL) { | ||||
|         goto error; | ||||
|     } | ||||
|     memset(ptr, SD_DUMMY_BYTE, sizeof(uint8_t) * BlockSize); | ||||
| 
 | ||||
|     /* Initialize the address */ | ||||
|     addr = (ReadAddr * ((flag_SDHC == 1) ? 1 : BlockSize)); | ||||
| 
 | ||||
| @ -461,7 +464,7 @@ uint8_t | ||||
|         /* Now look for the data token to signify the start of the data */ | ||||
|         if(SD_WaitData(SD_TOKEN_START_DATA_SINGLE_BLOCK_READ) == BSP_SD_OK) { | ||||
|             /* Read the SD block data : read NumByteToRead data */ | ||||
|             SD_IO_WriteReadData(ptr, (uint8_t*)pData + offset, BlockSize); | ||||
|             SD_IO_WriteReadData(NULL, (uint8_t*)pData + offset, BlockSize); | ||||
| 
 | ||||
|             /* Set next read address*/ | ||||
|             offset += BlockSize; | ||||
| @ -479,13 +482,16 @@ uint8_t | ||||
|         SD_IO_WriteByte(SD_DUMMY_BYTE); | ||||
|     } | ||||
| 
 | ||||
|     if(single_sector_read) { | ||||
|         sector_cache_put(ReadAddr, (uint8_t*)pData); | ||||
|     } | ||||
| 
 | ||||
|     retr = BSP_SD_OK; | ||||
| 
 | ||||
| error: | ||||
|     /* Send dummy byte: 8 Clock pulses of delay */ | ||||
|     SD_IO_CSState(1); | ||||
|     SD_IO_WriteByte(SD_DUMMY_BYTE); | ||||
|     if(ptr != NULL) free(ptr); | ||||
| 
 | ||||
|     /* Return the reponse */ | ||||
|     return retr; | ||||
| @ -509,9 +515,9 @@ uint8_t BSP_SD_WriteBlocks( | ||||
|     uint32_t offset = 0; | ||||
|     uint32_t addr; | ||||
|     uint8_t retr = BSP_SD_ERROR; | ||||
|     uint8_t* ptr = NULL; | ||||
|     SD_CmdAnswer_typedef response; | ||||
|     uint16_t BlockSize = 512; | ||||
|     sector_cache_invalidate_range(WriteAddr, WriteAddr + NumOfBlocks); | ||||
| 
 | ||||
|     /* Send CMD16 (SD_CMD_SET_BLOCKLEN) to set the size of the block and 
 | ||||
|      Check if the SD acknowledged the set block length command: R1 response (0x00: no errors) */ | ||||
| @ -522,11 +528,6 @@ uint8_t BSP_SD_WriteBlocks( | ||||
|         goto error; | ||||
|     } | ||||
| 
 | ||||
|     ptr = malloc(sizeof(uint8_t) * BlockSize); | ||||
|     if(ptr == NULL) { | ||||
|         goto error; | ||||
|     } | ||||
| 
 | ||||
|     /* Initialize the address */ | ||||
|     addr = (WriteAddr * ((flag_SDHC == 1) ? 1 : BlockSize)); | ||||
| 
 | ||||
| @ -547,7 +548,7 @@ uint8_t BSP_SD_WriteBlocks( | ||||
|         SD_IO_WriteByte(SD_TOKEN_START_DATA_SINGLE_BLOCK_WRITE); | ||||
| 
 | ||||
|         /* Write the block data to SD */ | ||||
|         SD_IO_WriteReadData((uint8_t*)pData + offset, ptr, BlockSize); | ||||
|         SD_IO_WriteReadData((uint8_t*)pData + offset, NULL, BlockSize); | ||||
| 
 | ||||
|         /* Set next write address */ | ||||
|         offset += BlockSize; | ||||
| @ -569,7 +570,7 @@ uint8_t BSP_SD_WriteBlocks( | ||||
|     retr = BSP_SD_OK; | ||||
| 
 | ||||
| error: | ||||
|     if(ptr != NULL) free(ptr); | ||||
| 
 | ||||
|     /* Send dummy byte: 8 Clock pulses of delay */ | ||||
|     SD_IO_CSState(1); | ||||
|     SD_IO_WriteByte(SD_DUMMY_BYTE); | ||||
|  | ||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Aleksandr Kutuzov
						Aleksandr Kutuzov