1 /*
2  * Copyright 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 "NciDiscoveryCommandBuilder.h"
18 
19 #include <phNfcNciConstants.h>
20 
21 using namespace std;
22 
23 /*****************************************************************************
24  *
25  * Function         parse
26  *
27  * Description      It parse the RF discovery commands and filters find the
28  *                  configurations
29  *
30  * Parameters       data - RF discovery command
31  *
32  * Returns          return true if parse is successful otherwise false
33  *
34  ****************************************************************************/
parse(vector<uint8_t> data)35 bool NciDiscoveryCommandBuilder::parse(vector<uint8_t> data) {
36   if (!isDiscoveryCommand(data)) return false;
37 
38   mRfDiscoverConfiguration.clear();
39   int dataSize = (int)data.size();
40 
41   if (dataSize <= NCI_HEADER_MIN_LEN &&
42       (dataSize < ((data[RF_DISC_CMD_NO_OF_CONFIG_INDEX] *
43                     RF_DISC_CMD_EACH_CONFIG_LENGTH) +
44                    NCI_HEADER_MIN_LEN))) {
45     return false;
46   }
47 
48   for (int i = RF_DISC_CMD_CONFIG_START_INDEX; i < ((int)data.size() - 1);
49        i = i + RF_DISC_CMD_EACH_CONFIG_LENGTH) {
50     mRfDiscoverConfiguration.push_back(
51         DiscoveryConfiguration(data[i], data[i + 1]));
52   }
53   return true;
54 }
55 
56 /*****************************************************************************
57  *
58  * Function         isDiscoveryCommand
59  *
60  * Description      Checks the command is RF discovery command or not
61  *
62  * Parameters       data - Any command
63  *
64  * Returns          return true if the command is RF discovery command
65  *                  otherwise false
66  *
67  ****************************************************************************/
isDiscoveryCommand(vector<uint8_t> data)68 bool NciDiscoveryCommandBuilder::isDiscoveryCommand(vector<uint8_t> data) {
69   if ((int)data.size() >= 2 && data[NCI_GID_INDEX] == NCI_RF_DISC_COMMD_GID &&
70       data[NCI_OID_INDEX] == NCI_RF_DISC_COMMAND_OID) {
71     return true;
72   }
73   return false;
74 }
75 
76 /*****************************************************************************
77  *
78  * Function         removeListenParams
79  *
80  * Description      Removes the listen mode from the configuration list
81  *
82  * Returns          void
83  *
84  ****************************************************************************/
removeListenParams()85 void NciDiscoveryCommandBuilder::removeListenParams() {
86   std::vector<DiscoveryConfiguration>::iterator configIterator =
87       mRfDiscoverConfiguration.begin();
88 
89   while (configIterator != mRfDiscoverConfiguration.end()) {
90     if (NFC_A_PASSIVE_LISTEN_MODE == configIterator->mRfTechMode ||
91         NFC_B_PASSIVE_LISTEN_MODE == configIterator->mRfTechMode ||
92         NFC_F_PASSIVE_LISTEN_MODE == configIterator->mRfTechMode ||
93         NFC_ACTIVE_LISTEN_MODE == configIterator->mRfTechMode) {
94       configIterator = mRfDiscoverConfiguration.erase(configIterator);
95     } else {
96       ++configIterator;
97     }
98   }
99 }
100 
101 /*****************************************************************************
102  *
103  * Function         addObserveModeParams
104  *
105  * Description      Adds Observe mode to the config list
106  *
107  * Returns          void
108  *
109  ****************************************************************************/
addObserveModeParams()110 void NciDiscoveryCommandBuilder::addObserveModeParams() {
111   mRfDiscoverConfiguration.push_back(
112       DiscoveryConfiguration(OBSERVE_MODE, OBSERVE_MODE_DISCOVERY_CYCLE));
113 }
114 
115 /*****************************************************************************
116  *
117  * Function         build
118  *
119  * Description      It frames the RF discovery command from the config list
120  *
121  * Returns          return the discovery command
122  *
123  ****************************************************************************/
build()124 vector<uint8_t> NciDiscoveryCommandBuilder::build() {
125   vector<uint8_t> discoveryCommand;
126   discoveryCommand.push_back(NCI_RF_DISC_COMMD_GID);
127   discoveryCommand.push_back(NCI_RF_DISC_COMMAND_OID);
128   int discoveryLength = (mRfDiscoverConfiguration.size() * 2) + 1;
129   int numberOfConfigurations = mRfDiscoverConfiguration.size();
130   discoveryCommand.push_back(discoveryLength);
131   discoveryCommand.push_back(numberOfConfigurations);
132   for (int i = 0; i < numberOfConfigurations; i++) {
133     discoveryCommand.push_back(mRfDiscoverConfiguration[i].mRfTechMode);
134     discoveryCommand.push_back(mRfDiscoverConfiguration[i].mDiscFrequency);
135   }
136   return discoveryCommand;
137 }
138 
139 /*****************************************************************************
140  *
141  * Function         reConfigRFDiscCmd
142  *
143  * Description      It parse the discovery command and alter the configuration
144  *                  to enable Observe Mode
145  *
146  * Parameters       data - RF discovery command
147  *
148  * Returns          return the discovery command for Observe mode
149  *
150  ****************************************************************************/
reConfigRFDiscCmd(uint16_t data_len,const uint8_t * p_data)151 vector<uint8_t> NciDiscoveryCommandBuilder::reConfigRFDiscCmd(
152     uint16_t data_len, const uint8_t* p_data) {
153   if (!p_data) {
154     return vector<uint8_t>();
155   }
156 
157   vector<uint8_t> discoveryCommand = vector<uint8_t>(p_data, p_data + data_len);
158   bool status = parse(std::move(discoveryCommand));
159   if (status) {
160     removeListenParams();
161     addObserveModeParams();
162     return build();
163   } else {
164     return vector<uint8_t>();
165   }
166 }
167