1 /* 2 * Copyright (C) 2010-2014 NXP Semiconductors 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 /* 18 * DAL I2C port implementation for linux 19 * 20 * Project: Trusted NFC Linux 21 * 22 */ 23 #include <hardware/nfc.h> 24 #include <stdlib.h> 25 #include <unistd.h> 26 #include <fcntl.h> 27 #include <termios.h> 28 #include <sys/ioctl.h> 29 #include <sys/select.h> 30 #include <errno.h> 31 32 #include <phNxpLog.h> 33 #include <phTmlNfc_i2c.h> 34 #include <phNfcStatus.h> 35 #include <string.h> 36 #include "phNxpNciHal_utils.h" 37 38 #define CRC_LEN 2 39 #define NORMAL_MODE_HEADER_LEN 3 40 #define FW_DNLD_HEADER_LEN 2 41 #define FW_DNLD_LEN_OFFSET 1 42 #define NORMAL_MODE_LEN_OFFSET 2 43 #define FRAGMENTSIZE_MAX PHNFC_I2C_FRAGMENT_SIZE 44 static bool_t bFwDnldFlag = FALSE; 45 46 /******************************************************************************* 47 ** 48 ** Function phTmlNfc_i2c_close 49 ** 50 ** Description Closes PN54X device 51 ** 52 ** Parameters pDevHandle - device handle 53 ** 54 ** Returns None 55 ** 56 *******************************************************************************/ 57 void phTmlNfc_i2c_close(void *pDevHandle) 58 { 59 if (NULL != pDevHandle) 60 { 61 close((intptr_t)pDevHandle); 62 } 63 64 return; 65 } 66 67 /******************************************************************************* 68 ** 69 ** Function phTmlNfc_i2c_open_and_configure 70 ** 71 ** Description Open and configure PN54X device 72 ** 73 ** Parameters pConfig - hardware information 74 ** pLinkHandle - device handle 75 ** 76 ** Returns NFC status: 77 ** NFCSTATUS_SUCCESS - open_and_configure operation success 78 ** NFCSTATUS_INVALID_DEVICE - device open operation failure 79 ** 80 *******************************************************************************/ 81 NFCSTATUS phTmlNfc_i2c_open_and_configure(pphTmlNfc_Config_t pConfig, void ** pLinkHandle) 82 { 83 int nHandle; 84 85 86 NXPLOG_TML_D("Opening port=%s\n", pConfig->pDevName); 87 /* open port */ 88 nHandle = open((char const *)pConfig->pDevName, O_RDWR); 89 if (nHandle < 0) 90 { 91 NXPLOG_TML_E("_i2c_open() Failed: retval %x",nHandle); 92 *pLinkHandle = NULL; 93 return NFCSTATUS_INVALID_DEVICE; 94 } 95 96 *pLinkHandle = (void*) ((intptr_t)nHandle); 97 98 /*Reset PN54X*/ 99 phTmlNfc_i2c_reset((void *)((intptr_t)nHandle), 1); 100 usleep(100 * 1000); 101 phTmlNfc_i2c_reset((void *)((intptr_t)nHandle), 0); 102 usleep(100 * 1000); 103 phTmlNfc_i2c_reset((void *)((intptr_t)nHandle), 1); 104 105 return NFCSTATUS_SUCCESS; 106 } 107 108 /******************************************************************************* 109 ** 110 ** Function phTmlNfc_i2c_read 111 ** 112 ** Description Reads requested number of bytes from PN54X device into given buffer 113 ** 114 ** Parameters pDevHandle - valid device handle 115 ** pBuffer - buffer for read data 116 ** nNbBytesToRead - number of bytes requested to be read 117 ** 118 ** Returns numRead - number of successfully read bytes 119 ** -1 - read operation failure 120 ** 121 *******************************************************************************/ 122 int phTmlNfc_i2c_read(void *pDevHandle, uint8_t * pBuffer, int nNbBytesToRead) 123 { 124 int ret_Read; 125 int ret_Select; 126 int numRead = 0; 127 struct timeval tv; 128 fd_set rfds; 129 uint16_t totalBtyesToRead = 0; 130 131 int i; 132 UNUSED(nNbBytesToRead); 133 if (NULL == pDevHandle) 134 { 135 return -1; 136 } 137 138 if (FALSE == bFwDnldFlag) 139 { 140 totalBtyesToRead = NORMAL_MODE_HEADER_LEN; 141 } 142 else 143 { 144 totalBtyesToRead = FW_DNLD_HEADER_LEN; 145 } 146 147 /* Read with 2 second timeout, so that the read thread can be aborted 148 when the PN54X does not respond and we need to switch to FW download 149 mode. This should be done via a control socket instead. */ 150 FD_ZERO(&rfds); 151 FD_SET((intptr_t) pDevHandle, &rfds); 152 tv.tv_sec = 2; 153 tv.tv_usec = 1; 154 155 ret_Select = select((int)((intptr_t)pDevHandle + (int)1), &rfds, NULL, NULL, &tv); 156 if (ret_Select < 0) 157 { 158 NXPLOG_TML_E("i2c select() errno : %x",errno); 159 return -1; 160 } 161 else if (ret_Select == 0) 162 { 163 NXPLOG_TML_E("i2c select() Timeout"); 164 return -1; 165 } 166 else 167 { 168 ret_Read = read((intptr_t)pDevHandle, pBuffer, totalBtyesToRead - numRead); 169 if (ret_Read > 0) 170 { 171 numRead += ret_Read; 172 } 173 else if (ret_Read == 0) 174 { 175 NXPLOG_TML_E("_i2c_read() [hdr]EOF"); 176 return -1; 177 } 178 else 179 { 180 NXPLOG_TML_E("_i2c_read() [hdr] errno : %x",errno); 181 return -1; 182 } 183 184 if (FALSE == bFwDnldFlag) 185 { 186 totalBtyesToRead = NORMAL_MODE_HEADER_LEN; 187 } 188 else 189 { 190 totalBtyesToRead = FW_DNLD_HEADER_LEN; 191 } 192 193 if(numRead < totalBtyesToRead) 194 { 195 ret_Read = read((intptr_t)pDevHandle, pBuffer, totalBtyesToRead - numRead); 196 if (ret_Read != totalBtyesToRead - numRead) 197 { 198 NXPLOG_TML_E("_i2c_read() [hdr] errno : %x",errno); 199 return -1; 200 } 201 else 202 { 203 numRead += ret_Read; 204 } 205 } 206 if(TRUE == bFwDnldFlag) 207 { 208 totalBtyesToRead = pBuffer[FW_DNLD_LEN_OFFSET] + FW_DNLD_HEADER_LEN + CRC_LEN; 209 } 210 else 211 { 212 totalBtyesToRead = pBuffer[NORMAL_MODE_LEN_OFFSET] + NORMAL_MODE_HEADER_LEN; 213 } 214 ret_Read = read((intptr_t)pDevHandle, (pBuffer + numRead), totalBtyesToRead - numRead); 215 if (ret_Read > 0) 216 { 217 numRead += ret_Read; 218 } 219 else if (ret_Read == 0) 220 { 221 NXPLOG_TML_E("_i2c_read() [pyld] EOF"); 222 return -1; 223 } 224 else 225 { 226 if(FALSE == bFwDnldFlag) 227 { 228 NXPLOG_TML_E("_i2c_read() [hdr] received"); 229 phNxpNciHal_print_packet("RECV",pBuffer, NORMAL_MODE_HEADER_LEN); 230 } 231 NXPLOG_TML_E("_i2c_read() [pyld] errno : %x",errno); 232 return -1; 233 } 234 } 235 return numRead; 236 } 237 238 /******************************************************************************* 239 ** 240 ** Function phTmlNfc_i2c_write 241 ** 242 ** Description Writes requested number of bytes from given buffer into PN54X device 243 ** 244 ** Parameters pDevHandle - valid device handle 245 ** pBuffer - buffer for read data 246 ** nNbBytesToWrite - number of bytes requested to be written 247 ** 248 ** Returns numWrote - number of successfully written bytes 249 ** -1 - write operation failure 250 ** 251 *******************************************************************************/ 252 int phTmlNfc_i2c_write(void *pDevHandle, uint8_t * pBuffer, int nNbBytesToWrite) 253 { 254 int ret; 255 int numWrote = 0; 256 int i; 257 int numBytes = nNbBytesToWrite; 258 if (NULL == pDevHandle) 259 { 260 return -1; 261 } 262 if(fragmentation_enabled == I2C_FRAGMENATATION_DISABLED && nNbBytesToWrite > FRAGMENTSIZE_MAX) 263 { 264 NXPLOG_TML_E("i2c_write() data larger than maximum I2C size,enable I2C fragmentation"); 265 return -1; 266 } 267 while (numWrote < nNbBytesToWrite) 268 { 269 if(fragmentation_enabled == I2C_FRAGMENTATION_ENABLED && nNbBytesToWrite > FRAGMENTSIZE_MAX) 270 { 271 if(nNbBytesToWrite - numWrote > FRAGMENTSIZE_MAX) 272 { 273 numBytes = numWrote+ FRAGMENTSIZE_MAX; 274 } 275 else 276 { 277 numBytes = nNbBytesToWrite; 278 } 279 } 280 ret = write((intptr_t)pDevHandle, pBuffer + numWrote, numBytes - numWrote); 281 if (ret > 0) 282 { 283 numWrote += ret; 284 if(fragmentation_enabled == I2C_FRAGMENTATION_ENABLED && numWrote < nNbBytesToWrite) 285 { 286 usleep(500); 287 } 288 } 289 else if (ret == 0) 290 { 291 NXPLOG_TML_E("_i2c_write() EOF"); 292 return -1; 293 } 294 else 295 { 296 NXPLOG_TML_E("_i2c_write() errno : %x",errno); 297 if (errno == EINTR || errno == EAGAIN) 298 { 299 continue; 300 } 301 return -1; 302 } 303 } 304 305 return numWrote; 306 } 307 308 /******************************************************************************* 309 ** 310 ** Function phTmlNfc_i2c_reset 311 ** 312 ** Description Reset PN54X device, using VEN pin 313 ** 314 ** Parameters pDevHandle - valid device handle 315 ** level - reset level 316 ** 317 ** Returns 0 - reset operation success 318 ** -1 - reset operation failure 319 ** 320 *******************************************************************************/ 321 #define PN544_SET_PWR _IOW(0xe9, 0x01, unsigned int) 322 int phTmlNfc_i2c_reset(void *pDevHandle, long level) 323 { 324 int ret; 325 NXPLOG_TML_D("phTmlNfc_i2c_reset(), VEN level %ld", level); 326 327 if (NULL == pDevHandle) 328 { 329 return -1; 330 } 331 332 ret = ioctl((intptr_t)pDevHandle, PN544_SET_PWR, level); 333 if(level == 2 && ret == 0) 334 { 335 bFwDnldFlag = TRUE; 336 }else{ 337 bFwDnldFlag = FALSE; 338 } 339 return ret; 340 } 341 342 /******************************************************************************* 343 ** 344 ** Function getDownloadFlag 345 ** 346 ** Description Returns the current mode 347 ** 348 ** Parameters none 349 ** 350 ** Returns Current mode download/NCI 351 *******************************************************************************/ 352 bool_t getDownloadFlag(void) 353 { 354 355 return bFwDnldFlag; 356 } 357