1
mirror of https://github.com/DarkFlippers/unleashed-firmware.git synced 2025-12-12 12:42:30 +04:00

Merge branch 'fz-dev' into dev

This commit is contained in:
MX
2022-08-30 11:42:39 +03:00
84 changed files with 1392 additions and 47 deletions

0
applications/bad_usb/views/bad_usb_view.h Executable file → Normal file
View File

0
applications/bt/bt_debug_app/views/bt_carrier_test.c Executable file → Normal file
View File

0
applications/bt/bt_debug_app/views/bt_test.c Executable file → Normal file
View File

0
applications/bt/bt_debug_app/views/bt_test.h Executable file → Normal file
View File

0
applications/bt/bt_hid_app/views/bt_hid_keynote.c Executable file → Normal file
View File

0
applications/bt/bt_hid_app/views/bt_hid_media.c Executable file → Normal file
View File

0
applications/bt/bt_settings_app/bt_settings_app.c Executable file → Normal file
View File

0
applications/bt/bt_settings_app/bt_settings_app.h Executable file → Normal file
View File

View File

View File

0
applications/cli/cli_i.h Executable file → Normal file
View File

0
applications/gpio/views/gpio_test.c Executable file → Normal file
View File

0
applications/gpio/views/gpio_test.h Executable file → Normal file
View File

0
applications/gpio/views/gpio_usb_uart.h Executable file → Normal file
View File

0
applications/gui/canvas.h Executable file → Normal file
View File

0
applications/gui/modules/dialog_ex.c Executable file → Normal file
View File

0
applications/gui/modules/menu.h Executable file → Normal file
View File

0
applications/gui/modules/text_box.c Executable file → Normal file
View File

0
applications/gui/modules/text_box.h Executable file → Normal file
View File

0
applications/gui/modules/variable_item_list.h Executable file → Normal file
View File

0
applications/gui/modules/widget.h Executable file → Normal file
View File

View File

View File

View File

0
applications/gui/scene_manager.c Executable file → Normal file
View File

0
applications/gui/scene_manager.h Executable file → Normal file
View File

0
applications/gui/scene_manager_i.h Executable file → Normal file
View File

0
applications/gui/view_dispatcher.h Executable file → Normal file
View File

0
applications/nfc/helpers/nfc_emv_parser.c Executable file → Normal file
View File

0
applications/nfc/helpers/nfc_emv_parser.h Executable file → Normal file
View File

0
applications/nfc/nfc_cli.c Executable file → Normal file
View File

0
applications/nfc/scenes/nfc_scene.c Executable file → Normal file
View File

0
applications/nfc/scenes/nfc_scene_config.h Executable file → Normal file
View File

0
applications/nfc/scenes/nfc_scene_delete.c Executable file → Normal file
View File

0
applications/nfc/scenes/nfc_scene_delete_success.c Executable file → Normal file
View File

0
applications/nfc/scenes/nfc_scene_emulate_uid.c Executable file → Normal file
View File

0
applications/nfc/scenes/nfc_scene_file_select.c Executable file → Normal file
View File

View File

0
applications/nfc/scenes/nfc_scene_read_card_success.c Executable file → Normal file
View File

0
applications/nfc/scenes/nfc_scene_set_atqa.c Executable file → Normal file
View File

0
applications/nfc/scenes/nfc_scene_set_sak.c Executable file → Normal file
View File

0
applications/nfc/scenes/nfc_scene_set_uid.c Executable file → Normal file
View File

0
applications/picopass/picopass_worker.h Executable file → Normal file
View File

0
applications/picopass/scenes/picopass_scene.c Executable file → Normal file
View File

0
applications/picopass/scenes/picopass_scene_config.h Executable file → Normal file
View File

View File

0
applications/power/battery_test_app/battery_test_app.c Executable file → Normal file
View File

0
applications/power/power_service/power_i.h Executable file → Normal file
View File

0
applications/system/system_settings.h Executable file → Normal file
View File

View File

@@ -6,7 +6,6 @@ It is invoked by `./fbt` in the firmware project root directory. Internally, it
## Requirements ## Requirements
Please install Python packages required by assets build scripts: `pip3 install -r scripts/requirements.txt` Please install Python packages required by assets build scripts: `pip3 install -r scripts/requirements.txt`
Make sure that `gcc-arm-none-eabi` toolchain & OpenOCD executables are in system's PATH.
## NB ## NB

0
lib/ST25RFAL002/source/rfal_nfc.c Executable file → Normal file
View File

View File

@@ -356,7 +356,7 @@ bool flipper_format_stream_read_value_line(
uint8_t* data = _data; uint8_t* data = _data;
if(string_size(value) >= 2) { if(string_size(value) >= 2) {
// sscanf "%02X" does not work here // sscanf "%02X" does not work here
if(hex_chars_to_uint8( if(hex_char_to_uint8(
string_get_char(value, 0), string_get_char(value, 0),
string_get_char(value, 1), string_get_char(value, 1),
&data[i])) { &data[i])) {

View File

@@ -27,16 +27,16 @@
#define LFRFID_WORKER_READ_DROP_TIME_MS 50 #define LFRFID_WORKER_READ_DROP_TIME_MS 50
#define LFRFID_WORKER_READ_STABILIZE_TIME_MS 450 #define LFRFID_WORKER_READ_STABILIZE_TIME_MS 450
#define LFRFID_WORKER_READ_SWITCH_TIME_MS 1500 #define LFRFID_WORKER_READ_SWITCH_TIME_MS 2000
#define LFRFID_WORKER_WRITE_VERIFY_TIME_MS 1500 #define LFRFID_WORKER_WRITE_VERIFY_TIME_MS 2000
#define LFRFID_WORKER_WRITE_DROP_TIME_MS 50 #define LFRFID_WORKER_WRITE_DROP_TIME_MS 50
#define LFRFID_WORKER_WRITE_TOO_LONG_TIME_MS 10000 #define LFRFID_WORKER_WRITE_TOO_LONG_TIME_MS 10000
#define LFRFID_WORKER_WRITE_MAX_UNSUCCESSFUL_READS 5 #define LFRFID_WORKER_WRITE_MAX_UNSUCCESSFUL_READS 5
#define LFRFID_WORKER_READ_BUFFER_SIZE 512 #define LFRFID_WORKER_READ_BUFFER_SIZE 512
#define LFRFID_WORKER_READ_BUFFER_COUNT 8 #define LFRFID_WORKER_READ_BUFFER_COUNT 16
#define LFRFID_WORKER_EMULATE_BUFFER_SIZE 1024 #define LFRFID_WORKER_EMULATE_BUFFER_SIZE 1024
@@ -132,6 +132,8 @@ static LFRFIDWorkerReadState lfrfid_worker_read_internal(
#ifdef LFRFID_WORKER_READ_DEBUG_GPIO #ifdef LFRFID_WORKER_READ_DEBUG_GPIO
furi_hal_gpio_init_simple(LFRFID_WORKER_READ_DEBUG_GPIO_VALUE, GpioModeOutputPushPull); furi_hal_gpio_init_simple(LFRFID_WORKER_READ_DEBUG_GPIO_VALUE, GpioModeOutputPushPull);
furi_hal_gpio_init_simple(LFRFID_WORKER_READ_DEBUG_GPIO_LOAD, GpioModeOutputPushPull); furi_hal_gpio_init_simple(LFRFID_WORKER_READ_DEBUG_GPIO_LOAD, GpioModeOutputPushPull);
furi_hal_gpio_write(LFRFID_WORKER_READ_DEBUG_GPIO_VALUE, false);
furi_hal_gpio_write(LFRFID_WORKER_READ_DEBUG_GPIO_LOAD, false);
#endif #endif
LFRFIDWorkerReadContext ctx; LFRFIDWorkerReadContext ctx;
@@ -171,10 +173,16 @@ static LFRFIDWorkerReadState lfrfid_worker_read_internal(
if(buffer_stream_get_overrun_count(ctx.stream) > 0) { if(buffer_stream_get_overrun_count(ctx.stream) > 0) {
FURI_LOG_E(TAG, "Read overrun, recovering"); FURI_LOG_E(TAG, "Read overrun, recovering");
buffer_stream_reset(ctx.stream); buffer_stream_reset(ctx.stream);
#ifdef LFRFID_WORKER_READ_DEBUG_GPIO
furi_hal_gpio_write(LFRFID_WORKER_READ_DEBUG_GPIO_LOAD, false);
#endif
continue; continue;
} }
if(buffer == NULL) { if(buffer == NULL) {
#ifdef LFRFID_WORKER_READ_DEBUG_GPIO
furi_hal_gpio_write(LFRFID_WORKER_READ_DEBUG_GPIO_LOAD, false);
#endif
continue; continue;
} }
@@ -261,24 +269,26 @@ static LFRFIDWorkerReadState lfrfid_worker_read_internal(
last_read_count = 0; last_read_count = 0;
} }
string_t string_info; if(furi_log_get_level() >= FuriLogLevelDebug) {
string_init(string_info); string_t string_info;
for(uint8_t i = 0; i < protocol_data_size; i++) { string_init(string_info);
if(i != 0) { for(uint8_t i = 0; i < protocol_data_size; i++) {
string_cat_printf(string_info, " "); if(i != 0) {
string_cat_printf(string_info, " ");
}
string_cat_printf(string_info, "%02X", protocol_data[i]);
} }
string_cat_printf(string_info, "%02X", protocol_data[i]); FURI_LOG_D(
TAG,
"%s, %d, [%s]",
protocol_dict_get_name(worker->protocols, protocol),
last_read_count,
string_get_cstr(string_info));
string_clear(string_info);
} }
FURI_LOG_D(
TAG,
"%s, %d, [%s]",
protocol_dict_get_name(worker->protocols, protocol),
last_read_count,
string_get_cstr(string_info));
string_clear(string_info);
protocol_dict_decoders_start(worker->protocols); protocol_dict_decoders_start(worker->protocols);
} }
} }
@@ -321,6 +331,8 @@ static LFRFIDWorkerReadState lfrfid_worker_read_internal(
free(last_data); free(last_data);
#ifdef LFRFID_WORKER_READ_DEBUG_GPIO #ifdef LFRFID_WORKER_READ_DEBUG_GPIO
furi_hal_gpio_write(LFRFID_WORKER_READ_DEBUG_GPIO_VALUE, false);
furi_hal_gpio_write(LFRFID_WORKER_READ_DEBUG_GPIO_LOAD, false);
furi_hal_gpio_init_simple(LFRFID_WORKER_READ_DEBUG_GPIO_VALUE, GpioModeAnalog); furi_hal_gpio_init_simple(LFRFID_WORKER_READ_DEBUG_GPIO_VALUE, GpioModeAnalog);
furi_hal_gpio_init_simple(LFRFID_WORKER_READ_DEBUG_GPIO_LOAD, GpioModeAnalog); furi_hal_gpio_init_simple(LFRFID_WORKER_READ_DEBUG_GPIO_LOAD, GpioModeAnalog);
#endif #endif

View File

@@ -8,6 +8,11 @@
#include "protocol_fdx_b.h" #include "protocol_fdx_b.h"
#include "protocol_hid_generic.h" #include "protocol_hid_generic.h"
#include "protocol_hid_ex_generic.h" #include "protocol_hid_ex_generic.h"
#include "protocol_pyramid.h"
#include "protocol_viking.h"
#include "protocol_jablotron.h"
#include "protocol_paradox.h"
#include "protocol_pac_stanley.h"
const ProtocolBase* lfrfid_protocols[] = { const ProtocolBase* lfrfid_protocols[] = {
[LFRFIDProtocolEM4100] = &protocol_em4100, [LFRFIDProtocolEM4100] = &protocol_em4100,
@@ -19,4 +24,9 @@ const ProtocolBase* lfrfid_protocols[] = {
[LFRFIDProtocolFDXB] = &protocol_fdx_b, [LFRFIDProtocolFDXB] = &protocol_fdx_b,
[LFRFIDProtocolHidGeneric] = &protocol_hid_generic, [LFRFIDProtocolHidGeneric] = &protocol_hid_generic,
[LFRFIDProtocolHidExGeneric] = &protocol_hid_ex_generic, [LFRFIDProtocolHidExGeneric] = &protocol_hid_ex_generic,
[LFRFIDProtocolPyramid] = &protocol_pyramid,
[LFRFIDProtocolViking] = &protocol_viking,
[LFRFIDProtocolJablotron] = &protocol_jablotron,
[LFRFIDProtocolParadox] = &protocol_paradox,
[LFRFIDProtocolPACStanley] = &protocol_pac_stanley,
}; };

View File

@@ -17,7 +17,11 @@ typedef enum {
LFRFIDProtocolFDXB, LFRFIDProtocolFDXB,
LFRFIDProtocolHidGeneric, LFRFIDProtocolHidGeneric,
LFRFIDProtocolHidExGeneric, LFRFIDProtocolHidExGeneric,
LFRFIDProtocolPyramid,
LFRFIDProtocolViking,
LFRFIDProtocolJablotron,
LFRFIDProtocolParadox,
LFRFIDProtocolPACStanley,
LFRFIDProtocolMax, LFRFIDProtocolMax,
} LFRFIDProtocol; } LFRFIDProtocol;

View File

@@ -53,7 +53,7 @@ void protocol_awid_decoder_start(ProtocolAwid* protocol) {
memset(protocol->encoded_data, 0, AWID_ENCODED_DATA_SIZE); memset(protocol->encoded_data, 0, AWID_ENCODED_DATA_SIZE);
}; };
static bool protocol_awid_can_be_decoded(const uint8_t* data) { static bool protocol_awid_can_be_decoded(uint8_t* data) {
bool result = false; bool result = false;
// Index map // Index map
@@ -77,6 +77,12 @@ static bool protocol_awid_can_be_decoded(const uint8_t* data) {
bool parity_error = bit_lib_test_parity(data, 8, 88, BitLibParityOdd, 4); bool parity_error = bit_lib_test_parity(data, 8, 88, BitLibParityOdd, 4);
if(parity_error) break; if(parity_error) break;
bit_lib_remove_bit_every_nth(data, 8, 88, 4);
// Avoid detection for invalid formats
uint8_t len = bit_lib_get_bits(data, 8, 8);
if(len != 26 && len != 50 && len != 37 && len != 34) break;
result = true; result = true;
} while(false); } while(false);
@@ -84,7 +90,6 @@ static bool protocol_awid_can_be_decoded(const uint8_t* data) {
} }
static void protocol_awid_decode(uint8_t* encoded_data, uint8_t* decoded_data) { static void protocol_awid_decode(uint8_t* encoded_data, uint8_t* decoded_data) {
bit_lib_remove_bit_every_nth(encoded_data, 8, 88, 4);
bit_lib_copy_bits(decoded_data, 0, 66, encoded_data, 8); bit_lib_copy_bits(decoded_data, 0, 66, encoded_data, 8);
} }

View File

@@ -264,7 +264,7 @@ bool protocol_em4100_write_data(ProtocolEM4100* protocol, void* data) {
void protocol_em4100_render_data(ProtocolEM4100* protocol, string_t result) { void protocol_em4100_render_data(ProtocolEM4100* protocol, string_t result) {
uint8_t* data = protocol->data; uint8_t* data = protocol->data;
string_printf(result, "ID: %03u,%05u", data[2], (uint16_t)((data[3] << 8) | (data[4]))); string_printf(result, "FC: %03u, Card: %05u", data[2], (uint16_t)((data[3] << 8) | (data[4])));
}; };
const ProtocolBase protocol_em4100 = { const ProtocolBase protocol_em4100 = {

View File

@@ -0,0 +1,207 @@
#include <furi.h>
#include "toolbox/level_duration.h"
#include "protocol_jablotron.h"
#include <toolbox/manchester_decoder.h>
#include <lfrfid/tools/bit_lib.h>
#include "lfrfid_protocols.h"
#define JABLOTRON_ENCODED_BIT_SIZE (64)
#define JABLOTRON_ENCODED_BYTE_SIZE (((JABLOTRON_ENCODED_BIT_SIZE) / 8))
#define JABLOTRON_PREAMBLE_BIT_SIZE (16)
#define JABLOTRON_PREAMBLE_BYTE_SIZE (2)
#define JABLOTRON_ENCODED_BYTE_FULL_SIZE \
(JABLOTRON_ENCODED_BYTE_SIZE + JABLOTRON_PREAMBLE_BYTE_SIZE)
#define JABLOTRON_DECODED_DATA_SIZE (5)
#define JABLOTRON_SHORT_TIME (256)
#define JABLOTRON_LONG_TIME (512)
#define JABLOTRON_JITTER_TIME (120)
#define JABLOTRON_SHORT_TIME_LOW (JABLOTRON_SHORT_TIME - JABLOTRON_JITTER_TIME)
#define JABLOTRON_SHORT_TIME_HIGH (JABLOTRON_SHORT_TIME + JABLOTRON_JITTER_TIME)
#define JABLOTRON_LONG_TIME_LOW (JABLOTRON_LONG_TIME - JABLOTRON_JITTER_TIME)
#define JABLOTRON_LONG_TIME_HIGH (JABLOTRON_LONG_TIME + JABLOTRON_JITTER_TIME)
typedef struct {
bool last_short;
bool last_level;
size_t encoded_index;
uint8_t encoded_data[JABLOTRON_ENCODED_BYTE_FULL_SIZE];
uint8_t data[JABLOTRON_DECODED_DATA_SIZE];
} ProtocolJablotron;
ProtocolJablotron* protocol_jablotron_alloc(void) {
ProtocolJablotron* protocol = malloc(sizeof(ProtocolJablotron));
return protocol;
};
void protocol_jablotron_free(ProtocolJablotron* protocol) {
free(protocol);
};
uint8_t* protocol_jablotron_get_data(ProtocolJablotron* proto) {
return proto->data;
};
void protocol_jablotron_decoder_start(ProtocolJablotron* protocol) {
memset(protocol->encoded_data, 0, JABLOTRON_ENCODED_BYTE_FULL_SIZE);
protocol->last_short = false;
};
uint8_t protocol_jablotron_checksum(uint8_t* bits) {
uint8_t chksum = 0;
for(uint8_t i = 16; i < 56; i += 8) {
chksum += bit_lib_get_bits(bits, i, 8);
}
chksum ^= 0x3A;
return chksum;
}
uint64_t protocol_jablotron_card_id(uint8_t* bytes) {
uint64_t id = 0;
for(int i = 0; i < 5; i++) {
id *= 100;
id += ((bytes[i] & 0xF0) >> 4) * 10 + (bytes[i] & 0x0F);
}
return id;
}
static bool protocol_jablotron_can_be_decoded(ProtocolJablotron* protocol) {
// check 11 bits preamble
if(bit_lib_get_bits_16(protocol->encoded_data, 0, 16) != 0b1111111111111111) return false;
// check next 11 bits preamble
if(bit_lib_get_bits_16(protocol->encoded_data, 64, 16) != 0b1111111111111111) return false;
uint8_t checksum = bit_lib_get_bits(protocol->encoded_data, 56, 8);
if(checksum != protocol_jablotron_checksum(protocol->encoded_data)) return false;
return true;
}
void protocol_jablotron_decode(ProtocolJablotron* protocol) {
bit_lib_copy_bits(protocol->data, 0, 40, protocol->encoded_data, 16);
}
bool protocol_jablotron_decoder_feed(ProtocolJablotron* protocol, bool level, uint32_t duration) {
UNUSED(level);
bool pushed = false;
// Bi-Phase Manchester decoding
if(duration >= JABLOTRON_SHORT_TIME_LOW && duration <= JABLOTRON_SHORT_TIME_HIGH) {
if(protocol->last_short == false) {
protocol->last_short = true;
} else {
pushed = true;
bit_lib_push_bit(protocol->encoded_data, JABLOTRON_ENCODED_BYTE_FULL_SIZE, false);
protocol->last_short = false;
}
} else if(duration >= JABLOTRON_LONG_TIME_LOW && duration <= JABLOTRON_LONG_TIME_HIGH) {
if(protocol->last_short == false) {
pushed = true;
bit_lib_push_bit(protocol->encoded_data, JABLOTRON_ENCODED_BYTE_FULL_SIZE, true);
} else {
// reset
protocol->last_short = false;
}
} else {
// reset
protocol->last_short = false;
}
if(pushed && protocol_jablotron_can_be_decoded(protocol)) {
protocol_jablotron_decode(protocol);
return true;
}
return false;
};
bool protocol_jablotron_encoder_start(ProtocolJablotron* protocol) {
// preamble
bit_lib_set_bits(protocol->encoded_data, 0, 0b11111111, 8);
bit_lib_set_bits(protocol->encoded_data, 8, 0b11111111, 8);
// Full code
bit_lib_copy_bits(protocol->encoded_data, 16, 40, protocol->data, 0);
// Checksum
bit_lib_set_bits(
protocol->encoded_data, 56, protocol_jablotron_checksum(protocol->encoded_data), 8);
protocol->encoded_index = 0;
protocol->last_short = false;
protocol->last_level = false;
return true;
};
LevelDuration protocol_jablotron_encoder_yield(ProtocolJablotron* protocol) {
uint32_t duration;
protocol->last_level = !protocol->last_level;
bool bit = bit_lib_get_bit(protocol->encoded_data, protocol->encoded_index);
// Bi-Phase Manchester encoder
if(bit) {
// one long pulse for 1
duration = JABLOTRON_LONG_TIME / 8;
bit_lib_increment_index(protocol->encoded_index, JABLOTRON_ENCODED_BIT_SIZE);
} else {
// two short pulses for 0
duration = JABLOTRON_SHORT_TIME / 8;
if(protocol->last_short) {
bit_lib_increment_index(protocol->encoded_index, JABLOTRON_ENCODED_BIT_SIZE);
protocol->last_short = false;
} else {
protocol->last_short = true;
}
}
return level_duration_make(protocol->last_level, duration);
};
void protocol_jablotron_render_data(ProtocolJablotron* protocol, string_t result) {
uint64_t id = protocol_jablotron_card_id(protocol->data);
string_printf(result, "ID: %llX\r\n", id);
};
bool protocol_jablotron_write_data(ProtocolJablotron* protocol, void* data) {
LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data;
bool result = false;
protocol_jablotron_encoder_start(protocol);
if(request->write_type == LFRFIDWriteTypeT5577) {
request->t5577.block[0] = LFRFID_T5577_MODULATION_DIPHASE | LFRFID_T5577_BITRATE_RF_64 |
(2 << 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.blocks_to_write = 3;
result = true;
}
return result;
};
const ProtocolBase protocol_jablotron = {
.name = "Jablotron",
.manufacturer = "Jablotron",
.data_size = JABLOTRON_DECODED_DATA_SIZE,
.features = LFRFIDFeatureASK,
.validate_count = 3,
.alloc = (ProtocolAlloc)protocol_jablotron_alloc,
.free = (ProtocolFree)protocol_jablotron_free,
.get_data = (ProtocolGetData)protocol_jablotron_get_data,
.decoder =
{
.start = (ProtocolDecoderStart)protocol_jablotron_decoder_start,
.feed = (ProtocolDecoderFeed)protocol_jablotron_decoder_feed,
},
.encoder =
{
.start = (ProtocolEncoderStart)protocol_jablotron_encoder_start,
.yield = (ProtocolEncoderYield)protocol_jablotron_encoder_yield,
},
.render_data = (ProtocolRenderData)protocol_jablotron_render_data,
.render_brief_data = (ProtocolRenderData)protocol_jablotron_render_data,
.write_data = (ProtocolWriteData)protocol_jablotron_write_data,
};

View File

@@ -0,0 +1,4 @@
#pragma once
#include <toolbox/protocols/protocol.h>
extern const ProtocolBase protocol_jablotron;

View File

@@ -0,0 +1,227 @@
#include <furi.h>
#include <math.h>
#include <toolbox/protocols/protocol.h>
#include <toolbox/hex.h>
#include <lfrfid/tools/bit_lib.h>
#include "lfrfid_protocols.h"
#define PAC_STANLEY_ENCODED_BIT_SIZE (128)
#define PAC_STANLEY_ENCODED_BYTE_SIZE (((PAC_STANLEY_ENCODED_BIT_SIZE) / 8))
#define PAC_STANLEY_PREAMBLE_BIT_SIZE (8)
#define PAC_STANLEY_PREAMBLE_BYTE_SIZE (1)
#define PAC_STANLEY_ENCODED_BYTE_FULL_SIZE \
(PAC_STANLEY_ENCODED_BYTE_SIZE + PAC_STANLEY_PREAMBLE_BYTE_SIZE)
#define PAC_STANLEY_BYTE_LENGTH (10) // start bit, 7 data bits, parity bit, stop bit
#define PAC_STANLEY_DATA_START_INDEX 8 + (3 * PAC_STANLEY_BYTE_LENGTH) + 1
#define PAC_STANLEY_DECODED_DATA_SIZE (4)
#define PAC_STANLEY_ENCODED_DATA_SIZE (sizeof(ProtocolPACStanley))
#define PAC_STANLEY_CLOCKS_IN_US (32)
#define PAC_STANLEY_CYCLE_LENGTH (256)
#define PAC_STANLEY_MIN_TIME (60)
#define PAC_STANLEY_MAX_TIME (4000)
typedef struct {
bool inverted;
bool got_preamble;
size_t encoded_index;
uint8_t encoded_data[PAC_STANLEY_ENCODED_BYTE_FULL_SIZE];
uint8_t data[PAC_STANLEY_DECODED_DATA_SIZE];
} ProtocolPACStanley;
ProtocolPACStanley* protocol_pac_stanley_alloc(void) {
ProtocolPACStanley* protocol = malloc(sizeof(ProtocolPACStanley));
return (void*)protocol;
}
void protocol_pac_stanley_free(ProtocolPACStanley* protocol) {
free(protocol);
}
uint8_t* protocol_pac_stanley_get_data(ProtocolPACStanley* protocol) {
return protocol->data;
}
static void protocol_pac_stanley_decode(ProtocolPACStanley* protocol) {
uint8_t asciiCardId[8];
for(size_t idx = 0; idx < 8; idx++) {
uint8_t byte = bit_lib_reverse_8_fast(bit_lib_get_bits(
protocol->encoded_data,
PAC_STANLEY_DATA_START_INDEX + (PAC_STANLEY_BYTE_LENGTH * idx),
8));
asciiCardId[idx] = byte & 0x7F; // discard the parity bit
}
hex_chars_to_uint8((char*)asciiCardId, protocol->data);
}
static bool protocol_pac_stanley_can_be_decoded(ProtocolPACStanley* protocol) {
// Check preamble
if(bit_lib_get_bits(protocol->encoded_data, 0, 8) != 0b11111111) return false;
if(bit_lib_get_bit(protocol->encoded_data, 8) != 0) return false;
if(bit_lib_get_bit(protocol->encoded_data, 9) != 0) return false;
if(bit_lib_get_bit(protocol->encoded_data, 10) != 1) return false;
if(bit_lib_get_bits(protocol->encoded_data, 11, 8) != 0b00000010) return false;
// Check next preamble
if(bit_lib_get_bits(protocol->encoded_data, 128, 8) != 0b11111111) return false;
// Checksum
uint8_t checksum = 0;
uint8_t stripped_byte;
for(size_t idx = 0; idx < 9; idx++) {
uint8_t byte = bit_lib_reverse_8_fast(bit_lib_get_bits(
protocol->encoded_data,
PAC_STANLEY_DATA_START_INDEX + (PAC_STANLEY_BYTE_LENGTH * idx),
8));
stripped_byte = byte & 0x7F; // discard the parity bit
if(bit_lib_test_parity_32(stripped_byte, BitLibParityOdd) != (byte & 0x80) >> 7) {
return false;
}
if(idx < 8) checksum ^= stripped_byte;
}
if(stripped_byte != checksum) return false;
return true;
}
void protocol_pac_stanley_decoder_start(ProtocolPACStanley* protocol) {
memset(protocol->data, 0, PAC_STANLEY_DECODED_DATA_SIZE);
protocol->inverted = false;
protocol->got_preamble = false;
}
bool protocol_pac_stanley_decoder_feed(ProtocolPACStanley* protocol, bool level, uint32_t duration) {
bool pushed = false;
if(duration > PAC_STANLEY_MAX_TIME) return false;
uint8_t pulses = (uint8_t)round((float)duration / PAC_STANLEY_CYCLE_LENGTH);
// Handle last stopbit & preamble (1 sb, 8 bit preamble)
if(pulses >= 9 && !protocol->got_preamble) {
pulses = 8;
protocol->got_preamble = true;
protocol->inverted = !level;
} else if(pulses >= 9 && protocol->got_preamble) {
protocol->got_preamble = false;
} else if(pulses == 0 && duration > PAC_STANLEY_MIN_TIME) {
pulses = 1;
}
if(pulses) {
for(uint8_t i = 0; i < pulses; i++) {
bit_lib_push_bit(
protocol->encoded_data,
PAC_STANLEY_ENCODED_BYTE_FULL_SIZE,
level ^ protocol->inverted);
}
pushed = true;
}
if(pushed && protocol_pac_stanley_can_be_decoded(protocol)) {
protocol_pac_stanley_decode(protocol);
return true;
}
return false;
}
bool protocol_pac_stanley_encoder_start(ProtocolPACStanley* protocol) {
memset(protocol->encoded_data, 0, PAC_STANLEY_ENCODED_BYTE_SIZE);
uint8_t idbytes[10];
idbytes[0] = '2';
idbytes[1] = '0';
uint8_to_hex_chars(protocol->data, &idbytes[2], 8);
// insert start and stop bits
for(size_t i = 0; i < 16; i++) protocol->encoded_data[i] = 0x40 >> (i + 3) % 5 * 2;
protocol->encoded_data[0] = 0xFF; // mark + stop
protocol->encoded_data[1] = 0x20; // start + reflect8(STX)
uint8_t checksum = 0;
for(size_t i = 2; i < 13; i++) {
uint8_t shift = 7 - (i + 3) % 4 * 2;
uint8_t index = i + (i - 1) / 4;
uint16_t pattern;
if(i < 12) {
pattern = bit_lib_reverse_8_fast(idbytes[i - 2]);
pattern |= bit_lib_test_parity_32(pattern, BitLibParityOdd);
if(i > 3) checksum ^= idbytes[i - 2];
} else {
pattern = (bit_lib_reverse_8_fast(checksum) & 0xFE) |
(bit_lib_test_parity_32(checksum, BitLibParityOdd));
}
pattern <<= shift;
protocol->encoded_data[index] |= pattern >> 8 & 0xFF;
protocol->encoded_data[index + 1] |= pattern & 0xFF;
}
protocol->encoded_index = 0;
return true;
}
LevelDuration protocol_pac_stanley_encoder_yield(ProtocolPACStanley* protocol) {
uint16_t length = PAC_STANLEY_CLOCKS_IN_US;
bool bit = bit_lib_get_bit(protocol->encoded_data, protocol->encoded_index);
bit_lib_increment_index(protocol->encoded_index, PAC_STANLEY_ENCODED_BIT_SIZE);
while(bit_lib_get_bit(protocol->encoded_data, protocol->encoded_index) == bit) {
length += PAC_STANLEY_CLOCKS_IN_US;
bit_lib_increment_index(protocol->encoded_index, PAC_STANLEY_ENCODED_BIT_SIZE);
}
return level_duration_make(bit, length);
}
bool protocol_pac_stanley_write_data(ProtocolPACStanley* protocol, void* data) {
LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data;
bool result = false;
protocol_pac_stanley_encoder_start(protocol);
if(request->write_type == LFRFIDWriteTypeT5577) {
request->t5577.block[0] = LFRFID_T5577_MODULATION_DIRECT | LFRFID_T5577_BITRATE_RF_32 |
(4 << 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.block[4] = bit_lib_get_bits_32(protocol->encoded_data, 96, 32);
request->t5577.blocks_to_write = 5;
result = true;
}
return result;
}
void protocol_pac_stanley_render_data(ProtocolPACStanley* protocol, string_t result) {
uint8_t* data = protocol->data;
string_printf(result, "CIN: %02X%02X%02X%02X", data[0], data[1], data[2], data[3]);
}
const ProtocolBase protocol_pac_stanley = {
.name = "PAC/Stanley",
.manufacturer = "N/A",
.data_size = PAC_STANLEY_DECODED_DATA_SIZE,
.features = LFRFIDFeatureASK,
.validate_count = 3,
.alloc = (ProtocolAlloc)protocol_pac_stanley_alloc,
.free = (ProtocolFree)protocol_pac_stanley_free,
.get_data = (ProtocolGetData)protocol_pac_stanley_get_data,
.decoder =
{
.start = (ProtocolDecoderStart)protocol_pac_stanley_decoder_start,
.feed = (ProtocolDecoderFeed)protocol_pac_stanley_decoder_feed,
},
.encoder =
{
.start = (ProtocolEncoderStart)protocol_pac_stanley_encoder_start,
.yield = (ProtocolEncoderYield)protocol_pac_stanley_encoder_yield,
},
.render_data = (ProtocolRenderData)protocol_pac_stanley_render_data,
.render_brief_data = (ProtocolRenderData)protocol_pac_stanley_render_data,
.write_data = (ProtocolWriteData)protocol_pac_stanley_write_data,
};

View File

@@ -0,0 +1,4 @@
#pragma once
#include <toolbox/protocols/protocol.h>
extern const ProtocolBase protocol_pac_stanley;

View File

@@ -0,0 +1,201 @@
#include <furi.h>
#include <toolbox/protocols/protocol.h>
#include <lfrfid/tools/fsk_demod.h>
#include <lfrfid/tools/fsk_osc.h>
#include <lfrfid/tools/bit_lib.h>
#include "lfrfid_protocols.h"
#define JITTER_TIME (20)
#define MIN_TIME (64 - JITTER_TIME)
#define MAX_TIME (80 + JITTER_TIME)
#define PARADOX_DECODED_DATA_SIZE (6)
#define PARADOX_PREAMBLE_LENGTH (8)
#define PARADOX_ENCODED_BIT_SIZE (96)
#define PARADOX_ENCODED_DATA_SIZE (((PARADOX_ENCODED_BIT_SIZE) / 8) + 1)
#define PARADOX_ENCODED_DATA_LAST (PARADOX_ENCODED_DATA_SIZE - 1)
typedef struct {
FSKDemod* fsk_demod;
} ProtocolParadoxDecoder;
typedef struct {
FSKOsc* fsk_osc;
uint8_t encoded_index;
} ProtocolParadoxEncoder;
typedef struct {
ProtocolParadoxDecoder decoder;
ProtocolParadoxEncoder encoder;
uint8_t encoded_data[PARADOX_ENCODED_DATA_SIZE];
uint8_t data[PARADOX_DECODED_DATA_SIZE];
} ProtocolParadox;
ProtocolParadox* protocol_paradox_alloc(void) {
ProtocolParadox* protocol = malloc(sizeof(ProtocolParadox));
protocol->decoder.fsk_demod = fsk_demod_alloc(MIN_TIME, 6, MAX_TIME, 5);
protocol->encoder.fsk_osc = fsk_osc_alloc(8, 10, 50);
return protocol;
};
void protocol_paradox_free(ProtocolParadox* protocol) {
fsk_demod_free(protocol->decoder.fsk_demod);
fsk_osc_free(protocol->encoder.fsk_osc);
free(protocol);
};
uint8_t* protocol_paradox_get_data(ProtocolParadox* protocol) {
return protocol->data;
};
void protocol_paradox_decoder_start(ProtocolParadox* protocol) {
memset(protocol->encoded_data, 0, PARADOX_ENCODED_DATA_SIZE);
};
static bool protocol_paradox_can_be_decoded(ProtocolParadox* protocol) {
// check preamble
if(protocol->encoded_data[0] != 0b00001111 ||
protocol->encoded_data[PARADOX_ENCODED_DATA_LAST] != 0b00001111)
return false;
for(uint32_t i = PARADOX_PREAMBLE_LENGTH; i < 96; i += 2) {
if(bit_lib_get_bit(protocol->encoded_data, i) ==
bit_lib_get_bit(protocol->encoded_data, i + 1)) {
return false;
}
}
return true;
}
static void protocol_paradox_decode(uint8_t* encoded_data, uint8_t* decoded_data) {
for(uint32_t i = PARADOX_PREAMBLE_LENGTH; i < 96; i += 2) {
if(bit_lib_get_bits(encoded_data, i, 2) == 0b01) {
bit_lib_push_bit(decoded_data, PARADOX_DECODED_DATA_SIZE, 0);
} else if(bit_lib_get_bits(encoded_data, i, 2) == 0b10) {
bit_lib_push_bit(decoded_data, PARADOX_DECODED_DATA_SIZE, 1);
}
}
bit_lib_push_bit(decoded_data, PARADOX_DECODED_DATA_SIZE, 0);
bit_lib_push_bit(decoded_data, PARADOX_DECODED_DATA_SIZE, 0);
bit_lib_push_bit(decoded_data, PARADOX_DECODED_DATA_SIZE, 0);
bit_lib_push_bit(decoded_data, PARADOX_DECODED_DATA_SIZE, 0);
}
bool protocol_paradox_decoder_feed(ProtocolParadox* protocol, bool level, uint32_t duration) {
bool value;
uint32_t count;
fsk_demod_feed(protocol->decoder.fsk_demod, level, duration, &value, &count);
if(count > 0) {
for(size_t i = 0; i < count; i++) {
bit_lib_push_bit(protocol->encoded_data, PARADOX_ENCODED_DATA_SIZE, value);
if(protocol_paradox_can_be_decoded(protocol)) {
protocol_paradox_decode(protocol->encoded_data, protocol->data);
return true;
}
}
}
return false;
};
static void protocol_paradox_encode(const uint8_t* decoded_data, uint8_t* encoded_data) {
// preamble
bit_lib_set_bits(encoded_data, 0, 0b00001111, 8);
for(size_t i = 0; i < 44; i++) {
if(bit_lib_get_bit(decoded_data, i)) {
bit_lib_set_bits(encoded_data, PARADOX_PREAMBLE_LENGTH + i * 2, 0b10, 2);
} else {
bit_lib_set_bits(encoded_data, PARADOX_PREAMBLE_LENGTH + i * 2, 0b01, 2);
}
}
};
bool protocol_paradox_encoder_start(ProtocolParadox* protocol) {
protocol_paradox_encode(protocol->data, (uint8_t*)protocol->encoded_data);
protocol->encoder.encoded_index = 0;
fsk_osc_reset(protocol->encoder.fsk_osc);
return true;
};
LevelDuration protocol_paradox_encoder_yield(ProtocolParadox* protocol) {
bool level;
uint32_t duration;
bool bit = bit_lib_get_bit(protocol->encoded_data, protocol->encoder.encoded_index);
bool advance = fsk_osc_next_half(protocol->encoder.fsk_osc, bit, &level, &duration);
if(advance) {
bit_lib_increment_index(protocol->encoder.encoded_index, PARADOX_ENCODED_BIT_SIZE);
}
return level_duration_make(level, duration);
};
void protocol_paradox_render_data(ProtocolParadox* protocol, string_t result) {
uint8_t* decoded_data = protocol->data;
uint8_t fc = bit_lib_get_bits(decoded_data, 10, 8);
uint16_t card_id = bit_lib_get_bits_16(decoded_data, 18, 16);
string_cat_printf(result, "Facility: %u\r\n", fc);
string_cat_printf(result, "Card: %lu\r\n", card_id);
string_cat_printf(result, "Data: ");
for(size_t i = 0; i < PARADOX_DECODED_DATA_SIZE; i++) {
string_cat_printf(result, "%02X", decoded_data[i]);
}
};
void protocol_paradox_render_brief_data(ProtocolParadox* protocol, string_t result) {
uint8_t* decoded_data = protocol->data;
uint8_t fc = bit_lib_get_bits(decoded_data, 10, 8);
uint16_t card_id = bit_lib_get_bits_16(decoded_data, 18, 16);
string_cat_printf(result, "FC: %03u, Card: %05u", fc, card_id);
};
bool protocol_paradox_write_data(ProtocolParadox* protocol, void* data) {
LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data;
bool result = false;
protocol_paradox_encode(protocol->data, (uint8_t*)protocol->encoded_data);
if(request->write_type == LFRFIDWriteTypeT5577) {
request->t5577.block[0] = LFRFID_T5577_MODULATION_FSK2a | LFRFID_T5577_BITRATE_RF_50 |
(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;
};
const ProtocolBase protocol_paradox = {
.name = "Paradox",
.manufacturer = "Paradox",
.data_size = PARADOX_DECODED_DATA_SIZE,
.features = LFRFIDFeatureASK,
.validate_count = 3,
.alloc = (ProtocolAlloc)protocol_paradox_alloc,
.free = (ProtocolFree)protocol_paradox_free,
.get_data = (ProtocolGetData)protocol_paradox_get_data,
.decoder =
{
.start = (ProtocolDecoderStart)protocol_paradox_decoder_start,
.feed = (ProtocolDecoderFeed)protocol_paradox_decoder_feed,
},
.encoder =
{
.start = (ProtocolEncoderStart)protocol_paradox_encoder_start,
.yield = (ProtocolEncoderYield)protocol_paradox_encoder_yield,
},
.render_data = (ProtocolRenderData)protocol_paradox_render_data,
.render_brief_data = (ProtocolRenderData)protocol_paradox_render_brief_data,
.write_data = (ProtocolWriteData)protocol_paradox_write_data,
};

View File

@@ -0,0 +1,4 @@
#pragma once
#include <toolbox/protocols/protocol.h>
extern const ProtocolBase protocol_paradox;

View File

@@ -0,0 +1,277 @@
#include <furi.h>
#include <toolbox/protocols/protocol.h>
#include <lfrfid/tools/fsk_demod.h>
#include <lfrfid/tools/fsk_osc.h>
#include "lfrfid_protocols.h"
#include <lfrfid/tools/bit_lib.h>
#define JITTER_TIME (20)
#define MIN_TIME (64 - JITTER_TIME)
#define MAX_TIME (80 + JITTER_TIME)
#define PYRAMID_DATA_SIZE 13
#define PYRAMID_PREAMBLE_SIZE 3
#define PYRAMID_ENCODED_DATA_SIZE \
(PYRAMID_PREAMBLE_SIZE + PYRAMID_DATA_SIZE + PYRAMID_PREAMBLE_SIZE)
#define PYRAMID_ENCODED_BIT_SIZE ((PYRAMID_PREAMBLE_SIZE + PYRAMID_DATA_SIZE) * 8)
#define PYRAMID_DECODED_DATA_SIZE (4)
#define PYRAMID_DECODED_BIT_SIZE ((PYRAMID_ENCODED_BIT_SIZE - PYRAMID_PREAMBLE_SIZE * 8) / 2)
typedef struct {
FSKDemod* fsk_demod;
} ProtocolPyramidDecoder;
typedef struct {
FSKOsc* fsk_osc;
uint8_t encoded_index;
uint32_t pulse;
} ProtocolPyramidEncoder;
typedef struct {
ProtocolPyramidDecoder decoder;
ProtocolPyramidEncoder encoder;
uint8_t encoded_data[PYRAMID_ENCODED_DATA_SIZE];
uint8_t data[PYRAMID_DECODED_DATA_SIZE];
} ProtocolPyramid;
ProtocolPyramid* protocol_pyramid_alloc(void) {
ProtocolPyramid* protocol = malloc(sizeof(ProtocolPyramid));
protocol->decoder.fsk_demod = fsk_demod_alloc(MIN_TIME, 6, MAX_TIME, 5);
protocol->encoder.fsk_osc = fsk_osc_alloc(8, 10, 50);
return protocol;
};
void protocol_pyramid_free(ProtocolPyramid* protocol) {
fsk_demod_free(protocol->decoder.fsk_demod);
fsk_osc_free(protocol->encoder.fsk_osc);
free(protocol);
};
uint8_t* protocol_pyramid_get_data(ProtocolPyramid* protocol) {
return protocol->data;
};
void protocol_pyramid_decoder_start(ProtocolPyramid* protocol) {
memset(protocol->encoded_data, 0, PYRAMID_ENCODED_DATA_SIZE);
};
static bool protocol_pyramid_can_be_decoded(uint8_t* data) {
// check preamble
if(bit_lib_get_bits_16(data, 0, 16) != 0b0000000000000001 ||
bit_lib_get_bits(data, 16, 8) != 0b00000001) {
return false;
}
if(bit_lib_get_bits_16(data, 128, 16) != 0b0000000000000001 ||
bit_lib_get_bits(data, 136, 8) != 0b00000001) {
return false;
}
uint8_t checksum = bit_lib_get_bits(data, 120, 8);
uint8_t checksum_data[13] = {0x00};
for(uint8_t i = 0; i < 13; i++) {
checksum_data[i] = bit_lib_get_bits(data, 16 + (i * 8), 8);
}
uint8_t calc_checksum = bit_lib_crc8(checksum_data, 13, 0x31, 0x00, true, true, 0x00);
if(checksum != calc_checksum) return false;
// Remove parity
bit_lib_remove_bit_every_nth(data, 8, 15 * 8, 8);
// Determine Startbit and format
int j;
for(j = 0; j < 105; ++j) {
if(bit_lib_get_bit(data, j)) break;
}
uint8_t fmt_len = 105 - j;
// Only suppport 26bit format for now
if(fmt_len != 26) return false;
return true;
}
static void protocol_pyramid_decode(ProtocolPyramid* protocol) {
// Format
bit_lib_set_bits(protocol->data, 0, 26, 8);
// Facility Code
bit_lib_copy_bits(protocol->data, 8, 8, protocol->encoded_data, 73 + 8);
// Card Number
bit_lib_copy_bits(protocol->data, 16, 16, protocol->encoded_data, 81 + 8);
}
bool protocol_pyramid_decoder_feed(ProtocolPyramid* protocol, bool level, uint32_t duration) {
bool value;
uint32_t count;
bool result = false;
fsk_demod_feed(protocol->decoder.fsk_demod, level, duration, &value, &count);
if(count > 0) {
for(size_t i = 0; i < count; i++) {
bit_lib_push_bit(protocol->encoded_data, PYRAMID_ENCODED_DATA_SIZE, value);
if(protocol_pyramid_can_be_decoded(protocol->encoded_data)) {
protocol_pyramid_decode(protocol);
result = true;
}
}
}
return result;
};
bool protocol_pyramid_get_parity(const uint8_t* bits, uint8_t type, int length) {
int x;
for(x = 0; length > 0; --length) x += bit_lib_get_bit(bits, length - 1);
x %= 2;
return x ^ type;
}
void protocol_pyramid_add_wiegand_parity(
uint8_t* target,
uint8_t target_position,
uint8_t* source,
uint8_t length) {
bit_lib_set_bit(
target, target_position, protocol_pyramid_get_parity(source, 0 /* even */, length / 2));
bit_lib_copy_bits(target, target_position + 1, length, source, 0);
bit_lib_set_bit(
target,
target_position + length + 1,
protocol_pyramid_get_parity(source + length / 2, 1 /* odd */, length / 2));
}
static void protocol_pyramid_encode(ProtocolPyramid* protocol) {
memset(protocol->encoded_data, 0, sizeof(protocol->encoded_data));
uint8_t pre[16];
memset(pre, 0, sizeof(pre));
// Format start bit
bit_lib_set_bit(pre, 79, 1);
uint8_t wiegand[3];
memset(wiegand, 0, sizeof(wiegand));
// FC
bit_lib_copy_bits(wiegand, 0, 8, protocol->data, 8);
// CardNum
bit_lib_copy_bits(wiegand, 8, 16, protocol->data, 16);
// Wiegand parity
protocol_pyramid_add_wiegand_parity(pre, 80, wiegand, 24);
bit_lib_add_parity(pre, 8, protocol->encoded_data, 8, 102, 8, 1);
// Add checksum
uint8_t checksum_buffer[13];
for(uint8_t i = 0; i < 13; i++)
checksum_buffer[i] = bit_lib_get_bits(protocol->encoded_data, 16 + (i * 8), 8);
uint8_t crc = bit_lib_crc8(checksum_buffer, 13, 0x31, 0x00, true, true, 0x00);
bit_lib_set_bits(protocol->encoded_data, 120, crc, 8);
}
bool protocol_pyramid_encoder_start(ProtocolPyramid* protocol) {
protocol->encoder.encoded_index = 0;
protocol->encoder.pulse = 0;
protocol_pyramid_encode(protocol);
return true;
};
LevelDuration protocol_pyramid_encoder_yield(ProtocolPyramid* protocol) {
bool level = 0;
uint32_t duration = 0;
// if pulse is zero, we need to output high, otherwise we need to output low
if(protocol->encoder.pulse == 0) {
// get bit
uint8_t bit = bit_lib_get_bit(protocol->encoded_data, protocol->encoder.encoded_index);
// get pulse from oscillator
bool advance = fsk_osc_next(protocol->encoder.fsk_osc, bit, &duration);
if(advance) {
bit_lib_increment_index(protocol->encoder.encoded_index, PYRAMID_ENCODED_BIT_SIZE);
}
// duration diveded by 2 because we need to output high and low
duration = duration / 2;
protocol->encoder.pulse = duration;
level = true;
} else {
// output low half and reset pulse
duration = protocol->encoder.pulse;
protocol->encoder.pulse = 0;
level = false;
}
return level_duration_make(level, duration);
};
bool protocol_pyramid_write_data(ProtocolPyramid* protocol, void* data) {
LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data;
bool result = false;
protocol_pyramid_encoder_start(protocol);
if(request->write_type == LFRFIDWriteTypeT5577) {
request->t5577.block[0] = LFRFID_T5577_MODULATION_FSK2a | LFRFID_T5577_BITRATE_RF_50 |
(4 << 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.block[4] = bit_lib_get_bits_32(protocol->encoded_data, 96, 32);
request->t5577.blocks_to_write = 5;
result = true;
}
return result;
};
void protocol_pyramid_render_data(ProtocolPyramid* protocol, string_t result) {
uint8_t* decoded_data = protocol->data;
uint8_t format_length = decoded_data[0];
string_cat_printf(result, "Format: 26\r\n", format_length);
if(format_length == 26) {
uint8_t facility;
bit_lib_copy_bits(&facility, 0, 8, decoded_data, 8);
uint16_t card_id;
bit_lib_copy_bits((uint8_t*)&card_id, 8, 8, decoded_data, 16);
bit_lib_copy_bits((uint8_t*)&card_id, 0, 8, decoded_data, 24);
string_cat_printf(result, "FC: %03u, Card: %05u", facility, card_id);
} else {
string_cat_printf(result, "Data: unknown");
}
};
const ProtocolBase protocol_pyramid = {
.name = "Pyramid",
.manufacturer = "Farpointe",
.data_size = PYRAMID_DECODED_DATA_SIZE,
.features = LFRFIDFeatureASK,
.validate_count = 3,
.alloc = (ProtocolAlloc)protocol_pyramid_alloc,
.free = (ProtocolFree)protocol_pyramid_free,
.get_data = (ProtocolGetData)protocol_pyramid_get_data,
.decoder =
{
.start = (ProtocolDecoderStart)protocol_pyramid_decoder_start,
.feed = (ProtocolDecoderFeed)protocol_pyramid_decoder_feed,
},
.encoder =
{
.start = (ProtocolEncoderStart)protocol_pyramid_encoder_start,
.yield = (ProtocolEncoderYield)protocol_pyramid_encoder_yield,
},
.render_data = (ProtocolRenderData)protocol_pyramid_render_data,
.render_brief_data = (ProtocolRenderData)protocol_pyramid_render_data,
.write_data = (ProtocolWriteData)protocol_pyramid_write_data,
};

View File

@@ -0,0 +1,4 @@
#pragma once
#include <toolbox/protocols/protocol.h>
extern const ProtocolBase protocol_pyramid;

View File

@@ -0,0 +1,201 @@
#include <furi.h>
#include <toolbox/protocols/protocol.h>
#include <toolbox/manchester_decoder.h>
#include <lfrfid/tools/bit_lib.h>
#include "lfrfid_protocols.h"
#define VIKING_CLOCK_PER_BIT (32)
#define VIKING_ENCODED_BIT_SIZE (64)
#define VIKING_ENCODED_BYTE_SIZE (((VIKING_ENCODED_BIT_SIZE) / 8))
#define VIKING_PREAMBLE_BIT_SIZE (24)
#define VIKING_PREAMBLE_BYTE_SIZE (3)
#define VIKING_ENCODED_BYTE_FULL_SIZE (VIKING_ENCODED_BYTE_SIZE + VIKING_PREAMBLE_BYTE_SIZE)
#define VIKING_DECODED_DATA_SIZE 4
#define VIKING_READ_SHORT_TIME (128)
#define VIKING_READ_LONG_TIME (256)
#define VIKING_READ_JITTER_TIME (60)
#define VIKING_READ_SHORT_TIME_LOW (VIKING_READ_SHORT_TIME - VIKING_READ_JITTER_TIME)
#define VIKING_READ_SHORT_TIME_HIGH (VIKING_READ_SHORT_TIME + VIKING_READ_JITTER_TIME)
#define VIKING_READ_LONG_TIME_LOW (VIKING_READ_LONG_TIME - VIKING_READ_JITTER_TIME)
#define VIKING_READ_LONG_TIME_HIGH (VIKING_READ_LONG_TIME + VIKING_READ_JITTER_TIME)
typedef struct {
uint8_t data[VIKING_DECODED_DATA_SIZE];
uint8_t encoded_data[VIKING_ENCODED_BYTE_FULL_SIZE];
uint8_t encoded_data_index;
bool encoded_polarity;
ManchesterState decoder_manchester_state;
} ProtocolViking;
ProtocolViking* protocol_viking_alloc(void) {
ProtocolViking* proto = malloc(sizeof(ProtocolViking));
return (void*)proto;
};
void protocol_viking_free(ProtocolViking* protocol) {
free(protocol);
};
uint8_t* protocol_viking_get_data(ProtocolViking* protocol) {
return protocol->data;
};
static void protocol_viking_decode(ProtocolViking* protocol) {
// Copy Card ID
bit_lib_copy_bits(protocol->data, 0, 32, protocol->encoded_data, 24);
}
static bool protocol_viking_can_be_decoded(ProtocolViking* protocol) {
// check 24 bits preamble
if(bit_lib_get_bits_16(protocol->encoded_data, 0, 16) != 0b1111001000000000) return false;
if(bit_lib_get_bits(protocol->encoded_data, 16, 8) != 0b00000000) return false;
// check next 24 bits preamble
if(bit_lib_get_bits_16(protocol->encoded_data, 64, 16) != 0b1111001000000000) return false;
if(bit_lib_get_bits(protocol->encoded_data, 80, 8) != 0b00000000) return false;
// Checksum
uint32_t checksum = bit_lib_get_bits(protocol->encoded_data, 0, 8) ^
bit_lib_get_bits(protocol->encoded_data, 8, 8) ^
bit_lib_get_bits(protocol->encoded_data, 16, 8) ^
bit_lib_get_bits(protocol->encoded_data, 24, 8) ^
bit_lib_get_bits(protocol->encoded_data, 32, 8) ^
bit_lib_get_bits(protocol->encoded_data, 40, 8) ^
bit_lib_get_bits(protocol->encoded_data, 48, 8) ^
bit_lib_get_bits(protocol->encoded_data, 56, 8) ^ 0xA8;
if(checksum != 0) return false;
return true;
}
void protocol_viking_decoder_start(ProtocolViking* protocol) {
memset(protocol->encoded_data, 0, VIKING_ENCODED_BYTE_FULL_SIZE);
manchester_advance(
protocol->decoder_manchester_state,
ManchesterEventReset,
&protocol->decoder_manchester_state,
NULL);
};
bool protocol_viking_decoder_feed(ProtocolViking* protocol, bool level, uint32_t duration) {
bool result = false;
ManchesterEvent event = ManchesterEventReset;
if(duration > VIKING_READ_SHORT_TIME_LOW && duration < VIKING_READ_SHORT_TIME_HIGH) {
if(!level) {
event = ManchesterEventShortHigh;
} else {
event = ManchesterEventShortLow;
}
} else if(duration > VIKING_READ_LONG_TIME_LOW && duration < VIKING_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, VIKING_ENCODED_BYTE_FULL_SIZE, data);
if(protocol_viking_can_be_decoded(protocol)) {
protocol_viking_decode(protocol);
result = true;
}
}
}
return result;
};
bool protocol_viking_encoder_start(ProtocolViking* protocol) {
// Preamble
bit_lib_set_bits(protocol->encoded_data, 0, 0b11110010, 8);
bit_lib_set_bits(protocol->encoded_data, 8, 0b00000000, 8);
bit_lib_set_bits(protocol->encoded_data, 16, 0b00000000, 8);
// Card Id
bit_lib_copy_bits(protocol->encoded_data, 24, 32, protocol->data, 0);
// Checksum
uint32_t id = bit_lib_get_bits_32(protocol->data, 0, 32);
uint8_t checksum = ((id >> 24) & 0xFF) ^ ((id >> 16) & 0xFF) ^ ((id >> 8) & 0xFF) ^
(id & 0xFF) ^ 0xF2 ^ 0xA8;
bit_lib_set_bits(protocol->encoded_data, 56, checksum, 8);
return true;
};
LevelDuration protocol_viking_encoder_yield(ProtocolViking* protocol) {
bool level = bit_lib_get_bit(protocol->encoded_data, protocol->encoded_data_index);
uint32_t duration = VIKING_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, VIKING_ENCODED_BIT_SIZE);
}
return level_duration_make(level, duration);
};
bool protocol_viking_write_data(ProtocolViking* protocol, void* data) {
LFRFIDWriteRequest* request = (LFRFIDWriteRequest*)data;
bool result = false;
protocol_viking_encoder_start(protocol);
if(request->write_type == LFRFIDWriteTypeT5577) {
request->t5577.block[0] =
(LFRFID_T5577_MODULATION_MANCHESTER | LFRFID_T5577_BITRATE_RF_32 |
(2 << 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.blocks_to_write = 3;
result = true;
}
return result;
};
void protocol_viking_render_data(ProtocolViking* protocol, string_t result) {
uint32_t id = bit_lib_get_bits_32(protocol->data, 0, 32);
string_printf(result, "ID: %08lX\r\n", id);
};
const ProtocolBase protocol_viking = {
.name = "Viking",
.manufacturer = "Viking",
.data_size = VIKING_DECODED_DATA_SIZE,
.features = LFRFIDFeatureASK,
.validate_count = 3,
.alloc = (ProtocolAlloc)protocol_viking_alloc,
.free = (ProtocolFree)protocol_viking_free,
.get_data = (ProtocolGetData)protocol_viking_get_data,
.decoder =
{
.start = (ProtocolDecoderStart)protocol_viking_decoder_start,
.feed = (ProtocolDecoderFeed)protocol_viking_decoder_feed,
},
.encoder =
{
.start = (ProtocolEncoderStart)protocol_viking_encoder_start,
.yield = (ProtocolEncoderYield)protocol_viking_encoder_yield,
},
.render_data = (ProtocolRenderData)protocol_viking_render_data,
.render_brief_data = (ProtocolRenderData)protocol_viking_render_data,
.write_data = (ProtocolWriteData)protocol_viking_write_data,
};

View File

@@ -0,0 +1,4 @@
#pragma once
#include <toolbox/protocols/protocol.h>
extern const ProtocolBase protocol_viking;

View File

@@ -129,6 +129,45 @@ bool bit_lib_test_parity(
return result; return result;
} }
size_t bit_lib_add_parity(
const uint8_t* data,
size_t position,
uint8_t* dest,
size_t dest_position,
uint8_t source_length,
uint8_t parity_length,
BitLibParity parity) {
uint32_t parity_word = 0;
size_t j = 0, bit_count = 0;
for(int word = 0; word < source_length; word += parity_length - 1) {
for(int bit = 0; bit < parity_length - 1; bit++) {
parity_word = (parity_word << 1) | bit_lib_get_bit(data, position + word + bit);
bit_lib_set_bit(
dest, dest_position + j++, bit_lib_get_bit(data, position + word + bit));
}
// if parity fails then return 0
switch(parity) {
case BitLibParityAlways0:
bit_lib_set_bit(dest, dest_position + j++, 0);
break; // marker bit which should be a 0
case BitLibParityAlways1:
bit_lib_set_bit(dest, dest_position + j++, 1);
break; // marker bit which should be a 1
default:
bit_lib_set_bit(
dest,
dest_position + j++,
(bit_lib_test_parity_32(parity_word, BitLibParityOdd) ^ parity) ^ 1);
break;
}
bit_count += parity_length;
parity_word = 0;
}
// if we got here then all the parities passed
// return bit count
return bit_count;
}
size_t bit_lib_remove_bit_every_nth(uint8_t* data, size_t position, uint8_t length, uint8_t n) { size_t bit_lib_remove_bit_every_nth(uint8_t* data, size_t position, uint8_t length, uint8_t n) {
size_t counter = 0; size_t counter = 0;
size_t result_counter = 0; size_t result_counter = 0;
@@ -262,6 +301,43 @@ uint16_t bit_lib_reverse_16_fast(uint16_t data) {
return result; return result;
} }
uint8_t bit_lib_reverse_8_fast(uint8_t byte) {
byte = (byte & 0xF0) >> 4 | (byte & 0x0F) << 4;
byte = (byte & 0xCC) >> 2 | (byte & 0x33) << 2;
byte = (byte & 0xAA) >> 1 | (byte & 0x55) << 1;
return byte;
}
uint16_t bit_lib_crc8(
uint8_t const* data,
size_t data_size,
uint8_t polynom,
uint8_t init,
bool ref_in,
bool ref_out,
uint8_t xor_out) {
uint8_t crc = init;
for(size_t i = 0; i < data_size; ++i) {
uint8_t byte = data[i];
if(ref_in) bit_lib_reverse_bits(&byte, 0, 8);
crc ^= byte;
for(size_t j = 8; j > 0; --j) {
if(crc & TOPBIT(8)) {
crc = (crc << 1) ^ polynom;
} else {
crc = (crc << 1);
}
}
}
if(ref_out) bit_lib_reverse_bits(&crc, 0, 8);
crc ^= xor_out;
return crc;
}
uint16_t bit_lib_crc16( uint16_t bit_lib_crc16(
uint8_t const* data, uint8_t const* data,
size_t data_size, size_t data_size,

View File

@@ -7,6 +7,8 @@
extern "C" { extern "C" {
#endif #endif
#define TOPBIT(X) (1 << (X - 1))
typedef enum { typedef enum {
BitLibParityEven, BitLibParityEven,
BitLibParityOdd, BitLibParityOdd,
@@ -114,6 +116,27 @@ bool bit_lib_test_parity(
BitLibParity parity, BitLibParity parity,
uint8_t parity_length); uint8_t parity_length);
/**
* @brief Add parity to bit array
*
* @param data Source bit array
* @param position Start position
* @param dest Destination bit array
* @param dest_position Destination position
* @param source_length Source bit count
* @param parity_length Parity block length
* @param parity Parity to test against
* @return size_t
*/
size_t bit_lib_add_parity(
const uint8_t* data,
size_t position,
uint8_t* dest,
size_t dest_position,
uint8_t source_length,
uint8_t parity_length,
BitLibParity parity);
/** /**
* @brief Remove bit every n in array and shift array left. Useful to remove parity. * @brief Remove bit every n in array and shift array left. Useful to remove parity.
* *
@@ -194,6 +217,35 @@ void bit_lib_print_regions(
*/ */
uint16_t bit_lib_reverse_16_fast(uint16_t data); uint16_t bit_lib_reverse_16_fast(uint16_t data);
/**
* @brief Reverse bits in uint8_t, faster than generic bit_lib_reverse_bits.
*
* @param byte Byte
* @return uint8_t the reversed byte
*/
uint8_t bit_lib_reverse_8_fast(uint8_t byte);
/**
* @brief Slow, but generic CRC8 implementation
*
* @param data
* @param data_size
* @param polynom CRC polynom
* @param init init value
* @param ref_in true if the right bit is older
* @param ref_out true to reverse output
* @param xor_out xor output with this value
* @return uint8_t
*/
uint16_t bit_lib_crc8(
uint8_t const* data,
size_t data_size,
uint8_t polynom,
uint8_t init,
bool ref_in,
bool ref_out,
uint8_t xor_out);
/** /**
* @brief Slow, but generic CRC16 implementation * @brief Slow, but generic CRC16 implementation
* *

View File

@@ -782,7 +782,7 @@ static void nfc_device_load_mifare_classic_block(
char hi = string_get_char(block_str, 3 * i); char hi = string_get_char(block_str, 3 * i);
char low = string_get_char(block_str, 3 * i + 1); char low = string_get_char(block_str, 3 * i + 1);
uint8_t byte = 0; uint8_t byte = 0;
if(hex_chars_to_uint8(hi, low, &byte)) { if(hex_char_to_uint8(hi, low, &byte)) {
block_tmp.value[i] = byte; block_tmp.value[i] = byte;
} else { } else {
FURI_BIT_SET(block_unknown_bytes_mask, i); FURI_BIT_SET(block_unknown_bytes_mask, i);

0
lib/nfc/nfc_worker.h Executable file → Normal file
View File

0
lib/nfc/protocols/emv.h Executable file → Normal file
View File

0
lib/nfc/protocols/nfca.c Executable file → Normal file
View File

View File

@@ -15,7 +15,7 @@ bool hex_char_to_hex_nibble(char c, uint8_t* nibble) {
} }
} }
bool hex_chars_to_uint8(char hi, char low, uint8_t* value) { bool hex_char_to_uint8(char hi, char low, uint8_t* value) {
uint8_t hi_nibble_value, low_nibble_value; uint8_t hi_nibble_value, low_nibble_value;
if(hex_char_to_hex_nibble(hi, &hi_nibble_value) && if(hex_char_to_hex_nibble(hi, &hi_nibble_value) &&
@@ -27,13 +27,29 @@ bool hex_chars_to_uint8(char hi, char low, uint8_t* value) {
} }
} }
bool hex_chars_to_uint8(const char* value_str, uint8_t* value) {
bool parse_success = false;
while(*value_str && value_str[1]) {
parse_success = hex_char_to_uint8(*value_str, value_str[1], value++);
if(!parse_success) break;
value_str += 2;
}
return parse_success;
}
bool hex_chars_to_uint64(const char* value_str, uint64_t* value) { bool hex_chars_to_uint64(const char* value_str, uint64_t* value) {
uint8_t* _value = (uint8_t*)value; uint8_t* _value = (uint8_t*)value;
bool parse_success = false; bool parse_success = false;
for(uint8_t i = 0; i < 8; i++) { for(uint8_t i = 0; i < 8; i++) {
parse_success = hex_chars_to_uint8(value_str[i * 2], value_str[i * 2 + 1], &_value[7 - i]); parse_success = hex_char_to_uint8(value_str[i * 2], value_str[i * 2 + 1], &_value[7 - i]);
if(!parse_success) break; if(!parse_success) break;
} }
return parse_success; return parse_success;
} }
void uint8_to_hex_chars(const uint8_t* src, uint8_t* target, int length) {
const char chars[] = "0123456789ABCDEF";
while(--length >= 0)
target[length] = chars[(src[length >> 1] >> ((1 - (length & 1)) << 2)) & 0xF];
}

View File

@@ -14,14 +14,22 @@ extern "C" {
*/ */
bool hex_char_to_hex_nibble(char c, uint8_t* nibble); bool hex_char_to_hex_nibble(char c, uint8_t* nibble);
/** Convert ASCII hex values to byte /** Convert ASCII hex value to byte
* @param hi hi nibble text * @param hi hi nibble text
* @param low low nibble text * @param low low nibble text
* @param value output value * @param value output value
* *
* @return bool conversion status * @return bool conversion status
*/ */
bool hex_chars_to_uint8(char hi, char low, uint8_t* value); bool hex_char_to_uint8(char hi, char low, uint8_t* value);
/** Convert ASCII hex values to uint8_t
* @param value_str ASCII data
* @param value output value
*
* @return bool conversion status
*/
bool hex_chars_to_uint8(const char* value_str, uint8_t* value);
/** Convert ASCII hex values to uint64_t /** Convert ASCII hex values to uint64_t
* @param value_str ASCII 64 bi data * @param value_str ASCII 64 bi data
@@ -31,6 +39,14 @@ bool hex_chars_to_uint8(char hi, char low, uint8_t* value);
*/ */
bool hex_chars_to_uint64(const char* value_str, uint64_t* value); bool hex_chars_to_uint64(const char* value_str, uint64_t* value);
/** Convert uint8_t to ASCII hex values
* @param src source data
* @param target output value
* @param length data length
*
*/
void uint8_to_hex_chars(const uint8_t* src, uint8_t* target, int length);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -26,7 +26,6 @@ Also display type, region and etc...
## Core1 and Core2 firmware flashing ## Core1 and Core2 firmware flashing
Main flashing sequence can be found in root `Makefile`.
Core2 goes first, then Core1. Core2 goes first, then Core1.
Never flash FUS or you will loose your job, girlfriend and keys in secure enclave. Never flash FUS or you will loose your job, girlfriend and keys in secure enclave.

View File

@@ -88,7 +88,7 @@ class Main(App):
def _fix_filename(self, filename: str): def _fix_filename(self, filename: str):
return filename.replace("-", "_") return filename.replace("-", "_")
def _replace_occurance(self, sources: list, old: str, new: str): def _replace_occurrence(self, sources: list, old: str, new: str):
old = old.encode() old = old.encode()
new = new.encode() new = new.encode()
for source in sources: for source in sources:
@@ -102,7 +102,7 @@ class Main(App):
pattern = re.compile(SOURCE_CODE_FILE_PATTERN) pattern = re.compile(SOURCE_CODE_FILE_PATTERN)
good = [] good = []
bad = [] bad = []
# Check sources for invalid filesname # Check sources for invalid filenames
for source in sources: for source in sources:
basename = os.path.basename(source) basename = os.path.basename(source)
if not pattern.match(basename): if not pattern.match(basename):
@@ -113,40 +113,63 @@ class Main(App):
bad.append((source, basename, new_basename)) bad.append((source, basename, new_basename))
else: else:
good.append(source) good.append(source)
# Notify about errors or replace all occurances # Notify about errors or replace all occurrences
if dry_run: if dry_run:
if len(bad) > 0: if len(bad) > 0:
self.logger.error(f"Found {len(bad)} incorrectly named files") self.logger.error(f"Found {len(bad)} incorrectly named files")
self.logger.info(bad) self.logger.info(bad)
return False return False
else: else:
# Replace occurances in text files # Replace occurrences in text files
for source, old, new in bad: for source, old, new in bad:
self._replace_occurance(sources, old, new) self._replace_occurrence(sources, old, new)
# Rename files # Rename files
for source, old, new in bad: for source, old, new in bad:
shutil.move(source, source.replace(old, new)) shutil.move(source, source.replace(old, new))
return True return True
def check(self): def _apply_file_permissions(self, sources: list, dry_run: bool = False):
execute_permissions = 0o111
pattern = re.compile(SOURCE_CODE_FILE_PATTERN)
good = []
bad = []
# Check sources for unexpected execute permissions
for source in sources:
st = os.stat(source)
perms_too_many = st.st_mode & execute_permissions
if perms_too_many:
good_perms = st.st_mode & ~perms_too_many
bad.append((source, oct(perms_too_many), good_perms))
else:
good.append(source)
# Notify or fix
if dry_run:
if len(bad) > 0:
self.logger.error(f"Found {len(bad)} incorrect permissions")
self.logger.info([record[0:2] for record in bad])
return False
else:
for source, perms_too_many, new_perms in bad:
os.chmod(source, new_perms)
return True
def _perform(self, dry_run: bool):
result = 0 result = 0
sources = self._find_sources(self.args.input) sources = self._find_sources(self.args.input)
if not self._format_sources(sources, dry_run=True): if not self._format_sources(sources, dry_run=dry_run):
result |= 0b01 result |= 0b001
if not self._apply_file_naming_convention(sources, dry_run=True): if not self._apply_file_naming_convention(sources, dry_run=dry_run):
result |= 0b10 result |= 0b010
if not self._apply_file_permissions(sources, dry_run=dry_run):
result |= 0b100
self._check_folders(self.args.input) self._check_folders(self.args.input)
return result return result
def check(self):
return self._perform(dry_run=True)
def format(self): def format(self):
result = 0 return self._perform(dry_run=False)
sources = self._find_sources(self.args.input)
if not self._format_sources(sources):
result |= 0b01
if not self._apply_file_naming_convention(sources):
result |= 0b10
self._check_folders(self.args.input)
return result
if __name__ == "__main__": if __name__ == "__main__":