1 /*
2 * Copyright 2024, The Android Open Source Project
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 "NfcVendorExtn.h"
18
19 #include <android-base/file.h>
20 #include <android-base/logging.h>
21 #include <android-base/properties.h>
22 #include <android-base/stringprintf.h>
23 #include <android/log.h>
24 #include <dlfcn.h>
25 #include <error.h>
26 #include <log/log.h>
27 #include <string>
28
29 using android::base::StringPrintf;
30 #define UNUSED_PROP(X) (void)(X);
31
32 const std::string vendor_nfc_init_name = "vendor_nfc_init";
33 const std::string vendor_nfc_de_init_name = "vendor_nfc_de_init";
34 const std::string vendor_nfc_handle_event_name = "vendor_nfc_handle_event";
35 const std::string vendor_nfc_on_config_update_name =
36 "vendor_nfc_on_config_update";
37
38 static NfcVendorExtn* sNfcVendorExtn;
39
40 typedef bool (*fp_extn_init_t)(VendorExtnCb*);
41 typedef bool (*fp_extn_deinit_t)();
42 typedef tNFC_STATUS (*fp_extn_handle_nfc_event_t)(NfcExtEvent_t,
43 NfcExtEventData_t);
44 typedef void (*fp_extn_on_config_update_t)(std::map<std::string, ConfigValue>*);
45
46 fp_extn_init_t fp_extn_init = NULL;
47 fp_extn_deinit_t fp_extn_deinit = NULL;
48 fp_extn_handle_nfc_event_t fp_extn_handle_nfc_event = NULL;
49 fp_extn_on_config_update_t fp_extn_on_config_update = NULL;
50
51 NfcExtEventData_t mNfcExtEventData;
52 std::string mLibPathName = "";
53
54 void* p_oem_extn_handle = NULL;
55
56 namespace {
searchLibPath(std::string file_name)57 std::string searchLibPath(std::string file_name) {
58 #if (defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64))
59 const std::vector<std::string> search_path = {
60 "/system/lib64/"
61 };
62 #else
63 const std::vector<std::string> search_path = {
64 "/system/lib/"
65 };
66 #endif
67 for (std::string path : search_path) {
68 path.append(file_name);
69 struct stat file_stat;
70 if (stat(path.c_str(), &file_stat) != 0) continue;
71 if (S_ISREG(file_stat.st_mode)) return path;
72 }
73 return "";
74 }
75 // Extension library file Search sequence
76 // 1. If prop_lib_file_name is defined.(where prop_config_file_name is the
77 // value of the property persist.nfc_vendor_extn.lib_file_name)
78 // Search a file matches prop_lib_file_name.
79 // 2. If SKU is defined (where SKU is the value of the property
80 // ro.boot.product.hardware.sku)
81 // Search a file matches libnfc_vendor_extn-SKU.so
82 // 3. If none of 1,2 is defined, search a default file name "libnfc_vendor_extn.so".
findLibPath()83 std::string findLibPath() {
84 std::string f_path = searchLibPath(
85 android::base::GetProperty("persist.nfc_vendor_extn.lib_file_name", ""));
86 if (!f_path.empty()) return f_path;
87
88 // Search for libnfc_vendor_extn-SKU.so
89 f_path = searchLibPath(
90 "libnfc_vendor_extn-" +
91 android::base::GetProperty("ro.boot.product.hardware.sku", "") + ".so");
92 if (!f_path.empty()) return f_path;
93
94 // load default file if the desired file not found.
95 return searchLibPath("libnfc_vendor_extn.so");
96 }
97 } // namespace
98
NfcVendorExtn()99 NfcVendorExtn::NfcVendorExtn() {}
100
~NfcVendorExtn()101 NfcVendorExtn::~NfcVendorExtn() { sNfcVendorExtn = nullptr; }
102
getInstance()103 NfcVendorExtn* NfcVendorExtn::getInstance() {
104 if (sNfcVendorExtn == nullptr) {
105 sNfcVendorExtn = new NfcVendorExtn();
106 }
107 return sNfcVendorExtn;
108 }
109
NfcExtn_LibInit()110 void NfcExtn_LibInit() {
111 LOG(VERBOSE) << __func__;
112 if (fp_extn_init != NULL) {
113 if (!fp_extn_init(NfcVendorExtn::getInstance()->getVendorExtnCb())) {
114 LOG(ERROR) << StringPrintf("%s: %s failed!", __func__,
115 vendor_nfc_init_name.c_str());
116 }
117 }
118 }
119
NfcExtn_LibSetup()120 bool NfcExtn_LibSetup() {
121 LOG(VERBOSE) << __func__;
122 mLibPathName = findLibPath();
123 if (mLibPathName.empty()) {
124 LOG(ERROR) << StringPrintf("%s: Failed to find %s !!", __func__,
125 mLibPathName.c_str());
126 return false;
127 }
128 p_oem_extn_handle = dlopen(mLibPathName.c_str(), RTLD_NOW);
129 if (p_oem_extn_handle == NULL) {
130 LOG(DEBUG) << StringPrintf(
131 "%s: Error : opening (%s) !! dlerror: "
132 "%s",
133 __func__, mLibPathName.c_str(), dlerror());
134 return false;
135 }
136 if ((fp_extn_init = (fp_extn_init_t)dlsym(
137 p_oem_extn_handle, vendor_nfc_init_name.c_str())) == NULL) {
138 LOG(ERROR) << StringPrintf("%s: Failed to find %s !!", __func__,
139 vendor_nfc_init_name.c_str());
140 }
141
142 if ((fp_extn_deinit = (fp_extn_deinit_t)dlsym(
143 p_oem_extn_handle, vendor_nfc_de_init_name.c_str())) == NULL) {
144 LOG(ERROR) << StringPrintf("%s: Failed to find %s !!", __func__,
145 vendor_nfc_de_init_name.c_str());
146 }
147
148 if ((fp_extn_handle_nfc_event = (fp_extn_handle_nfc_event_t)dlsym(
149 p_oem_extn_handle, vendor_nfc_handle_event_name.c_str())) == NULL) {
150 LOG(ERROR) << StringPrintf("%s: Failed to find %s !!", __func__,
151 vendor_nfc_handle_event_name.c_str());
152 }
153
154 if ((fp_extn_on_config_update = (fp_extn_on_config_update_t)dlsym(
155 p_oem_extn_handle, vendor_nfc_on_config_update_name.c_str())) ==
156 NULL) {
157 LOG(ERROR) << StringPrintf("%s: Failed to find %s !!", __func__,
158 vendor_nfc_on_config_update_name.c_str());
159 }
160
161 NfcExtn_LibInit();
162 return true;
163 }
164
Initialize(sp<INfc> hidlHal,std::shared_ptr<INfcAidl> aidlHal)165 bool NfcVendorExtn::Initialize(sp<INfc> hidlHal,
166 std::shared_ptr<INfcAidl> aidlHal) {
167 LOG(VERBOSE) << StringPrintf("%s:", __func__);
168 mVendorExtnCb.hidlHal = hidlHal;
169 mVendorExtnCb.aidlHal = aidlHal;
170 if (!NfcExtn_LibSetup()) {
171 mVendorExtnCb.hidlHal = nullptr;
172 mVendorExtnCb.aidlHal = nullptr;
173 return false;
174 }
175 return true;
176 }
177
setNciCallback(tHAL_NFC_CBACK * pHalCback,tHAL_NFC_DATA_CBACK * pDataCback)178 void NfcVendorExtn::setNciCallback(tHAL_NFC_CBACK* pHalCback,
179 tHAL_NFC_DATA_CBACK* pDataCback) {
180 LOG(VERBOSE) << __func__;
181 mVendorExtnCb.pHalCback = pHalCback;
182 mVendorExtnCb.pDataCback = pDataCback;
183 }
184
processCmd(uint16_t dataLen,uint8_t * pData)185 bool NfcVendorExtn::processCmd(uint16_t dataLen, uint8_t* pData) {
186 LOG(VERBOSE) << StringPrintf("%s: Enter dataLen=%d", __func__, dataLen);
187 NciData_t nci_data;
188 nci_data.data_len = dataLen;
189 nci_data.p_data = (uint8_t*)pData;
190 mNfcExtEventData.nci_msg = nci_data;
191
192 if (fp_extn_handle_nfc_event != NULL) {
193 tNFC_STATUS stat =
194 fp_extn_handle_nfc_event(HANDLE_VENDOR_NCI_MSG, mNfcExtEventData);
195 LOG(VERBOSE) << StringPrintf("%s: Exit status(%d)", __func__, stat);
196 return stat == NFCSTATUS_EXTN_FEATURE_SUCCESS;
197 } else {
198 LOG(ERROR) << StringPrintf("%s: not found", __func__);
199 return false;
200 }
201 }
202
processRspNtf(uint16_t dataLen,uint8_t * pData)203 bool NfcVendorExtn::processRspNtf(uint16_t dataLen, uint8_t* pData) {
204 LOG(VERBOSE) << StringPrintf("%s: dataLen=%d", __func__, dataLen);
205 NciData_t nciData;
206 nciData.data_len = dataLen;
207 nciData.p_data = (uint8_t*)pData;
208 mNfcExtEventData.nci_rsp_ntf = nciData;
209
210 if (fp_extn_handle_nfc_event != NULL) {
211 tNFC_STATUS stat =
212 fp_extn_handle_nfc_event(HANDLE_VENDOR_NCI_RSP_NTF, mNfcExtEventData);
213 LOG(VERBOSE) << StringPrintf("%s: Exit status(%d)", __func__, stat);
214 return stat == NFCSTATUS_EXTN_FEATURE_SUCCESS;
215 } else {
216 LOG(ERROR) << StringPrintf("%s: not found", __func__);
217 return false;
218 }
219 }
220
processEvent(uint8_t event,uint8_t status)221 bool NfcVendorExtn::processEvent(uint8_t event, uint8_t status) {
222 LOG(VERBOSE) << StringPrintf("%s: event=%d, status=%d", __func__, event,
223 status);
224 if (fp_extn_handle_nfc_event != NULL) {
225 mNfcExtEventData.hal_event = event;
226 mNfcExtEventData.hal_event_status = status;
227 tNFC_STATUS stat =
228 fp_extn_handle_nfc_event(HANDLE_HAL_EVENT, mNfcExtEventData);
229 LOG(DEBUG) << StringPrintf("%s: Exit status(%d)", __func__, stat);
230 return stat == NFCSTATUS_EXTN_FEATURE_SUCCESS;
231 } else {
232 LOG(ERROR) << StringPrintf("%s: not found", __func__);
233 return false;
234 }
235 }
236
getVendorConfigs(std::map<std::string,ConfigValue> * pConfigMap)237 void NfcVendorExtn::getVendorConfigs(
238 std::map<std::string, ConfigValue>* pConfigMap) {
239 LOG(VERBOSE) << __func__;
240 mVendorExtnCb.configMap = *pConfigMap;
241 if (fp_extn_on_config_update != NULL) {
242 fp_extn_on_config_update(pConfigMap);
243 } else {
244 LOG(ERROR) << StringPrintf("%s: not found", __func__);
245 }
246 }
247
getVendorExtnCb()248 VendorExtnCb* NfcVendorExtn::getVendorExtnCb() { return &mVendorExtnCb; }
249
phNfcExtn_LibClose()250 void phNfcExtn_LibClose() {
251 LOG(VERBOSE) << __func__;
252 if (fp_extn_deinit != NULL) {
253 if (!fp_extn_deinit()) {
254 LOG(ERROR) << StringPrintf("%s: %s failed", __func__,
255 vendor_nfc_de_init_name.c_str());
256 }
257 }
258 if (p_oem_extn_handle != NULL) {
259 LOG(DEBUG) << StringPrintf("%s: Closing %s!!", __func__, mLibPathName.c_str());
260 dlclose(p_oem_extn_handle);
261 p_oem_extn_handle = NULL;
262 }
263 }
264
finalize(void)265 bool NfcVendorExtn::finalize(void) {
266 LOG(VERBOSE) << __func__;
267 phNfcExtn_LibClose();
268 mVendorExtnCb.hidlHal = nullptr;
269 mVendorExtnCb.aidlHal = nullptr;
270 return true;
271 }
272