mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-06-11 19:33:30 -07:00
Merge pull request #984 from DoniyorI/feature/nfc-v-write-support
nfc: add ISO15693-3 and SLIX write-back support
This commit is contained in:
@@ -109,9 +109,75 @@ static void nfc_scene_emulate_on_enter_iso15693_3(NfcApp* instance) {
|
||||
instance->listener, nfc_scene_emulate_listener_callback_iso15693_3, instance);
|
||||
}
|
||||
|
||||
static NfcCommand
|
||||
nfc_scene_write_poller_callback_iso15693_3(NfcGenericEvent event, void* context) {
|
||||
furi_assert(event.protocol == NfcProtocolIso15693_3);
|
||||
|
||||
NfcApp* instance = context;
|
||||
Iso15693_3Poller* poller = event.instance;
|
||||
const Iso15693_3PollerEvent* iso15693_3_event = event.event_data;
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
|
||||
if(iso15693_3_event->type == Iso15693_3PollerEventTypeReady) {
|
||||
const Iso15693_3Data* write_data =
|
||||
nfc_device_get_data(instance->nfc_device, NfcProtocolIso15693_3);
|
||||
const Iso15693_3Data* card_data = iso15693_3_poller_get_data(poller);
|
||||
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventCardDetected);
|
||||
|
||||
if(card_data->system_info.block_count != write_data->system_info.block_count ||
|
||||
card_data->system_info.block_size != write_data->system_info.block_size) {
|
||||
furi_string_set(instance->text_box_store, "Incompatible card\n(block count/size\nmismatch)");
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcCustomEventPollerFailure);
|
||||
} else {
|
||||
Iso15693_3Error error = Iso15693_3ErrorNone;
|
||||
const uint8_t block_size = write_data->system_info.block_size;
|
||||
const uint8_t* write_block_data =
|
||||
(const uint8_t*)simple_array_cget_data(write_data->block_data);
|
||||
const uint8_t* card_block_data =
|
||||
(const uint8_t*)simple_array_cget_data(card_data->block_data);
|
||||
for(uint16_t i = 0; i < write_data->system_info.block_count; i++) {
|
||||
if(iso15693_3_is_block_locked(write_data, i)) continue;
|
||||
// Skip blocks that already contain the correct data
|
||||
if(memcmp(
|
||||
write_block_data + i * block_size,
|
||||
card_block_data + i * block_size,
|
||||
block_size) == 0)
|
||||
continue;
|
||||
error = iso15693_3_poller_write_block(
|
||||
poller, write_block_data + i * block_size, i, block_size);
|
||||
if(error == Iso15693_3ErrorInternal) {
|
||||
// Block is locked on the target card, skip it
|
||||
error = Iso15693_3ErrorNone;
|
||||
continue;
|
||||
}
|
||||
if(error != Iso15693_3ErrorNone) break;
|
||||
}
|
||||
|
||||
if(error == Iso15693_3ErrorNone) {
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcCustomEventPollerSuccess);
|
||||
} else {
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcCustomEventPollerFailure);
|
||||
}
|
||||
}
|
||||
command = NfcCommandStop;
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
static void nfc_scene_write_on_enter_iso15693_3(NfcApp* instance) {
|
||||
furi_string_set(instance->text_box_store, "Apply the\ntarget card now");
|
||||
instance->poller = nfc_poller_alloc(instance->nfc, NfcProtocolIso15693_3);
|
||||
nfc_poller_start(instance->poller, nfc_scene_write_poller_callback_iso15693_3, instance);
|
||||
}
|
||||
|
||||
const NfcProtocolSupportBase nfc_protocol_support_iso15693_3 = {
|
||||
.features = NfcProtocolFeatureEmulateFull | NfcProtocolFeatureEditUid |
|
||||
NfcProtocolFeatureMoreInfo,
|
||||
NfcProtocolFeatureMoreInfo | NfcProtocolFeatureWrite,
|
||||
|
||||
.scene_info =
|
||||
{
|
||||
@@ -155,7 +221,7 @@ const NfcProtocolSupportBase nfc_protocol_support_iso15693_3 = {
|
||||
},
|
||||
.scene_write =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_enter = nfc_scene_write_on_enter_iso15693_3,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -9,6 +9,10 @@
|
||||
#include "../nfc_protocol_support_common.h"
|
||||
#include "../nfc_protocol_support_gui_common.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define TAG "SlixWrite"
|
||||
|
||||
static void nfc_scene_info_on_enter_slix(NfcApp* instance) {
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const SlixData* data = nfc_device_get_data(device, NfcProtocolSlix);
|
||||
@@ -106,8 +110,105 @@ static void nfc_scene_emulate_on_enter_slix(NfcApp* instance) {
|
||||
nfc_listener_start(instance->listener, nfc_scene_emulate_listener_callback_slix, instance);
|
||||
}
|
||||
|
||||
static NfcCommand nfc_scene_write_poller_callback_slix(NfcGenericEvent event, void* context) {
|
||||
furi_assert(event.protocol == NfcProtocolSlix);
|
||||
|
||||
NfcApp* instance = context;
|
||||
SlixPoller* poller = event.instance;
|
||||
const SlixPollerEvent* slix_event = event.event_data;
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
|
||||
if(slix_event->type == SlixPollerEventTypeReady) {
|
||||
const SlixData* write_data = nfc_device_get_data(instance->nfc_device, NfcProtocolSlix);
|
||||
const Iso15693_3Data* write_iso_data = slix_get_base_data(write_data);
|
||||
const Iso15693_3Data* card_iso_data =
|
||||
slix_get_base_data((const SlixData*)nfc_poller_get_data(instance->poller));
|
||||
|
||||
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventCardDetected);
|
||||
|
||||
if(card_iso_data->system_info.block_count != write_iso_data->system_info.block_count ||
|
||||
card_iso_data->system_info.block_size != write_iso_data->system_info.block_size) {
|
||||
furi_string_set(
|
||||
instance->text_box_store,
|
||||
"Incompatible card\n(block count/size\nmismatch)");
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcCustomEventPollerFailure);
|
||||
} else {
|
||||
SlixError error = SlixErrorNone;
|
||||
uint16_t failed_block = 0;
|
||||
const uint8_t block_size = write_iso_data->system_info.block_size;
|
||||
const uint8_t* write_data_ptr =
|
||||
(const uint8_t*)simple_array_cget_data(write_iso_data->block_data);
|
||||
const uint8_t* card_data_ptr =
|
||||
(const uint8_t*)simple_array_cget_data(card_iso_data->block_data);
|
||||
for(uint16_t i = 0; i < write_iso_data->system_info.block_count; i++) {
|
||||
if(iso15693_3_is_block_locked(write_iso_data, i)) continue;
|
||||
// Skip blocks that already contain the correct data
|
||||
if(memcmp(
|
||||
write_data_ptr + i * block_size,
|
||||
card_data_ptr + i * block_size,
|
||||
block_size) == 0)
|
||||
continue;
|
||||
error = slix_poller_write_block(
|
||||
poller, write_data_ptr + i * block_size, i, block_size);
|
||||
if(error == SlixErrorInternal) {
|
||||
// Block is locked on the target card, skip it
|
||||
error = SlixErrorNone;
|
||||
continue;
|
||||
}
|
||||
if(error != SlixErrorNone) {
|
||||
failed_block = i;
|
||||
FURI_LOG_E(TAG, "Write failed: block %u, error %d", failed_block, (int)error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(error == SlixErrorNone) {
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcCustomEventPollerSuccess);
|
||||
} else {
|
||||
const char* err_name;
|
||||
switch(error) {
|
||||
case SlixErrorTimeout:
|
||||
err_name = "Timeout";
|
||||
break;
|
||||
case SlixErrorFormat:
|
||||
err_name = "BadCRC";
|
||||
break;
|
||||
case SlixErrorNotSupported:
|
||||
err_name = "NotSupported";
|
||||
break;
|
||||
case SlixErrorInternal:
|
||||
err_name = "Locked";
|
||||
break;
|
||||
case SlixErrorWrongPassword:
|
||||
err_name = "WrongPwd";
|
||||
break;
|
||||
default:
|
||||
err_name = "Unknown";
|
||||
break;
|
||||
}
|
||||
furi_string_printf(
|
||||
instance->text_box_store, "Block %u: %s", failed_block, err_name);
|
||||
view_dispatcher_send_custom_event(
|
||||
instance->view_dispatcher, NfcCustomEventPollerFailure);
|
||||
}
|
||||
}
|
||||
command = NfcCommandStop;
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
static void nfc_scene_write_on_enter_slix(NfcApp* instance) {
|
||||
furi_string_set(instance->text_box_store, "Apply the\ntarget card now");
|
||||
instance->poller = nfc_poller_alloc(instance->nfc, NfcProtocolSlix);
|
||||
nfc_poller_start(instance->poller, nfc_scene_write_poller_callback_slix, instance);
|
||||
}
|
||||
|
||||
const NfcProtocolSupportBase nfc_protocol_support_slix = {
|
||||
.features = NfcProtocolFeatureEmulateFull | NfcProtocolFeatureMoreInfo,
|
||||
.features = NfcProtocolFeatureEmulateFull | NfcProtocolFeatureMoreInfo |
|
||||
NfcProtocolFeatureWrite,
|
||||
|
||||
.scene_info =
|
||||
{
|
||||
@@ -151,7 +252,7 @@ const NfcProtocolSupportBase nfc_protocol_support_slix = {
|
||||
},
|
||||
.scene_write =
|
||||
{
|
||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||
.on_enter = nfc_scene_write_on_enter_slix,
|
||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -15,6 +15,11 @@ extern "C" {
|
||||
#define ISO15693_3_FDT_LISTEN_FC (4320U)
|
||||
#define ISO15693_3_POLL_POLL_MIN_US (1500U)
|
||||
|
||||
/* NVM write time varies by tag type (ICODE SLIX: 9.6ms, generic: up to 20ms).
|
||||
* ISO 15693-3 write commands require a longer FWT than reads to account for
|
||||
* EEPROM programming delays before the tag responds. 20ms covers all known tags. */
|
||||
#define ISO15693_3_FDT_WRITE_POLL_FC (271200U)
|
||||
|
||||
#define ISO15693_3_REQ_FLAG_SUBCARRIER_1 (0U << 0)
|
||||
#define ISO15693_3_REQ_FLAG_SUBCARRIER_2 (1U << 0)
|
||||
#define ISO15693_3_REQ_FLAG_DATA_RATE_LO (0U << 1)
|
||||
|
||||
@@ -176,6 +176,25 @@ Iso15693_3Error
|
||||
return ret;
|
||||
}
|
||||
|
||||
Iso15693_3Error iso15693_3_write_block_response_parse(const BitBuffer* buf) {
|
||||
Iso15693_3Error ret = Iso15693_3ErrorNone;
|
||||
|
||||
do {
|
||||
if(iso15693_3_error_response_parse(&ret, buf)) break;
|
||||
|
||||
typedef struct {
|
||||
uint8_t flags;
|
||||
} WriteBlockResponseLayout;
|
||||
|
||||
if(bit_buffer_get_size_bytes(buf) != sizeof(WriteBlockResponseLayout)) {
|
||||
ret = Iso15693_3ErrorUnexpectedResponse;
|
||||
break;
|
||||
}
|
||||
} while(false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Iso15693_3Error iso15693_3_get_block_security_response_parse(
|
||||
uint8_t* data,
|
||||
uint16_t block_count,
|
||||
|
||||
@@ -28,6 +28,8 @@ Iso15693_3Error
|
||||
Iso15693_3Error
|
||||
iso15693_3_read_block_response_parse(uint8_t* data, uint8_t block_size, const BitBuffer* buf);
|
||||
|
||||
Iso15693_3Error iso15693_3_write_block_response_parse(const BitBuffer* buf);
|
||||
|
||||
Iso15693_3Error iso15693_3_get_block_security_response_parse(
|
||||
uint8_t* data,
|
||||
uint16_t block_count,
|
||||
|
||||
@@ -13,6 +13,14 @@ extern "C" {
|
||||
*/
|
||||
typedef struct Iso15693_3Poller Iso15693_3Poller;
|
||||
|
||||
/**
|
||||
* @brief Get the Iso15693_3 data accumulated by the poller.
|
||||
*
|
||||
* @param[in] instance pointer to the Iso15693_3Poller instance.
|
||||
* @return pointer to the Iso15693_3Data structure filled during activation.
|
||||
*/
|
||||
const Iso15693_3Data* iso15693_3_poller_get_data(Iso15693_3Poller* instance);
|
||||
|
||||
/**
|
||||
* @brief Enumeration of possible Iso15693_3 poller event types.
|
||||
*/
|
||||
@@ -144,6 +152,40 @@ Iso15693_3Error iso15693_3_poller_get_blocks_security(
|
||||
uint8_t* data,
|
||||
uint16_t block_count);
|
||||
|
||||
/**
|
||||
* @brief Write a single Iso15693_3 block.
|
||||
*
|
||||
* Must ONLY be used inside the callback function.
|
||||
*
|
||||
* @param[in, out] instance pointer to the instance to be used in the transaction.
|
||||
* @param[in] data pointer to the buffer containing the data to write.
|
||||
* @param[in] block_number block number to write.
|
||||
* @param[in] block_size size of the block in bytes.
|
||||
* @return Iso15693_3ErrorNone on success, an error code on failure.
|
||||
*/
|
||||
Iso15693_3Error iso15693_3_poller_write_block(
|
||||
Iso15693_3Poller* instance,
|
||||
const uint8_t* data,
|
||||
uint8_t block_number,
|
||||
uint8_t block_size);
|
||||
|
||||
/**
|
||||
* @brief Write multiple consecutive Iso15693_3 blocks.
|
||||
*
|
||||
* Must ONLY be used inside the callback function.
|
||||
*
|
||||
* @param[in, out] instance pointer to the instance to be used in the transaction.
|
||||
* @param[in] data pointer to the buffer containing the data to write.
|
||||
* @param[in] block_count number of blocks to write.
|
||||
* @param[in] block_size size of each block in bytes.
|
||||
* @return Iso15693_3ErrorNone on success, an error code on failure.
|
||||
*/
|
||||
Iso15693_3Error iso15693_3_poller_write_blocks(
|
||||
Iso15693_3Poller* instance,
|
||||
const uint8_t* data,
|
||||
uint16_t block_count,
|
||||
uint8_t block_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -234,6 +234,57 @@ Iso15693_3Error iso15693_3_poller_read_blocks(
|
||||
return ret;
|
||||
}
|
||||
|
||||
Iso15693_3Error iso15693_3_poller_write_block(
|
||||
Iso15693_3Poller* instance,
|
||||
const uint8_t* data,
|
||||
uint8_t block_number,
|
||||
uint8_t block_size) {
|
||||
furi_assert(instance);
|
||||
furi_assert(data);
|
||||
|
||||
bit_buffer_reset(instance->tx_buffer);
|
||||
bit_buffer_reset(instance->rx_buffer);
|
||||
|
||||
bit_buffer_append_byte(
|
||||
instance->tx_buffer, ISO15693_3_REQ_FLAG_SUBCARRIER_1 | ISO15693_3_REQ_FLAG_DATA_RATE_HI);
|
||||
bit_buffer_append_byte(instance->tx_buffer, ISO15693_3_CMD_WRITE_BLOCK);
|
||||
bit_buffer_append_byte(instance->tx_buffer, block_number);
|
||||
bit_buffer_append_bytes(instance->tx_buffer, data, block_size);
|
||||
|
||||
Iso15693_3Error ret;
|
||||
|
||||
do {
|
||||
ret = iso15693_3_poller_send_frame(
|
||||
instance, instance->tx_buffer, instance->rx_buffer, ISO15693_3_FDT_WRITE_POLL_FC);
|
||||
if(ret != Iso15693_3ErrorNone) break;
|
||||
|
||||
ret = iso15693_3_write_block_response_parse(instance->rx_buffer);
|
||||
} while(false);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Iso15693_3Error iso15693_3_poller_write_blocks(
|
||||
Iso15693_3Poller* instance,
|
||||
const uint8_t* data,
|
||||
uint16_t block_count,
|
||||
uint8_t block_size) {
|
||||
furi_assert(instance);
|
||||
furi_assert(data);
|
||||
furi_assert(block_count);
|
||||
furi_assert(block_size);
|
||||
|
||||
Iso15693_3Error ret = Iso15693_3ErrorNone;
|
||||
|
||||
for(uint32_t i = 0; i < block_count; ++i) {
|
||||
ret = iso15693_3_poller_write_block(
|
||||
instance, &data[block_size * i], (uint8_t)i, block_size);
|
||||
if(ret != Iso15693_3ErrorNone) break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Iso15693_3Error iso15693_3_poller_get_blocks_security(
|
||||
Iso15693_3Poller* instance,
|
||||
uint8_t* data,
|
||||
|
||||
@@ -33,8 +33,6 @@ struct Iso15693_3Poller {
|
||||
void* context;
|
||||
};
|
||||
|
||||
const Iso15693_3Data* iso15693_3_poller_get_data(Iso15693_3Poller* instance);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -118,6 +118,40 @@ SlixError slix_poller_set_password(
|
||||
SlixPassword password,
|
||||
SlixRandomNumber random_number);
|
||||
|
||||
/**
|
||||
* @brief Write a single block to a Slix card.
|
||||
*
|
||||
* Must ONLY be used inside the callback function.
|
||||
*
|
||||
* @param[in, out] instance pointer to the instance to be used in the transaction.
|
||||
* @param[in] data pointer to the buffer containing the data to write.
|
||||
* @param[in] block_number block number to write.
|
||||
* @param[in] block_size size of the block in bytes.
|
||||
* @return SlixErrorNone on success, an error code on failure.
|
||||
*/
|
||||
SlixError slix_poller_write_block(
|
||||
SlixPoller* instance,
|
||||
const uint8_t* data,
|
||||
uint8_t block_number,
|
||||
uint8_t block_size);
|
||||
|
||||
/**
|
||||
* @brief Write multiple consecutive blocks to a Slix card.
|
||||
*
|
||||
* Must ONLY be used inside the callback function.
|
||||
*
|
||||
* @param[in, out] instance pointer to the instance to be used in the transaction.
|
||||
* @param[in] data pointer to the buffer containing the data to write.
|
||||
* @param[in] block_count number of blocks to write.
|
||||
* @param[in] block_size size of each block in bytes.
|
||||
* @return SlixErrorNone on success, an error code on failure.
|
||||
*/
|
||||
SlixError slix_poller_write_blocks(
|
||||
SlixPoller* instance,
|
||||
const uint8_t* data,
|
||||
uint16_t block_count,
|
||||
uint8_t block_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -128,3 +128,31 @@ SlixError slix_poller_set_password(
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
SlixError slix_poller_write_block(
|
||||
SlixPoller* instance,
|
||||
const uint8_t* data,
|
||||
uint8_t block_number,
|
||||
uint8_t block_size) {
|
||||
furi_assert(instance);
|
||||
furi_assert(data);
|
||||
|
||||
const Iso15693_3Error error =
|
||||
iso15693_3_poller_write_block(instance->iso15693_3_poller, data, block_number, block_size);
|
||||
return slix_process_iso15693_3_error(error);
|
||||
}
|
||||
|
||||
SlixError slix_poller_write_blocks(
|
||||
SlixPoller* instance,
|
||||
const uint8_t* data,
|
||||
uint16_t block_count,
|
||||
uint8_t block_size) {
|
||||
furi_assert(instance);
|
||||
furi_assert(data);
|
||||
furi_assert(block_count);
|
||||
furi_assert(block_size);
|
||||
|
||||
const Iso15693_3Error error =
|
||||
iso15693_3_poller_write_blocks(instance->iso15693_3_poller, data, block_count, block_size);
|
||||
return slix_process_iso15693_3_error(error);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
entry,status,name,type,params
|
||||
Version,+,87.6,,
|
||||
Version,+,87.7,,
|
||||
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
|
||||
Header,+,applications/services/applications.h,,
|
||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||
@@ -2360,11 +2360,14 @@ Function,+,iso15693_3_is_equal,_Bool,"const Iso15693_3Data*, const Iso15693_3Dat
|
||||
Function,+,iso15693_3_load,_Bool,"Iso15693_3Data*, FlipperFormat*, uint32_t"
|
||||
Function,+,iso15693_3_poller_activate,Iso15693_3Error,"Iso15693_3Poller*, Iso15693_3Data*"
|
||||
Function,+,iso15693_3_poller_get_blocks_security,Iso15693_3Error,"Iso15693_3Poller*, uint8_t*, uint16_t"
|
||||
Function,+,iso15693_3_poller_get_data,const Iso15693_3Data*,Iso15693_3Poller*
|
||||
Function,+,iso15693_3_poller_get_system_info,Iso15693_3Error,"Iso15693_3Poller*, Iso15693_3SystemInfo*"
|
||||
Function,+,iso15693_3_poller_inventory,Iso15693_3Error,"Iso15693_3Poller*, uint8_t*"
|
||||
Function,+,iso15693_3_poller_read_block,Iso15693_3Error,"Iso15693_3Poller*, uint8_t*, uint8_t, uint8_t"
|
||||
Function,+,iso15693_3_poller_read_blocks,Iso15693_3Error,"Iso15693_3Poller*, uint8_t*, uint16_t, uint8_t"
|
||||
Function,+,iso15693_3_poller_send_frame,Iso15693_3Error,"Iso15693_3Poller*, const BitBuffer*, BitBuffer*, uint32_t"
|
||||
Function,+,iso15693_3_poller_write_block,Iso15693_3Error,"Iso15693_3Poller*, const uint8_t*, uint8_t, uint8_t"
|
||||
Function,+,iso15693_3_poller_write_blocks,Iso15693_3Error,"Iso15693_3Poller*, const uint8_t*, uint16_t, uint8_t"
|
||||
Function,+,iso15693_3_reset,void,Iso15693_3Data*
|
||||
Function,+,iso15693_3_save,_Bool,"const Iso15693_3Data*, FlipperFormat*"
|
||||
Function,+,iso15693_3_set_uid,_Bool,"Iso15693_3Data*, const uint8_t*, size_t"
|
||||
@@ -3397,6 +3400,8 @@ Function,+,slix_poller_get_random_number,SlixError,"SlixPoller*, SlixRandomNumbe
|
||||
Function,+,slix_poller_read_signature,SlixError,"SlixPoller*, SlixSignature*"
|
||||
Function,+,slix_poller_send_frame,SlixError,"SlixPoller*, const BitBuffer*, BitBuffer*, uint32_t"
|
||||
Function,+,slix_poller_set_password,SlixError,"SlixPoller*, SlixPasswordType, SlixPassword, SlixRandomNumber"
|
||||
Function,+,slix_poller_write_block,SlixError,"SlixPoller*, const uint8_t*, uint8_t, uint8_t"
|
||||
Function,+,slix_poller_write_blocks,SlixError,"SlixPoller*, const uint8_t*, uint16_t, uint8_t"
|
||||
Function,+,slix_reset,void,SlixData*
|
||||
Function,+,slix_save,_Bool,"const SlixData*, FlipperFormat*"
|
||||
Function,+,slix_set_uid,_Bool,"SlixData*, const uint8_t*, size_t"
|
||||
|
||||
|
Reference in New Issue
Block a user