This commit is contained in:
Willy-JL
2023-05-26 19:33:56 +01:00
90 changed files with 8544 additions and 665 deletions
+21 -11
View File
@@ -40,8 +40,12 @@ struct InfraredWorkerSignal {
size_t timings_cnt;
union {
InfraredMessage message;
/* +1 is for pause we add at the beginning */
uint32_t timings[MAX_TIMINGS_AMOUNT + 1];
struct {
/* +1 is for pause we add at the beginning */
uint32_t timings[MAX_TIMINGS_AMOUNT + 1];
uint32_t frequency;
float duty_cycle;
} raw;
};
};
@@ -146,7 +150,7 @@ static void
}
if(instance->signal.timings_cnt < MAX_TIMINGS_AMOUNT) {
instance->signal.timings[instance->signal.timings_cnt] = duration;
instance->signal.raw.timings[instance->signal.timings_cnt] = duration;
++instance->signal.timings_cnt;
} else {
uint32_t flags_set = furi_thread_flags_set(
@@ -300,7 +304,7 @@ void infrared_worker_get_raw_signal(
furi_assert(timings);
furi_assert(timings_cnt);
*timings = signal->timings;
*timings = signal->raw.timings;
*timings_cnt = signal->timings_cnt;
}
@@ -390,8 +394,8 @@ static bool infrared_get_new_signal(InfraredWorker* instance) {
infrared_get_protocol_duty_cycle(instance->signal.message.protocol);
} else {
furi_assert(instance->signal.timings_cnt > 1);
new_tx_frequency = INFRARED_COMMON_CARRIER_FREQUENCY;
new_tx_duty_cycle = INFRARED_COMMON_DUTY_CYCLE;
new_tx_frequency = instance->signal.raw.frequency;
new_tx_duty_cycle = instance->signal.raw.duty_cycle;
}
instance->tx.tx_raw_cnt = 0;
@@ -426,7 +430,7 @@ static bool infrared_worker_tx_fill_buffer(InfraredWorker* instance) {
if(instance->signal.decoded) {
status = infrared_encode(instance->infrared_encoder, &timing.duration, &timing.level);
} else {
timing.duration = instance->signal.timings[instance->tx.tx_raw_cnt];
timing.duration = instance->signal.raw.timings[instance->tx.tx_raw_cnt];
/* raw always starts from Mark, but we fill it with space delay at start */
timing.level = (instance->tx.tx_raw_cnt % 2);
++instance->tx.tx_raw_cnt;
@@ -597,15 +601,21 @@ void infrared_worker_set_decoded_signal(InfraredWorker* instance, const Infrared
void infrared_worker_set_raw_signal(
InfraredWorker* instance,
const uint32_t* timings,
size_t timings_cnt) {
size_t timings_cnt,
uint32_t frequency,
float duty_cycle) {
furi_assert(instance);
furi_assert(timings);
furi_assert(timings_cnt > 0);
size_t max_copy_num = COUNT_OF(instance->signal.timings) - 1;
furi_assert((frequency <= INFRARED_MAX_FREQUENCY) && (frequency >= INFRARED_MIN_FREQUENCY));
furi_assert((duty_cycle < 1.0f) && (duty_cycle > 0.0f));
size_t max_copy_num = COUNT_OF(instance->signal.raw.timings) - 1;
furi_check(timings_cnt <= max_copy_num);
instance->signal.timings[0] = INFRARED_RAW_TX_TIMING_DELAY_US;
memcpy(&instance->signal.timings[1], timings, timings_cnt * sizeof(uint32_t));
instance->signal.raw.frequency = frequency;
instance->signal.raw.duty_cycle = duty_cycle;
instance->signal.raw.timings[0] = INFRARED_RAW_TX_TIMING_DELAY_US;
memcpy(&instance->signal.raw.timings[1], timings, timings_cnt * sizeof(uint32_t));
instance->signal.decoded = false;
instance->signal.timings_cnt = timings_cnt + 1;
}
+7 -3
View File
@@ -130,9 +130,9 @@ void infrared_worker_tx_set_signal_sent_callback(
/** Callback to pass to infrared_worker_tx_set_get_signal_callback() if signal
* is steady and will not be changed between infrared_worker start and stop.
* Before starting transmission, desired steady signal must be set with
* infrared_worker_make_decoded_signal() or infrared_worker_make_raw_signal().
* infrared_worker_set_decoded_signal() or infrared_worker_set_raw_signal().
*
* This function should not be implicitly called.
* This function should not be called directly.
*
* @param[in] context - context
* @param[out] instance - InfraredWorker instance
@@ -172,11 +172,15 @@ void infrared_worker_set_decoded_signal(InfraredWorker* instance, const Infrared
* @param[out] instance - InfraredWorker instance
* @param[in] timings - array of raw timings
* @param[in] timings_cnt - size of array of raw timings
* @param[in] frequency - carrier frequency in Hertz
* @param[in] duty_cycle - carrier duty cycle (0.0 - 1.0)
*/
void infrared_worker_set_raw_signal(
InfraredWorker* instance,
const uint32_t* timings,
size_t timings_cnt);
size_t timings_cnt,
uint32_t frequency,
float duty_cycle);
#ifdef __cplusplus
}
+2
View File
@@ -45,6 +45,8 @@ const char* nfc_mf_ul_type(MfUltralightType type, bool full_name) {
return "NTAG I2C Plus 2K";
} else if(type == MfUltralightTypeNTAG203) {
return "NTAG203";
} else if(type == MfUltralightTypeULC) {
return "Mifare Ultralight C";
} else if(type == MfUltralightTypeUL11 && full_name) {
return "Mifare Ultralight 11";
} else if(type == MfUltralightTypeUL21 && full_name) {
+35 -5
View File
@@ -80,6 +80,8 @@ static MfUltralightFeatures mf_ul_get_features(MfUltralightType type) {
MfUltralightSupportSectorSelect;
case MfUltralightTypeNTAG203:
return MfUltralightSupportCompatWrite | MfUltralightSupportCounterInMemory;
case MfUltralightTypeULC:
return MfUltralightSupportCompatWrite | MfUltralightSupport3DesAuth;
default:
// Assumed original MFUL 512-bit
return MfUltralightSupportCompatWrite;
@@ -96,6 +98,11 @@ static void mf_ul_set_version_ntag203(MfUltralightReader* reader, MfUltralightDa
reader->pages_to_read = 42;
}
static void mf_ul_set_version_ulc(MfUltralightReader* reader, MfUltralightData* data) {
data->type = MfUltralightTypeULC;
reader->pages_to_read = 48;
}
bool mf_ultralight_read_version(
FuriHalNfcTxRxContext* tx_rx,
MfUltralightReader* reader,
@@ -176,7 +183,7 @@ bool mf_ultralight_authenticate(FuriHalNfcTxRxContext* tx_rx, uint32_t key, uint
do {
FURI_LOG_D(TAG, "Authenticating");
tx_rx->tx_data[0] = MF_UL_AUTH;
tx_rx->tx_data[0] = MF_UL_PWD_AUTH;
nfc_util_num2bytes(key, 4, &tx_rx->tx_data[1]);
tx_rx->tx_bits = 40;
tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault;
@@ -717,6 +724,21 @@ bool mf_ultralight_read_tearing_flags(FuriHalNfcTxRxContext* tx_rx, MfUltralight
return flag_read == 2;
}
static bool mf_ul_probe_3des_auth(FuriHalNfcTxRxContext* tx_rx) {
tx_rx->tx_data[0] = MF_UL_AUTHENTICATE_1;
tx_rx->tx_data[1] = 0;
tx_rx->tx_bits = 16;
tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault;
bool rc = furi_hal_nfc_tx_rx(tx_rx, 50) && tx_rx->rx_bits == 9 * 8 &&
tx_rx->rx_data[0] == 0xAF;
// Reset just in case, we're not going to finish authenticating and need to if tag doesn't support auth
furi_hal_nfc_sleep();
furi_hal_nfc_activate_nfca(300, NULL);
return rc;
}
bool mf_ul_read_card(
FuriHalNfcTxRxContext* tx_rx,
MfUltralightReader* reader,
@@ -734,16 +756,20 @@ bool mf_ul_read_card(
mf_ultralight_read_signature(tx_rx, data);
}
} else {
// No GET_VERSION command, check for NTAG203 by reading last page (41)
uint8_t dummy[16];
if(mf_ultralight_read_pages_direct(tx_rx, 41, dummy)) {
// No GET_VERSION command, check if AUTHENTICATE command available (detect UL C).
if(mf_ul_probe_3des_auth(tx_rx)) {
mf_ul_set_version_ulc(reader, data);
} else if(mf_ultralight_read_pages_direct(tx_rx, 41, dummy)) {
// No AUTHENTICATE, check for NTAG203 by reading last page (41)
mf_ul_set_version_ntag203(reader, data);
reader->supported_features = mf_ul_get_features(data->type);
} else {
// We're really an original Mifare Ultralight, reset tag for safety
furi_hal_nfc_sleep();
furi_hal_nfc_activate_nfca(300, NULL);
}
reader->supported_features = mf_ul_get_features(data->type);
}
card_read = mf_ultralight_read_pages(tx_rx, reader, data);
@@ -1229,6 +1255,10 @@ static void mf_ul_emulate_write(
emulator->data_changed = true;
}
bool mf_ul_emulation_supported(MfUltralightData* data) {
return data->type != MfUltralightTypeULC;
}
void mf_ul_reset_emulation(MfUltralightEmulator* emulator, bool is_power_cycle) {
emulator->comp_write_cmd_started = false;
emulator->sector_select_cmd_started = false;
@@ -1733,7 +1763,7 @@ bool mf_ul_prepare_emulation_response(
}
}
}
} else if(cmd == MF_UL_AUTH) {
} else if(cmd == MF_UL_PWD_AUTH) {
if(emulator->supported_features & MfUltralightSupportAuth) {
if(buff_rx_len == (1 + 4) * 8) {
// Record password sent by PCD
+6 -1
View File
@@ -16,7 +16,8 @@
#define MF_UL_COMP_WRITE (0xA0)
#define MF_UL_READ_CNT (0x39)
#define MF_UL_INC_CNT (0xA5)
#define MF_UL_AUTH (0x1B)
#define MF_UL_AUTHENTICATE_1 (0x1A)
#define MF_UL_PWD_AUTH (0x1B)
#define MF_UL_READ_SIG (0x3C)
#define MF_UL_CHECK_TEARING (0x3E)
#define MF_UL_READ_VCSL (0x4B)
@@ -41,6 +42,7 @@ typedef enum {
typedef enum {
MfUltralightTypeUnknown,
MfUltralightTypeNTAG203,
MfUltralightTypeULC,
// Below have config pages and GET_VERSION support
MfUltralightTypeUL11,
MfUltralightTypeUL21,
@@ -77,6 +79,7 @@ typedef enum {
MfUltralightSupportAsciiMirror = 1 << 11,
// NTAG203 counter that's in memory rather than through a command
MfUltralightSupportCounterInMemory = 1 << 12,
MfUltralightSupport3DesAuth = 1 << 13,
} MfUltralightFeatures;
typedef enum {
@@ -237,6 +240,8 @@ bool mf_ul_read_card(
MfUltralightReader* reader,
MfUltralightData* data);
bool mf_ul_emulation_supported(MfUltralightData* data);
void mf_ul_reset_emulation(MfUltralightEmulator* emulator, bool is_power_cycle);
void mf_ul_prepare_emulation(MfUltralightEmulator* emulator, MfUltralightData* data);
+1
View File
@@ -8,6 +8,7 @@ env.Append(
"#/lib/toolbox",
],
SDK_HEADERS=[
File("api_lock.h"),
File("value_index.h"),
File("manchester_decoder.h"),
File("manchester_encoder.h"),