Skip to content

Commit 560e958

Browse files
committed
basic NFC support
1 parent 09f7507 commit 560e958

12 files changed

+132
-51
lines changed

actions/action.c

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ void action_tx(void* context, Item* item, FuriString* error) {
1212
action_ir_tx(context, item->path, error);
1313
} else if(!strcmp(item->ext, ".rfid")) {
1414
action_rfid_tx(context, item->path, error);
15+
} else if(!strcmp(item->ext, ".nfc")) {
16+
action_nfc_tx(context, item->path, error);
1517
} else if(!strcmp(item->ext, ".qpl")) {
1618
action_qpl_tx(context, item->path, error);
1719
} else {

actions/action_i.h

+1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@
88
void action_subghz_tx(void* context, const FuriString* action_path, FuriString* error);
99
void action_rfid_tx(void* context, const FuriString* action_path, FuriString* error);
1010
void action_ir_tx(void* context, const FuriString* action_path, FuriString* error);
11+
void action_nfc_tx(void* context, const FuriString* action_path, FuriString* error);
1112
void action_qpl_tx(void* context, const FuriString* action_path, FuriString* error);

actions/action_nfc.c

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Methods for NFC transmission
2+
3+
// nfc
4+
#include <furi.h>
5+
#include <furi_hal.h>
6+
#include <nfc/nfc.h>
7+
#include <nfc/nfc_device.h>
8+
#include <nfc/nfc_listener.h>
9+
10+
#include "action_i.h"
11+
#include "quac.h"
12+
13+
void action_nfc_tx(void* context, const FuriString* action_path, FuriString* error) {
14+
App* app = context;
15+
16+
FURI_LOG_I(TAG, "NFC: Tx %s", furi_string_get_cstr(action_path));
17+
Nfc* nfc = nfc_alloc();
18+
NfcDevice* device = nfc_device_alloc();
19+
20+
if(nfc_device_load(device, furi_string_get_cstr(action_path))) {
21+
NfcProtocol protocol = nfc_device_get_protocol(device);
22+
FURI_LOG_I(TAG, "NFC: Protocol %s", nfc_device_get_protocol_name(protocol));
23+
NfcListener* listener =
24+
nfc_listener_alloc(nfc, protocol, nfc_device_get_data(device, protocol));
25+
FURI_LOG_I(TAG, "NFC: Starting...");
26+
nfc_listener_start(listener, NULL, NULL);
27+
28+
int16_t time_ms = app->settings.nfc_duration;
29+
const int16_t interval_ms = 100;
30+
while(time_ms > 0) {
31+
furi_delay_ms(interval_ms);
32+
time_ms -= interval_ms;
33+
}
34+
35+
FURI_LOG_I(TAG, "NFC: Done");
36+
nfc_listener_stop(listener);
37+
nfc_listener_free(listener);
38+
} else {
39+
FURI_LOG_E(TAG, "NFC: Failed to load %s", furi_string_get_cstr(action_path));
40+
ACTION_SET_ERROR("Failed to load %s", furi_string_get_cstr(action_path));
41+
}
42+
nfc_device_clear(device); // probably not needed?
43+
nfc_free(nfc);
44+
nfc_device_free(device);
45+
}

actions/action_qpl.c

+14-9
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@
3030
void action_qpl_tx(void* context, const FuriString* action_path, FuriString* error) {
3131
App* app = context;
3232

33-
// Save the current RFID Duration, in case it is changed during playback
33+
// Save the current RFID and NFC Durations, in case the are changed during playback
3434
uint32_t orig_rfid_duration = app->settings.rfid_duration;
35+
uint32_t orig_nfc_duration = app->settings.nfc_duration;
3536

3637
FuriString* buffer;
3738
buffer = furi_string_alloc();
@@ -83,13 +84,6 @@ void action_qpl_tx(void* context, const FuriString* action_path, FuriString* err
8384
break;
8485
}
8586

86-
// FURI_LOG_I(TAG, "Still checking for commands...");
87-
// FURI_LOG_I(
88-
// TAG,
89-
// "args_temp: '%s', buffer: '%s'",
90-
// furi_string_get_cstr(args_tmp),
91-
// furi_string_get_cstr(buffer));
92-
9387
// First token wasn't "pause", so maybe args_tmp is a .rfid filename followed
9488
// by a transmit duration in ms in buffer
9589
// Note: Not using path_extract_extension since it expects to find slashes in the
@@ -101,13 +95,20 @@ void action_qpl_tx(void* context, const FuriString* action_path, FuriString* err
10195
}
10296

10397
// FURI_LOG_I(TAG, " - Found extension of %s", ext);
104-
uint32_t rfid_duration = 0;
98+
10599
if(!strcmp(ext, ".rfid")) {
100+
uint32_t rfid_duration = 0;
106101
// FURI_LOG_I(TAG, "RFID file with duration");
107102
if(sscanf(furi_string_get_cstr(buffer), "%lu", &rfid_duration) == 1) {
108103
FURI_LOG_I(TAG, "RFID duration = %lu", rfid_duration);
109104
app->settings.rfid_duration = rfid_duration;
110105
}
106+
} else if(!strcmp(ext, ".nfc")) {
107+
uint32_t nfc_duration = 0;
108+
if(sscanf(furi_string_get_cstr(buffer), "%lu", &nfc_duration) == 1) {
109+
FURI_LOG_I(TAG, "NFC duration = %lu", nfc_duration);
110+
app->settings.nfc_duration = nfc_duration;
111+
}
111112
}
112113

113114
} while(false);
@@ -140,6 +141,10 @@ void action_qpl_tx(void* context, const FuriString* action_path, FuriString* err
140141
app->settings.rfid_duration = orig_rfid_duration;
141142
} else if(!strcmp(ext, ".ir")) {
142143
action_ir_tx(context, buffer, error);
144+
} else if(!strcmp(ext, ".nfc")) {
145+
action_nfc_tx(context, buffer, error);
146+
// Reset our default duration back - in case it was changed during playback
147+
app->settings.nfc_duration = orig_nfc_duration;
143148
} else if(!strcmp(ext, ".qpl")) {
144149
ACTION_SET_ERROR("Playlist: Can't call playlist from playlist");
145150
} else {

item.c

+2
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ ItemType item_get_item_type_from_extension(const char* ext) {
155155
type = Item_RFID;
156156
} else if(!strcmp(ext, ".ir")) {
157157
type = Item_IR;
158+
} else if(!strcmp(ext, ".nfc")) {
159+
type = Item_NFC;
158160
} else if(!strcmp(ext, ".qpl")) {
159161
type = Item_Playlist;
160162
}

item.h

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ typedef enum {
1515
Item_SubGhz,
1616
Item_RFID,
1717
Item_IR,
18+
Item_NFC,
1819
Item_Playlist,
1920
Item_Group,
2021
Item_Settings,

quac.h

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ typedef struct App {
5959
bool show_icons; // Defaults to True
6060
bool show_headers; // Defaults to True
6161
uint32_t rfid_duration; // Defaults to 2500 ms
62+
uint32_t nfc_duration; // Defaults to 1000 ms
6263
bool subghz_use_ext_antenna; // Defaults to False
6364
bool show_hidden; // Defaults to False
6465
} settings;

quac_settings.c

+40-33
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@
77
#define QUAC_SETTINGS_FILE_VERSION 1
88

99
void quac_set_default_settings(App* app) {
10-
app->settings.rfid_duration = 2500;
1110
app->settings.layout = QUAC_APP_LANDSCAPE;
1211
app->settings.show_icons = true;
1312
app->settings.show_headers = true;
13+
app->settings.rfid_duration = 2500;
14+
app->settings.nfc_duration = 1000;
1415
app->settings.subghz_use_ext_antenna = false;
1516
app->settings.show_hidden = false;
1617
}
@@ -21,11 +22,13 @@ void quac_load_settings(App* app) {
2122
temp_str = furi_string_alloc();
2223
uint32_t temp_data32 = 0;
2324

25+
// Initialize settings to the defaults
26+
quac_set_default_settings(app);
27+
2428
FURI_LOG_I(TAG, "SETTINGS: Reading: %s", QUAC_SETTINGS_PATH);
25-
bool successful = false;
2629
do {
2730
if(!flipper_format_file_open_existing(fff_settings, QUAC_SETTINGS_PATH)) {
28-
FURI_LOG_I(TAG, "SETTINGS: File not found, loading defaults");
31+
FURI_LOG_I(TAG, "SETTINGS: File not found, using defaults");
2932
break;
3033
}
3134

@@ -43,55 +46,54 @@ void quac_load_settings(App* app) {
4346

4447
// Now read actual values we care about
4548
if(!flipper_format_read_string(fff_settings, "Layout", temp_str)) {
46-
FURI_LOG_E(TAG, "SETTINGS: Missing Layout");
47-
break;
48-
}
49-
if(!strcmp(furi_string_get_cstr(temp_str), "Landscape")) {
50-
app->settings.layout = QUAC_APP_LANDSCAPE;
51-
} else if(!strcmp(furi_string_get_cstr(temp_str), "Portrait")) {
52-
app->settings.layout = QUAC_APP_PORTRAIT;
49+
FURI_LOG_W(TAG, "SETTINGS: Missing Layout");
5350
} else {
54-
FURI_LOG_E(TAG, "SETTINGS: Invalid Layout");
55-
break;
51+
if(!strcmp(furi_string_get_cstr(temp_str), "Landscape")) {
52+
app->settings.layout = QUAC_APP_LANDSCAPE;
53+
} else if(!strcmp(furi_string_get_cstr(temp_str), "Portrait")) {
54+
app->settings.layout = QUAC_APP_PORTRAIT;
55+
} else {
56+
FURI_LOG_E(TAG, "SETTINGS: Invalid Layout");
57+
}
5658
}
5759

5860
if(!flipper_format_read_uint32(fff_settings, "Show Icons", &temp_data32, 1)) {
59-
FURI_LOG_E(TAG, "SETTINGS: Missing 'Show Icons'");
60-
break;
61+
FURI_LOG_W(TAG, "SETTINGS: Missing 'Show Icons'");
62+
} else {
63+
app->settings.show_icons = (temp_data32 == 0) ? false : true;
6164
}
62-
app->settings.show_icons = (temp_data32 == 0) ? false : true;
6365

6466
if(!flipper_format_read_uint32(fff_settings, "Show Headers", &temp_data32, 1)) {
65-
FURI_LOG_E(TAG, "SETTINGS: Missing 'Show Headers'");
66-
break;
67+
FURI_LOG_W(TAG, "SETTINGS: Missing 'Show Headers'");
68+
} else {
69+
app->settings.show_headers = (temp_data32 == 1) ? true : false;
6770
}
68-
app->settings.show_headers = (temp_data32 == 1) ? true : false;
6971

7072
if(!flipper_format_read_uint32(fff_settings, "RFID Duration", &temp_data32, 1)) {
71-
FURI_LOG_E(TAG, "SETTINGS: Missing 'RFID Duration'");
72-
break;
73+
FURI_LOG_W(TAG, "SETTINGS: Missing 'RFID Duration'");
74+
} else {
75+
app->settings.rfid_duration = temp_data32;
76+
}
77+
78+
if(!flipper_format_read_uint32(fff_settings, "NFC Duration", &temp_data32, 1)) {
79+
FURI_LOG_W(TAG, "SETTINGS: Missing 'NFC Duration'");
80+
} else {
81+
app->settings.nfc_duration = temp_data32;
7382
}
74-
app->settings.rfid_duration = temp_data32;
7583

7684
if(!flipper_format_read_uint32(fff_settings, "SubGHz Ext Antenna", &temp_data32, 1)) {
77-
FURI_LOG_E(TAG, "SETTINGS: Missing 'SubGHz Ext Antenna'");
78-
break;
85+
FURI_LOG_W(TAG, "SETTINGS: Missing 'SubGHz Ext Antenna'");
86+
} else {
87+
app->settings.subghz_use_ext_antenna = (temp_data32 == 1) ? true : false;
7988
}
80-
app->settings.subghz_use_ext_antenna = (temp_data32 == 1) ? true : false;
8189

8290
if(!flipper_format_read_uint32(fff_settings, "Show Hidden", &temp_data32, 1)) {
83-
FURI_LOG_E(TAG, "SETTINGS: Missing 'Show Hidden'");
84-
break;
91+
FURI_LOG_W(TAG, "SETTINGS: Missing 'Show Hidden'");
92+
} else {
93+
app->settings.show_hidden = (temp_data32 == 1) ? true : false;
8594
}
86-
app->settings.show_hidden = (temp_data32 == 1) ? true : false;
87-
88-
successful = true;
8995
} while(false);
9096

91-
if(!successful) {
92-
quac_set_default_settings(app);
93-
}
94-
9597
furi_string_free(temp_str);
9698
flipper_format_free(fff_settings);
9799
}
@@ -137,6 +139,11 @@ void quac_save_settings(App* app) {
137139
FURI_LOG_E(TAG, "SETTINGS: Failed to write 'RFID Duration'");
138140
break;
139141
}
142+
if(!flipper_format_write_uint32(
143+
fff_settings, "NFC Duration", &app->settings.nfc_duration, 1)) {
144+
FURI_LOG_E(TAG, "SETTINGS: Failed to write 'NFC Duration'");
145+
break;
146+
}
140147
temp_data32 = app->settings.subghz_use_ext_antenna ? 1 : 0;
141148
if(!flipper_format_write_uint32(fff_settings, "SubGHz Ext Antenna", &temp_data32, 1)) {
142149
FURI_LOG_E(TAG, "SETTINGS: Failed to write 'SubGHz Ext Antenna'");

scenes/scene_items.c

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ static const ActionMenuItemType ItemToMenuItem[] = {
1818
[Item_SubGhz] = ActionMenuItemTypeSubGHz,
1919
[Item_RFID] = ActionMenuItemTypeRFID,
2020
[Item_IR] = ActionMenuItemTypeIR,
21+
[Item_NFC] = ActionMenuItemTypeNFC,
2122
[Item_Playlist] = ActionMenuItemTypePlaylist,
2223
[Item_Group] = ActionMenuItemTypeGroup,
2324
[Item_Settings] = ActionMenuItemTypeSettings,

scenes/scene_settings.c

+23-9
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ typedef enum {
1919
SceneSettingsIcons,
2020
SceneSettingsHeaders,
2121
SceneSettingsRFIDDuration,
22+
SceneSettingsNFCDuration,
2223
SceneSettingsSubGHzExtAnt,
2324
SceneSettingsHidden,
2425
SceneSettingsAbout
@@ -30,8 +31,8 @@ static const uint32_t layout_value[2] = {QUAC_APP_PORTRAIT, QUAC_APP_LANDSCAPE};
3031
static const char* const show_offon_text[2] = {"OFF", "ON"};
3132
static const uint32_t show_offon_value[2] = {false, true};
3233

33-
#define V_RFID_DURATION_COUNT 8
34-
static const char* const rfid_duration_text[V_RFID_DURATION_COUNT] = {
34+
#define V_DURATION_COUNT 8
35+
static const char* const duration_text[V_DURATION_COUNT] = {
3536
"500 ms",
3637
"1 sec",
3738
"1.5 sec",
@@ -41,7 +42,7 @@ static const char* const rfid_duration_text[V_RFID_DURATION_COUNT] = {
4142
"5 sec",
4243
"10 sec",
4344
};
44-
static const uint32_t rfid_duration_value[V_RFID_DURATION_COUNT] = {
45+
static const uint32_t duration_value[V_DURATION_COUNT] = {
4546
500,
4647
1000,
4748
1500,
@@ -79,8 +80,15 @@ static void scene_settings_show_headers_changed(VariableItem* item) {
7980
static void scene_settings_rfid_duration_changed(VariableItem* item) {
8081
App* app = variable_item_get_context(item);
8182
uint8_t index = variable_item_get_current_value_index(item);
82-
variable_item_set_current_value_text(item, rfid_duration_text[index]);
83-
app->settings.rfid_duration = rfid_duration_value[index];
83+
variable_item_set_current_value_text(item, duration_text[index]);
84+
app->settings.rfid_duration = duration_value[index];
85+
}
86+
87+
static void scene_settings_nfc_duration_changed(VariableItem* item) {
88+
App* app = variable_item_get_context(item);
89+
uint8_t index = variable_item_get_current_value_index(item);
90+
variable_item_set_current_value_text(item, duration_text[index]);
91+
app->settings.nfc_duration = duration_value[index];
8492
}
8593

8694
static void scene_settings_subghz_ext_changed(VariableItem* item) {
@@ -129,11 +137,17 @@ void scene_settings_on_enter(void* context) {
129137
variable_item_set_current_value_text(item, show_offon_text[value_index]);
130138

131139
item = variable_item_list_add(
132-
vil, "RFID Duration", V_RFID_DURATION_COUNT, scene_settings_rfid_duration_changed, app);
133-
value_index = value_index_uint32(
134-
app->settings.rfid_duration, rfid_duration_value, V_RFID_DURATION_COUNT);
140+
vil, "RFID Duration", V_DURATION_COUNT, scene_settings_rfid_duration_changed, app);
141+
value_index =
142+
value_index_uint32(app->settings.rfid_duration, duration_value, V_DURATION_COUNT);
143+
variable_item_set_current_value_index(item, value_index);
144+
variable_item_set_current_value_text(item, duration_text[value_index]);
145+
146+
item = variable_item_list_add(
147+
vil, "NFC Duration", V_DURATION_COUNT, scene_settings_nfc_duration_changed, app);
148+
value_index = value_index_uint32(app->settings.nfc_duration, duration_value, V_DURATION_COUNT);
135149
variable_item_set_current_value_index(item, value_index);
136-
variable_item_set_current_value_text(item, rfid_duration_text[value_index]);
150+
variable_item_set_current_value_text(item, duration_text[value_index]);
137151

138152
item =
139153
variable_item_list_add(vil, "SubGHz Ext Ant", 2, scene_settings_subghz_ext_changed, app);

views/action_menu.c

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ static const Icon* ActionMenuIcons[] = {
2424
[ActionMenuItemTypeSubGHz] = &I_SubGHz_10px,
2525
[ActionMenuItemTypeRFID] = &I_RFID_10px,
2626
[ActionMenuItemTypeIR] = &I_IR_10px,
27+
[ActionMenuItemTypeNFC] = &I_NFC_10px,
2728
[ActionMenuItemTypePlaylist] = &I_Playlist_10px,
2829
[ActionMenuItemTypeGroup] = &I_Directory_10px,
2930
[ActionMenuItemTypeSettings] = &I_Settings_10px,

views/action_menu.h

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ typedef enum {
2121
ActionMenuItemTypeSubGHz,
2222
ActionMenuItemTypeRFID,
2323
ActionMenuItemTypeIR,
24+
ActionMenuItemTypeNFC,
2425
ActionMenuItemTypePlaylist,
2526
ActionMenuItemTypeGroup,
2627
ActionMenuItemTypeSettings,

0 commit comments

Comments
 (0)