2
2
3
3
#include <furi.h>
4
4
5
- #define ISO14443_4_BLOCK_PCB (1U << 1)
6
- #define ISO14443_4_BLOCK_PCB_I (0U)
7
- #define ISO14443_4_BLOCK_PCB_R (5U << 5)
8
- #define ISO14443_4_BLOCK_PCB_S (3U << 6)
5
+ #define ISO14443_4_BLOCK_PCB (1U << 1)
6
+ #define ISO14443_4_BLOCK_PCB_MASK (0x03)
7
+
8
+ #define ISO14443_4_BLOCK_PCB_I (0U)
9
+ #define ISO14443_4_BLOCK_PCB_I_NAD_OFFSET (2)
10
+ #define ISO14443_4_BLOCK_PCB_I_CID_OFFSET (3)
11
+ #define ISO14443_4_BLOCK_PCB_I_CHAIN_OFFSET (4)
12
+ #define ISO14443_4_BLOCK_PCB_I_NAD_MASK (1U << ISO14443_4_BLOCK_PCB_I_NAD_OFFSET)
13
+ #define ISO14443_4_BLOCK_PCB_I_CID_MASK (1U << ISO14443_4_BLOCK_PCB_I_CID_OFFSET)
14
+ #define ISO14443_4_BLOCK_PCB_I_CHAIN_MASK (1U << ISO14443_4_BLOCK_PCB_I_CHAIN_OFFSET)
15
+
16
+ #define ISO14443_4_BLOCK_PCB_R_MASK (5U << 5)
17
+ #define ISO14443_4_BLOCK_PCB_R_NACK_OFFSET (4)
18
+ #define ISO14443_4_BLOCK_PCB_R_CID_OFFSET (3)
19
+ #define ISO14443_4_BLOCK_PCB_R_CID_MASK (1U << ISO14443_4_BLOCK_PCB_R_CID_OFFSET)
20
+ #define ISO14443_4_BLOCK_PCB_R_NACK_MASK (1U << ISO14443_4_BLOCK_PCB_R_NACK_OFFSET)
21
+
22
+ #define ISO14443_4_BLOCK_PCB_S_MASK (3U << 6)
23
+ #define ISO14443_4_BLOCK_PCB_S_CID_OFFSET (3)
24
+ #define ISO14443_4_BLOCK_PCB_S_WTX_DESELECT_OFFSET (4)
25
+ #define ISO14443_4_BLOCK_PCB_S_CID_MASK (1U << ISO14443_4_BLOCK_PCB_R_CID_OFFSET)
26
+ #define ISO14443_4_BLOCK_PCB_S_WTX_DESELECT_MASK (3U << ISO14443_4_BLOCK_PCB_S_WTX_DESELECT_OFFSET)
27
+
28
+ #define ISO14443_4_BLOCK_PCB_BITS_ACTIVE (pcb , mask ) (((pcb) & (mask)) == (mask))
29
+
30
+ #define ISO14443_4_BLOCK_PCB_IS_R_BLOCK (pcb ) \
31
+ ISO14443_4_BLOCK_PCB_BITS_ACTIVE(pcb, ISO14443_4_BLOCK_PCB_R_MASK)
32
+
33
+ #define ISO14443_4_BLOCK_PCB_IS_S_BLOCK (pcb ) \
34
+ ISO14443_4_BLOCK_PCB_BITS_ACTIVE(pcb, ISO14443_4_BLOCK_PCB_S_MASK)
35
+
36
+ #define ISO14443_4_BLOCK_PCB_IS_CHAIN_ACTIVE (pcb ) \
37
+ ISO14443_4_BLOCK_PCB_BITS_ACTIVE(pcb, ISO14443_4_BLOCK_PCB_I_CHAIN_MASK)
38
+
39
+ #define ISO14443_4_BLOCK_PCB_R_NACK_ACTIVE (pcb ) \
40
+ ISO14443_4_BLOCK_PCB_BITS_ACTIVE(pcb, ISO14443_4_BLOCK_PCB_R_NACK_MASK)
9
41
10
42
struct Iso14443_4Layer {
11
43
uint8_t pcb ;
@@ -31,9 +63,31 @@ void iso14443_4_layer_free(Iso14443_4Layer* instance) {
31
63
32
64
void iso14443_4_layer_reset (Iso14443_4Layer * instance ) {
33
65
furi_assert (instance );
66
+ instance -> pcb_prev = 0 ;
34
67
instance -> pcb = ISO14443_4_BLOCK_PCB_I | ISO14443_4_BLOCK_PCB ;
35
68
}
36
69
70
+ void iso14443_4_layer_set_i_block (Iso14443_4Layer * instance , bool chaining , bool CID_present ) {
71
+ uint8_t block_pcb = instance -> pcb & ISO14443_4_BLOCK_PCB_MASK ;
72
+ instance -> pcb = ISO14443_4_BLOCK_PCB_I | (chaining << ISO14443_4_BLOCK_PCB_I_CHAIN_OFFSET ) |
73
+ (CID_present << ISO14443_4_BLOCK_PCB_I_CID_OFFSET ) | block_pcb ;
74
+ }
75
+
76
+ void iso14443_4_layer_set_r_block (Iso14443_4Layer * instance , bool acknowledged , bool CID_present ) {
77
+ furi_assert (instance );
78
+ uint8_t block_pcb = instance -> pcb & ISO14443_4_BLOCK_PCB_MASK ;
79
+ instance -> pcb = ISO14443_4_BLOCK_PCB_R_MASK |
80
+ (!acknowledged << ISO14443_4_BLOCK_PCB_R_NACK_OFFSET ) |
81
+ (CID_present << ISO14443_4_BLOCK_PCB_R_CID_OFFSET ) | block_pcb ;
82
+ }
83
+
84
+ void iso14443_4_layer_set_s_block (Iso14443_4Layer * instance , bool deselect , bool CID_present ) {
85
+ furi_assert (instance );
86
+ uint8_t des_wtx = !deselect ? (ISO14443_4_BLOCK_PCB_S_WTX_DESELECT_MASK ) : 0 ;
87
+ instance -> pcb = ISO14443_4_BLOCK_PCB_S_MASK | des_wtx |
88
+ (CID_present << ISO14443_4_BLOCK_PCB_S_CID_OFFSET ) | ISO14443_4_BLOCK_PCB ;
89
+ }
90
+
37
91
void iso14443_4_layer_encode_block (
38
92
Iso14443_4Layer * instance ,
39
93
const BitBuffer * input_data ,
@@ -46,6 +100,11 @@ void iso14443_4_layer_encode_block(
46
100
iso14443_4_layer_update_pcb (instance );
47
101
}
48
102
103
+ static inline uint8_t iso14443_4_layer_get_response_pcb (const BitBuffer * block_data ) {
104
+ const uint8_t * data = bit_buffer_get_data (block_data );
105
+ return data [0 ];
106
+ }
107
+
49
108
bool iso14443_4_layer_decode_block (
50
109
Iso14443_4Layer * instance ,
51
110
BitBuffer * output_data ,
@@ -55,9 +114,26 @@ bool iso14443_4_layer_decode_block(
55
114
bool ret = false;
56
115
57
116
do {
58
- if (!bit_buffer_starts_with_byte (block_data , instance -> pcb_prev )) break ;
59
- bit_buffer_copy_right (output_data , block_data , 1 );
60
- ret = true;
117
+ if (ISO14443_4_BLOCK_PCB_IS_R_BLOCK (instance -> pcb_prev )) {
118
+ const uint8_t response_pcb = iso14443_4_layer_get_response_pcb (block_data );
119
+ ret = (ISO14443_4_BLOCK_PCB_IS_R_BLOCK (response_pcb )) &&
120
+ (!ISO14443_4_BLOCK_PCB_R_NACK_ACTIVE (response_pcb ));
121
+ instance -> pcb &= ISO14443_4_BLOCK_PCB_MASK ;
122
+ iso14443_4_layer_update_pcb (instance );
123
+ } else if (ISO14443_4_BLOCK_PCB_IS_CHAIN_ACTIVE (instance -> pcb_prev )) {
124
+ const uint8_t response_pcb = iso14443_4_layer_get_response_pcb (block_data );
125
+ ret = (ISO14443_4_BLOCK_PCB_IS_R_BLOCK (response_pcb )) &&
126
+ (!ISO14443_4_BLOCK_PCB_R_NACK_ACTIVE (response_pcb ));
127
+ instance -> pcb &= ~(ISO14443_4_BLOCK_PCB_I_CHAIN_MASK );
128
+ } else if (ISO14443_4_BLOCK_PCB_IS_S_BLOCK (instance -> pcb_prev )) {
129
+ ret = bit_buffer_starts_with_byte (block_data , instance -> pcb_prev );
130
+ if (bit_buffer_get_size_bytes (block_data ) > 1 )
131
+ bit_buffer_copy_right (output_data , block_data , 1 );
132
+ } else {
133
+ if (!bit_buffer_starts_with_byte (block_data , instance -> pcb_prev )) break ;
134
+ bit_buffer_copy_right (output_data , block_data , 1 );
135
+ ret = true;
136
+ }
61
137
} while (false);
62
138
63
139
return ret ;
0 commit comments