Skip to content

Commit 4554b4c

Browse files
Add support to start NFC in CE and reader mode
1 parent c56add3 commit 4554b4c

File tree

7 files changed

+270
-15
lines changed

7 files changed

+270
-15
lines changed

Makefile.standard_app

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME), TARGET_STAX TARGET_FLEX))
3939
endif
4040
endif
4141

42+
ifeq ($(ENABLE_NFC_READER), 1)
43+
ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME), TARGET_STAX TARGET_FLEX))
44+
DEFINES += HAVE_NFC_READER
45+
endif
46+
endif
47+
4248
#####################################################################
4349
# SWAP #
4450
#####################################################################

include/os_io_nfc.h

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,74 @@
1919
#ifndef OS_IO_NFC_H
2020
#define OS_IO_NFC_H
2121

22+
#include "arch.h"
23+
24+
#include "os_io_seproxyhal.h"
25+
26+
/* Public API for reader application --------------------------------------- */
27+
#ifdef HAVE_NFC_READER
28+
29+
enum card_tech {
30+
NFC_A,
31+
NFC_B
32+
};
33+
34+
struct card_info {
35+
enum card_tech tech;
36+
uint8_t nfcid[7];
37+
size_t nfcid_len;
38+
};
39+
40+
enum nfc_event {
41+
CARD_DETECTED,
42+
CARD_REMOVED,
43+
};
44+
45+
typedef void (*nfc_evt_callback_t)(enum nfc_event event, struct card_info *info);
46+
typedef void (*nfc_resp_callback_t)(bool error, bool timeout, uint8_t *resp_data, size_t resp_len);
47+
48+
/* Functions */
49+
50+
/* return false in case of error
51+
in that case, callback will not be called */
52+
bool io_nfc_reader_send(const uint8_t *cmd_data,
53+
size_t cmd_len,
54+
nfc_resp_callback_t callback,
55+
int timeout_ms);
56+
57+
/* Return false if nfc reader can not be started in current conditions */
58+
bool io_nfc_reader_start(nfc_evt_callback_t callback);
59+
void io_nfc_reader_stop(void);
60+
bool io_nfc_is_reader(void);
61+
62+
#endif // HAVE_NFC_READER
63+
64+
/* SDK internal API --------------------------------------- */
65+
66+
#ifdef HAVE_NFC_READER
67+
68+
struct nfc_reader_context {
69+
nfc_resp_callback_t resp_callback;
70+
nfc_evt_callback_t evt_callback;
71+
bool reader_mode;
72+
bool event_happened;
73+
bool response_received;
74+
unsigned int remaining_ms;
75+
enum nfc_event last_event;
76+
struct card_info card;
77+
};
78+
79+
extern struct nfc_reader_context G_io_reader_ctx;
80+
#endif // HAVE_NFC_READER
81+
2282
void io_nfc_init(void);
2383
void io_nfc_recv_event(void);
2484
void io_nfc_send_response(const uint8_t *packet, uint16_t packet_length);
2585

86+
#ifdef HAVE_NFC_READER
87+
void io_nfc_event(void);
88+
void io_nfc_ticker(void);
89+
void io_nfc_process_events(void);
90+
#endif // HAVE_NFC_READER
91+
2692
#endif

include/seproxyhal_protocol.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,12 @@
112112
#define SEPROXYHAL_TAG_BOOTLOADER_RAPDU_EVENT 0x19 // <RAPDU from the bootloader>
113113
#define SEPROXYHAL_TAG_UX_EVENT 0x1A //
114114
#ifdef HAVE_NFC
115-
#define SEPROXYHAL_TAG_NFC_APDU_EVENT 0x1C
115+
#define SEPROXYHAL_TAG_NFC_APDU_EVENT 0x1C
116+
#define SEPROXYHAL_TAG_NFC_EVENT 0x1E
117+
#define SEPROXYHAL_TAG_NFC_EVENT_CARD_DETECTED 0x01 // card_detected + type a/b + nfcid[max 7]
118+
#define SEPROXYHAL_TAG_NFC_EVENT_CARD_DETECTED_A 0x01
119+
#define SEPROXYHAL_TAG_NFC_EVENT_CARD_DETECTED_B 0x02
120+
#define SEPROXYHAL_TAG_NFC_EVENT_CARD_LOST 0x02 // card lost
116121
#endif
117122

118123
#define SEPH_PROTOCOL_EVT_POWER_BUTTON_EVENT 0x1B
@@ -166,8 +171,11 @@
166171
// #define SEPROXYHAL_TAG_SCREEN_DISPLAY 0x4A // wait for display_event after sent
167172

168173
#ifdef HAVE_NFC
169-
#define SEPROXYHAL_TAG_NFC_RAPDU 0x4A
170-
#define SEPROXYHAL_TAG_NFC_POWER 0x34
174+
#define SEPROXYHAL_TAG_NFC_RAPDU 0x4A
175+
#define SEPROXYHAL_TAG_NFC_POWER 0x34
176+
#define SEPROXYHAL_TAG_NFC_POWER_OFF 0x00
177+
#define SEPROXYHAL_TAG_NFC_POWER_ON_CE 0x01
178+
#define SEPROXYHAL_TAG_NFC_POWER_ON_READER 0x02
171179
#endif
172180

173181
#define SEPROXYHAL_TAG_DEVICE_OFF 0x4B

lib_standard_app/io.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,21 @@
2525
#include "swap.h"
2626
#endif
2727

28+
#ifdef HAVE_NFC_READER
29+
#include "os_io_nfc.h"
30+
#endif // HAVE_NFC_READER
31+
2832
// TODO: Temporary workaround, at some point all status words should be defined by the SDK and
2933
// removed from the application
3034
#define SW_OK 0x9000
3135
#define SW_WRONG_RESPONSE_LENGTH 0xB000
3236

3337
uint8_t G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B];
3438

39+
#ifdef HAVE_NFC_READER
40+
struct nfc_reader_context G_io_reader_ctx;
41+
#endif
42+
3543
/**
3644
* Variable containing the length of the APDU response to send back.
3745
*/
@@ -83,6 +91,10 @@ WEAK uint8_t io_event(uint8_t channel)
8391
case SEPROXYHAL_TAG_TICKER_EVENT:
8492
app_ticker_event_callback();
8593
UX_TICKER_EVENT(G_io_seproxyhal_spi_buffer, {});
94+
#ifdef HAVE_NFC_READER
95+
io_nfc_ticker();
96+
io_nfc_process_events();
97+
#endif // HAVE_NFC_READER
8698
break;
8799
default:
88100
UX_DEFAULT_EVENT();

src/os_io_nfc.c

Lines changed: 152 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@
1515
* See the License for the specific language governing permissions and
1616
* limitations under the License.
1717
********************************************************************************/
18-
#include "bolos_target.h"
18+
19+
#include "os.h"
20+
#include "os_settings.h"
21+
#include "os_io_seproxyhal.h"
22+
1923
#include "errors.h"
2024
#include "exceptions.h"
2125
#ifdef HAVE_NFC
@@ -25,17 +29,11 @@
2529
#endif // DEBUG_OS_STACK_CONSUMPTION
2630

2731
#include "os_io.h"
32+
#include "os_io_nfc.h"
2833
#include "os_utils.h"
2934
#include "os_io_seproxyhal.h"
3035
#include <string.h>
3136

32-
#ifdef DEBUG
33-
#define LOG printf
34-
#else
35-
#define LOG(...)
36-
#endif
37-
38-
#include "os.h"
3937
#include "ledger_protocol.h"
4038

4139
static uint8_t rx_apdu_buffer[IO_APDU_BUFFER_SIZE];
@@ -55,6 +53,9 @@ void io_nfc_init(void)
5553
ledger_protocol_data.rx_dst_buffer = G_io_apdu_buffer;
5654
#endif
5755
LEDGER_PROTOCOL_init(&ledger_protocol_data);
56+
#ifdef HAVE_NFC_READER
57+
memset((void *) &G_io_reader_ctx, 0, sizeof(G_io_reader_ctx));
58+
#endif // HAVE_NFC_READER
5859
}
5960

6061
void io_nfc_recv_event(void)
@@ -65,6 +66,13 @@ void io_nfc_recv_event(void)
6566

6667
// Full apdu is received, copy it to global apdu buffer
6768
if (ledger_protocol_data.rx_apdu_status == APDU_STATUS_COMPLETE) {
69+
#ifdef HAVE_NFC_READER
70+
if (G_io_reader_ctx.reader_mode) {
71+
G_io_reader_ctx.response_received = true;
72+
return;
73+
}
74+
#endif // HAVE_NFC_READER
75+
6876
memcpy(ledger_protocol_data.rx_dst_buffer,
6977
ledger_protocol_data.rx_apdu_buffer,
7078
ledger_protocol_data.rx_apdu_length);
@@ -106,4 +114,140 @@ void io_nfc_send_response(const uint8_t *packet, uint16_t packet_length)
106114
}
107115
}
108116

117+
#ifdef HAVE_NFC_READER
118+
119+
void io_nfc_event(void)
120+
{
121+
size_t size = U2BE(G_io_seproxyhal_spi_buffer, 1);
122+
123+
if (size >= 1) {
124+
switch (G_io_seproxyhal_spi_buffer[3]) {
125+
case SEPROXYHAL_TAG_NFC_EVENT_CARD_DETECTED: {
126+
G_io_reader_ctx.event_happened = true;
127+
G_io_reader_ctx.last_event = CARD_DETECTED;
128+
G_io_reader_ctx.card.tech
129+
= (G_io_seproxyhal_spi_buffer[4] == SEPROXYHAL_TAG_NFC_EVENT_CARD_DETECTED_A)
130+
? NFC_A
131+
: NFC_B;
132+
G_io_reader_ctx.card.nfcid_len = MIN(size - 2, sizeof(G_io_reader_ctx.card.nfcid));
133+
memcpy((void *) G_io_reader_ctx.card.nfcid,
134+
G_io_seproxyhal_spi_buffer + 5,
135+
G_io_reader_ctx.card.nfcid_len);
136+
} break;
137+
138+
case SEPROXYHAL_TAG_NFC_EVENT_CARD_LOST:
139+
if (G_io_reader_ctx.evt_callback != NULL) {
140+
G_io_reader_ctx.event_happened = true;
141+
G_io_reader_ctx.last_event = CARD_REMOVED;
142+
}
143+
break;
144+
}
145+
}
146+
}
147+
148+
void io_nfc_process_events(void)
149+
{
150+
if (G_io_reader_ctx.response_received) {
151+
G_io_reader_ctx.response_received = false;
152+
if (G_io_reader_ctx.resp_callback != NULL) {
153+
nfc_resp_callback_t resp_cb = G_io_reader_ctx.resp_callback;
154+
G_io_reader_ctx.resp_callback = NULL;
155+
resp_cb(false,
156+
false,
157+
ledger_protocol_data.rx_apdu_buffer,
158+
ledger_protocol_data.rx_apdu_length);
159+
}
160+
memset(ledger_protocol_data.rx_apdu_buffer, 0, ledger_protocol_data.rx_apdu_length);
161+
}
162+
163+
if (G_io_reader_ctx.resp_callback != NULL && G_io_reader_ctx.remaining_ms == 0) {
164+
nfc_resp_callback_t resp_cb = G_io_reader_ctx.resp_callback;
165+
G_io_reader_ctx.resp_callback = NULL;
166+
resp_cb(false, true, NULL, 0);
167+
}
168+
169+
if (G_io_reader_ctx.event_happened) {
170+
G_io_reader_ctx.event_happened = 0;
171+
172+
// If card is removed during an APDU processing, call the resp_callback with an error
173+
if (G_io_reader_ctx.resp_callback != NULL && G_io_reader_ctx.last_event == CARD_REMOVED) {
174+
nfc_resp_callback_t resp_cb = G_io_reader_ctx.resp_callback;
175+
G_io_reader_ctx.resp_callback = NULL;
176+
resp_cb(true, false, NULL, 0);
177+
}
178+
179+
if (G_io_reader_ctx.evt_callback != NULL) {
180+
G_io_reader_ctx.evt_callback(G_io_reader_ctx.last_event,
181+
(struct card_info *) &G_io_reader_ctx.card);
182+
}
183+
if (G_io_reader_ctx.last_event == CARD_REMOVED) {
184+
memset((void *) &G_io_reader_ctx.card, 0, sizeof(G_io_reader_ctx.card));
185+
}
186+
}
187+
}
188+
189+
void io_nfc_ticker(void)
190+
{
191+
if (G_io_reader_ctx.resp_callback != NULL) {
192+
if (G_io_reader_ctx.remaining_ms <= 100) {
193+
G_io_reader_ctx.remaining_ms = 0;
194+
}
195+
else {
196+
G_io_reader_ctx.remaining_ms -= 100;
197+
}
198+
}
199+
}
200+
201+
bool io_nfc_reader_send(const uint8_t *cmd_data,
202+
size_t cmd_len,
203+
nfc_resp_callback_t callback,
204+
int timeout_ms)
205+
{
206+
G_io_reader_ctx.resp_callback = PIC(callback);
207+
io_nfc_send_response(PIC(cmd_data), cmd_len);
208+
209+
G_io_reader_ctx.response_received = false;
210+
G_io_reader_ctx.remaining_ms = timeout_ms;
211+
212+
return true;
213+
}
214+
215+
void io_nfc_reader_power(void)
216+
{
217+
uint8_t buffer[4];
218+
buffer[0] = SEPROXYHAL_TAG_NFC_POWER;
219+
buffer[1] = 0;
220+
buffer[2] = 1;
221+
buffer[3] = SEPROXYHAL_TAG_NFC_POWER_ON_READER;
222+
io_seproxyhal_spi_send(buffer, 4);
223+
}
224+
225+
bool io_nfc_reader_start(nfc_evt_callback_t callback)
226+
{
227+
G_io_reader_ctx.evt_callback = PIC(callback);
228+
G_io_reader_ctx.reader_mode = true;
229+
G_io_reader_ctx.event_happened = false;
230+
G_io_reader_ctx.resp_callback = NULL;
231+
G_io_reader_ctx.response_received = false;
232+
io_nfc_reader_power();
233+
return true;
234+
}
235+
236+
void io_nfc_reader_stop()
237+
{
238+
G_io_reader_ctx.evt_callback = NULL;
239+
G_io_reader_ctx.reader_mode = false;
240+
G_io_reader_ctx.event_happened = false;
241+
G_io_reader_ctx.resp_callback = NULL;
242+
G_io_reader_ctx.response_received = false;
243+
io_seproxyhal_nfc_power(false);
244+
}
245+
246+
bool io_nfc_is_reader(void)
247+
{
248+
return G_io_reader_ctx.reader_mode;
249+
}
250+
251+
#endif // HAVE_NFC_READER
252+
109253
#endif // HAVE_NFC

src/os_io_seproxyhal.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -273,8 +273,19 @@ unsigned int io_seproxyhal_handle_event(void)
273273
#ifdef HAVE_NFC
274274
case SEPROXYHAL_TAG_NFC_APDU_EVENT:
275275
io_nfc_recv_event();
276+
#if defined(HAVE_NFC_READER) && !defined(HAVE_BOLOS)
277+
io_nfc_process_events();
278+
#endif // HAVE_NFC_READER && !HAVE_BOLOS
276279
return 1;
277-
#endif
280+
#ifdef HAVE_NFC_READER
281+
case SEPROXYHAL_TAG_NFC_EVENT:
282+
io_nfc_event();
283+
#ifndef HAVE_BOLOS
284+
io_nfc_process_events();
285+
#endif // !HAVE_BOLOS
286+
return 1;
287+
#endif // HAVE_NFC_READER
288+
#endif // HAVE_NFC
278289

279290
case SEPROXYHAL_TAG_UX_EVENT:
280291
switch (G_io_seproxyhal_spi_buffer[3]) {
@@ -502,9 +513,10 @@ void io_seproxyhal_nfc_power(bool forceInit)
502513
{
503514
uint8_t buffer[4];
504515
uint8_t power
505-
= forceInit
506-
? 1
507-
: (os_setting_get(OS_SETTING_FEATURES, NULL, 0) & OS_SETTING_FEATURES_NFC_ENABLED);
516+
= (forceInit
517+
|| (os_setting_get(OS_SETTING_FEATURES, NULL, 0) & OS_SETTING_FEATURES_NFC_ENABLED))
518+
? SEPROXYHAL_TAG_NFC_POWER_ON_CE
519+
: SEPROXYHAL_TAG_NFC_POWER_OFF;
508520
buffer[0] = SEPROXYHAL_TAG_NFC_POWER;
509521
buffer[1] = 0;
510522
buffer[2] = 1;

0 commit comments

Comments
 (0)