1 /******************************************************************************
2  *
3  *  Copyright (C) 2018 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 "NfcHalFd"
20 #include "hal_fd.h"
21 #include <cutils/properties.h>
22 #include <dlfcn.h>
23 #include <errno.h>
24 #include <hardware/nfc.h>
25 #include <string.h>
26 #include "android_logmsg.h"
27 #include "halcore.h"
28 /* Initialize fw info structure pointer used to access fw info structure */
29 FWInfo *mFWInfo = NULL;
30 FILE *mFwFileBin;
31 FILE *mCustomFileBin;
32 fpos_t mPos;
33 fpos_t mPosInit;
34 uint8_t mBinData[260];
35 bool mRetry = true;
36 bool mCustomParamFailed = false;
37 bool mCustomParamDone = false;
38 bool mUwbConfigDone = false;
39 bool mUwbConfigNeeded = false;
40 bool mGetCustomerField = false;
41 uint8_t *pCmd;
42 int mFWRecovCount = 0;
43 const char *FwType = "generic";
44 char mApduAuthent[24];
45 
46 static const uint8_t propNfcModeSetCmdOn[] = {0x2f, 0x02, 0x02, 0x02, 0x01};
47 static const uint8_t coreInitCmd[] = {0x20, 0x01, 0x02, 0x00, 0x00};
48 static const uint8_t NciPropNfcFwUpdate[] = {0x2F, 0x02, 0x05, 0x06,
49                                              0x00, 0x01, 0x02, 0x03};
50 
51 static uint8_t ApduEraseNfcKeepAppliAndNdef[] = {
52     0x2F, 0x04, 0x16, 0x80, 0x0C, 0x00, 0x00, 0x11, 0x05,
53     0x00, 0x23, 0xDF, 0x00, 0x00, 0x23, 0xDF, 0xFF, 0x00,
54     0x23, 0xE0, 0x00, 0x00, 0x23, 0xFF, 0xFF};
55 
56 static const uint8_t ApduExitLoadMode[] = {0x2F, 0x04, 0x06, 0x80, 0xA0,
57                                            0x00, 0x00, 0x01, 0x01};
58 static const uint8_t nciHeaderPropSetUwbConfig[9] = {
59     0x2F, 0x02, 0x00, 0x04, 0x00, 0x16, 0x01, 0x00, 0x00};
60 static const uint8_t nciGetPropConfig[8] = {0x2F, 0x02, 0x05, 0x03,
61                                             0x00, 0x06, 0x01, 0x00};
62 static const uint8_t nciSetPropConfig[9] = {0x2F, 0x02, 0x00, 0x04, 0x00,
63                                             0x06, 0x01, 0x00, 0x00};
64 static uint8_t nciPropSetUwbConfig[128];
65 static uint8_t nciPropSetConfig_CustomField[64];
66 hal_fd_state_e mHalFDState = HAL_FD_STATE_AUTHENTICATE;
67 void SendExitLoadMode(HALHANDLE mmHalHandle);
68 extern void hal_wrapper_update_complete();
69 
70 typedef size_t (*STLoadUwbParams)(void *out_buff,
71                                   size_t buf_size);
72 
73 /**
74  * Send a HW reset and decode NCI_CORE_RESET_NTF information
75  * @param pHwVersion is used to return HW version, part of NCI_CORE_RESET_NTF
76  * @param pFwVersion is used to return FW version, part of NCI_CORE_RESET_NTF
77  * @param pLoaderVersion is used to return Loader version, part of
78  * NCI_CORE_RESET_NTF
79  * @param pCustVersion si used to return Customer field value, part of
80  * NCI_CORE_RESET_NTF when in router mode
81  *
82  * @return mode: FT_CLF_MODE_ROUTER if router mode
83  *               FT_CLF_MODE_LOADER if loader mode
84  *               FT_CLF_MODE_ERROR if Error
85  */
86 
hal_fd_init()87 int hal_fd_init() {
88   uint8_t result = 0;
89   char FwPath[256];
90   char ConfPath[256];
91   char fwBinName[256];
92   char fwConfName[256];
93 
94   STLOG_HAL_D("  %s - enter", __func__);
95 
96   if (!GetStrValue(NAME_STNFC_FW_PATH_STORAGE, (char *)FwPath,
97                    sizeof(FwPath))) {
98     STLOG_HAL_D(
99         "%s - FW path not found in conf. use default location /vendor/firmware "
100         "\n", __func__);
101     strcpy(FwPath, "/vendor/firmware");
102   }
103 
104   if (!GetStrValue(NAME_STNFC_FW_BIN_NAME, (char *)fwBinName,
105                    sizeof(fwBinName))) {
106     STLOG_HAL_D(
107         "%s - FW binary file name not found in conf. use default name "
108         "/st21nfc_fw.bin \n", __func__);
109     strcpy(fwBinName, "/st21nfc_fw.bin");
110   }
111 
112   if (!GetStrValue(NAME_STNFC_FW_CONF_NAME, (char *)fwConfName,
113                    sizeof(fwConfName))) {
114     STLOG_HAL_D(
115         "%s - FW config file name not found in conf. use default name "
116         "/st21nfc_conf.bin \n", __func__);
117     strcpy(fwConfName, "/st21nfc_conf.bin");
118   }
119 
120   // Getting information about FW patch, if any
121   strcpy(ConfPath, FwPath);
122   strncat(FwPath, fwBinName, sizeof(FwPath) - strlen(FwPath) - 1);
123   strncat(ConfPath, fwConfName, sizeof(ConfPath) - strlen(ConfPath) - 1);
124   STLOG_HAL_D("%s - FW update binary file = %s", __func__, FwPath);
125   STLOG_HAL_D("%s - FW config binary file = %s", __func__, ConfPath);
126 
127   // Initializing structure holding FW patch details
128   mFWInfo = (FWInfo *)malloc(sizeof(FWInfo));
129 
130   if (mFWInfo == NULL) {
131     result = 0;
132   }
133 
134   memset(mFWInfo, 0, sizeof(FWInfo));
135 
136   mFwFileBin = NULL;
137   mCustomFileBin = NULL;
138 
139   // Check if FW patch binary file is present
140   // If not, get recovery FW patch file
141   if ((mFwFileBin = fopen((char *)FwPath, "r")) == NULL) {
142     STLOG_HAL_D("%s - %s not detected", __func__, fwBinName);
143   } else {
144     STLOG_HAL_D("%s - %s file detected\n", __func__, fwBinName);
145 
146     result |= FW_PATCH_AVAILABLE;
147     fread(mBinData, sizeof(uint8_t), 4, mFwFileBin);
148     mFWInfo->patchVersion =
149         mBinData[0] << 24 | mBinData[1] << 16 | mBinData[2] << 8 | mBinData[3];
150 
151     fread(mApduAuthent, sizeof(uint8_t), 24, mFwFileBin);
152 
153     fgetpos(mFwFileBin, &mPosInit);
154 
155     STLOG_HAL_D(
156         "%s --> st21nfc_fw integrates patch NFC FW version 0x%08X (%s)\n",
157         __func__, mFWInfo->patchVersion, FwType);
158   }
159 
160   if ((mCustomFileBin = fopen((char *)ConfPath, "r")) == NULL) {
161     STLOG_HAL_D("%s - st21nfc custom configuration not detected\n", __func__);
162   } else {
163     STLOG_HAL_D("%s - %s file detected\n", __func__, ConfPath);
164     fread(mBinData, sizeof(uint8_t), 2, mCustomFileBin);
165     mFWInfo->confVersion = mBinData[0] << 8 | mBinData[1];
166     STLOG_HAL_D("%s --> st21nfc_custom configuration version 0x%04X \n",
167                 __func__, mFWInfo->confVersion);
168     result |= FW_CUSTOM_PARAM_AVAILABLE;
169   }
170 
171   if (ft_CheckUWBConf()) {
172     result |= FW_UWB_PARAM_AVAILABLE;
173   }
174 
175   return result;
176 }
177 
hal_fd_close()178 void hal_fd_close() {
179   STLOG_HAL_D("  %s -enter", __func__);
180   mCustomParamFailed = false;
181   if (mFWInfo != NULL) {
182     free(mFWInfo);
183     mFWInfo = NULL;
184   }
185   if (mFwFileBin != NULL) {
186     fclose(mFwFileBin);
187     mFwFileBin = NULL;
188   }
189   if (mCustomFileBin != NULL) {
190     fclose(mCustomFileBin);
191     mCustomFileBin = NULL;
192   }
193 }
194 
195 /**
196  * Send a HW reset and decode NCI_CORE_RESET_NTF information
197  * @param pHwVersion is used to return HW version, part of NCI_CORE_RESET_NTF
198  * @param pFwVersion is used to return FW version, part of NCI_CORE_RESET_NTF
199  * @param pLoaderVersion is used to return Loader version, part of
200  * NCI_CORE_RESET_NTF
201  * @param pCustVersion si used to return Customer field value, part of
202  * NCI_CORE_RESET_NTF when in router mode
203  *
204  * @return mode: FT_CLF_MODE_ROUTER if router mode
205  *               FT_CLF_MODE_LOADER if loader mode
206  *               FT_CLF_MODE_ERROR if Error
207  */
208 
ft_cmd_HwReset(uint8_t * pdata,uint8_t * clf_mode)209 uint8_t ft_cmd_HwReset(uint8_t *pdata, uint8_t *clf_mode) {
210   uint8_t result = 0;
211 
212   STLOG_HAL_D("  %s - execution", __func__);
213 
214   if ((pdata[1] == 0x0) && (pdata[3] == 0x1)) {
215     STLOG_HAL_D("-> Router Mode NCI_CORE_RESET_NTF received after HW Reset");
216 
217     /* retrieve HW Version from NCI_CORE_RESET_NTF */
218     mFWInfo->hwVersion = pdata[8];
219     STLOG_HAL_D("   HwVersion = 0x%02X", mFWInfo->hwVersion);
220 
221     /* retrieve FW Version from NCI_CORE_RESET_NTF */
222     mFWInfo->fwVersion =
223         (pdata[10] << 24) | (pdata[11] << 16) | (pdata[12] << 8) | pdata[13];
224     STLOG_HAL_D("   FwVersion = 0x%08X", mFWInfo->fwVersion);
225 
226     /* retrieve Loader Version from NCI_CORE_RESET_NTF */
227     mFWInfo->loaderVersion = (pdata[14] << 16) | (pdata[15] << 8) | pdata[16];
228     STLOG_HAL_D("   LoaderVersion = 0x%06X", mFWInfo->loaderVersion);
229 
230     /* retrieve Customer Version from NCI_CORE_RESET_NTF */
231     mFWInfo->custVersion = (pdata[31] << 8) | pdata[32];
232     STLOG_HAL_D("   CustomerVersion = 0x%04X", mFWInfo->custVersion);
233 
234     /* retrieve Uwb param Version from NCI_CORE_RESET_NTF */
235     mFWInfo->uwbFwVersion = (pdata[29] << 8) | pdata[30];
236     STLOG_HAL_D("   uwbVersion = 0x%04X", mFWInfo->uwbFwVersion);
237 
238     *clf_mode = FT_CLF_MODE_ROUTER;
239   } else if ((pdata[2] == 0x39) && (pdata[3] == 0xA1)) {
240     STLOG_HAL_D("-> Loader Mode NCI_CORE_RESET_NTF received after HW Reset");
241 
242     /* deduce HW Version from Factory Loader version */
243     if (pdata[16] == 0x01) {
244       mFWInfo->hwVersion = 0x05;  // ST54J
245     } else if (pdata[16] == 0x02) {
246       mFWInfo->hwVersion = 0x04;  // ST21NFCD
247     } else {
248       mFWInfo->hwVersion = 0x03;  // ST21NFCD
249     }
250     STLOG_HAL_D("   HwVersion = 0x%02X", mFWInfo->hwVersion);
251 
252     /* Identify the Active loader. Normally only one should be detected*/
253     if (pdata[11] == 0xA0) {
254       mFWInfo->loaderVersion = (pdata[8] << 16) | (pdata[9] << 8) | pdata[10];
255       STLOG_HAL_D("         - Most recent loader activated, revision 0x%06X",
256                   mFWInfo->loaderVersion);
257     }
258     if (pdata[15] == 0xA0) {
259       mFWInfo->loaderVersion = (pdata[12] << 16) | (pdata[13] << 8) | pdata[14];
260       STLOG_HAL_D("         - Least recent loader activated, revision 0x%06X",
261                   mFWInfo->loaderVersion);
262     }
263     if (pdata[19] == 0xA0) {
264       mFWInfo->loaderVersion = (pdata[16] << 16) | (pdata[17] << 8) | pdata[18];
265       STLOG_HAL_D("         - Factory loader activated, revision 0x%06X",
266                   mFWInfo->loaderVersion);
267     }
268 
269     *clf_mode = FT_CLF_MODE_LOADER;
270   } else {
271     STLOG_HAL_E(
272         "%s --> ERROR: wrong NCI_CORE_RESET_NTF received after HW Reset",
273         __func__);
274     *clf_mode = FT_CLF_MODE_ERROR;
275   }
276 
277   // Allow update only for ST54J
278   if (mFWInfo->hwVersion == 0x05) {
279     if ((mFwFileBin != NULL) && (mFWInfo->patchVersion != mFWInfo->fwVersion)) {
280       STLOG_HAL_D("---> Firmware update needed\n");
281       result |= FW_UPDATE_NEEDED;
282     } else {
283       STLOG_HAL_D("---> No Firmware update needed\n");
284     }
285 
286     if ((mFWInfo->confVersion != 0) &&
287         (mFWInfo->custVersion != mFWInfo->confVersion)) {
288       STLOG_HAL_D(
289           "%s - Need to apply new st21nfc custom configuration settings\n",
290           __func__);
291       if (!mCustomParamFailed) result |= CONF_UPDATE_NEEDED;
292     } else {
293       STLOG_HAL_D("%s - No need to apply custom configuration settings\n",
294                   __func__);
295     }
296   }
297   if ((mFWInfo->uwbVersion != 0) &&
298       (mFWInfo->uwbVersion != mFWInfo->uwbFwVersion)) {
299     result |= UWB_CONF_UPDATE_NEEDED;
300     STLOG_HAL_D("%s - Need to apply new uwb param configuration \n", __func__);
301     mUwbConfigNeeded = true;
302   }
303 
304   return result;
305 } /* ft_cmd_HwReset */
306 
ExitHibernateHandler(HALHANDLE mHalHandle,uint16_t data_len,uint8_t * p_data)307 void ExitHibernateHandler(HALHANDLE mHalHandle, uint16_t data_len,
308                           uint8_t *p_data) {
309   STLOG_HAL_D("%s - Enter", __func__);
310   if (data_len < 3) {
311     STLOG_HAL_E("%s - Error, too short data (%d)", __func__, data_len);
312     return;
313   }
314   switch (p_data[0]) {
315     case 0x40:  //
316       STLOG_HAL_D("%s - hibernate_exited = %d ", __func__,
317                   mFWInfo->hibernate_exited);
318 
319       // CORE_INIT_RSP
320       if ((p_data[1] == 0x1) && (p_data[3] == 0x0) &&
321           (mFWInfo->hibernate_exited == 0)) {
322         // Send PROP_NFC_MODE_SET_CMD(ON)
323         if (!HalSendDownstream(mHalHandle, propNfcModeSetCmdOn,
324                                sizeof(propNfcModeSetCmdOn))) {
325           STLOG_HAL_E("%s - SendDownstream failed", __func__);
326         }
327       } else if ((p_data[1] == 0x1) && (p_data[3] == 0x0) &&
328                  (mFWInfo->hibernate_exited == 1)) {
329         STLOG_HAL_D(
330             "%s - send NCI_PROP_NFC_FW_UPDATE_CMD and use 100 ms timer for "
331             "each cmd from here",
332             __func__);
333 
334         if (!HalSendDownstreamTimer(mHalHandle, NciPropNfcFwUpdate,
335                                     sizeof(NciPropNfcFwUpdate),
336                                     FW_TIMER_DURATION)) {
337           STLOG_HAL_E("%s  SendDownstream failed", __func__);
338         }
339       } else if (p_data[3] != 0x00) {
340         STLOG_HAL_D("%s - Wrong response. Retry HW reset", __func__);
341         I2cResetPulse();
342         hal_wrapper_set_state(HAL_WRAPPER_STATE_OPEN);
343       }
344       break;
345 
346     case 0x4f:  //
347       if ((p_data[1] == 0x02) && (p_data[3] == 0x00) &&
348           (mFWInfo->hibernate_exited == 1)) {
349         STLOG_HAL_D("%s - NCI_PROP_NFC_FW_RSP : loader mode", __func__);
350         I2cResetPulse();
351         hal_wrapper_set_state(HAL_WRAPPER_STATE_OPEN);
352       } else if (p_data[3] != 0x00) {
353         STLOG_HAL_D("%s - Wrong response. Retry HW reset", __func__);
354         I2cResetPulse();
355         hal_wrapper_set_state(HAL_WRAPPER_STATE_OPEN);
356       }
357       break;
358     case 0x60:  //
359       if (p_data[3] == 0x2) {
360         STLOG_HAL_D("%s - CORE_RESET_NTF : after core_reset_cmd", __func__);
361 
362         if (!HalSendDownstream(mHalHandle, coreInitCmd, sizeof(coreInitCmd))) {
363           STLOG_HAL_E("%s - SendDownstream failed", __func__);
364         }
365       } else if (p_data[3] == 0xa0) {
366         mFWInfo->hibernate_exited = 1;
367         STLOG_HAL_D("%s - hibernate_exited = %d ", __func__,
368                     mFWInfo->hibernate_exited);
369 
370         if (!HalSendDownstream(mHalHandle, coreInitCmd, sizeof(coreInitCmd))) {
371           STLOG_HAL_E("%s - SendDownstream failed", __func__);
372         }
373       }
374       break;
375   }
376 }
377 
ft_CheckUWBConf()378 bool ft_CheckUWBConf() {
379 
380   char uwbLibName[256];
381   STLOG_HAL_D("%s", __func__);
382 
383   if (!GetStrValue(NAME_STNFC_UWB_LIB_NAME, (char *)uwbLibName,
384                    sizeof(uwbLibName))) {
385     STLOG_HAL_D(
386         "%s - UWB conf library name not found in conf. use default name ", __func__);
387     strcpy(uwbLibName, "/vendor/lib64/libqorvo_uwb_params_nfcc.so");
388   }
389 
390   STLOG_HAL_D("%s - UWB conf library = %s", __func__, uwbLibName);
391 
392   void *stdll = dlopen(uwbLibName, RTLD_NOW);
393   if (stdll) {
394     STLoadUwbParams fn =
395         (STLoadUwbParams)dlsym(stdll, "load_uwb_params_from_files");
396   if (fn) {
397     size_t lengthOutput =
398         fn(nciPropSetUwbConfig + 9, 100);
399     STLOG_HAL_D("%s: lengthOutput = %zu", __func__, lengthOutput);
400     if (lengthOutput > 0) {
401       memcpy(nciPropSetUwbConfig, nciHeaderPropSetUwbConfig, 9);
402       nciPropSetUwbConfig[2] = lengthOutput + 6;
403       nciPropSetUwbConfig[8] = lengthOutput;
404       mFWInfo->uwbVersion =
405           nciPropSetUwbConfig[9] << 8 | nciPropSetUwbConfig[10];
406       STLOG_HAL_D("%s --> uwb configuration version 0x%04X \n", __func__,
407                   mFWInfo->uwbVersion);
408       return true;
409     } else {
410       STLOG_HAL_D("%s: lengthOutput null", __func__);
411     }
412    }
413   } else {
414     STLOG_HAL_D("libqorvo_uwb_params_nfcc not found, do nothing.");
415   }
416   return false;
417 }
resetHandlerState()418 void resetHandlerState() {
419   STLOG_HAL_D("%s", __func__);
420   mHalFDState = HAL_FD_STATE_AUTHENTICATE;
421 }
422 
UpdateHandler(HALHANDLE mHalHandle,uint16_t data_len,uint8_t * p_data)423 void UpdateHandler(HALHANDLE mHalHandle, uint16_t data_len, uint8_t *p_data) {
424   HalSendDownstreamStopTimer(mHalHandle);
425 
426   switch (mHalFDState) {
427     case HAL_FD_STATE_AUTHENTICATE:
428       STLOG_HAL_D("%s - mHalFDState = HAL_FD_STATE_AUTHENTICATE", __func__);
429 
430       if ((p_data[data_len - 2] == 0x90) && (p_data[data_len - 1] == 0x00)) {
431         STLOG_HAL_D("%s - send APDU_AUTHENTICATION_CMD", __func__);
432         if (!HalSendDownstreamTimer(mHalHandle, (uint8_t *)mApduAuthent,
433                                     sizeof(mApduAuthent), FW_TIMER_DURATION)) {
434           STLOG_HAL_E("%s - SendDownstream failed", __func__);
435         }
436         mHalFDState = HAL_FD_STATE_ERASE_FLASH;
437       } else {
438         STLOG_HAL_D("%s - FW flash not succeeded", __func__);
439         SendExitLoadMode(mHalHandle);
440       }
441       break;
442 
443     case HAL_FD_STATE_ERASE_FLASH:  // 1
444       STLOG_HAL_D("%s - mHalFDState = HAL_FD_STATE_ERASE_FLASH", __func__);
445 
446       if ((p_data[0] == 0x4f) && (p_data[1] == 0x04)) {
447         if ((p_data[data_len - 2] == 0x90) && (p_data[data_len - 1] == 0x00)) {
448           STLOG_HAL_D(
449               " %s - send APDU_ERASE_FLASH_CMD (keep appli and NDEF areas)",
450               __func__);
451 
452           if (!HalSendDownstreamTimer(mHalHandle, ApduEraseNfcKeepAppliAndNdef,
453                                       sizeof(ApduEraseNfcKeepAppliAndNdef),
454                                       FW_TIMER_DURATION)) {
455             STLOG_HAL_E("%s - SendDownstream failed", __func__);
456           }
457 
458           fsetpos(mFwFileBin, &mPosInit);  // reset pos in stream
459 
460           mHalFDState = HAL_FD_STATE_SEND_RAW_APDU;
461 
462         } else {
463           STLOG_HAL_D("%s - FW flash not succeeded", __func__);
464           SendExitLoadMode(mHalHandle);
465         }
466       }
467       break;
468 
469     case HAL_FD_STATE_SEND_RAW_APDU:  // 3
470       STLOG_HAL_D("%s - mHalFDState = HAL_FD_STATE_SEND_RAW_APDU", __func__);
471       if ((p_data[0] == 0x4f) && (p_data[1] == 0x04)) {
472         if ((p_data[data_len - 2] == 0x90) && (p_data[data_len - 1] == 0x00)) {
473           mRetry = true;
474 
475           fgetpos(mFwFileBin, &mPos);  // save current position in stream
476           if ((fread(mBinData, sizeof(uint8_t), 3, mFwFileBin) == 3) &&
477               (fread(mBinData + 3, sizeof(uint8_t), mBinData[2], mFwFileBin) ==
478                mBinData[2])) {
479             if (!HalSendDownstreamTimer(mHalHandle, mBinData, mBinData[2] + 3,
480                                         FW_TIMER_DURATION)) {
481               STLOG_HAL_E("%s - SendDownstream failed", __func__);
482             }
483           } else {
484             STLOG_HAL_D("%s - EOF of FW binary", __func__);
485             SendExitLoadMode(mHalHandle);
486           }
487         } else if (mRetry == true) {
488           STLOG_HAL_D("%s - Last Tx was NOK. Retry", __func__);
489           mRetry = false;
490           fsetpos(mFwFileBin, &mPos);
491           if ((fread(mBinData, sizeof(uint8_t), 3, mFwFileBin) == 3) &&
492               (fread(mBinData + 3, sizeof(uint8_t), mBinData[2], mFwFileBin) ==
493                mBinData[2])) {
494             if (!HalSendDownstreamTimer(mHalHandle, mBinData, mBinData[2] + 3,
495                                         FW_TIMER_DURATION)) {
496               STLOG_HAL_E("%s - SendDownstream failed", __func__);
497             }
498             fgetpos(mFwFileBin, &mPos);  // save current position in stream
499           } else {
500             STLOG_HAL_D("%s - EOF of FW binary", __func__);
501             SendExitLoadMode(mHalHandle);
502           }
503         } else {
504           STLOG_HAL_D("%s - FW flash not succeeded.", __func__);
505           I2cResetPulse();
506           SendExitLoadMode(mHalHandle);
507         }
508       }
509       break;
510 
511     case HAL_FD_STATE_EXIT_APDU:  // 2
512       STLOG_HAL_D("%s - mHalFDState = HAL_FD_STATE_EXIT_APDU", __func__);
513       if ((p_data[data_len - 2] != 0x90) || (p_data[data_len - 1] != 0x00)) {
514         STLOG_HAL_D(
515             "%s - Error exiting loader mode, i.e. a problem occured during FW "
516             "update", __func__);
517       }
518 
519       I2cResetPulse();
520       hal_wrapper_set_state(HAL_WRAPPER_STATE_OPEN);
521       mHalFDState = HAL_FD_STATE_AUTHENTICATE;
522       break;
523 
524     default:
525       STLOG_HAL_D("%s - mHalFDState = unknown", __func__);
526       STLOG_HAL_D("%s - FW flash not succeeded", __func__);
527       SendExitLoadMode(mHalHandle);
528       break;
529   }
530 }
531 
ApplyCustomParamHandler(HALHANDLE mHalHandle,uint16_t data_len,uint8_t * p_data)532 void ApplyCustomParamHandler(HALHANDLE mHalHandle, uint16_t data_len,
533                              uint8_t *p_data) {
534   STLOG_HAL_D("%s - Enter ", __func__);
535   if (data_len < 3) {
536     STLOG_HAL_E("%s : Error, too short data (%d)", __func__, data_len);
537     return;
538   }
539 
540   switch (p_data[0]) {
541     case 0x40:  //
542       // CORE_RESET_RSP
543       if ((p_data[1] == 0x0) && (p_data[3] == 0x0)) {
544         // do nothing
545       } else if ((p_data[1] == 0x1) && (p_data[3] == 0x0)) {
546         if (mFWInfo->hibernate_exited == 0) {
547           // Send a NFC mode on .
548           if (!HalSendDownstream(mHalHandle, propNfcModeSetCmdOn,
549                                  sizeof(propNfcModeSetCmdOn))) {
550             STLOG_HAL_E("%s - SendDownstream failed", __func__);
551           }
552           // CORE_INIT_RSP
553         } else if (mFWInfo->hibernate_exited == 1) {
554           if ((fread(mBinData, sizeof(uint8_t), 3, mCustomFileBin)) &&
555               (fread(mBinData + 3, sizeof(uint8_t), mBinData[2],
556                      mCustomFileBin))) {
557             if (!HalSendDownstream(mHalHandle, mBinData, mBinData[2] + 3)) {
558               STLOG_HAL_E("%s - SendDownstream failed", __func__);
559             }
560           }
561         }
562 
563       } else {
564         STLOG_HAL_D("%s - Error in custom param application", __func__);
565         mCustomParamFailed = true;
566         I2cResetPulse();
567         hal_wrapper_set_state(HAL_WRAPPER_STATE_OPEN);
568       }
569       break;
570 
571     case 0x4f:
572       if (mFWInfo->hibernate_exited == 1) {
573         if ((fread(mBinData, sizeof(uint8_t), 3, mCustomFileBin) == 3) &&
574             (fread(mBinData + 3, sizeof(uint8_t), mBinData[2],
575                    mCustomFileBin) == mBinData[2])) {
576           if (!HalSendDownstream(mHalHandle, mBinData, mBinData[2] + 3)) {
577             STLOG_HAL_E("%s - SendDownstream failed", __func__);
578           }
579         } else {
580           STLOG_HAL_D("%s - mCustomParamDone = %d", __func__, mCustomParamDone);
581           if (!mGetCustomerField) {
582             mGetCustomerField = true;
583             if (!HalSendDownstream(mHalHandle, nciGetPropConfig,
584                                    sizeof(nciGetPropConfig))) {
585               STLOG_HAL_E("%s - SendDownstream failed", __func__);
586             }
587             mGetCustomerField = true;
588 
589           } else if (!mCustomParamDone) {
590 
591             STLOG_HAL_D("%s - EOF of custom file.", __func__);
592             memset(nciPropSetConfig_CustomField, 0x0,
593                    sizeof(nciPropSetConfig_CustomField));
594             memcpy(nciPropSetConfig_CustomField, nciSetPropConfig, 9);
595             nciPropSetConfig_CustomField[8] = p_data[6];
596             nciPropSetConfig_CustomField[2] = p_data[6] + 6;
597             memcpy(nciPropSetConfig_CustomField + 9, p_data + 7, p_data[6]);
598             nciPropSetConfig_CustomField[13] = mFWInfo->uwbFwVersion >> 8;
599             nciPropSetConfig_CustomField[14] = mFWInfo->uwbFwVersion;
600 
601             if (!HalSendDownstream(mHalHandle, nciPropSetConfig_CustomField,
602                                    nciPropSetConfig_CustomField[2] + 3)) {
603               STLOG_HAL_E("%s - SendDownstream failed", __func__);
604             }
605 
606             mCustomParamDone = true;
607 
608           } else {
609             I2cResetPulse();
610             if (mUwbConfigNeeded) {
611               mCustomParamDone = false;
612               mGetCustomerField = false;
613               hal_wrapper_set_state(HAL_WRAPPER_STATE_APPLY_UWB_PARAM);
614             }
615           }
616         }
617       }
618 
619       // Check if an error has occurred for PROP_SET_CONFIG_CMD
620       // Only log a warning, do not exit code
621       if (p_data[3] != 0x00) {
622         STLOG_HAL_D("%s - Error in custom file, continue anyway", __func__);
623       }
624 
625       break;
626 
627     case 0x60:  //
628       if (p_data[1] == 0x0) {
629         if (p_data[3] == 0xa0) {
630           mFWInfo->hibernate_exited = 1;
631         }
632         if (!HalSendDownstream(mHalHandle, coreInitCmd, sizeof(coreInitCmd))) {
633           STLOG_HAL_E("%s - SendDownstream failed", __func__);
634         }
635 
636       } else if ((p_data[1] == 0x6) && mCustomParamDone) {
637         mCustomParamDone = false;
638         mGetCustomerField = false;
639         hal_wrapper_update_complete();
640       }
641       break;
642   }
643 }
644 
ApplyUwbParamHandler(HALHANDLE mHalHandle,uint16_t data_len,uint8_t * p_data)645 void ApplyUwbParamHandler(HALHANDLE mHalHandle, uint16_t data_len,
646                           uint8_t *p_data) {
647   STLOG_HAL_D("%s - Enter ", __func__);
648   if (data_len < 3) {
649     STLOG_HAL_E("%s : Error, too short data (%d)", __func__, data_len);
650     return;
651   }
652 
653   switch (p_data[0]) {
654     case 0x40:  //
655       // CORE_RESET_RSP
656       if ((p_data[1] == 0x0) && (p_data[3] == 0x0)) {
657         // do nothing
658       } else if ((p_data[1] == 0x1) && (p_data[3] == 0x0)) {
659         if (mFWInfo->hibernate_exited == 0) {
660           // Send a NFC mode on .
661           if (!HalSendDownstream(mHalHandle, propNfcModeSetCmdOn,
662                                  sizeof(propNfcModeSetCmdOn))) {
663             STLOG_HAL_E("%s - SendDownstream failed", __func__);
664           }
665           // CORE_INIT_RSP
666         } else if ((mFWInfo->hibernate_exited == 1) && !mUwbConfigDone) {
667           if (!HalSendDownstream(mHalHandle, nciPropSetUwbConfig,
668                                  nciPropSetUwbConfig[2] + 3)) {
669             STLOG_HAL_E("%s - SendDownstream failed", __func__);
670           }
671         }
672 
673       } else {
674         STLOG_HAL_D("%s - Error in uwb param application", __func__);
675         I2cResetPulse();
676         hal_wrapper_set_state(HAL_WRAPPER_STATE_OPEN);
677       }
678       break;
679 
680     case 0x4f:
681       if (mFWInfo->hibernate_exited == 1) {
682         if (!mUwbConfigDone) {
683           mUwbConfigDone = true;
684           // Check if an error has occurred for PROP_SET_CONFIG_CMD
685           // Only log a warning, do not exit code
686           if (p_data[3] != 0x00) {
687             STLOG_HAL_D("%s - Error in uwb file, continue anyway", __func__);
688           }
689           if (!HalSendDownstream(mHalHandle, nciGetPropConfig,
690                                  sizeof(nciGetPropConfig))) {
691             STLOG_HAL_E("%s - SendDownstream failed", __func__);
692           }
693         } else if ((p_data[1] == 0x2) && (p_data[2] == 0x0c)) {
694           memset(nciPropSetConfig_CustomField, 0x0,
695                  sizeof(nciPropSetConfig_CustomField));
696           memcpy(nciPropSetConfig_CustomField, nciSetPropConfig, 9);
697           nciPropSetConfig_CustomField[8] = p_data[6];
698           nciPropSetConfig_CustomField[2] = p_data[6] + 6;
699           memcpy(nciPropSetConfig_CustomField + 9, p_data + 7, p_data[6]);
700           nciPropSetConfig_CustomField[13] = mFWInfo->uwbVersion >> 8;
701           nciPropSetConfig_CustomField[14] = mFWInfo->uwbVersion;
702 
703           if (!HalSendDownstream(mHalHandle, nciPropSetConfig_CustomField,
704                                  nciPropSetConfig_CustomField[2] + 3)) {
705             STLOG_HAL_E("%s - SendDownstream failed", __func__);
706           }
707 
708         } else {
709           I2cResetPulse();
710         }
711       }
712 
713       break;
714 
715     case 0x60:  //
716       if (p_data[1] == 0x0) {
717         if (p_data[3] == 0xa0) {
718           mFWInfo->hibernate_exited = 1;
719         }
720         if (!HalSendDownstream(mHalHandle, coreInitCmd, sizeof(coreInitCmd))) {
721           STLOG_HAL_E("%s - SendDownstream failed", __func__);
722         }
723 
724       } else if ((p_data[1] == 0x6) && mUwbConfigDone) {
725         mUwbConfigNeeded = false;
726         mUwbConfigDone = false;
727         hal_wrapper_update_complete();
728       }
729       break;
730   }
731 }
732 
SendExitLoadMode(HALHANDLE mmHalHandle)733 void SendExitLoadMode(HALHANDLE mmHalHandle) {
734   STLOG_HAL_D("%s - Send APDU_EXIT_LOAD_MODE_CMD", __func__);
735 
736   if (!HalSendDownstreamTimer(mmHalHandle, ApduExitLoadMode,
737                               sizeof(ApduExitLoadMode), FW_TIMER_DURATION)) {
738     STLOG_HAL_E("%s - SendDownstream failed", __func__);
739   }
740   mHalFDState = HAL_FD_STATE_EXIT_APDU;
741 }
742