1 /*
2  * Copyright 2022-2024 NXP
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 #include "phNxpNciHal_ULPDet.h"
18 
19 #include <phNfcNciConstants.h>
20 #include <phNxpLog.h>
21 #include <phTmlNfc.h>
22 
23 #include "phNfcCommon.h"
24 #include "phNxpNciHal_IoctlOperations.h"
25 #include "phNxpNciHal_PowerTrackerIface.h"
26 #include "phNxpNciHal_extOperations.h"
27 
28 extern phNxpNciHal_Control_t nxpncihal_ctrl;
29 extern NFCSTATUS phNxpNciHal_ext_send_sram_config_to_flash();
30 extern PowerTrackerHandle gPowerTrackerHandle;
31 
32 /*******************************************************************************
33 **
34 ** Function         phNxpNciHal_isULPDetSupported()
35 **
36 ** Description      this function is to check ULPDet feature is supported or not
37 **
38 ** Returns          true or false
39 *******************************************************************************/
phNxpNciHal_isULPDetSupported()40 bool phNxpNciHal_isULPDetSupported() {
41   unsigned long num = 0;
42   if ((GetNxpNumValue(NAME_NXP_DEFAULT_ULPDET_MODE, &num, sizeof(num)))) {
43     if ((uint8_t)num > 0) {
44       NXPLOG_NCIHAL_E("%s: NxpNci isULPDetSupported true", __func__);
45       return true;
46     }
47   }
48   NXPLOG_NCIHAL_E("%s: NxpNci isULPDetSupported false", __func__);
49   return false;
50 }
51 
52 /*******************************************************************************
53 **
54 ** Function         phNxpNciHal_setULPDetFlag()
55 **
56 ** Description      this function is called by Framework API to set ULPDet mode
57 **                  enable/disable
58 **
59 ** Parameters       flag - true to enable ULPDet, false to disable
60 **
61 ** Returns          true or false
62 *******************************************************************************/
phNxpNciHal_setULPDetFlag(bool flag)63 void phNxpNciHal_setULPDetFlag(bool flag) {
64   nxpncihal_ctrl.isUlpdetModeEnabled = flag;
65   if (gPowerTrackerHandle.stateChange != NULL) {
66     RefreshNfccPowerState state = (flag) ? ULPDET_ON : ULPDET_OFF;
67     gPowerTrackerHandle.stateChange(state);
68   }
69 }
70 
71 /*******************************************************************************
72 **
73 ** Function         phNxpNciHal_getULPDetFlag()
74 **
75 ** Description      this function get the ULPDet state, true if it is enabled
76 **                  false if it is disabled
77 **
78 ** Returns          true or false
79 *******************************************************************************/
phNxpNciHal_getULPDetFlag()80 bool phNxpNciHal_getULPDetFlag() { return nxpncihal_ctrl.isUlpdetModeEnabled; }
81 
82 /*******************************************************************************
83 **
84 ** Function         phNxpNciHal_propConfULPDetMode()
85 **
86 ** Description      this function applies the configurations to enable/disable
87 **                  ULPDet Mode
88 **
89 ** Parameters       bEnable - true to enable, false to disable
90 **
91 ** Returns          NFCSTATUS_FAILED or NFCSTATUS_SUCCESS
92 *******************************************************************************/
phNxpNciHal_propConfULPDetMode(bool bEnable)93 NFCSTATUS phNxpNciHal_propConfULPDetMode(bool bEnable) {
94   NFCSTATUS status = NFCSTATUS_SUCCESS;
95   NXPLOG_NCIHAL_E("%s flag %d", __func__, bEnable);
96   if (!phNxpNciHal_isULPDetSupported()) return false;
97 
98   uint8_t cmd_coreULPDET[] = {0x2F, 0x00, 0x01, 0x03};
99   uint8_t getConfig_A015[] = {0x20, 0x03, 0x03, 0x01, 0xA0, 0x15};
100   uint8_t setConfig_A015[] = {0x20, 0x02, 0x05, 0x01, 0xA0, 0x15, 0x01, 0x01};
101   uint8_t getConfig_A10F[] = {0x20, 0x03, 0x03, 0x01, 0xA1, 0x0F};
102   uint8_t setConfig_A10F[] = {0x20, 0x02, 0x06, 0x01, 0xA1,
103                               0x0F, 0x02, 0x00, 0x00};
104 
105   uint8_t setUlpdetConfig[] = {0x20, 0x02, 0x0A, 0x02, 0xA0, 0x15, 0x01,
106                                0x02, 0xA1, 0x0F, 0x02, 0x01, 0x01};
107 
108   do {
109     if (bEnable) {
110       status =
111           phNxpNciHal_send_ext_cmd(sizeof(setUlpdetConfig), setUlpdetConfig);
112       if (status != NFCSTATUS_SUCCESS) {
113         NXPLOG_NCIHAL_E("ulpdet configs set: Failed");
114         break;
115       }
116 
117       status = phNxpNciHal_send_ext_cmd(sizeof(cmd_coreULPDET), cmd_coreULPDET);
118       if (status != NFCSTATUS_SUCCESS) {
119         NXPLOG_NCIHAL_E("coreULPDET: Failed");
120         break;
121       }
122 
123       nxpncihal_ctrl.halStatus = HAL_STATUS_CLOSE;
124       status = phNxpNciHal_ext_send_sram_config_to_flash();
125       if (status != NFCSTATUS_SUCCESS) {
126         NXPLOG_NCIHAL_E("Updation of the SRAM contents failed");
127         break;
128       }
129       (void)phTmlNfc_IoCtl(phTmlNfc_e_PullVenLow);
130     } else {
131       status = phNxpNciHal_send_ext_cmd(sizeof(getConfig_A015), getConfig_A015);
132       if ((status == NFCSTATUS_SUCCESS) &&
133           (nxpncihal_ctrl.p_rx_data[8] != 0x01)) {
134         status =
135             phNxpNciHal_send_ext_cmd(sizeof(setConfig_A015), setConfig_A015);
136         if (status != NFCSTATUS_SUCCESS) {
137           NXPLOG_NCIHAL_E("Set Config : Failed");
138         }
139       }
140 
141       status = phNxpNciHal_send_ext_cmd(sizeof(getConfig_A10F), getConfig_A10F);
142       if ((status == NFCSTATUS_SUCCESS) &&
143           (nxpncihal_ctrl.p_rx_data[8] != 0x00)) {
144         status =
145             phNxpNciHal_send_ext_cmd(sizeof(setConfig_A10F), setConfig_A10F);
146         if (status != NFCSTATUS_SUCCESS) {
147           NXPLOG_NCIHAL_E("Set Config: Failed");
148         }
149       }
150       /* reset the flag upon exit ulpdet mode */
151       phNxpNciHal_setULPDetFlag(false);
152     }
153   } while (false);
154   NXPLOG_NCIHAL_E("%s: exit. status = %d", __func__, status);
155 
156   return status;
157 }
158 
159 /*******************************************************************************
160 **
161 ** Function         phNxpNciHal_handleULPDetCommand()
162 **
163 ** Description      This handles the ULPDET command and sets the ULPDET flag
164 **
165 ** Returns          It returns number of bytes received.
166 *******************************************************************************/
phNxpNciHal_handleULPDetCommand(uint16_t data_len,const uint8_t * p_data)167 int phNxpNciHal_handleULPDetCommand(uint16_t data_len, const uint8_t* p_data) {
168   if (data_len <= 4) {
169     return 0;
170   }
171   uint8_t status = NCI_RSP_FAIL;
172   if (phNxpNciHal_isULPDetSupported()) {
173     phNxpNciHal_setULPDetFlag(p_data[NCI_MSG_INDEX_FEATURE_VALUE]);
174     status = NCI_RSP_OK;
175   }
176 
177   phNxpNciHal_vendorSpecificCallback(
178       p_data[NCI_OID_INDEX], p_data[NCI_MSG_INDEX_FOR_FEATURE], {status});
179 
180   return p_data[NCI_MSG_LEN_INDEX];
181 }
182