1 /******************************************************************************
2  *
3  *  Copyright (C) 1999-2012 Broadcom Corporation
4  *  Copyright (C) 2013 ST Microelectronics S.A.
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at:
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  *
18  *  Modified by ST Microelectronics S.A. (adaptation of nfc_nci.c for ST21NFC
19  *NCI version)
20  *
21  ******************************************************************************/
22 
23 #include <cutils/properties.h>
24 #include <errno.h>
25 #include <hardware/nfc.h>
26 #include <string.h>
27 #include <pthread.h>
28 
29 #include "android_logmsg.h"
30 #include "halcore.h"
31 
32 extern void HalCoreCallback(void* context, uint32_t event, const void* d,
33                             size_t length);
34 extern bool I2cOpenLayer(void* dev, HAL_CALLBACK callb, HALHANDLE* pHandle);
35 
36 
37 typedef struct {
38   struct nfc_nci_device nci_device;  // nci_device must be first struct member
39   // below declarations are private variables within HAL
40   nfc_stack_callback_t* p_cback;
41   nfc_stack_data_callback_t* p_data_cback;
42   HALHANDLE hHAL;
43 } st21nfc_dev_t;
44 
45 char* halVersion = "ST21NFC NCI Version 3.0.5";
46 uint8_t cmd_set_nfc_mode_enable[] = {0x2f, 0x02, 0x02, 0x02, 0x01};
47 uint8_t hal_is_closed = 1;
48 pthread_mutex_t hal_mtx = PTHREAD_MUTEX_INITIALIZER;
49 
50 uint8_t hal_dta_state = 0;
51 
52 
53 /*
54  * NCI HAL method implementations. These must be overridden
55  */
56 
57 extern bool hal_wrapper_open(st21nfc_dev_t* dev, nfc_stack_callback_t* p_cback,
58                              nfc_stack_data_callback_t* p_data_cback,
59                              HALHANDLE* pHandle);
60 
61 extern int hal_wrapper_close(int call_cb);
62 
hal_open(const struct nfc_nci_device * p_dev,nfc_stack_callback_t * p_cback,nfc_stack_data_callback_t * p_data_cback)63 static int hal_open(const struct nfc_nci_device* p_dev,
64                     nfc_stack_callback_t* p_cback,
65                     nfc_stack_data_callback_t* p_data_cback) {
66   bool result = false;
67 
68   STLOG_HAL_D("NFC-NCI HAL: %s %s", __func__, halVersion);
69 
70   (void)pthread_mutex_lock(&hal_mtx);
71   st21nfc_dev_t* dev = (st21nfc_dev_t*)p_dev;
72   if (! hal_is_closed ) {
73     hal_wrapper_close(0);
74   }
75   dev->p_cback = p_cback;
76   dev->p_data_cback = p_data_cback;
77 
78   hal_dta_state = 0;
79 
80   result = hal_wrapper_open(dev, p_cback, p_data_cback, &dev->hHAL);
81 
82   if (!result || !dev->hHAL)
83     {
84       dev->p_cback(HAL_NFC_OPEN_CPLT_EVT, HAL_NFC_STATUS_FAILED);
85       (void) pthread_mutex_unlock(&hal_mtx);
86       return -1;  // We are doomed, stop it here, NOW !
87     }
88   hal_is_closed = 0;
89   (void)pthread_mutex_unlock(&hal_mtx);
90   return 0;
91 }
92 
hal_write(const struct nfc_nci_device * p_dev,uint16_t data_len,const uint8_t * p_data)93 static int hal_write(const struct nfc_nci_device* p_dev, uint16_t data_len,
94                      const uint8_t* p_data) {
95   STLOG_HAL_D("NFC-NCI HAL: %s", __func__);
96 
97   st21nfc_dev_t* dev = (st21nfc_dev_t*)p_dev;
98 
99   /* check if HAL is closed */
100   int ret = (int)data_len;
101   (void) pthread_mutex_lock(&hal_mtx);
102   if (hal_is_closed)
103     {
104       ret = 0;
105     }
106 
107   if (!ret)
108     {
109       (void) pthread_mutex_unlock(&hal_mtx);
110       return ret;
111     }
112   if (!HalSendDownstream(dev->hHAL, p_data, data_len))
113     {
114       STLOG_HAL_E("NFC-NCI HAL: %s  SendDownstream failed", __func__);
115       (void) pthread_mutex_unlock(&hal_mtx);
116       return 0;
117     }
118   (void) pthread_mutex_unlock(&hal_mtx);
119 
120   return ret;
121 }
122 
hal_core_initialized(const struct nfc_nci_device * p_dev,uint8_t * p_core_init_rsp_params)123 static int hal_core_initialized(const struct nfc_nci_device* p_dev,
124                                 uint8_t* p_core_init_rsp_params) {
125   STLOG_HAL_D("NFC-NCI HAL: %s", __func__);
126 
127   (void)pthread_mutex_lock(&hal_mtx);
128   st21nfc_dev_t* dev = (st21nfc_dev_t*)p_dev;
129   hal_dta_state = *p_core_init_rsp_params;
130   dev->p_cback(HAL_NFC_POST_INIT_CPLT_EVT, HAL_NFC_STATUS_OK);
131   (void) pthread_mutex_unlock(&hal_mtx);
132 
133   return 0;  // return != 0 to signal ready immediate
134 }
135 
hal_pre_discover(const struct nfc_nci_device * p_dev)136 static int hal_pre_discover(__attribute__((unused)) const struct nfc_nci_device* p_dev) {
137   STLOG_HAL_D("NFC-NCI HAL: %s", __func__);
138 
139   return 0;  // false if no vendor-specific pre-discovery actions are needed
140 }
141 
hal_close(const struct nfc_nci_device * p_dev)142 static int hal_close(__attribute__((unused)) const struct nfc_nci_device* p_dev) {
143   STLOG_HAL_D("NFC-NCI HAL: %s", __func__);
144 
145   /* check if HAL is closed */
146   (void)pthread_mutex_lock(&hal_mtx);
147   if ( hal_is_closed ) {
148     (void)pthread_mutex_unlock(&hal_mtx);
149     return 1;
150   }
151   if (hal_wrapper_close(1) == 0) {
152     hal_is_closed = 1;
153     (void)pthread_mutex_unlock(&hal_mtx);
154     return 1;
155   }
156   hal_is_closed = 1;
157   (void)pthread_mutex_unlock(&hal_mtx);
158 
159   hal_dta_state = 0;
160 
161   return 0;
162 }
163 
hal_control_granted(const struct nfc_nci_device * p_dev)164 static int hal_control_granted(__attribute__((unused)) const struct nfc_nci_device* p_dev) {
165   STLOG_HAL_D("NFC-NCI HAL: %s", __func__);
166 
167   return 0;
168 }
169 
hal_power_cycle(const struct nfc_nci_device * p_dev)170 static int hal_power_cycle(const struct nfc_nci_device* p_dev) {
171   STLOG_HAL_D("NFC-NCI HAL: %s", __func__);
172 
173   st21nfc_dev_t* dev = (st21nfc_dev_t*)p_dev;
174 
175   /* check if HAL is closed */
176   int ret = HAL_NFC_STATUS_OK;
177   (void) pthread_mutex_lock(&hal_mtx);
178   if (hal_is_closed)
179     {
180       ret = HAL_NFC_STATUS_FAILED;
181     }
182 
183   if (ret != HAL_NFC_STATUS_OK)
184     {
185       (void) pthread_mutex_unlock(&hal_mtx);
186       return ret;
187     }
188   dev->p_cback(HAL_NFC_OPEN_CPLT_EVT, HAL_NFC_STATUS_OK);
189 
190   (void) pthread_mutex_unlock(&hal_mtx);
191   return HAL_NFC_STATUS_OK;
192 }
193 
194 /*
195  * Generic device handling below
196  */
197 
198 /* Close an opened nfc device instance */
nfc_close(hw_device_t * dev)199 static int nfc_close(hw_device_t* dev) {
200   (void) pthread_mutex_lock(&hal_mtx);
201   free(dev);
202   (void) pthread_mutex_unlock(&hal_mtx);
203   return 0;
204 }
205 
nfc_open(const hw_module_t * module,const char * name,hw_device_t ** device)206 static int nfc_open(const hw_module_t* module, const char* name,
207                     hw_device_t** device) {
208 
209   if (strcmp(name, NFC_NCI_CONTROLLER) == 0) {
210     st21nfc_dev_t* dev = calloc(1, sizeof(st21nfc_dev_t));
211 
212     dev->nci_device.common.tag = HARDWARE_DEVICE_TAG;
213     dev->nci_device.common.version = 0x00010000;  // [31:16] major, [15:0] minor
214     dev->nci_device.common.module = (struct hw_module_t*)module;
215     dev->nci_device.common.close = nfc_close;
216 
217     // NCI HAL method pointers
218     dev->nci_device.open = hal_open;
219     dev->nci_device.write = hal_write;
220     dev->nci_device.core_initialized = hal_core_initialized;
221     dev->nci_device.pre_discover = hal_pre_discover;
222     dev->nci_device.close = hal_close;
223     dev->nci_device.control_granted = hal_control_granted;
224     dev->nci_device.power_cycle = hal_power_cycle;
225 
226     *device = (hw_device_t*)dev;
227 
228     // Initialize and get global logging level
229     InitializeSTLogLevel();
230 
231     return 0;
232   } else {
233     return -EINVAL;
234   }
235 }
236 
237 static struct hw_module_methods_t nfc_module_methods = {
238     .open = nfc_open,
239 };
240 
241 struct nfc_nci_module_t HAL_MODULE_INFO_SYM = {
242     .common =
243         {
244             .tag = HARDWARE_MODULE_TAG,
245             .module_api_version = 0x0100,  // [15:8] major, [7:0] minor (1.0)
246             .hal_api_version = 0x00,       // 0 is only valid value
247             .id = "nfc_nci.st21nfc",
248             .name = "ST Micro ST21NFC NCI HW HAL",
249             .author = "ST Microelectronics SA ",
250             .methods = &nfc_module_methods,
251         },
252 };
253