blob: 7e17926ddd75d6792b698bc1101842f6b477986d [file] [log] [blame]
Bhuvan Varshney6909f732019-03-28 16:22:09 +05301/*
2 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of The Linux Foundation nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#define LOG_TAG "android.hardware.nfc@1.1-impl"
31
32#include "NfcApiGet.h"
33#include <log/log.h>
34#include <stdint.h>
35#include <sys/ioctl.h>
36#include <errno.h>
37#include <cstring>
38#include <dlfcn.h>
39
40struct nqx_devinfo {
41 // Must be kept in sync with nqx_ UAPI
42 unsigned char chip_type;
43 unsigned char rom_version;
44 unsigned char fw_major;
45 unsigned char fw_minor;
46};
47
48union nqx_uinfo {
49 unsigned int i;
50 struct nqx_devinfo info;
51};
52
53bool nfc_debug_enabled = false;
54static hal_api_struct_t *hal_api_s = nullptr;
55static bool struct_initialized = false;
56static void* hal_handle = nullptr;
57
58/******************************************************************************
59 * Function chipInfo
60 *
61 * Description This function returns a success/fail integer, and populates
62 * nqx_info with chip information.
63 *
64 * Returns int return status (0/-1).
65 *
66 ******************************************************************************/
67static int chipInfo(union nqx_uinfo* nqx_info) {
68 int fp;
69
70 fp = open(DEV_NODE, O_RDONLY);
71 if (fp < 0) {
72 ALOGE("Not able to open dev node %s due to errno (%d) %s", DEV_NODE, errno, strerror(errno));
73 return STATUS_FAILURE;
74 }
75
76 nqx_info->i = ioctl(fp, NFCC_GET_INFO, 0);
77 int retval = static_cast<int> (nqx_info->i);
78 if (retval < 0) {
79 ALOGE("Failed to retrieve chip ID from hardware due to errno (%d), %s", errno, strerror(errno));
80 return STATUS_FAILURE;
81 }
82
83 ALOGD("NFC chip id = 0x%x\n", nqx_info->info.chip_type);
84 ALOGD("NFC FW Ver = %02x.%02x.%02x\n", nqx_info->info.rom_version, nqx_info->info.fw_major, nqx_info->info.fw_minor);
85
86 close(fp);
87 return STATUS_SUCCESS;
88}
89
90/******************************************************************************
91 * Function getHalFileName
92 *
93 * Description This function determines which library should be opened,
94 * based on the NFC chip ID from chipInfo().
95 *
96 * Returns char const* file_name
97 *
98 ******************************************************************************/
99static char const* getHalFileName() {
100 // get chip info from hardware, and return the correct HAL file name.
101 union nqx_uinfo nqx_info;
102 int ret = chipInfo(&nqx_info);
103
104 if (ret == 0) {
105
106 switch(nqx_info.info.chip_type) {
107
michaellin4c05a3e2020-11-16 16:16:36 +0800108 case PN553_ID_A0:
109 case NQ310_ID: // ALSO PN553 B0
Bhuvan Varshney6909f732019-03-28 16:22:09 +0530110 case NQ210_ID:
111 case NQ440_ID: // ALSO NQ330
112 case NQ220_ID:
113 ALOGD("NFC HW chip-id matches with NQxxx");
114 return NQX_FILE_NAME;
115
116 case SN100X_ID_A:
117 case SN100X_ID_B:
118 // SN100 has chip id 0xa4 or 0xa3
119 ALOGD("NFC HW chip-id matches with SN100X");
120 return SN100X_FILE_NAME;
121
122 default:
123 // if chip id isn't matched, load the NQxxx HAL.
124 ALOGD("Chip does not match known ID - defaulting to NQX library.");
125 return NQX_FILE_NAME;
126 }
127 }
128
129 else {
130 ALOGD("Obtaining Chip ID failed, attempting loading of default shared library instead.");
131 return NQX_FILE_NAME;
132 }
133}
134
135/******************************************************************************
136 * Function unloadHalApiStruct
137 *
138 * Description This function is responsible for closing the dynamic library
139 * and unloading the HAL struct; in order to save memory on low
140 * memory targets.
141 *
142 * Returns void.
143 *
144 ******************************************************************************/
145void unloadHalApiStruct() {
146 hal_api_s = nullptr;
147 struct_initialized = false;
148 dlclose(hal_handle);
149 ALOGD("Unloaded HAL API Struct");
150}
151
152/******************************************************************************
153 * Function getHalApiStruct
154 *
155 * Description This function initializes a struct of pointers to functions
156 * within the NFC HAL implementation.
157 *
158 * Returns hal_api_s pointer or nullptr.
159 *
160 ******************************************************************************/
161hal_api_struct_t* getHalApiStruct() {
162
163 char const* linkerror = nullptr;
164 char const* file_name = nullptr;
165
166 /*
167 * If our HAL has been loaded successfully, we don't want to re-open it on every NFC function call.
168 * Conversely, if loading the HAL failed, we want to ensure we're not repeatedly trying to link.
169 */
170 if (struct_initialized) {
171 return hal_api_s;
172 }
173
174 // Obtain the file name for the HAL library we wish to load
175 file_name = getHalFileName();
176 // Reset any errors
177 dlerror();
178
179 /*
180 * Attempt to load the library!
181 * /vendor/lib(64)/hw/nci_nfc.nqx.default.hw.so for NQx
182 * /vendor/lib(64)/hw/nci_nfc.sn100x.default.hw.so otherwise
183 */
184 hal_handle = dlopen(file_name, RTLD_NOW);
185 linkerror = dlerror();
186 if (linkerror != nullptr) {
187 ALOGE("Error opening HAL file: %s with linking error: %s", file_name, linkerror);
188 /*
189 * Set struct as initialized even if loading fails, so that loading is only attempted
190 * once per NFC service initialization attempt.
191 */
192 struct_initialized = true;
193 return nullptr;
194 }
195
196 ALOGD("Loading nfc HAL function table");
197 // Reset errors again
198 dlerror();
199 hal_api_s = (hal_api_struct_t*)dlsym(hal_handle, "api_funcs");
200 linkerror = dlerror();
201 if (linkerror != nullptr) {
202 ALOGE("Error loading HAL function API symbol table: %s", linkerror);
203 struct_initialized = true;
204 return nullptr;
205 }
206
207 //set the debug status and set the active status of the HIDL.
208 nfc_debug_enabled = hal_api_s->phNxpNciHal_get_debug_status();
209 struct_initialized = true;
210 return hal_api_s;
211}