Embedded SDK
Embedded SDK
Loading...
Searching...
No Matches
nfc_ledger.c
Go to the documentation of this file.
1/*****************************************************************************
2 * (c) 2025 Ledger SAS.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
16
17#ifdef HAVE_NFC
18/* Includes ------------------------------------------------------------------*/
19#include <string.h>
20#include "os.h"
21#include "ledger_protocol.h"
22#include "seproxyhal_protocol.h"
23#include "os_io.h"
24#include "os_io_seph_cmd.h"
25#include "os_utils.h"
26#include "nfc_ledger.h"
27
28/* Private enumerations ------------------------------------------------------*/
29typedef enum nfc_state_e {
30 NFC_STATE_IDLE,
31 NFC_STATE_INITIALIZED,
32 NFC_STATE_STARTED,
33 NFC_STATE_RUNNING,
34} nfc_state_t;
35
36/* Private defines------------------------------------------------------------*/
37
38/* Private types, structures, unions -----------------------------------------*/
39typedef struct nfc_ledger_data_s {
40 nfc_state_t state;
41 uint8_t mode; // nfc_ledger_mode_e
42 ledger_protocol_t protocol_data;
43} nfc_ledger_data_t;
44
45#ifdef HAVE_PRINTF
46#define LOG_IO PRINTF
47#else // !HAVE_PRINTF
48#define LOG_IO(...)
49#endif // !HAVE_PRINTF
50
51/* Private macros-------------------------------------------------------------*/
52
53/* Private functions prototypes ----------------------------------------------*/
54static void nfc_ledger_send_rapdu(uint8_t *buffer, uint16_t length, uint32_t timeout_ms);
55
56/* Exported variables --------------------------------------------------------*/
57static uint8_t NFC_LEDGER_io_buffer[OS_IO_BUFFER_SIZE + 1];
58
59/* Private variables ---------------------------------------------------------*/
60static nfc_ledger_data_t nfc_ledger_data;
61static uint8_t
62 nfc_ledger_protocol_chunk_buffer[156 + 2]; // TODO_IO : BLE buffer size, can be changed though
63
64/* Private functions ---------------------------------------------------------*/
65static void nfc_ledger_send_rapdu(uint8_t *buffer, uint16_t length, uint32_t timeout_ms)
66{
67 UNUSED(timeout_ms);
68
69 if (length) {
70 unsigned char hdr[3];
71 hdr[0] = SEPROXYHAL_TAG_NFC_RAPDU;
72 hdr[1] = length >> 8;
73 hdr[2] = length;
74 os_io_tx_cmd(OS_IO_PACKET_TYPE_SEPH, hdr, 3, NULL);
75 os_io_tx_cmd(OS_IO_PACKET_TYPE_SEPH, buffer, length, NULL);
76 }
77}
78
79/* Exported functions --------------------------------------------------------*/
80
81void NFC_LEDGER_init(uint8_t force_restart)
82{
83 if (force_restart) {
84 memset(&nfc_ledger_data, 0, sizeof(nfc_ledger_data));
85 nfc_ledger_data.state = NFC_STATE_INITIALIZED;
86 LOG_IO("NFC_LEDGER_init deep\n");
87 }
88 else {
89 LOG_IO("NFC_LEDGER_init\n");
90 }
91}
92
93void NFC_LEDGER_start(uint8_t mode)
94{
95 LOG_IO("NFC_LEDGER_start %d\n", mode);
96
97 if ((nfc_ledger_data.state == NFC_STATE_INITIALIZED) || (nfc_ledger_data.mode != mode)) {
98 memset(&nfc_ledger_data.protocol_data, 0, sizeof(nfc_ledger_data.protocol_data));
99 nfc_ledger_data.protocol_data.mtu = 0;
100 nfc_ledger_data.mode = mode;
101 nfc_ledger_data.state = NFC_STATE_STARTED;
102 }
103 if ((nfc_ledger_data.state == NFC_STATE_STARTED)
104 && (os_setting_get(OS_SETTING_FEATURES, NULL, 0) & OS_SETTING_FEATURES_NFC_ENABLED)) {
105 if (nfc_ledger_data.mode == NFC_LEDGER_MODE_CARD_EMULATION) {
106 ledger_protocol_result_t result
107 = LEDGER_PROTOCOL_init(&nfc_ledger_data.protocol_data, OS_IO_PACKET_TYPE_NFC_APDU);
108 if (result != LP_SUCCESS) {
109 goto error;
110 }
111 os_io_nfc_cmd_power(SEPROXYHAL_TAG_NFC_POWER_ON_CE);
112 nfc_ledger_data.state = NFC_STATE_RUNNING;
113 }
114 else if (nfc_ledger_data.mode == NFC_LEDGER_MODE_READER) {
115 ledger_protocol_result_t result = LEDGER_PROTOCOL_init(&nfc_ledger_data.protocol_data,
116 OS_IO_PACKET_TYPE_NFC_APDU_RSP);
117 if (result != LP_SUCCESS) {
118 goto error;
119 }
120 os_io_nfc_cmd_power(SEPROXYHAL_TAG_NFC_POWER_ON_READER);
121 nfc_ledger_data.state = NFC_STATE_RUNNING;
122 }
123 }
124
125error:
126 return;
127}
128
129void NFC_LEDGER_stop(void)
130{
131 if (nfc_ledger_data.state == NFC_STATE_RUNNING) {
132 os_io_nfc_cmd_power(SEPROXYHAL_TAG_NFC_POWER_OFF);
133 nfc_ledger_data.state = NFC_STATE_INITIALIZED;
134 }
135}
136
137int NFC_LEDGER_rx_seph_apdu_evt(uint8_t *seph_buffer,
138 uint16_t seph_buffer_length,
139 uint8_t *apdu_buffer,
140 uint16_t apdu_buffer_max_length)
141{
142 int status = -1;
143
144 if (nfc_ledger_data.state == NFC_STATE_RUNNING) {
145 seph_t seph = {0};
146 if (seph_buffer_length
147 && !seph_parse_header(&seph_buffer[1], seph_buffer_length - 1, &seph)) {
148 status = -1;
149 goto error;
150 }
151
152 ledger_protocol_result_t result
153 = LEDGER_PROTOCOL_rx(&nfc_ledger_data.protocol_data,
154 seph.data,
155 seph.size,
156 nfc_ledger_protocol_chunk_buffer,
157 sizeof(nfc_ledger_protocol_chunk_buffer),
158 NFC_LEDGER_io_buffer,
159 sizeof(NFC_LEDGER_io_buffer),
160 sizeof(nfc_ledger_protocol_chunk_buffer));
161 if (result != LP_SUCCESS) {
162 status = -1;
163 goto error;
164 }
165
166 if (nfc_ledger_data.protocol_data.rx_apdu_status == APDU_STATUS_COMPLETE) {
167 if ((apdu_buffer_max_length < nfc_ledger_data.protocol_data.rx_apdu_length)
168 || (sizeof(NFC_LEDGER_io_buffer) < nfc_ledger_data.protocol_data.rx_apdu_length)) {
169 status = -1;
170 }
171 else {
172 memmove(apdu_buffer,
173 NFC_LEDGER_io_buffer,
174 nfc_ledger_data.protocol_data.rx_apdu_length);
175 status = nfc_ledger_data.protocol_data.rx_apdu_length;
176 }
177 nfc_ledger_data.protocol_data.rx_apdu_status = APDU_STATUS_WAITING;
178 }
179 }
180
181error:
182 return status;
183}
184
185uint32_t NFC_LEDGER_send(const uint8_t *packet, uint16_t packet_length, uint32_t timeout_ms)
186{
187 uint32_t status = 1;
188
189 if (nfc_ledger_data.state == NFC_STATE_RUNNING) {
190 ledger_protocol_result_t result
191 = LEDGER_PROTOCOL_tx(&nfc_ledger_data.protocol_data,
192 packet,
193 packet_length,
194 nfc_ledger_protocol_chunk_buffer,
195 sizeof(nfc_ledger_protocol_chunk_buffer),
196 sizeof(nfc_ledger_protocol_chunk_buffer));
197 if (result != LP_SUCCESS) {
198 status = 1;
199 goto error;
200 }
201 if (nfc_ledger_data.protocol_data.tx_chunk_length >= 2) {
202 nfc_ledger_send_rapdu(nfc_ledger_protocol_chunk_buffer,
203 nfc_ledger_data.protocol_data.tx_chunk_length,
204 timeout_ms);
205 }
206
207 while (nfc_ledger_data.protocol_data.tx_apdu_buffer) {
208 ledger_protocol_result_t result
209 = LEDGER_PROTOCOL_tx(&nfc_ledger_data.protocol_data,
210 NULL,
211 0,
212 nfc_ledger_protocol_chunk_buffer,
213 sizeof(nfc_ledger_protocol_chunk_buffer),
214 sizeof(nfc_ledger_protocol_chunk_buffer));
215 if (result != LP_SUCCESS) {
216 status = 1;
217 goto error;
218 }
219 if (nfc_ledger_data.protocol_data.tx_chunk_length >= 2) {
220 nfc_ledger_send_rapdu(nfc_ledger_protocol_chunk_buffer,
221 nfc_ledger_data.protocol_data.tx_chunk_length,
222 timeout_ms);
223 }
224 }
225 // TODO: status is never read? nfc_ledger_send_apdu should return an error code
226 status = 0;
227 }
228
229error:
230 return status;
231}
232
233#endif // HAVE_NFC
void NFC_LEDGER_stop(void)
void NFC_LEDGER_init(uint8_t force_restart)
int NFC_LEDGER_rx_seph_apdu_evt(uint8_t *seph_buffer, uint16_t seph_buffer_length, uint8_t *apdu_buffer, uint16_t apdu_buffer_max_length)
uint32_t NFC_LEDGER_send(const uint8_t *packet, uint16_t packet_length, uint32_t timeout_ms)
void NFC_LEDGER_start(uint8_t mode)
@ NFC_LEDGER_MODE_READER
Definition nfc_ledger.h:25
@ NFC_LEDGER_MODE_CARD_EMULATION
Definition nfc_ledger.h:24
#define LOG_IO(...)