1 /******************************************************************************
2 *
3 * Copyright (C) 2023 ST Microelectronics S.A.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *
18 ******************************************************************************/
19 #define LOG_TAG "NfcHalFwLog"
20
21 #include "hal_fwlog.h"
22 #include <cutils/properties.h>
23 #include <dlfcn.h>
24 #include <errno.h>
25 #include <hardware/nfc.h>
26 #include <string.h>
27 #include "android_logmsg.h"
28 #include "halcore.h"
29 #include "hal_fd.h"
30
31 extern void DispHal(const char* title, const void* data, size_t length);
32
handlePollingLoopData(uint8_t format,uint8_t * tlvBuffer,uint16_t data_len,uint8_t ** NewTlv)33 uint8_t handlePollingLoopData(uint8_t format, uint8_t* tlvBuffer,
34 uint16_t data_len, uint8_t** NewTlv) {
35 uint8_t value_len = 0;
36 uint8_t flag= 0;
37
38 uint32_t timestamp = (tlvBuffer[data_len - 4] << 24) |
39 (tlvBuffer[data_len - 3] << 16) |
40 (tlvBuffer[data_len - 2] << 8) | tlvBuffer[data_len - 1];
41
42 uint32_t ts = 0;
43
44 if ((format & 0x30) == 0x30) {
45 // ST54L: 3.95us unit
46 ts = (uint32_t)(((timestamp * 1024) / 259) + 0.5);
47 } else {
48 // ST54J/K: 4.57us unit
49 ts = (uint32_t)(((timestamp * 128) / 28) + 0.5);
50 }
51
52 int t = tlvBuffer[0];
53
54 switch (t) {
55 case T_fieldOn:
56 case T_fieldOff:
57 STLOG_HAL_D("%s - FieldOn/Off", __func__);
58 *NewTlv = (uint8_t*)malloc(9 * sizeof(uint8_t));
59 value_len = 0x06;
60 (*NewTlv)[0] = TYPE_REMOTE_FIELD;
61 (*NewTlv)[1] = flag;
62 (*NewTlv)[2] = value_len;
63 (*NewTlv)[3] = (ts >> 24) & 0xFF;
64 (*NewTlv)[4] = (ts >> 16) & 0xFF;
65 (*NewTlv)[5] = (ts >> 8) & 0xFF;
66 (*NewTlv)[6] = ts & 0xFF;
67 (*NewTlv)[7] = 0xFF;
68 (*NewTlv)[8] = (t == T_fieldOn) ? 0x1 : 0x0;
69 break;
70 case T_CERxError:
71 case T_CERx: {
72 STLOG_HAL_D("%s - T_CERx", __func__);
73 int tlv_size = tlvBuffer[1] - 2;
74 if (tlv_size < 9) {
75 tlv_size = 8;
76 }
77
78 // work-around type-A short frame notification bug
79 if (hal_fd_getFwInfo()->chipHwVersion == HW_ST54J &&
80 (tlvBuffer[2] & 0xF) == 0x01 && // short frame
81 tlvBuffer[5] == 0x00 && // no error
82 tlvBuffer[6] == 0x0F // incorrect real size
83 ) {
84 tlv_size = 9;
85 }
86
87 value_len = tlv_size- 3;
88 *NewTlv = (uint8_t*)malloc(tlv_size * sizeof(uint8_t));
89 uint8_t gain;
90 uint8_t type;
91 int length_value = tlv_size - 8;
92 gain = (tlvBuffer[3] & 0xF0) >> 4;
93
94 switch (tlvBuffer[2] & 0xF) {
95 case 0x1:
96 flag |= 0x01;
97 type = TYPE_A;
98 break;
99 case 0x2:
100 case 0x3:
101 case 0x4:
102 case 0x5:
103 case 0x6:
104 case 0xB:
105 case 0xD:
106 type = TYPE_A;
107 break;
108 case 0x7:
109 case 0xC:
110 type = TYPE_B;
111 break;
112 case 0x8:
113 case 0x9:
114 type = TYPE_F;
115 break;
116 case 0xA:
117 type = TYPE_V;
118 break;
119 default:
120 type = TYPE_UNKNOWN;
121 break;
122 }
123 if ((tlvBuffer[5] != 0) ||
124 ((type == TYPE_A) &&
125 (tlvBuffer[8] != 0x26 && tlvBuffer[8] != 0x52)) ||
126 ((type == TYPE_B) && (tlvBuffer[8] != 0x05) &&
127 (length_value == 0x3))) {
128 // if error flag is set, consider the frame as unknown.
129 type = TYPE_UNKNOWN;
130 }
131 (*NewTlv)[0] = type;
132 (*NewTlv)[1] = flag;
133 (*NewTlv)[2] = value_len;
134 (*NewTlv)[3] = (ts >> 24) & 0xFF;
135 (*NewTlv)[4] = (ts >> 16) & 0xFF;
136 (*NewTlv)[5] = (ts >> 8) & 0xFF;
137 (*NewTlv)[6] = ts & 0xFF;
138 (*NewTlv)[7] = gain;
139 if (tlv_size > 8) {
140 memcpy(*NewTlv + 8, tlvBuffer + 8, length_value);
141 }
142 } break;
143 default:
144 break;
145 }
146 if (value_len)
147 return value_len + 3;
148 else
149 return 0;
150 }
151
notifyPollingLoopFrames(uint8_t * p_data,uint16_t data_len,uint8_t * bufferToSend)152 int notifyPollingLoopFrames(uint8_t* p_data, uint16_t data_len,
153 uint8_t* bufferToSend) {
154 int current_tlv_length = 0;
155 int tlv_len = 0;
156 int ntf_len = 4;
157 uint8_t* tlvFormatted = NULL;
158 uint8_t* ObserverNtf = NULL;
159 uint8_t* PreviousObserverNtf;
160 uint8_t NCI_ANDROID_PASSIVE_OBSERVER_HEADER[4] = {0x6f, 0xc, 0x01, 0x3};
161
162 for (int current_tlv_pos = 6;
163 current_tlv_pos + p_data[current_tlv_pos + 1] + 2 <= data_len;
164 current_tlv_pos += current_tlv_length) {
165 current_tlv_length = p_data[current_tlv_pos + 1] + 2;
166 uint8_t* tlvBuffer = p_data + current_tlv_pos;
167
168 tlv_len = handlePollingLoopData(p_data[3], tlvBuffer, current_tlv_length,
169 &tlvFormatted);
170
171 if (tlvFormatted != NULL) {
172
173 if (ObserverNtf == NULL) {
174 ObserverNtf = (uint8_t*)malloc(4 * sizeof(uint8_t));
175 memcpy(ObserverNtf, NCI_ANDROID_PASSIVE_OBSERVER_HEADER, 4);
176 }
177
178 PreviousObserverNtf = ObserverNtf;
179
180 ObserverNtf = (uint8_t*)malloc((ntf_len + tlv_len) * sizeof(uint8_t));
181 memcpy(ObserverNtf, PreviousObserverNtf, ntf_len);
182 memcpy(ObserverNtf + ntf_len, tlvFormatted, tlv_len);
183 ObserverNtf[2] = ntf_len + tlv_len - 3;
184 ntf_len += tlv_len;
185 free(tlvFormatted);
186 tlvFormatted = NULL;
187 free(PreviousObserverNtf);
188 }
189 }
190 if (ObserverNtf != nullptr) {
191 if (ntf_len <= 258) {
192 memcpy(bufferToSend, ObserverNtf, ntf_len);
193 }
194 free(ObserverNtf);
195 return ntf_len;
196 } else {
197 return 0;
198 }
199 }
200