[FL-663] Read EMV cards (#460)

* nfc: add emv decoder
* api-hal-nfc: add data exchange api
* nfc_worker: add read emv routine
* nfc: add emv reader view
* nfc: add support for Mastercard reading
* api-hal-nfc: fix incorrect merge changes
* nfc_worker: set to zero emv app object on each cycle
* api-hal-nfc: add api for f6 target
* nfc: move emv_decoder to lib folder

Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
gornekich
2021-05-18 21:12:01 +03:00
committed by GitHub
parent df4a170213
commit 725981f431
13 changed files with 590 additions and 15 deletions

View File

@@ -25,8 +25,10 @@ void nfc_menu_callback(void* context, uint32_t index) {
if(index == 0) {
message.type = NfcMessageTypeDetect;
} else if(index == 1) {
message.type = NfcMessageTypeEmulate;
message.type = NfcMessageTypeReadEMV;
} else if(index == 2) {
message.type = NfcMessageTypeEmulate;
} else if(index == 3) {
message.type = NfcMessageTypeField;
}
furi_check(osMessageQueuePut(message_queue, &message, 0, osWaitForever) == osOK);
@@ -49,8 +51,9 @@ Nfc* nfc_alloc() {
// Menu
nfc->submenu = submenu_alloc();
submenu_add_item(nfc->submenu, "Detect", 0, nfc_menu_callback, nfc);
submenu_add_item(nfc->submenu, "Emulate", 1, nfc_menu_callback, nfc);
submenu_add_item(nfc->submenu, "Field", 2, nfc_menu_callback, nfc);
submenu_add_item(nfc->submenu, "Read EMV", 1, nfc_menu_callback, nfc);
submenu_add_item(nfc->submenu, "Emulate", 2, nfc_menu_callback, nfc);
submenu_add_item(nfc->submenu, "Field", 3, nfc_menu_callback, nfc);
View* submenu_view = submenu_get_view(nfc->submenu);
view_set_previous_callback(submenu_view, nfc_view_exit);
view_dispatcher_add_view(nfc->view_dispatcher, NfcViewMenu, submenu_view);
@@ -63,6 +66,14 @@ Nfc* nfc_alloc() {
view_allocate_model(nfc->view_detect, ViewModelTypeLocking, sizeof(NfcViewReadModel));
view_dispatcher_add_view(nfc->view_dispatcher, NfcViewRead, nfc->view_detect);
// Read EMV
nfc->view_read_emv = view_alloc();
view_set_context(nfc->view_read_emv, nfc);
view_set_draw_callback(nfc->view_read_emv, nfc_view_read_emv_draw);
view_set_previous_callback(nfc->view_read_emv, nfc_view_stop);
view_allocate_model(nfc->view_read_emv, ViewModelTypeLocking, sizeof(NfcViewReadModel));
view_dispatcher_add_view(nfc->view_dispatcher, NfcViewReadEmv, nfc->view_read_emv);
// Emulate
nfc->view_emulate = view_alloc();
view_set_context(nfc->view_emulate, nfc);
@@ -143,7 +154,7 @@ void nfc_cli_detect(Cli* cli, string_t args, void* context) {
printf("Detecting nfc...\r\nPress Ctrl+C to abort\r\n");
while(!cmd_exit) {
cmd_exit |= cli_cmd_interrupt_received(cli);
cmd_exit |= api_hal_nfc_detect(&dev_list, &dev_cnt, 100);
cmd_exit |= api_hal_nfc_detect(&dev_list, &dev_cnt, 100, true);
if(dev_cnt > 0) {
printf("Found %d devices\r\n", dev_cnt);
for(uint8_t i = 0; i < dev_cnt; i++) {
@@ -196,6 +207,13 @@ int32_t nfc_task(void* p) {
return true;
});
nfc_start(nfc, NfcViewRead, NfcWorkerStatePoll);
} else if(message.type == NfcMessageTypeReadEMV) {
with_view_model(
nfc->view_read_emv, (NfcViewReadModel * model) {
model->found = false;
return true;
});
nfc_start(nfc, NfcViewReadEmv, NfcWorkerStateReadEMV);
} else if(message.type == NfcMessageTypeEmulate) {
nfc_start(nfc, NfcViewEmulate, NfcWorkerStateEmulate);
} else if(message.type == NfcMessageTypeField) {
@@ -215,6 +233,19 @@ int32_t nfc_task(void* p) {
model->found = false;
return true;
});
} else if(message.type == NfcMessageTypeEMVFound) {
with_view_model(
nfc->view_read_emv, (NfcViewReadModel * model) {
model->found = true;
model->device = message.device;
return true;
});
} else if(message.type == NfcMessageTypeEMVNotFound) {
with_view_model(
nfc->view_read_emv, (NfcViewReadModel * model) {
model->found = false;
return true;
});
} else if(message.type == NfcMessageTypeExit) {
nfc_free(nfc);
break;