mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-06-29 21:52:03 -07:00
Merge branch 'dev' into mrtd
This commit is contained in:
@@ -45,6 +45,19 @@ jobs:
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
|
||||
- name: 'Escape pull request title'
|
||||
if: github.event_name == 'pull_request'
|
||||
run: |
|
||||
import json
|
||||
import os
|
||||
import shlex
|
||||
with open('${{ github.event_path }}') as fh:
|
||||
event = json.load(fh)
|
||||
escaped = shlex.quote(event['pull_request']['title'])
|
||||
with open(os.environ['GITHUB_ENV'], 'a') as fh:
|
||||
print(f'PULL_NAME={escaped}', file=fh)
|
||||
shell: python3 {0}
|
||||
|
||||
- name: 'Generate prefixes by commit'
|
||||
id: names
|
||||
run: |
|
||||
@@ -58,7 +71,6 @@ jobs:
|
||||
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}}"
|
||||
fi
|
||||
BRANCH_NAME=${REF#refs/*/}
|
||||
SUFFIX=${BRANCH_NAME//\//_}-$(date +'%d%m%Y')-${SHA}
|
||||
@@ -78,7 +90,6 @@ 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;
|
||||
@@ -112,7 +123,6 @@ jobs:
|
||||
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 \
|
||||
|
||||
+2
-2
@@ -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))
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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 208
|
||||
#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,14 @@ 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");
|
||||
}
|
||||
|
||||
//test encoders
|
||||
MU_TEST(subghz_encoder_princeton_test) {
|
||||
mu_assert(
|
||||
@@ -528,6 +536,12 @@ 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_random_test) {
|
||||
mu_assert(subghz_decode_random_test(TEST_RANDOM_DIR_NAME), "Random test error\r\n");
|
||||
}
|
||||
@@ -566,6 +580,7 @@ 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_encoder_princeton_test);
|
||||
MU_RUN_TEST(subghz_encoder_came_test);
|
||||
@@ -585,6 +600,7 @@ 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_random_test);
|
||||
subghz_test_deinit();
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -124,7 +124,9 @@ bool furi_hal_nfc_detect(FuriHalNfcDevData* nfc_data, uint32_t timeout) {
|
||||
}
|
||||
nfc_data->cuid = (cuid_start[0] << 24) | (cuid_start[1] << 16) | (cuid_start[2] << 8) |
|
||||
(cuid_start[3]);
|
||||
} else if(dev_list[0].type == RFAL_NFC_LISTEN_TYPE_NFCB) {
|
||||
} else if(dev_list[0].type == RFAL_NFC_LISTEN_TYPE_NFCB ||
|
||||
dev_list[0].type == RFAL_NFC_LISTEN_TYPE_ST25TB)
|
||||
{
|
||||
nfc_data->type = FuriHalNfcTypeB;
|
||||
} else if(dev_list[0].type == RFAL_NFC_LISTEN_TYPE_NFCF) {
|
||||
nfc_data->type = FuriHalNfcTypeF;
|
||||
|
||||
@@ -26,7 +26,7 @@ enum {
|
||||
RFAL_PICOPASS_CMD_READCHECK = 0x88,
|
||||
RFAL_PICOPASS_CMD_CHECK = 0x05,
|
||||
RFAL_PICOPASS_CMD_READ = 0x0C,
|
||||
RFAL_PICOPASS_CMD_WRITE = 0x0C,
|
||||
RFAL_PICOPASS_CMD_WRITE = 0x87,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
#include "rfal_picopass.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define TAG "RFAL_PICOPASS"
|
||||
|
||||
typedef struct {
|
||||
uint8_t CMD;
|
||||
uint8_t CSN[RFAL_PICOPASS_UID_LEN];
|
||||
@@ -169,18 +171,14 @@ ReturnCode rfalPicoPassPollerWriteBlock(uint8_t blockNum, uint8_t data[8], uint8
|
||||
uint16_t recvLen = 0;
|
||||
uint32_t flags = RFAL_PICOPASS_TXRX_FLAGS;
|
||||
uint32_t fwt = rfalConvMsTo1fc(20);
|
||||
rfalPicoPassReadBlockRes readRes;
|
||||
rfalPicoPassReadBlockRes block;
|
||||
|
||||
ret = rfalTransceiveBlockingTxRx(
|
||||
txBuf,
|
||||
sizeof(txBuf),
|
||||
(uint8_t*)&readRes,
|
||||
sizeof(rfalPicoPassReadBlockRes),
|
||||
&recvLen,
|
||||
flags,
|
||||
fwt);
|
||||
txBuf, sizeof(txBuf), (uint8_t*)&block, sizeof(block), &recvLen, flags, fwt);
|
||||
|
||||
// TODO: compare response
|
||||
if(ret == ERR_NONE) {
|
||||
// TODO: compare response
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include "protocol_jablotron.h"
|
||||
#include "protocol_paradox.h"
|
||||
#include "protocol_pac_stanley.h"
|
||||
#include "protocol_keri.h"
|
||||
#include "protocol_gallagher.h"
|
||||
|
||||
const ProtocolBase* lfrfid_protocols[] = {
|
||||
[LFRFIDProtocolEM4100] = &protocol_em4100,
|
||||
@@ -29,4 +31,6 @@ const ProtocolBase* lfrfid_protocols[] = {
|
||||
[LFRFIDProtocolJablotron] = &protocol_jablotron,
|
||||
[LFRFIDProtocolParadox] = &protocol_paradox,
|
||||
[LFRFIDProtocolPACStanley] = &protocol_pac_stanley,
|
||||
[LFRFIDProtocolKeri] = &protocol_keri,
|
||||
[LFRFIDProtocolGallagher] = &protocol_gallagher,
|
||||
};
|
||||
@@ -22,6 +22,8 @@ typedef enum {
|
||||
LFRFIDProtocolJablotron,
|
||||
LFRFIDProtocolParadox,
|
||||
LFRFIDProtocolPACStanley,
|
||||
LFRFIDProtocolKeri,
|
||||
LFRFIDProtocolGallagher,
|
||||
LFRFIDProtocolMax,
|
||||
} LFRFIDProtocol;
|
||||
|
||||
|
||||
@@ -0,0 +1,300 @@
|
||||
#include <furi.h>
|
||||
#include <toolbox/protocols/protocol.h>
|
||||
#include <toolbox/manchester_decoder.h>
|
||||
#include <lfrfid/tools/bit_lib.h>
|
||||
#include "lfrfid_protocols.h"
|
||||
|
||||
#define GALLAGHER_CLOCK_PER_BIT (32)
|
||||
|
||||
#define GALLAGHER_ENCODED_BIT_SIZE (96)
|
||||
#define GALLAGHER_ENCODED_BYTE_SIZE ((GALLAGHER_ENCODED_BIT_SIZE) / 8)
|
||||
#define GALLAGHER_PREAMBLE_BIT_SIZE (16)
|
||||
#define GALLAGHER_PREAMBLE_BYTE_SIZE ((GALLAGHER_PREAMBLE_BIT_SIZE) / 8)
|
||||
#define GALLAGHER_ENCODED_BYTE_FULL_SIZE \
|
||||
(GALLAGHER_ENCODED_BYTE_SIZE + GALLAGHER_PREAMBLE_BYTE_SIZE)
|
||||
#define GALLAGHER_DECODED_DATA_SIZE 8
|
||||
|
||||
#define GALLAGHER_READ_SHORT_TIME (128)
|
||||
#define GALLAGHER_READ_LONG_TIME (256)
|
||||
#define GALLAGHER_READ_JITTER_TIME (60)
|
||||
|
||||
#define GALLAGHER_READ_SHORT_TIME_LOW (GALLAGHER_READ_SHORT_TIME - GALLAGHER_READ_JITTER_TIME)
|
||||
#define GALLAGHER_READ_SHORT_TIME_HIGH (GALLAGHER_READ_SHORT_TIME + GALLAGHER_READ_JITTER_TIME)
|
||||
#define GALLAGHER_READ_LONG_TIME_LOW (GALLAGHER_READ_LONG_TIME - GALLAGHER_READ_JITTER_TIME)
|
||||
#define GALLAGHER_READ_LONG_TIME_HIGH (GALLAGHER_READ_LONG_TIME + GALLAGHER_READ_JITTER_TIME)
|
||||
|
||||
typedef struct {
|
||||
uint8_t data[GALLAGHER_DECODED_DATA_SIZE];
|
||||
uint8_t encoded_data[GALLAGHER_ENCODED_BYTE_FULL_SIZE];
|
||||
|
||||
uint8_t encoded_data_index;
|
||||
bool encoded_polarity;
|
||||
|
||||
ManchesterState decoder_manchester_state;
|
||||
} ProtocolGallagher;
|
||||
|
||||
ProtocolGallagher* protocol_gallagher_alloc(void) {
|
||||
ProtocolGallagher* proto = malloc(sizeof(ProtocolGallagher));
|
||||
return (void*)proto;
|
||||
};
|
||||
|
||||
void protocol_gallagher_free(ProtocolGallagher* protocol) {
|
||||
free(protocol);
|
||||
};
|
||||
|
||||
uint8_t* protocol_gallagher_get_data(ProtocolGallagher* protocol) {
|
||||
return protocol->data;
|
||||
};
|
||||
|
||||
static void protocol_gallagher_scramble(uint8_t* data, size_t length) {
|
||||
const uint8_t lut[] = {
|
||||
0xa3, 0xb0, 0x80, 0xc6, 0xb2, 0xf4, 0x5c, 0x6c, 0x81, 0xf1, 0xbb, 0xeb, 0x55, 0x67, 0x3c,
|
||||
0x05, 0x1a, 0x0e, 0x61, 0xf6, 0x22, 0xce, 0xaa, 0x8f, 0xbd, 0x3b, 0x1f, 0x5e, 0x44, 0x04,
|
||||
0x51, 0x2e, 0x4d, 0x9a, 0x84, 0xea, 0xf8, 0x66, 0x74, 0x29, 0x7f, 0x70, 0xd8, 0x31, 0x7a,
|
||||
0x6d, 0xa4, 0x00, 0x82, 0xb9, 0x5f, 0xb4, 0x16, 0xab, 0xff, 0xc2, 0x39, 0xdc, 0x19, 0x65,
|
||||
0x57, 0x7c, 0x20, 0xfa, 0x5a, 0x49, 0x13, 0xd0, 0xfb, 0xa8, 0x91, 0x73, 0xb1, 0x33, 0x18,
|
||||
0xbe, 0x21, 0x72, 0x48, 0xb6, 0xdb, 0xa0, 0x5d, 0xcc, 0xe6, 0x17, 0x27, 0xe5, 0xd4, 0x53,
|
||||
0x42, 0xf3, 0xdd, 0x7b, 0x24, 0xac, 0x2b, 0x58, 0x1e, 0xa7, 0xe7, 0x86, 0x40, 0xd3, 0x98,
|
||||
0x97, 0x71, 0xcb, 0x3a, 0x0f, 0x01, 0x9b, 0x6e, 0x1b, 0xfc, 0x34, 0xa6, 0xda, 0x07, 0x0c,
|
||||
0xae, 0x37, 0xca, 0x54, 0xfd, 0x26, 0xfe, 0x0a, 0x45, 0xa2, 0x2a, 0xc4, 0x12, 0x0d, 0xf5,
|
||||
0x4f, 0x69, 0xe0, 0x8a, 0x77, 0x60, 0x3f, 0x99, 0x95, 0xd2, 0x38, 0x36, 0x62, 0xb7, 0x32,
|
||||
0x7e, 0x79, 0xc0, 0x46, 0x93, 0x2f, 0xa5, 0xba, 0x5b, 0xaf, 0x52, 0x1d, 0xc3, 0x75, 0xcf,
|
||||
0xd6, 0x4c, 0x83, 0xe8, 0x3d, 0x30, 0x4e, 0xbc, 0x08, 0x2d, 0x09, 0x06, 0xd9, 0x25, 0x9e,
|
||||
0x89, 0xf2, 0x96, 0x88, 0xc1, 0x8c, 0x94, 0x0b, 0x28, 0xf0, 0x47, 0x63, 0xd5, 0xb3, 0x68,
|
||||
0x56, 0x9c, 0xf9, 0x6f, 0x41, 0x50, 0x85, 0x8b, 0x9d, 0x59, 0xbf, 0x9f, 0xe2, 0x8e, 0x6a,
|
||||
0x11, 0x23, 0xa1, 0xcd, 0xb5, 0x7d, 0xc7, 0xa9, 0xc8, 0xef, 0xdf, 0x02, 0xb8, 0x03, 0x6b,
|
||||
0x35, 0x3e, 0x2c, 0x76, 0xc9, 0xde, 0x1c, 0x4b, 0xd1, 0xed, 0x14, 0xc5, 0xad, 0xe9, 0x64,
|
||||
0x4a, 0xec, 0x8d, 0xf7, 0x10, 0x43, 0x78, 0x15, 0x87, 0xe4, 0xd7, 0x92, 0xe1, 0xee, 0xe3,
|
||||
0x90};
|
||||
for(size_t i = 0; i < length; i++) {
|
||||
data[i] = lut[data[i]];
|
||||
}
|
||||
}
|
||||
|
||||
static void protocol_gallagher_descramble(uint8_t* data, size_t length) {
|
||||
const uint8_t lut[] = {
|
||||
0x2f, 0x6e, 0xdd, 0xdf, 0x1d, 0x0f, 0xb0, 0x76, 0xad, 0xaf, 0x7f, 0xbb, 0x77, 0x85, 0x11,
|
||||
0x6d, 0xf4, 0xd2, 0x84, 0x42, 0xeb, 0xf7, 0x34, 0x55, 0x4a, 0x3a, 0x10, 0x71, 0xe7, 0xa1,
|
||||
0x62, 0x1a, 0x3e, 0x4c, 0x14, 0xd3, 0x5e, 0xb2, 0x7d, 0x56, 0xbc, 0x27, 0x82, 0x60, 0xe3,
|
||||
0xae, 0x1f, 0x9b, 0xaa, 0x2b, 0x95, 0x49, 0x73, 0xe1, 0x92, 0x79, 0x91, 0x38, 0x6c, 0x19,
|
||||
0x0e, 0xa9, 0xe2, 0x8d, 0x66, 0xc7, 0x5a, 0xf5, 0x1c, 0x80, 0x99, 0xbe, 0x4e, 0x41, 0xf0,
|
||||
0xe8, 0xa6, 0x20, 0xab, 0x87, 0xc8, 0x1e, 0xa0, 0x59, 0x7b, 0x0c, 0xc3, 0x3c, 0x61, 0xcc,
|
||||
0x40, 0x9e, 0x06, 0x52, 0x1b, 0x32, 0x8c, 0x12, 0x93, 0xbf, 0xef, 0x3b, 0x25, 0x0d, 0xc2,
|
||||
0x88, 0xd1, 0xe0, 0x07, 0x2d, 0x70, 0xc6, 0x29, 0x6a, 0x4d, 0x47, 0x26, 0xa3, 0xe4, 0x8b,
|
||||
0xf6, 0x97, 0x2c, 0x5d, 0x3d, 0xd7, 0x96, 0x28, 0x02, 0x08, 0x30, 0xa7, 0x22, 0xc9, 0x65,
|
||||
0xf8, 0xb7, 0xb4, 0x8a, 0xca, 0xb9, 0xf2, 0xd0, 0x17, 0xff, 0x46, 0xfb, 0x9a, 0xba, 0x8f,
|
||||
0xb6, 0x69, 0x68, 0x8e, 0x21, 0x6f, 0xc4, 0xcb, 0xb3, 0xce, 0x51, 0xd4, 0x81, 0x00, 0x2e,
|
||||
0x9c, 0x74, 0x63, 0x45, 0xd9, 0x16, 0x35, 0x5f, 0xed, 0x78, 0x9f, 0x01, 0x48, 0x04, 0xc1,
|
||||
0x33, 0xd6, 0x4f, 0x94, 0xde, 0x31, 0x9d, 0x0a, 0xac, 0x18, 0x4b, 0xcd, 0x98, 0xb8, 0x37,
|
||||
0xa2, 0x83, 0xec, 0x03, 0xd8, 0xda, 0xe5, 0x7a, 0x6b, 0x53, 0xd5, 0x15, 0xa4, 0x43, 0xe9,
|
||||
0x90, 0x67, 0x58, 0xc0, 0xa5, 0xfa, 0x2a, 0xb1, 0x75, 0x50, 0x39, 0x5c, 0xe6, 0xdc, 0x89,
|
||||
0xfc, 0xcf, 0xfe, 0xf9, 0x57, 0x54, 0x64, 0xa8, 0xee, 0x23, 0x0b, 0xf1, 0xea, 0xfd, 0xdb,
|
||||
0xbd, 0x09, 0xb5, 0x5b, 0x05, 0x86, 0x13, 0xf3, 0x24, 0xc5, 0x3f, 0x44, 0x72, 0x7c, 0x7e,
|
||||
0x36};
|
||||
|
||||
for(size_t i = 0; i < length; i++) {
|
||||
data[i] = lut[data[i]];
|
||||
}
|
||||
}
|
||||
|
||||
static void protocol_gallagher_decode(ProtocolGallagher* protocol) {
|
||||
bit_lib_remove_bit_every_nth(protocol->encoded_data, 16, 9 * 8, 9);
|
||||
protocol_gallagher_descramble(protocol->encoded_data + 2, 8);
|
||||
|
||||
// Region code
|
||||
bit_lib_set_bits(protocol->data, 0, (protocol->encoded_data[5] & 0x1E) >> 1, 4);
|
||||
|
||||
// Issue Level
|
||||
bit_lib_set_bits(protocol->data, 4, (protocol->encoded_data[9] & 0x0F), 4);
|
||||
|
||||
// Facility Code
|
||||
uint32_t fc = (protocol->encoded_data[7] & 0x0F) << 12 | protocol->encoded_data[3] << 4 |
|
||||
((protocol->encoded_data[9] >> 4) & 0x0F);
|
||||
protocol->data[3] = (uint8_t)fc;
|
||||
protocol->data[2] = (uint8_t)(fc >>= 8);
|
||||
protocol->data[1] = (uint8_t)(fc >>= 8);
|
||||
|
||||
// Card Number
|
||||
uint32_t card = protocol->encoded_data[2] << 16 | (protocol->encoded_data[6] & 0x1F) << 11 |
|
||||
protocol->encoded_data[4] << 3 | (protocol->encoded_data[5] & 0xE0) >> 5;
|
||||
protocol->data[7] = (uint8_t)card;
|
||||
protocol->data[6] = (uint8_t)(card >>= 8);
|
||||
protocol->data[5] = (uint8_t)(card >>= 8);
|
||||
protocol->data[4] = (uint8_t)(card >>= 8);
|
||||
}
|
||||
|
||||
static bool protocol_gallagher_can_be_decoded(ProtocolGallagher* protocol) {
|
||||
// check 16 bits preamble
|
||||
if(bit_lib_get_bits_16(protocol->encoded_data, 0, 16) != 0b0111111111101010) return false;
|
||||
|
||||
// check next 16 bits preamble
|
||||
if(bit_lib_get_bits_16(protocol->encoded_data, 96, 16) != 0b0111111111101010) return false;
|
||||
|
||||
uint8_t checksum_arr[8] = {0};
|
||||
for(int i = 0, pos = 0; i < 8; i++) {
|
||||
// Following the preamble, every 9th bit is a checksum-bit for the preceding byte
|
||||
pos = 16 + (9 * i);
|
||||
checksum_arr[i] = bit_lib_get_bits(protocol->encoded_data, pos, 8);
|
||||
}
|
||||
uint8_t crc = bit_lib_get_bits(protocol->encoded_data, 16 + (9 * 8), 8);
|
||||
uint8_t calc_crc = bit_lib_crc8(checksum_arr, 8, 0x7, 0x2c, false, false, 0x00);
|
||||
|
||||
// crc
|
||||
if(crc != calc_crc) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void protocol_gallagher_decoder_start(ProtocolGallagher* protocol) {
|
||||
memset(protocol->encoded_data, 0, GALLAGHER_ENCODED_BYTE_FULL_SIZE);
|
||||
manchester_advance(
|
||||
protocol->decoder_manchester_state,
|
||||
ManchesterEventReset,
|
||||
&protocol->decoder_manchester_state,
|
||||
NULL);
|
||||
};
|
||||
|
||||
bool protocol_gallagher_decoder_feed(ProtocolGallagher* protocol, bool level, uint32_t duration) {
|
||||
bool result = false;
|
||||
|
||||
ManchesterEvent event = ManchesterEventReset;
|
||||
|
||||
if(duration > GALLAGHER_READ_SHORT_TIME_LOW && duration < GALLAGHER_READ_SHORT_TIME_HIGH) {
|
||||
if(!level) {
|
||||
event = ManchesterEventShortHigh;
|
||||
} else {
|
||||
event = ManchesterEventShortLow;
|
||||
}
|
||||
} else if(duration > GALLAGHER_READ_LONG_TIME_LOW && duration < GALLAGHER_READ_LONG_TIME_HIGH) {
|
||||
if(!level) {
|
||||
event = ManchesterEventLongHigh;
|
||||
} else {
|
||||
event = ManchesterEventLongLow;
|
||||
}
|
||||
}
|
||||
|
||||
if(event != ManchesterEventReset) {
|
||||
bool data;
|
||||
bool data_ok = manchester_advance(
|
||||
protocol->decoder_manchester_state, event, &protocol->decoder_manchester_state, &data);
|
||||
|
||||
if(data_ok) {
|
||||
bit_lib_push_bit(protocol->encoded_data, GALLAGHER_ENCODED_BYTE_FULL_SIZE, data);
|
||||
|
||||
if(protocol_gallagher_can_be_decoded(protocol)) {
|
||||
protocol_gallagher_decode(protocol);
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
bool protocol_gallagher_encoder_start(ProtocolGallagher* protocol) {
|
||||
// Preamble
|
||||
bit_lib_set_bits(protocol->encoded_data, 0, 0b01111111, 8);
|
||||
bit_lib_set_bits(protocol->encoded_data, 8, 0b11101010, 8);
|
||||
|
||||
uint8_t rc = bit_lib_get_bits(protocol->data, 0, 4);
|
||||
uint8_t il = bit_lib_get_bits(protocol->data, 4, 4);
|
||||
uint32_t fc = bit_lib_get_bits_32(protocol->data, 8, 24);
|
||||
uint32_t cn = bit_lib_get_bits_32(protocol->data, 32, 32);
|
||||
|
||||
uint8_t payload[8] = {0};
|
||||
payload[0] = (cn & 0xffffff) >> 16;
|
||||
payload[1] = (fc & 0xfff) >> 4;
|
||||
payload[2] = (cn & 0x7ff) >> 3;
|
||||
payload[3] = (cn & 0x7) << 5 | (rc & 0xf) << 1;
|
||||
payload[4] = (cn & 0xffff) >> 11;
|
||||
payload[5] = (fc & 0xffff) >> 12;
|
||||
payload[6] = 0;
|
||||
payload[7] = (fc & 0xf) << 4 | (il & 0xf);
|
||||
|
||||
// Gallagher scramble
|
||||
protocol_gallagher_scramble(payload, 8);
|
||||
|
||||
for(int i = 0; i < 8; i++) {
|
||||
// data byte
|
||||
bit_lib_set_bits(protocol->encoded_data, 16 + (i * 9), payload[i], 8);
|
||||
|
||||
// every byte is followed by a bit which is the inverse of the last bit
|
||||
bit_lib_set_bit(protocol->encoded_data, 16 + (i * 9) + 8, !(payload[i] & 0x1));
|
||||
}
|
||||
|
||||
// checksum
|
||||
uint8_t crc = bit_lib_crc8(payload, 8, 0x7, 0x2c, false, false, 0x00);
|
||||
bit_lib_set_bits(protocol->encoded_data, 16 + (9 * 8), crc, 8);
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
LevelDuration protocol_gallagher_encoder_yield(ProtocolGallagher* protocol) {
|
||||
bool level = bit_lib_get_bit(protocol->encoded_data, protocol->encoded_data_index);
|
||||
uint32_t duration = GALLAGHER_CLOCK_PER_BIT / 2;
|
||||
|
||||
if(protocol->encoded_polarity) {
|
||||
protocol->encoded_polarity = false;
|
||||
} else {
|
||||
level = !level;
|
||||
|
||||
protocol->encoded_polarity = true;
|
||||
bit_lib_increment_index(protocol->encoded_data_index, GALLAGHER_ENCODED_BIT_SIZE);
|
||||
}
|
||||
|
||||
return level_duration_make(level, duration);
|
||||
};
|
||||
|
||||
bool protocol_gallagher_write_data(ProtocolGallagher* protocol, void* data) {
|
||||
LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data;
|
||||
bool result = false;
|
||||
|
||||
protocol_gallagher_encoder_start(protocol);
|
||||
|
||||
if(request->write_type == LFRFIDWriteTypeT5577) {
|
||||
request->t5577.block[0] =
|
||||
(LFRFID_T5577_MODULATION_MANCHESTER | LFRFID_T5577_BITRATE_RF_32 |
|
||||
(3 << LFRFID_T5577_MAXBLOCK_SHIFT));
|
||||
request->t5577.block[1] = bit_lib_get_bits_32(protocol->encoded_data, 0, 32);
|
||||
request->t5577.block[2] = bit_lib_get_bits_32(protocol->encoded_data, 32, 32);
|
||||
request->t5577.block[3] = bit_lib_get_bits_32(protocol->encoded_data, 64, 32);
|
||||
request->t5577.blocks_to_write = 4;
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
void protocol_gallagher_render_data(ProtocolGallagher* protocol, string_t result) {
|
||||
UNUSED(protocol);
|
||||
uint8_t rc = bit_lib_get_bits(protocol->data, 0, 4);
|
||||
uint8_t il = bit_lib_get_bits(protocol->data, 4, 4);
|
||||
uint32_t fc = bit_lib_get_bits_32(protocol->data, 8, 24);
|
||||
uint32_t card_id = bit_lib_get_bits_32(protocol->data, 32, 32);
|
||||
|
||||
string_cat_printf(result, "Region: %u, Issue Level: %u\r\n", rc, il);
|
||||
string_cat_printf(result, "FC: %u, C: %lu\r\n", fc, card_id);
|
||||
};
|
||||
|
||||
const ProtocolBase protocol_gallagher = {
|
||||
.name = "Gallagher",
|
||||
.manufacturer = "Gallagher",
|
||||
.data_size = GALLAGHER_DECODED_DATA_SIZE,
|
||||
.features = LFRFIDFeatureASK,
|
||||
.validate_count = 3,
|
||||
.alloc = (ProtocolAlloc)protocol_gallagher_alloc,
|
||||
.free = (ProtocolFree)protocol_gallagher_free,
|
||||
.get_data = (ProtocolGetData)protocol_gallagher_get_data,
|
||||
.decoder =
|
||||
{
|
||||
.start = (ProtocolDecoderStart)protocol_gallagher_decoder_start,
|
||||
.feed = (ProtocolDecoderFeed)protocol_gallagher_decoder_feed,
|
||||
},
|
||||
.encoder =
|
||||
{
|
||||
.start = (ProtocolEncoderStart)protocol_gallagher_encoder_start,
|
||||
.yield = (ProtocolEncoderYield)protocol_gallagher_encoder_yield,
|
||||
},
|
||||
.render_data = (ProtocolRenderData)protocol_gallagher_render_data,
|
||||
.render_brief_data = (ProtocolRenderData)protocol_gallagher_render_data,
|
||||
.write_data = (ProtocolWriteData)protocol_gallagher_write_data,
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
#include <toolbox/protocols/protocol.h>
|
||||
|
||||
extern const ProtocolBase protocol_gallagher;
|
||||
@@ -0,0 +1,264 @@
|
||||
#include <furi.h>
|
||||
#include <toolbox/protocols/protocol.h>
|
||||
#include <lfrfid/tools/bit_lib.h>
|
||||
#include "lfrfid_protocols.h"
|
||||
|
||||
#define KERI_PREAMBLE_BIT_SIZE (33)
|
||||
#define KERI_PREAMBLE_DATA_SIZE (5)
|
||||
|
||||
#define KERI_ENCODED_BIT_SIZE (64)
|
||||
#define KERI_ENCODED_DATA_SIZE (((KERI_ENCODED_BIT_SIZE) / 8) + KERI_PREAMBLE_DATA_SIZE)
|
||||
#define KERI_ENCODED_DATA_LAST ((KERI_ENCODED_BIT_SIZE) / 8)
|
||||
|
||||
#define KERI_DECODED_BIT_SIZE (28)
|
||||
#define KERI_DECODED_DATA_SIZE (4)
|
||||
|
||||
#define KERI_US_PER_BIT (255)
|
||||
#define KERI_ENCODER_PULSES_PER_BIT (16)
|
||||
|
||||
typedef struct {
|
||||
uint8_t data_index;
|
||||
uint8_t bit_clock_index;
|
||||
bool last_bit;
|
||||
bool current_polarity;
|
||||
bool pulse_phase;
|
||||
} ProtocolKeriEncoder;
|
||||
|
||||
typedef struct {
|
||||
uint8_t encoded_data[KERI_ENCODED_DATA_SIZE];
|
||||
uint8_t negative_encoded_data[KERI_ENCODED_DATA_SIZE];
|
||||
uint8_t corrupted_encoded_data[KERI_ENCODED_DATA_SIZE];
|
||||
uint8_t corrupted_negative_encoded_data[KERI_ENCODED_DATA_SIZE];
|
||||
|
||||
uint8_t data[KERI_DECODED_DATA_SIZE];
|
||||
ProtocolKeriEncoder encoder;
|
||||
} ProtocolKeri;
|
||||
|
||||
ProtocolKeri* protocol_keri_alloc(void) {
|
||||
ProtocolKeri* protocol = malloc(sizeof(ProtocolKeri));
|
||||
return protocol;
|
||||
};
|
||||
|
||||
void protocol_keri_free(ProtocolKeri* protocol) {
|
||||
free(protocol);
|
||||
};
|
||||
|
||||
uint8_t* protocol_keri_get_data(ProtocolKeri* protocol) {
|
||||
return protocol->data;
|
||||
};
|
||||
|
||||
void protocol_keri_decoder_start(ProtocolKeri* protocol) {
|
||||
memset(protocol->encoded_data, 0, KERI_ENCODED_DATA_SIZE);
|
||||
memset(protocol->negative_encoded_data, 0, KERI_ENCODED_DATA_SIZE);
|
||||
memset(protocol->corrupted_encoded_data, 0, KERI_ENCODED_DATA_SIZE);
|
||||
memset(protocol->corrupted_negative_encoded_data, 0, KERI_ENCODED_DATA_SIZE);
|
||||
};
|
||||
|
||||
static bool protocol_keri_check_preamble(uint8_t* data, size_t bit_index) {
|
||||
// Preamble 11100000 00000000 00000000 00000000 1
|
||||
if(*(uint32_t*)&data[bit_index / 8] != 0b00000000000000000000000011100000) return false;
|
||||
if(bit_lib_get_bit(data, bit_index + 32) != 1) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool protocol_keri_can_be_decoded(uint8_t* data) {
|
||||
if(!protocol_keri_check_preamble(data, 0)) return false;
|
||||
if(!protocol_keri_check_preamble(data, 64)) return false;
|
||||
///if(bit_lib_get_bit(data, 61) != 0) return false;
|
||||
//if(bit_lib_get_bit(data, 60) != 0) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool protocol_keri_decoder_feed_internal(bool polarity, uint32_t time, uint8_t* data) {
|
||||
time += (KERI_US_PER_BIT / 2);
|
||||
|
||||
size_t bit_count = (time / KERI_US_PER_BIT);
|
||||
bool result = false;
|
||||
|
||||
if(bit_count < KERI_ENCODED_BIT_SIZE) {
|
||||
for(size_t i = 0; i < bit_count; i++) {
|
||||
bit_lib_push_bit(data, KERI_ENCODED_DATA_SIZE, polarity);
|
||||
if(protocol_keri_can_be_decoded(data)) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void protocol_keri_descramble(uint32_t* fc, uint32_t* cn, uint32_t* internal_id) {
|
||||
const uint8_t card_to_id[] = {255, 255, 255, 255, 13, 12, 20, 5, 16, 6, 21,
|
||||
17, 8, 255, 0, 7, 10, 15, 255, 11, 4, 1,
|
||||
255, 18, 255, 19, 2, 14, 3, 9, 255, 255};
|
||||
|
||||
const uint8_t card_to_fc[] = {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 0, 255, 255, 255, 255, 2, 255, 255, 255,
|
||||
3, 255, 4, 255, 255, 255, 255, 255, 1, 255};
|
||||
|
||||
*fc = 0;
|
||||
*cn = 0;
|
||||
for(uint8_t card_idx = 0; card_idx < 32; card_idx++) {
|
||||
bool bit = (*internal_id >> card_idx) & 1;
|
||||
// Card ID
|
||||
if(card_to_id[card_idx] < 32) {
|
||||
*cn = *cn | (bit << card_to_id[card_idx]);
|
||||
}
|
||||
// Card FC
|
||||
if(card_to_fc[card_idx] < 32) {
|
||||
*fc = *fc | (bit << card_to_fc[card_idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void protocol_keri_decoder_save(uint8_t* data_to, const uint8_t* data_from) {
|
||||
uint32_t id = bit_lib_get_bits_32(data_from, 32, 32);
|
||||
data_to[3] = (uint8_t)id;
|
||||
data_to[2] = (uint8_t)(id >>= 8);
|
||||
data_to[1] = (uint8_t)(id >>= 8);
|
||||
data_to[0] = (uint8_t)(id >>= 8);
|
||||
}
|
||||
|
||||
bool protocol_keri_decoder_feed(ProtocolKeri* protocol, bool level, uint32_t duration) {
|
||||
bool result = false;
|
||||
|
||||
if(duration > (KERI_US_PER_BIT / 2)) {
|
||||
if(protocol_keri_decoder_feed_internal(level, duration, protocol->encoded_data)) {
|
||||
protocol_keri_decoder_save(protocol->data, protocol->encoded_data);
|
||||
result = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
if(protocol_keri_decoder_feed_internal(!level, duration, protocol->negative_encoded_data)) {
|
||||
protocol_keri_decoder_save(protocol->data, protocol->negative_encoded_data);
|
||||
result = true;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if(duration > (KERI_US_PER_BIT / 4)) {
|
||||
// Try to decode wrong phase synced data
|
||||
if(level) {
|
||||
duration += 120;
|
||||
} else {
|
||||
if(duration > 120) {
|
||||
duration -= 120;
|
||||
}
|
||||
}
|
||||
|
||||
if(protocol_keri_decoder_feed_internal(level, duration, protocol->corrupted_encoded_data)) {
|
||||
protocol_keri_decoder_save(protocol->data, protocol->corrupted_encoded_data);
|
||||
|
||||
result = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
if(protocol_keri_decoder_feed_internal(
|
||||
!level, duration, protocol->corrupted_negative_encoded_data)) {
|
||||
protocol_keri_decoder_save(protocol->data, protocol->corrupted_negative_encoded_data);
|
||||
|
||||
result = true;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
bool protocol_keri_encoder_start(ProtocolKeri* protocol) {
|
||||
memset(protocol->encoded_data, 0, KERI_ENCODED_DATA_SIZE);
|
||||
*(uint32_t*)&protocol->encoded_data[0] = 0b00000000000000000000000011100000;
|
||||
bit_lib_copy_bits(protocol->encoded_data, 32, 32, protocol->data, 0);
|
||||
|
||||
protocol->encoder.last_bit =
|
||||
bit_lib_get_bit(protocol->encoded_data, KERI_ENCODED_BIT_SIZE - 1);
|
||||
protocol->encoder.data_index = 0;
|
||||
protocol->encoder.current_polarity = true;
|
||||
protocol->encoder.pulse_phase = true;
|
||||
protocol->encoder.bit_clock_index = 0;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
LevelDuration protocol_keri_encoder_yield(ProtocolKeri* protocol) {
|
||||
LevelDuration level_duration;
|
||||
ProtocolKeriEncoder* encoder = &protocol->encoder;
|
||||
|
||||
if(encoder->pulse_phase) {
|
||||
level_duration = level_duration_make(encoder->current_polarity, 1);
|
||||
encoder->pulse_phase = false;
|
||||
} else {
|
||||
level_duration = level_duration_make(!encoder->current_polarity, 1);
|
||||
encoder->pulse_phase = true;
|
||||
|
||||
encoder->bit_clock_index++;
|
||||
if(encoder->bit_clock_index >= KERI_ENCODER_PULSES_PER_BIT) {
|
||||
encoder->bit_clock_index = 0;
|
||||
|
||||
bool current_bit = bit_lib_get_bit(protocol->encoded_data, encoder->data_index);
|
||||
|
||||
if(current_bit != encoder->last_bit) {
|
||||
encoder->current_polarity = !encoder->current_polarity;
|
||||
}
|
||||
|
||||
encoder->last_bit = current_bit;
|
||||
|
||||
bit_lib_increment_index(encoder->data_index, KERI_ENCODED_BIT_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
return level_duration;
|
||||
};
|
||||
|
||||
void protocol_keri_render_data(ProtocolKeri* protocol, string_t result) {
|
||||
uint32_t data = bit_lib_get_bits_32(protocol->data, 0, 32);
|
||||
uint32_t internal_id = data & 0x7FFFFFFF;
|
||||
uint32_t fc = 0;
|
||||
uint32_t cn = 0;
|
||||
protocol_keri_descramble(&fc, &cn, &data);
|
||||
string_printf(result, "Internal ID: %u\r\nFC: %u, Card: %u\r\n", internal_id, fc, cn);
|
||||
}
|
||||
|
||||
bool protocol_keri_write_data(ProtocolKeri* protocol, void* data) {
|
||||
LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data;
|
||||
bool result = false;
|
||||
|
||||
protocol_keri_encoder_start(protocol);
|
||||
|
||||
if(request->write_type == LFRFIDWriteTypeT5577) {
|
||||
request->t5577.block[0] = LFRFID_T5577_TESTMODE_DISABLED | LFRFID_T5577_X_MODE |
|
||||
LFRFID_T5577_MODULATION_PSK1 | LFRFID_T5577_PSKCF_RF_2 |
|
||||
(2 << LFRFID_T5577_MAXBLOCK_SHIFT);
|
||||
request->t5577.block[0] |= 0xF << 18;
|
||||
request->t5577.block[1] = bit_lib_get_bits_32(protocol->encoded_data, 0, 32);
|
||||
request->t5577.block[2] = bit_lib_get_bits_32(protocol->encoded_data, 32, 32);
|
||||
request->t5577.blocks_to_write = 3;
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
const ProtocolBase protocol_keri = {
|
||||
.name = "Keri",
|
||||
.manufacturer = "Keri",
|
||||
.data_size = KERI_DECODED_DATA_SIZE,
|
||||
.features = LFRFIDFeaturePSK,
|
||||
.validate_count = 6,
|
||||
.alloc = (ProtocolAlloc)protocol_keri_alloc,
|
||||
.free = (ProtocolFree)protocol_keri_free,
|
||||
.get_data = (ProtocolGetData)protocol_keri_get_data,
|
||||
.decoder =
|
||||
{
|
||||
.start = (ProtocolDecoderStart)protocol_keri_decoder_start,
|
||||
.feed = (ProtocolDecoderFeed)protocol_keri_decoder_feed,
|
||||
},
|
||||
.encoder =
|
||||
{
|
||||
.start = (ProtocolEncoderStart)protocol_keri_encoder_start,
|
||||
.yield = (ProtocolEncoderYield)protocol_keri_encoder_yield,
|
||||
},
|
||||
.render_data = (ProtocolRenderData)protocol_keri_render_data,
|
||||
.render_brief_data = (ProtocolRenderData)protocol_keri_render_data,
|
||||
.write_data = (ProtocolWriteData)protocol_keri_write_data,
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
#include <toolbox/protocols/protocol.h>
|
||||
|
||||
extern const ProtocolBase protocol_keri;
|
||||
@@ -13,6 +13,9 @@
|
||||
*/
|
||||
|
||||
#define TAG "SubGhzProtocolCAME"
|
||||
#define CAME_24_COUNT_BIT 24
|
||||
#define PRASTEL_COUNT_BIT 25
|
||||
#define PRASTEL_NAME "Prastel"
|
||||
|
||||
static const SubGhzBlockConst subghz_protocol_came_const = {
|
||||
.te_short = 320,
|
||||
@@ -114,9 +117,9 @@ static bool subghz_protocol_encoder_came_get_upload(SubGhzProtocolEncoderCame* i
|
||||
//Send header
|
||||
instance->encoder.upload[index++] = level_duration_make(
|
||||
false,
|
||||
((instance->generic.data_count_bit == subghz_protocol_came_const.min_count_bit_for_found) ?
|
||||
(uint32_t)subghz_protocol_came_const.te_short * 39 :
|
||||
(uint32_t)subghz_protocol_came_const.te_short * 76));
|
||||
((instance->generic.data_count_bit == CAME_24_COUNT_BIT) ?
|
||||
(uint32_t)subghz_protocol_came_const.te_short * 76 :
|
||||
(uint32_t)subghz_protocol_came_const.te_short * 39));
|
||||
//Send start bit
|
||||
instance->encoder.upload[index++] =
|
||||
level_duration_make(true, (uint32_t)subghz_protocol_came_const.te_short);
|
||||
@@ -150,8 +153,8 @@ bool subghz_protocol_encoder_came_deserialize(void* context, FlipperFormat* flip
|
||||
}
|
||||
if((instance->generic.data_count_bit !=
|
||||
subghz_protocol_came_const.min_count_bit_for_found) &&
|
||||
(instance->generic.data_count_bit !=
|
||||
2 * subghz_protocol_came_const.min_count_bit_for_found)) {
|
||||
(instance->generic.data_count_bit != CAME_24_COUNT_BIT) &&
|
||||
(instance->generic.data_count_bit != PRASTEL_COUNT_BIT)) {
|
||||
FURI_LOG_E(TAG, "Wrong number of bits in key");
|
||||
break;
|
||||
}
|
||||
@@ -309,8 +312,8 @@ bool subghz_protocol_decoder_came_deserialize(void* context, FlipperFormat* flip
|
||||
}
|
||||
if((instance->generic.data_count_bit !=
|
||||
subghz_protocol_came_const.min_count_bit_for_found) &&
|
||||
(instance->generic.data_count_bit !=
|
||||
2 * subghz_protocol_came_const.min_count_bit_for_found)) {
|
||||
(instance->generic.data_count_bit != CAME_24_COUNT_BIT) &&
|
||||
(instance->generic.data_count_bit != PRASTEL_COUNT_BIT)) {
|
||||
FURI_LOG_E(TAG, "Wrong number of bits in key");
|
||||
break;
|
||||
}
|
||||
@@ -335,7 +338,8 @@ void subghz_protocol_decoder_came_get_string(void* context, string_t output) {
|
||||
"%s %dbit\r\n"
|
||||
"Key:0x%08lX\r\n"
|
||||
"Yek:0x%08lX\r\n",
|
||||
instance->generic.protocol_name,
|
||||
(instance->generic.data_count_bit == PRASTEL_COUNT_BIT ? PRASTEL_NAME :
|
||||
instance->generic.protocol_name),
|
||||
instance->generic.data_count_bit,
|
||||
code_found_lo,
|
||||
code_found_reverse_lo);
|
||||
|
||||
@@ -0,0 +1,472 @@
|
||||
#include "intertechno_v3.h"
|
||||
|
||||
#include "../blocks/const.h"
|
||||
#include "../blocks/decoder.h"
|
||||
#include "../blocks/encoder.h"
|
||||
#include "../blocks/generic.h"
|
||||
#include "../blocks/math.h"
|
||||
|
||||
#define TAG "SubGhzProtocolIntertechnoV3"
|
||||
|
||||
#define CH_PATTERN "%c%c%c%c"
|
||||
#define CNT_TO_CH(ch) \
|
||||
(ch & 0x8 ? '1' : '0'), (ch & 0x4 ? '1' : '0'), (ch & 0x2 ? '1' : '0'), (ch & 0x1 ? '1' : '0')
|
||||
|
||||
#define INTERTECHNO_V3_DIMMING_COUNT_BIT 36
|
||||
|
||||
static const SubGhzBlockConst subghz_protocol_intertechno_v3_const = {
|
||||
.te_short = 275,
|
||||
.te_long = 1375,
|
||||
.te_delta = 150,
|
||||
.min_count_bit_for_found = 32,
|
||||
};
|
||||
|
||||
struct SubGhzProtocolDecoderIntertechno_V3 {
|
||||
SubGhzProtocolDecoderBase base;
|
||||
|
||||
SubGhzBlockDecoder decoder;
|
||||
SubGhzBlockGeneric generic;
|
||||
};
|
||||
|
||||
struct SubGhzProtocolEncoderIntertechno_V3 {
|
||||
SubGhzProtocolEncoderBase base;
|
||||
|
||||
SubGhzProtocolBlockEncoder encoder;
|
||||
SubGhzBlockGeneric generic;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
IntertechnoV3DecoderStepReset = 0,
|
||||
IntertechnoV3DecoderStepStartSync,
|
||||
IntertechnoV3DecoderStepFoundSync,
|
||||
IntertechnoV3DecoderStepStartDuration,
|
||||
IntertechnoV3DecoderStepSaveDuration,
|
||||
IntertechnoV3DecoderStepCheckDuration,
|
||||
IntertechnoV3DecoderStepEndDuration,
|
||||
} IntertechnoV3DecoderStep;
|
||||
|
||||
const SubGhzProtocolDecoder subghz_protocol_intertechno_v3_decoder = {
|
||||
.alloc = subghz_protocol_decoder_intertechno_v3_alloc,
|
||||
.free = subghz_protocol_decoder_intertechno_v3_free,
|
||||
|
||||
.feed = subghz_protocol_decoder_intertechno_v3_feed,
|
||||
.reset = subghz_protocol_decoder_intertechno_v3_reset,
|
||||
|
||||
.get_hash_data = subghz_protocol_decoder_intertechno_v3_get_hash_data,
|
||||
.serialize = subghz_protocol_decoder_intertechno_v3_serialize,
|
||||
.deserialize = subghz_protocol_decoder_intertechno_v3_deserialize,
|
||||
.get_string = subghz_protocol_decoder_intertechno_v3_get_string,
|
||||
};
|
||||
|
||||
const SubGhzProtocolEncoder subghz_protocol_intertechno_v3_encoder = {
|
||||
.alloc = subghz_protocol_encoder_intertechno_v3_alloc,
|
||||
.free = subghz_protocol_encoder_intertechno_v3_free,
|
||||
|
||||
.deserialize = subghz_protocol_encoder_intertechno_v3_deserialize,
|
||||
.stop = subghz_protocol_encoder_intertechno_v3_stop,
|
||||
.yield = subghz_protocol_encoder_intertechno_v3_yield,
|
||||
};
|
||||
|
||||
const SubGhzProtocol subghz_protocol_intertechno_v3 = {
|
||||
.name = SUBGHZ_PROTOCOL_INTERTECHNO_V3_NAME,
|
||||
.type = SubGhzProtocolTypeStatic,
|
||||
.flag = SubGhzProtocolFlag_433 | SubGhzProtocolFlag_315 | SubGhzProtocolFlag_868 |
|
||||
SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | SubGhzProtocolFlag_Load |
|
||||
SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send,
|
||||
|
||||
.decoder = &subghz_protocol_intertechno_v3_decoder,
|
||||
.encoder = &subghz_protocol_intertechno_v3_encoder,
|
||||
};
|
||||
|
||||
void* subghz_protocol_encoder_intertechno_v3_alloc(SubGhzEnvironment* environment) {
|
||||
UNUSED(environment);
|
||||
SubGhzProtocolEncoderIntertechno_V3* instance =
|
||||
malloc(sizeof(SubGhzProtocolEncoderIntertechno_V3));
|
||||
|
||||
instance->base.protocol = &subghz_protocol_intertechno_v3;
|
||||
instance->generic.protocol_name = instance->base.protocol->name;
|
||||
|
||||
instance->encoder.repeat = 10;
|
||||
instance->encoder.size_upload = 256;
|
||||
instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration));
|
||||
instance->encoder.is_running = false;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_protocol_encoder_intertechno_v3_free(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhzProtocolEncoderIntertechno_V3* instance = context;
|
||||
free(instance->encoder.upload);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generating an upload from data.
|
||||
* @param instance Pointer to a SubGhzProtocolEncoderIntertechno_V3 instance
|
||||
* @return true On success
|
||||
*/
|
||||
static bool subghz_protocol_encoder_intertechno_v3_get_upload(
|
||||
SubGhzProtocolEncoderIntertechno_V3* instance) {
|
||||
furi_assert(instance);
|
||||
size_t index = 0;
|
||||
|
||||
//Send header
|
||||
instance->encoder.upload[index++] =
|
||||
level_duration_make(true, (uint32_t)subghz_protocol_intertechno_v3_const.te_short);
|
||||
instance->encoder.upload[index++] =
|
||||
level_duration_make(false, (uint32_t)subghz_protocol_intertechno_v3_const.te_short * 38);
|
||||
//Send sync
|
||||
instance->encoder.upload[index++] =
|
||||
level_duration_make(true, (uint32_t)subghz_protocol_intertechno_v3_const.te_short);
|
||||
instance->encoder.upload[index++] =
|
||||
level_duration_make(false, (uint32_t)subghz_protocol_intertechno_v3_const.te_short * 10);
|
||||
//Send key data
|
||||
for(uint8_t i = instance->generic.data_count_bit; i > 0; i--) {
|
||||
if((instance->generic.data_count_bit == INTERTECHNO_V3_DIMMING_COUNT_BIT) && (i == 9)) {
|
||||
//send bit dimm
|
||||
instance->encoder.upload[index++] =
|
||||
level_duration_make(true, (uint32_t)subghz_protocol_intertechno_v3_const.te_short);
|
||||
instance->encoder.upload[index++] = level_duration_make(
|
||||
false, (uint32_t)subghz_protocol_intertechno_v3_const.te_short);
|
||||
instance->encoder.upload[index++] =
|
||||
level_duration_make(true, (uint32_t)subghz_protocol_intertechno_v3_const.te_short);
|
||||
instance->encoder.upload[index++] = level_duration_make(
|
||||
false, (uint32_t)subghz_protocol_intertechno_v3_const.te_short);
|
||||
} else if(bit_read(instance->generic.data, i - 1)) {
|
||||
//send bit 1
|
||||
instance->encoder.upload[index++] =
|
||||
level_duration_make(true, (uint32_t)subghz_protocol_intertechno_v3_const.te_short);
|
||||
instance->encoder.upload[index++] =
|
||||
level_duration_make(false, (uint32_t)subghz_protocol_intertechno_v3_const.te_long);
|
||||
instance->encoder.upload[index++] =
|
||||
level_duration_make(true, (uint32_t)subghz_protocol_intertechno_v3_const.te_short);
|
||||
instance->encoder.upload[index++] = level_duration_make(
|
||||
false, (uint32_t)subghz_protocol_intertechno_v3_const.te_short);
|
||||
} else {
|
||||
//send bit 0
|
||||
instance->encoder.upload[index++] =
|
||||
level_duration_make(true, (uint32_t)subghz_protocol_intertechno_v3_const.te_short);
|
||||
instance->encoder.upload[index++] = level_duration_make(
|
||||
false, (uint32_t)subghz_protocol_intertechno_v3_const.te_short);
|
||||
instance->encoder.upload[index++] =
|
||||
level_duration_make(true, (uint32_t)subghz_protocol_intertechno_v3_const.te_short);
|
||||
instance->encoder.upload[index++] =
|
||||
level_duration_make(false, (uint32_t)subghz_protocol_intertechno_v3_const.te_long);
|
||||
}
|
||||
}
|
||||
instance->encoder.size_upload = index;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool subghz_protocol_encoder_intertechno_v3_deserialize(
|
||||
void* context,
|
||||
FlipperFormat* flipper_format) {
|
||||
furi_assert(context);
|
||||
SubGhzProtocolEncoderIntertechno_V3* instance = context;
|
||||
bool res = false;
|
||||
do {
|
||||
if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) {
|
||||
FURI_LOG_E(TAG, "Deserialize error");
|
||||
break;
|
||||
}
|
||||
if((instance->generic.data_count_bit !=
|
||||
subghz_protocol_intertechno_v3_const.min_count_bit_for_found) &&
|
||||
(instance->generic.data_count_bit != INTERTECHNO_V3_DIMMING_COUNT_BIT)) {
|
||||
FURI_LOG_E(TAG, "Wrong number of bits in key");
|
||||
break;
|
||||
}
|
||||
//optional parameter parameter
|
||||
flipper_format_read_uint32(
|
||||
flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1);
|
||||
|
||||
subghz_protocol_encoder_intertechno_v3_get_upload(instance);
|
||||
instance->encoder.is_running = true;
|
||||
|
||||
res = true;
|
||||
} while(false);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void subghz_protocol_encoder_intertechno_v3_stop(void* context) {
|
||||
SubGhzProtocolEncoderIntertechno_V3* instance = context;
|
||||
instance->encoder.is_running = false;
|
||||
}
|
||||
|
||||
LevelDuration subghz_protocol_encoder_intertechno_v3_yield(void* context) {
|
||||
SubGhzProtocolEncoderIntertechno_V3* instance = context;
|
||||
|
||||
if(instance->encoder.repeat == 0 || !instance->encoder.is_running) {
|
||||
instance->encoder.is_running = false;
|
||||
return level_duration_reset();
|
||||
}
|
||||
|
||||
LevelDuration ret = instance->encoder.upload[instance->encoder.front];
|
||||
|
||||
if(++instance->encoder.front == instance->encoder.size_upload) {
|
||||
instance->encoder.repeat--;
|
||||
instance->encoder.front = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void* subghz_protocol_decoder_intertechno_v3_alloc(SubGhzEnvironment* environment) {
|
||||
UNUSED(environment);
|
||||
SubGhzProtocolDecoderIntertechno_V3* instance =
|
||||
malloc(sizeof(SubGhzProtocolDecoderIntertechno_V3));
|
||||
instance->base.protocol = &subghz_protocol_intertechno_v3;
|
||||
instance->generic.protocol_name = instance->base.protocol->name;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void subghz_protocol_decoder_intertechno_v3_free(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhzProtocolDecoderIntertechno_V3* instance = context;
|
||||
free(instance);
|
||||
}
|
||||
|
||||
void subghz_protocol_decoder_intertechno_v3_reset(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhzProtocolDecoderIntertechno_V3* instance = context;
|
||||
instance->decoder.parser_step = IntertechnoV3DecoderStepReset;
|
||||
}
|
||||
|
||||
void subghz_protocol_decoder_intertechno_v3_feed(void* context, bool level, uint32_t duration) {
|
||||
furi_assert(context);
|
||||
SubGhzProtocolDecoderIntertechno_V3* instance = context;
|
||||
switch(instance->decoder.parser_step) {
|
||||
case IntertechnoV3DecoderStepReset:
|
||||
if((!level) &&
|
||||
(DURATION_DIFF(duration, subghz_protocol_intertechno_v3_const.te_short * 37) <
|
||||
subghz_protocol_intertechno_v3_const.te_delta * 15)) {
|
||||
instance->decoder.parser_step = IntertechnoV3DecoderStepStartSync;
|
||||
}
|
||||
break;
|
||||
case IntertechnoV3DecoderStepStartSync:
|
||||
if(level && (DURATION_DIFF(duration, subghz_protocol_intertechno_v3_const.te_short) <
|
||||
subghz_protocol_intertechno_v3_const.te_delta)) {
|
||||
instance->decoder.parser_step = IntertechnoV3DecoderStepFoundSync;
|
||||
} else {
|
||||
instance->decoder.parser_step = IntertechnoV3DecoderStepReset;
|
||||
}
|
||||
break;
|
||||
|
||||
case IntertechnoV3DecoderStepFoundSync:
|
||||
if(!level && (DURATION_DIFF(duration, subghz_protocol_intertechno_v3_const.te_short * 10) <
|
||||
subghz_protocol_intertechno_v3_const.te_delta * 3)) {
|
||||
instance->decoder.parser_step = IntertechnoV3DecoderStepStartDuration;
|
||||
instance->decoder.decode_data = 0;
|
||||
instance->decoder.decode_count_bit = 0;
|
||||
} else {
|
||||
instance->decoder.parser_step = IntertechnoV3DecoderStepReset;
|
||||
}
|
||||
break;
|
||||
|
||||
case IntertechnoV3DecoderStepStartDuration:
|
||||
if(level && (DURATION_DIFF(duration, subghz_protocol_intertechno_v3_const.te_short) <
|
||||
subghz_protocol_intertechno_v3_const.te_delta)) {
|
||||
instance->decoder.parser_step = IntertechnoV3DecoderStepSaveDuration;
|
||||
} else {
|
||||
instance->decoder.parser_step = IntertechnoV3DecoderStepReset;
|
||||
}
|
||||
break;
|
||||
|
||||
case IntertechnoV3DecoderStepSaveDuration:
|
||||
if(!level) { //save interval
|
||||
if(duration >= (subghz_protocol_intertechno_v3_const.te_short * 11)) {
|
||||
instance->decoder.parser_step = IntertechnoV3DecoderStepStartSync;
|
||||
if((instance->decoder.decode_count_bit ==
|
||||
subghz_protocol_intertechno_v3_const.min_count_bit_for_found) ||
|
||||
(instance->decoder.decode_count_bit == INTERTECHNO_V3_DIMMING_COUNT_BIT)) {
|
||||
instance->generic.data = instance->decoder.decode_data;
|
||||
instance->generic.data_count_bit = instance->decoder.decode_count_bit;
|
||||
|
||||
if(instance->base.callback)
|
||||
instance->base.callback(&instance->base, instance->base.context);
|
||||
}
|
||||
break;
|
||||
}
|
||||
instance->decoder.te_last = duration;
|
||||
instance->decoder.parser_step = IntertechnoV3DecoderStepCheckDuration;
|
||||
} else {
|
||||
instance->decoder.parser_step = IntertechnoV3DecoderStepReset;
|
||||
}
|
||||
break;
|
||||
case IntertechnoV3DecoderStepCheckDuration:
|
||||
if(level) {
|
||||
//Add 0 bit
|
||||
if((DURATION_DIFF(
|
||||
instance->decoder.te_last, subghz_protocol_intertechno_v3_const.te_short) <
|
||||
subghz_protocol_intertechno_v3_const.te_delta) &&
|
||||
(DURATION_DIFF(duration, subghz_protocol_intertechno_v3_const.te_short) <
|
||||
subghz_protocol_intertechno_v3_const.te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(&instance->decoder, 0);
|
||||
instance->decoder.parser_step = IntertechnoV3DecoderStepEndDuration;
|
||||
} else if(
|
||||
//Add 1 bit
|
||||
(DURATION_DIFF(
|
||||
instance->decoder.te_last, subghz_protocol_intertechno_v3_const.te_long) <
|
||||
subghz_protocol_intertechno_v3_const.te_delta * 2) &&
|
||||
(DURATION_DIFF(duration, subghz_protocol_intertechno_v3_const.te_short) <
|
||||
subghz_protocol_intertechno_v3_const.te_delta)) {
|
||||
subghz_protocol_blocks_add_bit(&instance->decoder, 1);
|
||||
instance->decoder.parser_step = IntertechnoV3DecoderStepEndDuration;
|
||||
|
||||
} else if(
|
||||
//Add dimm_state
|
||||
(DURATION_DIFF(
|
||||
instance->decoder.te_last, subghz_protocol_intertechno_v3_const.te_short) <
|
||||
subghz_protocol_intertechno_v3_const.te_delta * 2) &&
|
||||
(DURATION_DIFF(duration, subghz_protocol_intertechno_v3_const.te_short) <
|
||||
subghz_protocol_intertechno_v3_const.te_delta) &&
|
||||
(instance->decoder.decode_count_bit == 27)) {
|
||||
subghz_protocol_blocks_add_bit(&instance->decoder, 0);
|
||||
instance->decoder.parser_step = IntertechnoV3DecoderStepEndDuration;
|
||||
|
||||
} else
|
||||
instance->decoder.parser_step = IntertechnoV3DecoderStepReset;
|
||||
} else {
|
||||
instance->decoder.parser_step = IntertechnoV3DecoderStepReset;
|
||||
}
|
||||
break;
|
||||
|
||||
case IntertechnoV3DecoderStepEndDuration:
|
||||
if(!level && ((DURATION_DIFF(duration, subghz_protocol_intertechno_v3_const.te_short) <
|
||||
subghz_protocol_intertechno_v3_const.te_delta) ||
|
||||
(DURATION_DIFF(duration, subghz_protocol_intertechno_v3_const.te_long) <
|
||||
subghz_protocol_intertechno_v3_const.te_delta * 2))) {
|
||||
instance->decoder.parser_step = IntertechnoV3DecoderStepStartDuration;
|
||||
} else {
|
||||
instance->decoder.parser_step = IntertechnoV3DecoderStepReset;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Analysis of received data
|
||||
* @param instance Pointer to a SubGhzBlockGeneric* instance
|
||||
*/
|
||||
static void subghz_protocol_intertechno_v3_check_remote_controller(SubGhzBlockGeneric* instance) {
|
||||
/*
|
||||
* A frame is either 32 or 36 bits:
|
||||
*
|
||||
* _
|
||||
* start bit: | |__________ (T,10T)
|
||||
* _ _
|
||||
* '0': | |_| |_____ (T,T,T,5T)
|
||||
* _ _
|
||||
* '1': | |_____| |_ (T,5T,T,T)
|
||||
* _ _
|
||||
* dimm: | |_| |_ (T,T,T,T)
|
||||
*
|
||||
* _
|
||||
* stop bit: | |____...____ (T,38T)
|
||||
*
|
||||
* if frame 32 bits
|
||||
* SSSSSSSSSSSSSSSSSSSSSSSSSS all_ch on/off ~ch
|
||||
* Key:0x3F86C59F => 00111111100001101100010110 0 1 1111
|
||||
*
|
||||
* if frame 36 bits
|
||||
* SSSSSSSSSSSSSSSSSSSSSSSSSS all_ch dimm ~ch dimm_level
|
||||
* Key:0x42D2E8856 => 01000010110100101110100010 0 X 0101 0110
|
||||
*
|
||||
*/
|
||||
|
||||
if(instance->data_count_bit == subghz_protocol_intertechno_v3_const.min_count_bit_for_found) {
|
||||
instance->serial = (instance->data >> 6) & 0x3FFFFFF;
|
||||
if((instance->data >> 5) & 0x1) {
|
||||
instance->cnt = 1 << 5;
|
||||
} else {
|
||||
instance->cnt = (~instance->data & 0xF);
|
||||
}
|
||||
instance->btn = (instance->data >> 4) & 0x1;
|
||||
} else if(instance->data_count_bit == INTERTECHNO_V3_DIMMING_COUNT_BIT) {
|
||||
instance->serial = (instance->data >> 10) & 0x3FFFFFF;
|
||||
if((instance->data >> 9) & 0x1) {
|
||||
instance->cnt = 1 << 5;
|
||||
} else {
|
||||
instance->cnt = (~(instance->data >> 4) & 0xF);
|
||||
}
|
||||
instance->btn = (instance->data) & 0xF;
|
||||
} else {
|
||||
instance->serial = 0;
|
||||
instance->cnt = 0;
|
||||
instance->btn = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t subghz_protocol_decoder_intertechno_v3_get_hash_data(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhzProtocolDecoderIntertechno_V3* instance = context;
|
||||
return subghz_protocol_blocks_get_hash_data(
|
||||
&instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
|
||||
}
|
||||
|
||||
bool subghz_protocol_decoder_intertechno_v3_serialize(
|
||||
void* context,
|
||||
FlipperFormat* flipper_format,
|
||||
SubGhzPresetDefinition* preset) {
|
||||
furi_assert(context);
|
||||
SubGhzProtocolDecoderIntertechno_V3* instance = context;
|
||||
return subghz_block_generic_serialize(&instance->generic, flipper_format, preset);
|
||||
}
|
||||
|
||||
bool subghz_protocol_decoder_intertechno_v3_deserialize(
|
||||
void* context,
|
||||
FlipperFormat* flipper_format) {
|
||||
furi_assert(context);
|
||||
SubGhzProtocolDecoderIntertechno_V3* instance = context;
|
||||
bool ret = false;
|
||||
do {
|
||||
if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) {
|
||||
break;
|
||||
}
|
||||
if((instance->generic.data_count_bit !=
|
||||
subghz_protocol_intertechno_v3_const.min_count_bit_for_found) &&
|
||||
(instance->generic.data_count_bit != INTERTECHNO_V3_DIMMING_COUNT_BIT)) {
|
||||
FURI_LOG_E(TAG, "Wrong number of bits in key");
|
||||
break;
|
||||
}
|
||||
ret = true;
|
||||
} while(false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void subghz_protocol_decoder_intertechno_v3_get_string(void* context, string_t output) {
|
||||
furi_assert(context);
|
||||
SubGhzProtocolDecoderIntertechno_V3* instance = context;
|
||||
|
||||
subghz_protocol_intertechno_v3_check_remote_controller(&instance->generic);
|
||||
|
||||
string_cat_printf(
|
||||
output,
|
||||
"%.11s %db\r\n"
|
||||
"Key:0x%08llX\r\n"
|
||||
"Sn:%07lX\r\n",
|
||||
instance->generic.protocol_name,
|
||||
instance->generic.data_count_bit,
|
||||
instance->generic.data,
|
||||
instance->generic.serial);
|
||||
|
||||
if(instance->generic.data_count_bit ==
|
||||
subghz_protocol_intertechno_v3_const.min_count_bit_for_found) {
|
||||
if(instance->generic.cnt >> 5) {
|
||||
string_cat_printf(
|
||||
output, "Ch: All Btn:%s\r\n", (instance->generic.btn ? "On" : "Off"));
|
||||
} else {
|
||||
string_cat_printf(
|
||||
output,
|
||||
"Ch:" CH_PATTERN " Btn:%s\r\n",
|
||||
CNT_TO_CH(instance->generic.cnt),
|
||||
(instance->generic.btn ? "On" : "Off"));
|
||||
}
|
||||
} else if(instance->generic.data_count_bit == INTERTECHNO_V3_DIMMING_COUNT_BIT) {
|
||||
string_cat_printf(
|
||||
output,
|
||||
"Ch:" CH_PATTERN " Dimm:%d%%\r\n",
|
||||
CNT_TO_CH(instance->generic.cnt),
|
||||
(int)(6.67 * (float)instance->generic.btn));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
#pragma once
|
||||
|
||||
#include "base.h"
|
||||
|
||||
#define SUBGHZ_PROTOCOL_INTERTECHNO_V3_NAME "Intertechno_V3"
|
||||
|
||||
typedef struct SubGhzProtocolDecoderIntertechno_V3 SubGhzProtocolDecoderIntertechno_V3;
|
||||
typedef struct SubGhzProtocolEncoderIntertechno_V3 SubGhzProtocolEncoderIntertechno_V3;
|
||||
|
||||
extern const SubGhzProtocolDecoder subghz_protocol_intertechno_v3_decoder;
|
||||
extern const SubGhzProtocolEncoder subghz_protocol_intertechno_v3_encoder;
|
||||
extern const SubGhzProtocol subghz_protocol_intertechno_v3;
|
||||
|
||||
/**
|
||||
* Allocate SubGhzProtocolEncoderIntertechno_V3.
|
||||
* @param environment Pointer to a SubGhzEnvironment instance
|
||||
* @return SubGhzProtocolEncoderIntertechno_V3* pointer to a SubGhzProtocolEncoderIntertechno_V3 instance
|
||||
*/
|
||||
void* subghz_protocol_encoder_intertechno_v3_alloc(SubGhzEnvironment* environment);
|
||||
|
||||
/**
|
||||
* Free SubGhzProtocolEncoderIntertechno_V3.
|
||||
* @param context Pointer to a SubGhzProtocolEncoderIntertechno_V3 instance
|
||||
*/
|
||||
void subghz_protocol_encoder_intertechno_v3_free(void* context);
|
||||
|
||||
/**
|
||||
* Deserialize and generating an upload to send.
|
||||
* @param context Pointer to a SubGhzProtocolEncoderIntertechno_V3 instance
|
||||
* @param flipper_format Pointer to a FlipperFormat instance
|
||||
* @return true On success
|
||||
*/
|
||||
bool subghz_protocol_encoder_intertechno_v3_deserialize(
|
||||
void* context,
|
||||
FlipperFormat* flipper_format);
|
||||
|
||||
/**
|
||||
* Forced transmission stop.
|
||||
* @param context Pointer to a SubGhzProtocolEncoderIntertechno_V3 instance
|
||||
*/
|
||||
void subghz_protocol_encoder_intertechno_v3_stop(void* context);
|
||||
|
||||
/**
|
||||
* Getting the level and duration of the upload to be loaded into DMA.
|
||||
* @param context Pointer to a SubGhzProtocolEncoderIntertechno_V3 instance
|
||||
* @return LevelDuration
|
||||
*/
|
||||
LevelDuration subghz_protocol_encoder_intertechno_v3_yield(void* context);
|
||||
|
||||
/**
|
||||
* Allocate SubGhzProtocolDecoderIntertechno_V3.
|
||||
* @param environment Pointer to a SubGhzEnvironment instance
|
||||
* @return SubGhzProtocolDecoderIntertechno_V3* pointer to a SubGhzProtocolDecoderIntertechno_V3 instance
|
||||
*/
|
||||
void* subghz_protocol_decoder_intertechno_v3_alloc(SubGhzEnvironment* environment);
|
||||
|
||||
/**
|
||||
* Free SubGhzProtocolDecoderIntertechno_V3.
|
||||
* @param context Pointer to a SubGhzProtocolDecoderIntertechno_V3 instance
|
||||
*/
|
||||
void subghz_protocol_decoder_intertechno_v3_free(void* context);
|
||||
|
||||
/**
|
||||
* Reset decoder SubGhzProtocolDecoderIntertechno_V3.
|
||||
* @param context Pointer to a SubGhzProtocolDecoderIntertechno_V3 instance
|
||||
*/
|
||||
void subghz_protocol_decoder_intertechno_v3_reset(void* context);
|
||||
|
||||
/**
|
||||
* Parse a raw sequence of levels and durations received from the air.
|
||||
* @param context Pointer to a SubGhzProtocolDecoderIntertechno_V3 instance
|
||||
* @param level Signal level true-high false-low
|
||||
* @param duration Duration of this level in, us
|
||||
*/
|
||||
void subghz_protocol_decoder_intertechno_v3_feed(void* context, bool level, uint32_t duration);
|
||||
|
||||
/**
|
||||
* Getting the hash sum of the last randomly received parcel.
|
||||
* @param context Pointer to a SubGhzProtocolDecoderIntertechno_V3 instance
|
||||
* @return hash Hash sum
|
||||
*/
|
||||
uint8_t subghz_protocol_decoder_intertechno_v3_get_hash_data(void* context);
|
||||
|
||||
/**
|
||||
* Serialize data SubGhzProtocolDecoderIntertechno_V3.
|
||||
* @param context Pointer to a SubGhzProtocolDecoderIntertechno_V3 instance
|
||||
* @param flipper_format Pointer to a FlipperFormat instance
|
||||
* @param preset The modulation on which the signal was received, SubGhzPresetDefinition
|
||||
* @return true On success
|
||||
*/
|
||||
bool subghz_protocol_decoder_intertechno_v3_serialize(
|
||||
void* context,
|
||||
FlipperFormat* flipper_format,
|
||||
SubGhzPresetDefinition* preset);
|
||||
|
||||
/**
|
||||
* Deserialize data SubGhzProtocolDecoderIntertechno_V3.
|
||||
* @param context Pointer to a SubGhzProtocolDecoderIntertechno_V3 instance
|
||||
* @param flipper_format Pointer to a FlipperFormat instance
|
||||
* @return true On success
|
||||
*/
|
||||
bool subghz_protocol_decoder_intertechno_v3_deserialize(
|
||||
void* context,
|
||||
FlipperFormat* flipper_format);
|
||||
|
||||
/**
|
||||
* Getting a textual representation of the received data.
|
||||
* @param context Pointer to a SubGhzProtocolDecoderIntertechno_V3 instance
|
||||
* @param output Resulting text
|
||||
*/
|
||||
void subghz_protocol_decoder_intertechno_v3_get_string(void* context, string_t output);
|
||||
@@ -360,11 +360,11 @@ static void subghz_protocol_magellen_check_remote_controller(SubGhzBlockGeneric*
|
||||
* 0x1275EC => 0x12-event codes, 0x75EC-serial (dec 117236)
|
||||
*
|
||||
* event codes
|
||||
* bit_0: 1-alarm, 0-close
|
||||
* bit_0: 1-Open/Motion, 0-close/ok
|
||||
* bit_1: 1-Tamper On (alarm), 0-Tamper Off (ok)
|
||||
* bit_2: ?
|
||||
* bit_3: 1-power on
|
||||
* bit_4: model type - door alarm
|
||||
* bit_4: model type - wireless reed
|
||||
* bit_5: model type - motion sensor
|
||||
* bit_6: ?
|
||||
* bit_7: ?
|
||||
@@ -379,11 +379,12 @@ static void subghz_protocol_magellen_get_event_serialize(uint8_t event, string_t
|
||||
string_cat_printf(
|
||||
output,
|
||||
"%s%s%s%s%s%s%s%s",
|
||||
(event & 0x1 ? " Alarm" : "Ok"),
|
||||
((event >> 4) & 0x1 ? (event & 0x1 ? " Open" : " Close") :
|
||||
(event & 0x1 ? " Motion" : " Ok")),
|
||||
((event >> 1) & 0x1 ? ", Tamper On (Alarm)" : ""),
|
||||
((event >> 2) & 0x1 ? ", ?" : ""),
|
||||
((event >> 3) & 0x1 ? ", Power On" : ""),
|
||||
((event >> 4) & 0x1 ? ", MT:Door_Alarm" : ""),
|
||||
((event >> 4) & 0x1 ? ", MT:Wireless_Reed" : ""),
|
||||
((event >> 5) & 0x1 ? ", MT:Motion_Sensor" : ""),
|
||||
((event >> 6) & 0x1 ? ", ?" : ""),
|
||||
((event >> 7) & 0x1 ? ", ?" : ""));
|
||||
|
||||
@@ -11,7 +11,7 @@ const SubGhzProtocol* subghz_protocol_registry[] = {
|
||||
&subghz_protocol_secplus_v1, &subghz_protocol_megacode, &subghz_protocol_holtek,
|
||||
&subghz_protocol_chamb_code, &subghz_protocol_power_smart, &subghz_protocol_marantec,
|
||||
&subghz_protocol_bett, &subghz_protocol_doitrand, &subghz_protocol_phoenix_v2,
|
||||
&subghz_protocol_honeywell_wdb, &subghz_protocol_magellen,
|
||||
&subghz_protocol_honeywell_wdb, &subghz_protocol_magellen, &subghz_protocol_intertechno_v3,
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "phoenix_v2.h"
|
||||
#include "honeywell_wdb.h"
|
||||
#include "magellen.h"
|
||||
#include "intertechno_v3.h"
|
||||
|
||||
/**
|
||||
* Registration by name SubGhzProtocol.
|
||||
|
||||
Reference in New Issue
Block a user