mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2024-12-24 13:52:38 +03:00
OFW PR 2658: Hitag
by blackvault88
This commit is contained in:
parent
d620285e0a
commit
c9ddecff87
@ -186,11 +186,16 @@ int32_t lfrfid_app(void* p) {
|
|||||||
DOLPHIN_DEED(DolphinDeedRfidEmulate);
|
DOLPHIN_DEED(DolphinDeedRfidEmulate);
|
||||||
} else {
|
} else {
|
||||||
furi_string_set(app->file_path, args);
|
furi_string_set(app->file_path, args);
|
||||||
lfrfid_load_key_data(app, app->file_path, true);
|
if(lfrfid_load_key_data(app, app->file_path, true)) {
|
||||||
view_dispatcher_attach_to_gui(
|
view_dispatcher_attach_to_gui(
|
||||||
app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
|
app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
|
||||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneEmulate);
|
scene_manager_next_scene(app->scene_manager, LfRfidSceneEmulate);
|
||||||
DOLPHIN_DEED(DolphinDeedRfidEmulate);
|
DOLPHIN_DEED(DolphinDeedRfidEmulate);
|
||||||
|
} else {
|
||||||
|
// TODO: exit properly
|
||||||
|
lfrfid_free(app);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -56,6 +56,8 @@ enum LfRfidCustomEvent {
|
|||||||
LfRfidEventReadSenseCardEnd,
|
LfRfidEventReadSenseCardEnd,
|
||||||
LfRfidEventReadStartASK,
|
LfRfidEventReadStartASK,
|
||||||
LfRfidEventReadStartPSK,
|
LfRfidEventReadStartPSK,
|
||||||
|
LfRfidEventReadStartRTF,
|
||||||
|
LfRfidEventReadSenseHitag, //TODO combine with sensecardstart?
|
||||||
LfRfidEventReadDone,
|
LfRfidEventReadDone,
|
||||||
LfRfidEventReadOverrun,
|
LfRfidEventReadOverrun,
|
||||||
LfRfidEventReadError,
|
LfRfidEventReadError,
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
SubmenuIndexASK,
|
SubmenuIndexASK,
|
||||||
SubmenuIndexPSK,
|
SubmenuIndexPSK,
|
||||||
|
SubmenuIndexHitag,
|
||||||
SubmenuIndexClearT5577,
|
SubmenuIndexClearT5577,
|
||||||
SubmenuIndexRAW,
|
SubmenuIndexRAW,
|
||||||
SubmenuIndexRAWEmulate,
|
SubmenuIndexRAWEmulate,
|
||||||
@ -31,6 +32,12 @@ void lfrfid_scene_extra_actions_on_enter(void* context) {
|
|||||||
SubmenuIndexPSK,
|
SubmenuIndexPSK,
|
||||||
lfrfid_scene_extra_actions_submenu_callback,
|
lfrfid_scene_extra_actions_submenu_callback,
|
||||||
app);
|
app);
|
||||||
|
submenu_add_item(
|
||||||
|
submenu,
|
||||||
|
"Read RTF (Reader Talks First)",
|
||||||
|
SubmenuIndexHitag,
|
||||||
|
lfrfid_scene_extra_actions_submenu_callback,
|
||||||
|
app);
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
submenu,
|
submenu,
|
||||||
"Clear T5577 Password",
|
"Clear T5577 Password",
|
||||||
@ -79,6 +86,11 @@ bool lfrfid_scene_extra_actions_on_event(void* context, SceneManagerEvent event)
|
|||||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneRead);
|
scene_manager_next_scene(app->scene_manager, LfRfidSceneRead);
|
||||||
DOLPHIN_DEED(DolphinDeedRfidRead);
|
DOLPHIN_DEED(DolphinDeedRfidRead);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
|
} else if(event.event == SubmenuIndexHitag) {
|
||||||
|
app->read_type = LFRFIDWorkerReadTypeRTFOnly;
|
||||||
|
scene_manager_next_scene(app->scene_manager, LfRfidSceneRead);
|
||||||
|
DOLPHIN_DEED(DolphinDeedRfidRead);
|
||||||
|
consumed = true;
|
||||||
} else if(event.event == SubmenuIndexClearT5577) {
|
} else if(event.event == SubmenuIndexClearT5577) {
|
||||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneClearT5577Confirm);
|
scene_manager_next_scene(app->scene_manager, LfRfidSceneClearT5577Confirm);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
|
@ -36,6 +36,10 @@ static void
|
|||||||
event = LfRfidEventReadStartASK;
|
event = LfRfidEventReadStartASK;
|
||||||
} else if(result == LFRFIDWorkerReadStartPSK) {
|
} else if(result == LFRFIDWorkerReadStartPSK) {
|
||||||
event = LfRfidEventReadStartPSK;
|
event = LfRfidEventReadStartPSK;
|
||||||
|
} else if(result == LFRFIDWorkerReadStartRTF) {
|
||||||
|
event = LfRfidEventReadStartRTF;
|
||||||
|
} else if(result == LFRFIDWorkerReadSenseHitag) { //TODO combine with sensecardstart?
|
||||||
|
event = LfRfidEventReadSenseHitag;
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -50,6 +54,9 @@ void lfrfid_scene_read_on_enter(void* context) {
|
|||||||
lfrfid_view_read_set_read_mode(app->read_view, LfRfidReadPskOnly);
|
lfrfid_view_read_set_read_mode(app->read_view, LfRfidReadPskOnly);
|
||||||
} else if(app->read_type == LFRFIDWorkerReadTypeASKOnly) {
|
} else if(app->read_type == LFRFIDWorkerReadTypeASKOnly) {
|
||||||
lfrfid_view_read_set_read_mode(app->read_view, LfRfidReadAskOnly);
|
lfrfid_view_read_set_read_mode(app->read_view, LfRfidReadAskOnly);
|
||||||
|
} else if(app->read_type == LFRFIDWorkerReadTypeRTFOnly) {
|
||||||
|
lfrfid_view_read_set_read_state(app->read_view, LfRfidReadScanning);
|
||||||
|
lfrfid_view_read_set_read_mode(app->read_view, LfRfidReadRtfOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
lfrfid_worker_start_thread(app->lfworker);
|
lfrfid_worker_start_thread(app->lfworker);
|
||||||
@ -93,6 +100,17 @@ bool lfrfid_scene_read_on_event(void* context, SceneManagerEvent event) {
|
|||||||
lfrfid_view_read_set_read_mode(app->read_view, LfRfidReadAsk);
|
lfrfid_view_read_set_read_mode(app->read_view, LfRfidReadAsk);
|
||||||
}
|
}
|
||||||
consumed = true;
|
consumed = true;
|
||||||
|
} else if(event.event == LfRfidEventReadStartRTF) {
|
||||||
|
if(app->read_type == LFRFIDWorkerReadTypeAuto) {
|
||||||
|
lfrfid_view_read_set_read_state(app->read_view, LfRfidReadScanning);
|
||||||
|
lfrfid_view_read_set_read_mode(app->read_view, LfRfidReadHitag);
|
||||||
|
}
|
||||||
|
consumed = true;
|
||||||
|
} else if(event.event == LfRfidEventReadSenseHitag) { //TODO combine with sensecardstart?
|
||||||
|
if(app->read_type == LFRFIDWorkerReadTypeAuto ||
|
||||||
|
app->read_type == LFRFIDWorkerReadTypeRTFOnly) {
|
||||||
|
lfrfid_view_read_set_read_state(app->read_view, LfRfidReadTagDetected);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,9 @@ void lfrfid_scene_save_type_on_enter(void* context) {
|
|||||||
SaveTypeCtx* state = malloc(sizeof(SaveTypeCtx));
|
SaveTypeCtx* state = malloc(sizeof(SaveTypeCtx));
|
||||||
FuriString* protocol_string = furi_string_alloc();
|
FuriString* protocol_string = furi_string_alloc();
|
||||||
for(uint8_t i = 0; i < LFRFIDProtocolMax; i++) {
|
for(uint8_t i = 0; i < LFRFIDProtocolMax; i++) {
|
||||||
|
if(i == LFRFIDProtocolHitag1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if((strcmp(
|
if((strcmp(
|
||||||
protocol_dict_get_manufacturer(app->dict, i),
|
protocol_dict_get_manufacturer(app->dict, i),
|
||||||
protocol_dict_get_name(app->dict, i)) != 0) &&
|
protocol_dict_get_name(app->dict, i)) != 0) &&
|
||||||
|
@ -17,12 +17,16 @@ void lfrfid_scene_saved_info_on_enter(void* context) {
|
|||||||
uint8_t* data = (uint8_t*)malloc(size);
|
uint8_t* data = (uint8_t*)malloc(size);
|
||||||
protocol_dict_get_data(app->dict, app->protocol_id, data, size);
|
protocol_dict_get_data(app->dict, app->protocol_id, data, size);
|
||||||
for(uint8_t i = 0; i < size; i++) {
|
for(uint8_t i = 0; i < size; i++) {
|
||||||
|
if(i >= 18) {
|
||||||
|
furi_string_cat_printf(tmp_string, "..");
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
if(i != 0) {
|
if(i != 0) {
|
||||||
furi_string_cat_printf(tmp_string, ":");
|
furi_string_cat_printf(tmp_string, ":");
|
||||||
}
|
}
|
||||||
|
|
||||||
furi_string_cat_printf(tmp_string, "%02X", data[i]);
|
furi_string_cat_printf(tmp_string, "%02X", data[i]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
free(data);
|
free(data);
|
||||||
|
|
||||||
FuriString* render_data;
|
FuriString* render_data;
|
||||||
|
@ -11,6 +11,7 @@ struct LfRfidReadView {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
IconAnimation* icon;
|
IconAnimation* icon;
|
||||||
LfRfidReadViewMode read_mode;
|
LfRfidReadViewMode read_mode;
|
||||||
|
LfRfidReadViewState read_state;
|
||||||
} LfRfidReadViewModel;
|
} LfRfidReadViewModel;
|
||||||
|
|
||||||
static void lfrfid_view_read_draw_callback(Canvas* canvas, void* _model) {
|
static void lfrfid_view_read_draw_callback(Canvas* canvas, void* _model) {
|
||||||
@ -22,36 +23,69 @@ static void lfrfid_view_read_draw_callback(Canvas* canvas, void* _model) {
|
|||||||
canvas_set_font(canvas, FontPrimary);
|
canvas_set_font(canvas, FontPrimary);
|
||||||
|
|
||||||
if(model->read_mode == LfRfidReadAsk) {
|
if(model->read_mode == LfRfidReadAsk) {
|
||||||
canvas_draw_str(canvas, 70, 16, "Reading 1/2");
|
canvas_draw_str(canvas, 70, 8, "Reading 1/3");
|
||||||
|
|
||||||
canvas_draw_str(canvas, 77, 29, "ASK");
|
canvas_draw_str(canvas, 77, 20, "ASK");
|
||||||
canvas_draw_icon(canvas, 70, 22, &I_ButtonRight_4x7);
|
canvas_draw_icon(canvas, 70, 13, &I_ButtonRight_4x7);
|
||||||
canvas_draw_icon_animation(canvas, 102, 21, model->icon);
|
canvas_draw_icon_animation(canvas, 112, 12, model->icon);
|
||||||
|
|
||||||
canvas_set_font(canvas, FontSecondary);
|
canvas_set_font(canvas, FontSecondary);
|
||||||
canvas_draw_str(canvas, 77, 43, "PSK");
|
canvas_draw_str(canvas, 77, 33, "PSK");
|
||||||
|
canvas_draw_str(canvas, 77, 46, "RTF");
|
||||||
} else if(model->read_mode == LfRfidReadPsk) {
|
} else if(model->read_mode == LfRfidReadPsk) {
|
||||||
canvas_draw_str(canvas, 70, 16, "Reading 2/2");
|
canvas_draw_str(canvas, 70, 8, "Reading 2/3");
|
||||||
|
|
||||||
canvas_draw_str(canvas, 77, 43, "PSK");
|
canvas_draw_str(canvas, 77, 33, "PSK");
|
||||||
canvas_draw_icon(canvas, 70, 36, &I_ButtonRight_4x7);
|
canvas_draw_icon(canvas, 70, 26, &I_ButtonRight_4x7);
|
||||||
canvas_draw_icon_animation(canvas, 102, 35, model->icon);
|
canvas_draw_icon_animation(canvas, 112, 25, model->icon);
|
||||||
|
|
||||||
canvas_set_font(canvas, FontSecondary);
|
canvas_set_font(canvas, FontSecondary);
|
||||||
canvas_draw_str(canvas, 77, 29, "ASK");
|
canvas_draw_str(canvas, 77, 20, "ASK");
|
||||||
} else {
|
canvas_draw_str(canvas, 77, 46, "RTF");
|
||||||
|
} else if(model->read_mode == LfRfidReadHitag) {
|
||||||
|
if(model->read_state == LfRfidReadScanning) {
|
||||||
|
canvas_draw_str(canvas, 70, 8, "Reading 3/3");
|
||||||
|
|
||||||
|
canvas_draw_str(canvas, 77, 46, "RTF");
|
||||||
|
canvas_draw_icon(canvas, 70, 39, &I_ButtonRight_4x7);
|
||||||
|
canvas_draw_icon_animation(canvas, 112, 38, model->icon);
|
||||||
|
|
||||||
|
canvas_set_font(canvas, FontSecondary);
|
||||||
|
canvas_draw_str(canvas, 77, 20, "ASK");
|
||||||
|
canvas_draw_str(canvas, 77, 33, "PSK");
|
||||||
|
} else if(model->read_state == LfRfidReadTagDetected) { //TODO switch to other scene?
|
||||||
|
canvas_draw_str(canvas, 65, 8, "Hitag1 found");
|
||||||
|
|
||||||
|
canvas_set_font(canvas, FontSecondary);
|
||||||
|
//canvas_draw_str(canvas, 70, 20, "## ## ## ##"); //TODO get tag SN from hitag worker
|
||||||
|
canvas_draw_str(canvas, 70, 33, "Reading data");
|
||||||
|
//canvas_draw_str(canvas, 70, 46, "Page: X/64"); //TODO get current page index from hitag worker
|
||||||
|
}
|
||||||
|
} else if(model->read_mode == LfRfidReadAskOnly) {
|
||||||
canvas_draw_str(canvas, 72, 16, "Reading");
|
canvas_draw_str(canvas, 72, 16, "Reading");
|
||||||
|
|
||||||
if(model->read_mode == LfRfidReadAskOnly) {
|
|
||||||
canvas_draw_str(canvas, 77, 35, "ASK");
|
canvas_draw_str(canvas, 77, 35, "ASK");
|
||||||
} else {
|
canvas_draw_icon_animation(canvas, 112, 27, model->icon);
|
||||||
|
} else if(model->read_mode == LfRfidReadPskOnly) {
|
||||||
|
canvas_draw_str(canvas, 72, 16, "Reading");
|
||||||
canvas_draw_str(canvas, 77, 35, "PSK");
|
canvas_draw_str(canvas, 77, 35, "PSK");
|
||||||
|
canvas_draw_icon_animation(canvas, 112, 27, model->icon);
|
||||||
|
} else if(model->read_mode == LfRfidReadRtfOnly) {
|
||||||
|
if(model->read_state == LfRfidReadScanning) {
|
||||||
|
canvas_draw_str(canvas, 72, 16, "Reading");
|
||||||
|
canvas_draw_str(canvas, 77, 35, "RTF");
|
||||||
|
canvas_draw_icon_animation(canvas, 112, 27, model->icon);
|
||||||
|
} else if(model->read_state == LfRfidReadTagDetected) { //TODO switch to other scene?
|
||||||
|
canvas_draw_str(canvas, 65, 8, "Hitag1 found");
|
||||||
|
|
||||||
|
canvas_set_font(canvas, FontSecondary);
|
||||||
|
//canvas_draw_str(canvas, 70, 20, "## ## ## ##"); //TODO get tag SN from hitag worker
|
||||||
|
canvas_draw_str(canvas, 70, 33, "Reading data");
|
||||||
|
//canvas_draw_str(canvas, 70, 46, "Page: X/64"); //TODO get current page index from hitag worker
|
||||||
}
|
}
|
||||||
canvas_draw_icon_animation(canvas, 102, 27, model->icon);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas_set_font(canvas, FontSecondary);
|
canvas_set_font(canvas, FontSecondary);
|
||||||
canvas_draw_str(canvas, 61, 56, "Don't move card");
|
canvas_draw_str(canvas, 61, 60, "Don't move card");
|
||||||
}
|
}
|
||||||
|
|
||||||
void lfrfid_view_read_enter(void* context) {
|
void lfrfid_view_read_enter(void* context) {
|
||||||
@ -111,3 +145,8 @@ void lfrfid_view_read_set_read_mode(LfRfidReadView* read_view, LfRfidReadViewMod
|
|||||||
},
|
},
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lfrfid_view_read_set_read_state(LfRfidReadView* read_view, LfRfidReadViewState state) {
|
||||||
|
with_view_model(
|
||||||
|
read_view->view, LfRfidReadViewModel * model, { model->read_state = state; }, true);
|
||||||
|
}
|
@ -4,10 +4,17 @@
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
LfRfidReadAsk,
|
LfRfidReadAsk,
|
||||||
LfRfidReadPsk,
|
LfRfidReadPsk,
|
||||||
|
LfRfidReadHitag,
|
||||||
LfRfidReadAskOnly,
|
LfRfidReadAskOnly,
|
||||||
LfRfidReadPskOnly
|
LfRfidReadPskOnly,
|
||||||
|
LfRfidReadRtfOnly,
|
||||||
} LfRfidReadViewMode;
|
} LfRfidReadViewMode;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
LfRfidReadScanning,
|
||||||
|
LfRfidReadTagDetected,
|
||||||
|
} LfRfidReadViewState;
|
||||||
|
|
||||||
typedef struct LfRfidReadView LfRfidReadView;
|
typedef struct LfRfidReadView LfRfidReadView;
|
||||||
|
|
||||||
LfRfidReadView* lfrfid_view_read_alloc();
|
LfRfidReadView* lfrfid_view_read_alloc();
|
||||||
@ -17,3 +24,5 @@ void lfrfid_view_read_free(LfRfidReadView* read_view);
|
|||||||
View* lfrfid_view_read_get_view(LfRfidReadView* read_view);
|
View* lfrfid_view_read_get_view(LfRfidReadView* read_view);
|
||||||
|
|
||||||
void lfrfid_view_read_set_read_mode(LfRfidReadView* read_view, LfRfidReadViewMode mode);
|
void lfrfid_view_read_set_read_mode(LfRfidReadView* read_view, LfRfidReadViewMode mode);
|
||||||
|
|
||||||
|
void lfrfid_view_read_set_read_state(LfRfidReadView* read_view, LfRfidReadViewState state);
|
@ -17,17 +17,17 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
const char* header;
|
const char* header;
|
||||||
uint8_t* bytes;
|
uint8_t* bytes;
|
||||||
uint8_t bytes_count;
|
uint16_t bytes_count;
|
||||||
|
|
||||||
ByteInputCallback input_callback;
|
ByteInputCallback input_callback;
|
||||||
ByteChangedCallback changed_callback;
|
ByteChangedCallback changed_callback;
|
||||||
void* callback_context;
|
void* callback_context;
|
||||||
|
|
||||||
bool selected_high_nibble;
|
bool selected_high_nibble;
|
||||||
uint8_t selected_byte;
|
uint16_t selected_byte;
|
||||||
int8_t selected_row; // row -1 - input, row 0 & 1 - keyboard
|
int8_t selected_row; // row -1 - input, row 0 & 1 - keyboard
|
||||||
uint8_t selected_column;
|
uint8_t selected_column;
|
||||||
uint8_t first_visible_byte;
|
uint16_t first_visible_byte;
|
||||||
} ByteInputModel;
|
} ByteInputModel;
|
||||||
|
|
||||||
static const uint8_t keyboard_origin_x = 7;
|
static const uint8_t keyboard_origin_x = 7;
|
||||||
@ -164,7 +164,7 @@ static void byte_input_draw_input(Canvas* canvas, ByteInputModel* model) {
|
|||||||
canvas_draw_icon(canvas, 2, 19, &I_ButtonLeftSmall_3x5);
|
canvas_draw_icon(canvas, 2, 19, &I_ButtonLeftSmall_3x5);
|
||||||
canvas_draw_icon(canvas, 123, 19, &I_ButtonRightSmall_3x5);
|
canvas_draw_icon(canvas, 123, 19, &I_ButtonRightSmall_3x5);
|
||||||
|
|
||||||
for(uint8_t i = model->first_visible_byte;
|
for(uint16_t i = model->first_visible_byte;
|
||||||
i < model->first_visible_byte + MIN(model->bytes_count, max_drawable_bytes);
|
i < model->first_visible_byte + MIN(model->bytes_count, max_drawable_bytes);
|
||||||
i++) {
|
i++) {
|
||||||
uint8_t byte_position = i - model->first_visible_byte;
|
uint8_t byte_position = i - model->first_visible_byte;
|
||||||
@ -253,7 +253,7 @@ static void byte_input_draw_input_selected(Canvas* canvas, ByteInputModel* model
|
|||||||
canvas_draw_icon(canvas, 2, 19, &I_ButtonLeftSmall_3x5);
|
canvas_draw_icon(canvas, 2, 19, &I_ButtonLeftSmall_3x5);
|
||||||
canvas_draw_icon(canvas, 122, 19, &I_ButtonRightSmall_3x5);
|
canvas_draw_icon(canvas, 122, 19, &I_ButtonRightSmall_3x5);
|
||||||
|
|
||||||
for(uint8_t i = model->first_visible_byte;
|
for(uint16_t i = model->first_visible_byte;
|
||||||
i < model->first_visible_byte + MIN(model->bytes_count, max_drawable_bytes);
|
i < model->first_visible_byte + MIN(model->bytes_count, max_drawable_bytes);
|
||||||
i++) {
|
i++) {
|
||||||
uint8_t byte_position = i - model->first_visible_byte;
|
uint8_t byte_position = i - model->first_visible_byte;
|
||||||
@ -305,7 +305,7 @@ static void byte_input_draw_input_selected(Canvas* canvas, ByteInputModel* model
|
|||||||
* @param value char value
|
* @param value char value
|
||||||
* @param high_nibble set high nibble
|
* @param high_nibble set high nibble
|
||||||
*/
|
*/
|
||||||
static void byte_input_set_nibble(uint8_t* data, uint8_t position, char value, bool high_nibble) {
|
static void byte_input_set_nibble(uint8_t* data, uint16_t position, char value, bool high_nibble) {
|
||||||
switch(value) {
|
switch(value) {
|
||||||
case '0':
|
case '0':
|
||||||
case '1':
|
case '1':
|
||||||
@ -750,7 +750,7 @@ void byte_input_set_result_callback(
|
|||||||
ByteChangedCallback changed_callback,
|
ByteChangedCallback changed_callback,
|
||||||
void* callback_context,
|
void* callback_context,
|
||||||
uint8_t* bytes,
|
uint8_t* bytes,
|
||||||
uint8_t bytes_count) {
|
uint16_t bytes_count) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
byte_input->view,
|
byte_input->view,
|
||||||
ByteInputModel * model,
|
ByteInputModel * model,
|
||||||
|
@ -55,7 +55,7 @@ void byte_input_set_result_callback(
|
|||||||
ByteChangedCallback changed_callback,
|
ByteChangedCallback changed_callback,
|
||||||
void* callback_context,
|
void* callback_context,
|
||||||
uint8_t* bytes,
|
uint8_t* bytes,
|
||||||
uint8_t bytes_count);
|
uint16_t bytes_count);
|
||||||
|
|
||||||
/** Set byte input header text
|
/** Set byte input header text
|
||||||
*
|
*
|
||||||
|
@ -626,7 +626,7 @@ Function,+,byte_input_alloc,ByteInput*,
|
|||||||
Function,+,byte_input_free,void,ByteInput*
|
Function,+,byte_input_free,void,ByteInput*
|
||||||
Function,+,byte_input_get_view,View*,ByteInput*
|
Function,+,byte_input_get_view,View*,ByteInput*
|
||||||
Function,+,byte_input_set_header_text,void,"ByteInput*, const char*"
|
Function,+,byte_input_set_header_text,void,"ByteInput*, const char*"
|
||||||
Function,+,byte_input_set_result_callback,void,"ByteInput*, ByteInputCallback, ByteChangedCallback, void*, uint8_t*, uint8_t"
|
Function,+,byte_input_set_result_callback,void,"ByteInput*, ByteInputCallback, ByteChangedCallback, void*, uint8_t*, uint16_t"
|
||||||
Function,-,bzero,void,"void*, size_t"
|
Function,-,bzero,void,"void*, size_t"
|
||||||
Function,-,calloc,void*,"size_t, size_t"
|
Function,-,calloc,void*,"size_t, size_t"
|
||||||
Function,+,canvas_clear,void,Canvas*
|
Function,+,canvas_clear,void,Canvas*
|
||||||
|
|
@ -5,6 +5,42 @@
|
|||||||
|
|
||||||
#define LFRFID_DICT_FILETYPE "Flipper RFID key"
|
#define LFRFID_DICT_FILETYPE "Flipper RFID key"
|
||||||
|
|
||||||
|
bool lfrfid_dict_file_save_hitag1_data(FlipperFormat* file, uint8_t* data) {
|
||||||
|
FuriString* string = furi_string_alloc();
|
||||||
|
bool result = false;
|
||||||
|
uint8_t pageSize = 4;
|
||||||
|
|
||||||
|
do {
|
||||||
|
//write shortened data (tag ID)
|
||||||
|
if(!flipper_format_write_hex(file, "Data", data, pageSize)) break;
|
||||||
|
|
||||||
|
if(!flipper_format_write_comment_cstr(file, "Hitag1 specific data")) break;
|
||||||
|
|
||||||
|
//write pages
|
||||||
|
for(uint8_t p = 0; p < 64; p++) {
|
||||||
|
furi_string_printf(string, "Page %2u", p);
|
||||||
|
if(data[64 * pageSize + p]) {
|
||||||
|
//write page data
|
||||||
|
if(!flipper_format_write_hex(
|
||||||
|
file, furi_string_get_cstr(string), data + p * pageSize, pageSize))
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
//write ?? ?? ?? ??
|
||||||
|
if(!flipper_format_write_string_cstr(
|
||||||
|
file, furi_string_get_cstr(string), "?? ?? ?? ??"))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(p == 64 - 1) {
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
furi_string_free(string);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
bool lfrfid_dict_file_save(ProtocolDict* dict, ProtocolId protocol, const char* filename) {
|
bool lfrfid_dict_file_save(ProtocolDict* dict, ProtocolId protocol, const char* filename) {
|
||||||
furi_check(protocol != PROTOCOL_NO);
|
furi_check(protocol != PROTOCOL_NO);
|
||||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
@ -26,8 +62,12 @@ bool lfrfid_dict_file_save(ProtocolDict* dict, ProtocolId protocol, const char*
|
|||||||
// TODO: write comment about protocol sizes into file
|
// TODO: write comment about protocol sizes into file
|
||||||
|
|
||||||
protocol_dict_get_data(dict, protocol, data, data_size);
|
protocol_dict_get_data(dict, protocol, data, data_size);
|
||||||
|
if(protocol == LFRFIDProtocolHitag1) {
|
||||||
|
if(!lfrfid_dict_file_save_hitag1_data(file, data)) break;
|
||||||
|
} else {
|
||||||
if(!flipper_format_write_hex(file, "Data", data, data_size)) break;
|
if(!flipper_format_write_hex(file, "Data", data, data_size)) break;
|
||||||
|
}
|
||||||
|
|
||||||
result = true;
|
result = true;
|
||||||
} while(false);
|
} while(false);
|
||||||
|
|
||||||
@ -138,6 +178,41 @@ static ProtocolId lfrfid_dict_protocol_fallback(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool lfrfid_dict_file_load_hitag1_data(FlipperFormat* file, uint8_t* data) {
|
||||||
|
FuriString* string = furi_string_alloc();
|
||||||
|
bool result = false;
|
||||||
|
uint8_t tagID[4];
|
||||||
|
uint8_t pageSize = 4;
|
||||||
|
|
||||||
|
do {
|
||||||
|
//read shortened data (tag ID)
|
||||||
|
if(!flipper_format_read_hex(file, "Data", tagID, 4)) break;
|
||||||
|
|
||||||
|
//read pages
|
||||||
|
for(uint8_t p = 0; p < 64; p++) {
|
||||||
|
furi_string_printf(string, "Page %2u", p);
|
||||||
|
if(flipper_format_read_hex(
|
||||||
|
file, furi_string_get_cstr(string), data + p * pageSize, pageSize)) {
|
||||||
|
data[64 * pageSize + p] = 1;
|
||||||
|
} else {
|
||||||
|
data[64 * pageSize + p] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//check data consistency
|
||||||
|
if(memcmp(tagID, data, pageSize) != 0) break;
|
||||||
|
|
||||||
|
//check if tag ID & config page are succesfully read
|
||||||
|
if(data[64 * pageSize + 0] && data[64 * pageSize + 1]) {
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
furi_string_free(string);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
ProtocolId lfrfid_dict_file_load(ProtocolDict* dict, const char* filename) {
|
ProtocolId lfrfid_dict_file_load(ProtocolDict* dict, const char* filename) {
|
||||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
FlipperFormat* file = flipper_format_file_alloc(storage);
|
FlipperFormat* file = flipper_format_file_alloc(storage);
|
||||||
@ -163,6 +238,11 @@ ProtocolId lfrfid_dict_file_load(ProtocolDict* dict, const char* filename) {
|
|||||||
if(protocol == PROTOCOL_NO) {
|
if(protocol == PROTOCOL_NO) {
|
||||||
protocol = lfrfid_dict_protocol_fallback(dict, furi_string_get_cstr(str_result), file);
|
protocol = lfrfid_dict_protocol_fallback(dict, furi_string_get_cstr(str_result), file);
|
||||||
if(protocol == PROTOCOL_NO) break;
|
if(protocol == PROTOCOL_NO) break;
|
||||||
|
} else if(protocol == LFRFIDProtocolHitag1) {
|
||||||
|
// Hitag1 data
|
||||||
|
size_t data_size = protocol_dict_get_data_size(dict, protocol);
|
||||||
|
if(!lfrfid_dict_file_load_hitag1_data(file, data)) break;
|
||||||
|
protocol_dict_set_data(dict, protocol, data, data_size);
|
||||||
} else {
|
} else {
|
||||||
// data
|
// data
|
||||||
size_t data_size = protocol_dict_get_data_size(dict, protocol);
|
size_t data_size = protocol_dict_get_data_size(dict, protocol);
|
||||||
|
2370
lib/lfrfid/lfrfid_hitag_worker.c
Normal file
2370
lib/lfrfid/lfrfid_hitag_worker.c
Normal file
File diff suppressed because it is too large
Load Diff
86
lib/lfrfid/lfrfid_hitag_worker.h
Normal file
86
lib/lfrfid/lfrfid_hitag_worker.h
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <furi.h>
|
||||||
|
#include <furi_hal.h>
|
||||||
|
#include <furi_hal_rfid.h>
|
||||||
|
#include <furi_hal_interrupt.h>
|
||||||
|
#include <furi_hal_resources.h>
|
||||||
|
#include <flipper_format/flipper_format.h>
|
||||||
|
//#include <toolbox/protocols/protocol_dict.h>
|
||||||
|
#include "protocols/lfrfid_protocols.h"
|
||||||
|
|
||||||
|
#include <toolbox/stream/file_stream.h>
|
||||||
|
#include <toolbox/buffer_stream.h>
|
||||||
|
#include <toolbox/varint.h>
|
||||||
|
#include <tools/varint_pair.h>
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include <stm32wbxx_ll_tim.h>
|
||||||
|
#include <stm32wbxx_ll_comp.h>
|
||||||
|
#include <stm32wbxx_ll_dma.h>
|
||||||
|
|
||||||
|
#include <lfrfid_worker_i.h>
|
||||||
|
|
||||||
|
#include <dolphin/dolphin.h>
|
||||||
|
|
||||||
|
#define HITAG_BLOCKS 16
|
||||||
|
#define HITAG_BLOCKPAGES 4
|
||||||
|
#define HITAG_PAGES 64
|
||||||
|
#define HITAG_PAGEBYTES 4
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
LFRFIDHitagWorkerSettingRead,
|
||||||
|
LFRFIDHitagWorkerSettingEmulate,
|
||||||
|
} LFRFIDHitagWorkerSetting;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
LFRFIDHitagStatusScanning,
|
||||||
|
LFRFIDHitagStatusDetected,
|
||||||
|
LFRFIDHitagStatusRead,
|
||||||
|
} LFRFIDHitagStatus;
|
||||||
|
|
||||||
|
typedef struct LFRFIDHitagWorker LFRFIDHitagWorker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the tag read status
|
||||||
|
*
|
||||||
|
* @return tag read status
|
||||||
|
*/
|
||||||
|
LFRFIDHitagStatus lfrfid_hitag_worker_get_status(LFRFIDHitagWorker* worker);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allocate a new LFRFIDHitagWorker instance
|
||||||
|
*
|
||||||
|
* @return LFRFIDHitagWorker*
|
||||||
|
*/
|
||||||
|
LFRFIDHitagWorker* lfrfid_hitag_worker_alloc(ProtocolDict* dict);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Free a LFRFIDHitagWorker instance
|
||||||
|
*
|
||||||
|
* @param worker LFRFIDHitagWorker instance
|
||||||
|
*/
|
||||||
|
void lfrfid_hitag_worker_free(LFRFIDHitagWorker* worker);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Start hitag worker from own generated field
|
||||||
|
*
|
||||||
|
* @param worker LFRFIDHitagWorker instance
|
||||||
|
* @param setting read/emulate
|
||||||
|
*/
|
||||||
|
void lfrfid_hitag_worker_start(LFRFIDHitagWorker* worker, LFRFIDHitagWorkerSetting setting);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stop worker
|
||||||
|
*
|
||||||
|
* @param worker
|
||||||
|
*/
|
||||||
|
void lfrfid_hitag_worker_stop(LFRFIDHitagWorker* worker);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@ -23,6 +23,7 @@ typedef enum {
|
|||||||
LFRFIDWorkerReadTypeAuto,
|
LFRFIDWorkerReadTypeAuto,
|
||||||
LFRFIDWorkerReadTypeASKOnly,
|
LFRFIDWorkerReadTypeASKOnly,
|
||||||
LFRFIDWorkerReadTypePSKOnly,
|
LFRFIDWorkerReadTypePSKOnly,
|
||||||
|
LFRFIDWorkerReadTypeRTFOnly,
|
||||||
} LFRFIDWorkerReadType;
|
} LFRFIDWorkerReadType;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -32,6 +33,8 @@ typedef enum {
|
|||||||
LFRFIDWorkerReadSenseCardEnd,
|
LFRFIDWorkerReadSenseCardEnd,
|
||||||
LFRFIDWorkerReadStartASK,
|
LFRFIDWorkerReadStartASK,
|
||||||
LFRFIDWorkerReadStartPSK,
|
LFRFIDWorkerReadStartPSK,
|
||||||
|
LFRFIDWorkerReadStartRTF,
|
||||||
|
LFRFIDWorkerReadSenseHitag, //TODO combine with sense carstart?
|
||||||
LFRFIDWorkerReadDone,
|
LFRFIDWorkerReadDone,
|
||||||
} LFRFIDWorkerReadResult;
|
} LFRFIDWorkerReadResult;
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include "lfrfid_worker.h"
|
#include "lfrfid_worker.h"
|
||||||
#include "lfrfid_raw_worker.h"
|
#include "lfrfid_raw_worker.h"
|
||||||
|
#include "lfrfid_hitag_worker.h"
|
||||||
#include "protocols/lfrfid_protocols.h"
|
#include "protocols/lfrfid_protocols.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -94,7 +94,7 @@ typedef enum {
|
|||||||
LFRFIDWorkerReadTimeout,
|
LFRFIDWorkerReadTimeout,
|
||||||
} LFRFIDWorkerReadState;
|
} LFRFIDWorkerReadState;
|
||||||
|
|
||||||
static LFRFIDWorkerReadState lfrfid_worker_read_internal(
|
static LFRFIDWorkerReadState lfrfid_worker_read_ttf( //tag talks first
|
||||||
LFRFIDWorker* worker,
|
LFRFIDWorker* worker,
|
||||||
LFRFIDFeature feature,
|
LFRFIDFeature feature,
|
||||||
uint32_t timeout,
|
uint32_t timeout,
|
||||||
@ -334,6 +334,63 @@ static LFRFIDWorkerReadState lfrfid_worker_read_internal(
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static LFRFIDWorkerReadState lfrfid_worker_read_rtf( //reader talks first
|
||||||
|
LFRFIDWorker* worker,
|
||||||
|
LFRFIDFeature feature,
|
||||||
|
uint32_t timeout,
|
||||||
|
ProtocolId* result_protocol) {
|
||||||
|
UNUSED(feature);
|
||||||
|
LFRFIDWorkerReadState state = LFRFIDWorkerReadTimeout;
|
||||||
|
|
||||||
|
FURI_LOG_D(TAG, "Start RTF");
|
||||||
|
if(worker->read_cb) {
|
||||||
|
worker->read_cb(LFRFIDWorkerReadStartRTF, PROTOCOL_NO, worker->cb_ctx);
|
||||||
|
}
|
||||||
|
LFRFIDHitagWorker* hitag_worker = lfrfid_hitag_worker_alloc(worker->protocols);
|
||||||
|
|
||||||
|
lfrfid_hitag_worker_start(hitag_worker, LFRFIDHitagWorkerSettingRead);
|
||||||
|
|
||||||
|
FURI_LOG_D(TAG, "Read started");
|
||||||
|
|
||||||
|
//scan for hitag for a while and stay in hitag mode if card was detected
|
||||||
|
uint8_t delays = 0;
|
||||||
|
uint8_t delay_ms = 100;
|
||||||
|
bool notified = false;
|
||||||
|
while(1) {
|
||||||
|
furi_delay_ms(delay_ms);
|
||||||
|
|
||||||
|
if(lfrfid_worker_check_for_stop(worker)) {
|
||||||
|
state = LFRFIDWorkerReadExit;
|
||||||
|
*result_protocol = PROTOCOL_NO;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lfrfid_hitag_worker_get_status(hitag_worker) == LFRFIDHitagStatusDetected) {
|
||||||
|
*result_protocol =
|
||||||
|
LFRFIDProtocolHitag1; //TODO get protocol ID from hitag_worker when expanding the worker to include other hitag protocols
|
||||||
|
if(!notified && worker->read_cb) {
|
||||||
|
worker->read_cb(LFRFIDWorkerReadSenseHitag, *result_protocol, worker->cb_ctx);
|
||||||
|
notified = true;
|
||||||
|
}
|
||||||
|
} else if(lfrfid_hitag_worker_get_status(hitag_worker) == LFRFIDHitagStatusRead) {
|
||||||
|
state = LFRFIDWorkerReadOK;
|
||||||
|
*result_protocol =
|
||||||
|
LFRFIDProtocolHitag1; //TODO get protocol ID from hitag_worker when expanding the worker to include other hitag protocols
|
||||||
|
break;
|
||||||
|
} else if(++delays >= timeout / delay_ms) {
|
||||||
|
state = LFRFIDWorkerReadTimeout;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lfrfid_hitag_worker_stop(hitag_worker);
|
||||||
|
lfrfid_hitag_worker_free(hitag_worker);
|
||||||
|
|
||||||
|
FURI_LOG_D(TAG, "Read stopped");
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
static void lfrfid_worker_mode_read_process(LFRFIDWorker* worker) {
|
static void lfrfid_worker_mode_read_process(LFRFIDWorker* worker) {
|
||||||
ProtocolId read_result = PROTOCOL_NO;
|
ProtocolId read_result = PROTOCOL_NO;
|
||||||
LFRFIDWorkerReadState state;
|
LFRFIDWorkerReadState state;
|
||||||
@ -341,6 +398,8 @@ static void lfrfid_worker_mode_read_process(LFRFIDWorker* worker) {
|
|||||||
|
|
||||||
if(worker->read_type == LFRFIDWorkerReadTypePSKOnly) {
|
if(worker->read_type == LFRFIDWorkerReadTypePSKOnly) {
|
||||||
feature = LFRFIDFeaturePSK;
|
feature = LFRFIDFeaturePSK;
|
||||||
|
} else if(worker->read_type == LFRFIDWorkerReadTypeRTFOnly) {
|
||||||
|
feature = LFRFIDFeatureRTF;
|
||||||
} else {
|
} else {
|
||||||
feature = LFRFIDFeatureASK;
|
feature = LFRFIDFeatureASK;
|
||||||
}
|
}
|
||||||
@ -348,8 +407,14 @@ static void lfrfid_worker_mode_read_process(LFRFIDWorker* worker) {
|
|||||||
if(worker->read_type == LFRFIDWorkerReadTypeAuto) {
|
if(worker->read_type == LFRFIDWorkerReadTypeAuto) {
|
||||||
while(1) {
|
while(1) {
|
||||||
// read for a while
|
// read for a while
|
||||||
state = lfrfid_worker_read_internal(
|
|
||||||
|
if(feature == LFRFIDFeatureASK || feature == LFRFIDFeaturePSK) {
|
||||||
|
state = lfrfid_worker_read_ttf(
|
||||||
worker, feature, LFRFID_WORKER_READ_SWITCH_TIME_MS, &read_result);
|
worker, feature, LFRFID_WORKER_READ_SWITCH_TIME_MS, &read_result);
|
||||||
|
} else if(feature == LFRFIDFeatureRTF) {
|
||||||
|
state = lfrfid_worker_read_rtf(
|
||||||
|
worker, feature, LFRFID_WORKER_READ_SWITCH_TIME_MS, &read_result);
|
||||||
|
}
|
||||||
|
|
||||||
if(state == LFRFIDWorkerReadOK || state == LFRFIDWorkerReadExit) {
|
if(state == LFRFIDWorkerReadOK || state == LFRFIDWorkerReadExit) {
|
||||||
break;
|
break;
|
||||||
@ -358,7 +423,9 @@ static void lfrfid_worker_mode_read_process(LFRFIDWorker* worker) {
|
|||||||
// switch to next feature
|
// switch to next feature
|
||||||
if(feature == LFRFIDFeatureASK) {
|
if(feature == LFRFIDFeatureASK) {
|
||||||
feature = LFRFIDFeaturePSK;
|
feature = LFRFIDFeaturePSK;
|
||||||
} else {
|
} else if(feature == LFRFIDFeaturePSK) {
|
||||||
|
feature = LFRFIDFeatureRTF;
|
||||||
|
} else if(feature == LFRFIDFeatureRTF) {
|
||||||
feature = LFRFIDFeatureASK;
|
feature = LFRFIDFeatureASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,10 +434,12 @@ static void lfrfid_worker_mode_read_process(LFRFIDWorker* worker) {
|
|||||||
} else {
|
} else {
|
||||||
while(1) {
|
while(1) {
|
||||||
if(worker->read_type == LFRFIDWorkerReadTypeASKOnly) {
|
if(worker->read_type == LFRFIDWorkerReadTypeASKOnly) {
|
||||||
state = lfrfid_worker_read_internal(worker, feature, UINT32_MAX, &read_result);
|
state = lfrfid_worker_read_ttf(worker, feature, UINT32_MAX, &read_result);
|
||||||
} else {
|
} else if(worker->read_type == LFRFIDWorkerReadTypePSKOnly) {
|
||||||
state = lfrfid_worker_read_internal(
|
state = lfrfid_worker_read_ttf(
|
||||||
worker, feature, LFRFID_WORKER_READ_SWITCH_TIME_MS, &read_result);
|
worker, feature, LFRFID_WORKER_READ_SWITCH_TIME_MS, &read_result);
|
||||||
|
} else {
|
||||||
|
state = lfrfid_worker_read_rtf(worker, feature, UINT32_MAX, &read_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(state == LFRFIDWorkerReadOK || state == LFRFIDWorkerReadExit) {
|
if(state == LFRFIDWorkerReadOK || state == LFRFIDWorkerReadExit) {
|
||||||
@ -406,7 +475,7 @@ static void lfrfid_worker_emulate_dma_isr(bool half, void* context) {
|
|||||||
furi_stream_buffer_send(stream, &flag, sizeof(uint32_t), 0);
|
furi_stream_buffer_send(stream, &flag, sizeof(uint32_t), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lfrfid_worker_mode_emulate_process(LFRFIDWorker* worker) {
|
static void lfrfid_worker_emulate_ttf(LFRFIDWorker* worker) {
|
||||||
LFRFIDWorkerEmulateBuffer* buffer = malloc(sizeof(LFRFIDWorkerEmulateBuffer));
|
LFRFIDWorkerEmulateBuffer* buffer = malloc(sizeof(LFRFIDWorkerEmulateBuffer));
|
||||||
FuriStreamBuffer* stream = furi_stream_buffer_alloc(sizeof(uint32_t), sizeof(uint32_t));
|
FuriStreamBuffer* stream = furi_stream_buffer_alloc(sizeof(uint32_t), sizeof(uint32_t));
|
||||||
LFRFIDProtocol protocol = worker->protocol;
|
LFRFIDProtocol protocol = worker->protocol;
|
||||||
@ -495,6 +564,39 @@ static void lfrfid_worker_mode_emulate_process(LFRFIDWorker* worker) {
|
|||||||
pulse_glue_free(pulse_glue);
|
pulse_glue_free(pulse_glue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void lfrfid_worker_emulate_rtf(LFRFIDWorker* worker) {
|
||||||
|
LFRFIDHitagWorker* hitag_worker = lfrfid_hitag_worker_alloc(
|
||||||
|
worker->protocols); //todo, pass protocols & protocol id when expanding the worker to include other hitag protocols
|
||||||
|
|
||||||
|
lfrfid_hitag_worker_start(hitag_worker, LFRFIDHitagWorkerSettingEmulate);
|
||||||
|
uint8_t delay_ms = 100;
|
||||||
|
while(1) {
|
||||||
|
furi_delay_ms(delay_ms);
|
||||||
|
|
||||||
|
if(lfrfid_worker_check_for_stop(worker)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lfrfid_hitag_worker_stop(hitag_worker);
|
||||||
|
lfrfid_hitag_worker_free(hitag_worker);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lfrfid_worker_mode_emulate_process(LFRFIDWorker* worker) {
|
||||||
|
if(worker != NULL) {
|
||||||
|
if(worker->protocols != NULL) {
|
||||||
|
LFRFIDFeature feature =
|
||||||
|
protocol_dict_get_features(worker->protocols, worker->protocol);
|
||||||
|
|
||||||
|
if(feature == LFRFIDFeatureRTF) {
|
||||||
|
lfrfid_worker_emulate_rtf(worker);
|
||||||
|
} else {
|
||||||
|
lfrfid_worker_emulate_ttf(worker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**************************************************************************************************/
|
/**************************************************************************************************/
|
||||||
/********************************************* WRITE **********************************************/
|
/********************************************* WRITE **********************************************/
|
||||||
/**************************************************************************************************/
|
/**************************************************************************************************/
|
||||||
@ -521,7 +623,7 @@ static void lfrfid_worker_mode_write_process(LFRFIDWorker* worker) {
|
|||||||
t5577_write(&request->t5577);
|
t5577_write(&request->t5577);
|
||||||
|
|
||||||
ProtocolId read_result = PROTOCOL_NO;
|
ProtocolId read_result = PROTOCOL_NO;
|
||||||
LFRFIDWorkerReadState state = lfrfid_worker_read_internal(
|
LFRFIDWorkerReadState state = lfrfid_worker_read_ttf(
|
||||||
worker,
|
worker,
|
||||||
protocol_dict_get_features(worker->protocols, protocol),
|
protocol_dict_get_features(worker->protocols, protocol),
|
||||||
LFRFID_WORKER_WRITE_VERIFY_TIME_MS,
|
LFRFID_WORKER_WRITE_VERIFY_TIME_MS,
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "protocol_pac_stanley.h"
|
#include "protocol_pac_stanley.h"
|
||||||
#include "protocol_keri.h"
|
#include "protocol_keri.h"
|
||||||
#include "protocol_gallagher.h"
|
#include "protocol_gallagher.h"
|
||||||
|
#include "protocol_hitag1.h"
|
||||||
|
|
||||||
const ProtocolBase* lfrfid_protocols[] = {
|
const ProtocolBase* lfrfid_protocols[] = {
|
||||||
[LFRFIDProtocolEM4100] = &protocol_em4100,
|
[LFRFIDProtocolEM4100] = &protocol_em4100,
|
||||||
@ -35,4 +36,5 @@ const ProtocolBase* lfrfid_protocols[] = {
|
|||||||
[LFRFIDProtocolPACStanley] = &protocol_pac_stanley,
|
[LFRFIDProtocolPACStanley] = &protocol_pac_stanley,
|
||||||
[LFRFIDProtocolKeri] = &protocol_keri,
|
[LFRFIDProtocolKeri] = &protocol_keri,
|
||||||
[LFRFIDProtocolGallagher] = &protocol_gallagher,
|
[LFRFIDProtocolGallagher] = &protocol_gallagher,
|
||||||
|
[LFRFIDProtocolHitag1] = &protocol_hitag1,
|
||||||
};
|
};
|
@ -5,6 +5,7 @@
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
LFRFIDFeatureASK = 1 << 0, /** ASK Demodulation */
|
LFRFIDFeatureASK = 1 << 0, /** ASK Demodulation */
|
||||||
LFRFIDFeaturePSK = 1 << 1, /** PSK Demodulation */
|
LFRFIDFeaturePSK = 1 << 1, /** PSK Demodulation */
|
||||||
|
LFRFIDFeatureRTF = 1 << 2, /** Reader Talks First: ASK Demodulation with 2 way communication */
|
||||||
} LFRFIDFeature;
|
} LFRFIDFeature;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -25,6 +26,7 @@ typedef enum {
|
|||||||
LFRFIDProtocolPACStanley,
|
LFRFIDProtocolPACStanley,
|
||||||
LFRFIDProtocolKeri,
|
LFRFIDProtocolKeri,
|
||||||
LFRFIDProtocolGallagher,
|
LFRFIDProtocolGallagher,
|
||||||
|
LFRFIDProtocolHitag1,
|
||||||
LFRFIDProtocolMax,
|
LFRFIDProtocolMax,
|
||||||
} LFRFIDProtocol;
|
} LFRFIDProtocol;
|
||||||
|
|
||||||
|
104
lib/lfrfid/protocols/protocol_hitag1.c
Normal file
104
lib/lfrfid/protocols/protocol_hitag1.c
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
#include <furi.h>
|
||||||
|
#include <toolbox/protocols/protocol.h>
|
||||||
|
#include "lfrfid_protocols.h"
|
||||||
|
|
||||||
|
#define HITAG1_PAGES 64
|
||||||
|
#define HITAG1_DATA_SIZE HITAG1_PAGES * 4 + HITAG1_PAGES
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t tagData[HITAG1_DATA_SIZE];
|
||||||
|
} ProtocolHitag1;
|
||||||
|
|
||||||
|
ProtocolHitag1* protocol_hitag1_alloc(void) {
|
||||||
|
ProtocolHitag1* protocol = malloc(sizeof(ProtocolHitag1));
|
||||||
|
|
||||||
|
return protocol;
|
||||||
|
};
|
||||||
|
|
||||||
|
void protocol_hitag1_free(ProtocolHitag1* protocol) {
|
||||||
|
free(protocol);
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t* protocol_hitag1_get_data(ProtocolHitag1* protocol) {
|
||||||
|
return protocol->tagData;
|
||||||
|
};
|
||||||
|
|
||||||
|
void protocol_hitag1_decoder_start(ProtocolHitag1* protocol) {
|
||||||
|
UNUSED(protocol);
|
||||||
|
// Not applicalble, encoding & decoding is handled in lfrfid_hitag_worker...
|
||||||
|
};
|
||||||
|
|
||||||
|
bool protocol_hitag1_decoder_feed(ProtocolHitag1* protocol, bool level, uint32_t duration) {
|
||||||
|
UNUSED(protocol);
|
||||||
|
UNUSED(level);
|
||||||
|
UNUSED(duration);
|
||||||
|
// Not applicalble, encoding & decoding is handled in lfrfid_hitag_worker...
|
||||||
|
|
||||||
|
bool result = false;
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool protocol_hitag1_encoder_start(ProtocolHitag1* protocol) {
|
||||||
|
UNUSED(protocol);
|
||||||
|
// Not applicalble, encoding & decoding is handled in lfrfid_hitag_worker...
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
LevelDuration protocol_hitag1_encoder_yield(ProtocolHitag1* protocol) {
|
||||||
|
UNUSED(protocol);
|
||||||
|
// Not applicalble, encoding & decoding is handled in lfrfid_hitag_worker...
|
||||||
|
|
||||||
|
bool level = 0;
|
||||||
|
uint32_t duration = 0;
|
||||||
|
return level_duration_make(level, duration);
|
||||||
|
};
|
||||||
|
|
||||||
|
bool protocol_hitag1_write_data(ProtocolHitag1* protocol, void* data) {
|
||||||
|
UNUSED(protocol);
|
||||||
|
UNUSED(data);
|
||||||
|
|
||||||
|
//this protocol cannot be simply written to card --> don't do anything, just return false
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
void protocol_hitag1_render_data(ProtocolHitag1* protocol, FuriString* result) {
|
||||||
|
uint8_t pages = 0;
|
||||||
|
for(uint8_t p = 0; p < HITAG1_PAGES; p++) {
|
||||||
|
pages += protocol->tagData[HITAG1_PAGES * 4 + p];
|
||||||
|
}
|
||||||
|
furi_string_printf(
|
||||||
|
result,
|
||||||
|
"SN: %02X %02X %02X %02X\r\n"
|
||||||
|
"Pages read: %u / 64",
|
||||||
|
protocol->tagData[0],
|
||||||
|
protocol->tagData[1],
|
||||||
|
protocol->tagData[2],
|
||||||
|
protocol->tagData[3],
|
||||||
|
pages);
|
||||||
|
};
|
||||||
|
|
||||||
|
const ProtocolBase protocol_hitag1 = {
|
||||||
|
.name = "Hitag1",
|
||||||
|
.manufacturer = "Philips",
|
||||||
|
.data_size = HITAG1_DATA_SIZE,
|
||||||
|
.features = LFRFIDFeatureRTF,
|
||||||
|
.validate_count = 1,
|
||||||
|
.alloc = (ProtocolAlloc)protocol_hitag1_alloc,
|
||||||
|
.free = (ProtocolFree)protocol_hitag1_free,
|
||||||
|
.get_data = (ProtocolGetData)protocol_hitag1_get_data,
|
||||||
|
.decoder =
|
||||||
|
{
|
||||||
|
.start = (ProtocolDecoderStart)protocol_hitag1_decoder_start,
|
||||||
|
.feed = (ProtocolDecoderFeed)protocol_hitag1_decoder_feed,
|
||||||
|
},
|
||||||
|
.encoder =
|
||||||
|
{
|
||||||
|
.start = (ProtocolEncoderStart)protocol_hitag1_encoder_start,
|
||||||
|
.yield = (ProtocolEncoderYield)protocol_hitag1_encoder_yield,
|
||||||
|
},
|
||||||
|
.render_data = (ProtocolRenderData)protocol_hitag1_render_data,
|
||||||
|
.render_brief_data = (ProtocolRenderData)protocol_hitag1_render_data,
|
||||||
|
.write_data = (ProtocolWriteData)protocol_hitag1_write_data,
|
||||||
|
};
|
4
lib/lfrfid/protocols/protocol_hitag1.h
Normal file
4
lib/lfrfid/protocols/protocol_hitag1.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <toolbox/protocols/protocol.h>
|
||||||
|
|
||||||
|
extern const ProtocolBase protocol_hitag1;
|
Loading…
Reference in New Issue
Block a user