From 9224c881cf3f8575194823a6c779c0d65c42258a Mon Sep 17 00:00:00 2001 From: Arian Date: Mon, 30 Sep 2019 11:10:42 +0200 Subject: shinano-common: pn54x: Import from lineage-15.1 * https://github.com/LineageOS/android_system_nfc/tree/lineage-15.1/halimpl/pn54x/common * support for pn54x has been dropped in lineage-16.0 and above Change-Id: I19f2c3a6e3066bf9aaaaf4ddcd7d7ad867de0ed8 --- pn54x/tml/phTmlNfc_i2c.c | 315 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 315 insertions(+) create mode 100644 pn54x/tml/phTmlNfc_i2c.c (limited to 'pn54x/tml/phTmlNfc_i2c.c') diff --git a/pn54x/tml/phTmlNfc_i2c.c b/pn54x/tml/phTmlNfc_i2c.c new file mode 100644 index 0000000..781f19b --- /dev/null +++ b/pn54x/tml/phTmlNfc_i2c.c @@ -0,0 +1,315 @@ +/* + * Copyright (C) 2010-2014 NXP Semiconductors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * DAL I2C port implementation for linux + * + * Project: Trusted NFC Linux + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "phNxpNciHal_utils.h" + +#define CRC_LEN 2 +#define NORMAL_MODE_HEADER_LEN 3 +#define FW_DNLD_HEADER_LEN 2 +#define FW_DNLD_LEN_OFFSET 1 +#define NORMAL_MODE_LEN_OFFSET 2 +#define FRAGMENTSIZE_MAX PHNFC_I2C_FRAGMENT_SIZE +static bool_t bFwDnldFlag = false; +extern phTmlNfc_i2cfragmentation_t fragmentation_enabled; + +/******************************************************************************* +** +** Function phTmlNfc_i2c_close +** +** Description Closes PN54X device +** +** Parameters pDevHandle - device handle +** +** Returns None +** +*******************************************************************************/ +void phTmlNfc_i2c_close(void* pDevHandle) { + if (NULL != pDevHandle) { + close((intptr_t)pDevHandle); + } + + return; +} + +/******************************************************************************* +** +** Function phTmlNfc_i2c_open_and_configure +** +** Description Open and configure PN54X device +** +** Parameters pConfig - hardware information +** pLinkHandle - device handle +** +** Returns NFC status: +** NFCSTATUS_SUCCESS - open_and_configure operation success +** NFCSTATUS_INVALID_DEVICE - device open operation failure +** +*******************************************************************************/ +NFCSTATUS phTmlNfc_i2c_open_and_configure(pphTmlNfc_Config_t pConfig, + void** pLinkHandle) { + int nHandle; + + NXPLOG_TML_D("Opening port=%s\n", pConfig->pDevName); + /* open port */ + nHandle = open((const char*)pConfig->pDevName, O_RDWR); + if (nHandle < 0) { + NXPLOG_TML_E("_i2c_open() Failed: retval %x", nHandle); + *pLinkHandle = NULL; + return NFCSTATUS_INVALID_DEVICE; + } + + *pLinkHandle = (void*)((intptr_t)nHandle); + + /*Reset PN54X*/ + phTmlNfc_i2c_reset((void*)((intptr_t)nHandle), 0); + usleep(10 * 1000); + phTmlNfc_i2c_reset((void*)((intptr_t)nHandle), 1); + + return NFCSTATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function phTmlNfc_i2c_read +** +** Description Reads requested number of bytes from PN54X device into given +** buffer +** +** Parameters pDevHandle - valid device handle +** pBuffer - buffer for read data +** nNbBytesToRead - number of bytes requested to be read +** +** Returns numRead - number of successfully read bytes +** -1 - read operation failure +** +*******************************************************************************/ +int phTmlNfc_i2c_read(void* pDevHandle, uint8_t* pBuffer, int nNbBytesToRead) { + int ret_Read; + int ret_Select; + int numRead = 0; + struct timeval tv; + fd_set rfds; + uint16_t totalBtyesToRead = 0; + + int i; + UNUSED(nNbBytesToRead); + if (NULL == pDevHandle) { + return -1; + } + + if (bFwDnldFlag == false) { + totalBtyesToRead = NORMAL_MODE_HEADER_LEN; + } else { + totalBtyesToRead = FW_DNLD_HEADER_LEN; + } + + /* Read with 2 second timeout, so that the read thread can be aborted + when the PN54X does not respond and we need to switch to FW download + mode. This should be done via a control socket instead. */ + FD_ZERO(&rfds); + FD_SET((intptr_t)pDevHandle, &rfds); + tv.tv_sec = 2; + tv.tv_usec = 1; + + ret_Select = + select((int)((intptr_t)pDevHandle + (int)1), &rfds, NULL, NULL, &tv); + if (ret_Select < 0) { + NXPLOG_TML_E("i2c select() errno : %x", errno); + return -1; + } else if (ret_Select == 0) { + NXPLOG_TML_E("i2c select() Timeout"); + return -1; + } else { + ret_Read = read((intptr_t)pDevHandle, pBuffer, totalBtyesToRead - numRead); + if (ret_Read > 0) { + numRead += ret_Read; + } else if (ret_Read == 0) { + NXPLOG_TML_E("_i2c_read() [hdr]EOF"); + return -1; + } else { + NXPLOG_TML_E("_i2c_read() [hdr] errno : %x", errno); + return -1; + } + + if (bFwDnldFlag == false) { + totalBtyesToRead = NORMAL_MODE_HEADER_LEN; + } else { + totalBtyesToRead = FW_DNLD_HEADER_LEN; + } + + if (numRead < totalBtyesToRead) { + ret_Read = + read((intptr_t)pDevHandle, pBuffer, totalBtyesToRead - numRead); + if (ret_Read != totalBtyesToRead - numRead) { + NXPLOG_TML_E("_i2c_read() [hdr] errno : %x", errno); + return -1; + } else { + numRead += ret_Read; + } + } + if (bFwDnldFlag == true) { + totalBtyesToRead = + pBuffer[FW_DNLD_LEN_OFFSET] + FW_DNLD_HEADER_LEN + CRC_LEN; + } else { + totalBtyesToRead = + pBuffer[NORMAL_MODE_LEN_OFFSET] + NORMAL_MODE_HEADER_LEN; + } + if ((totalBtyesToRead - numRead) != 0) { + ret_Read = read((intptr_t)pDevHandle, (pBuffer + numRead), + totalBtyesToRead - numRead); + if (ret_Read > 0) { + numRead += ret_Read; + } else if (ret_Read == 0) { + NXPLOG_TML_E("_i2c_read() [pyld] EOF"); + return -1; + } else { + if (bFwDnldFlag == false) { + NXPLOG_TML_E("_i2c_read() [hdr] received"); + phNxpNciHal_print_packet("RECV", pBuffer, NORMAL_MODE_HEADER_LEN); + } + NXPLOG_TML_E("_i2c_read() [pyld] errno : %x", errno); + return -1; + } + } else { + NXPLOG_TML_E("_>>>>> Empty packet recieved !!"); + } + } + return numRead; +} + +/******************************************************************************* +** +** Function phTmlNfc_i2c_write +** +** Description Writes requested number of bytes from given buffer into +** PN54X device +** +** Parameters pDevHandle - valid device handle +** pBuffer - buffer for read data +** nNbBytesToWrite - number of bytes requested to be written +** +** Returns numWrote - number of successfully written bytes +** -1 - write operation failure +** +*******************************************************************************/ +int phTmlNfc_i2c_write(void* pDevHandle, uint8_t* pBuffer, + int nNbBytesToWrite) { + int ret; + int numWrote = 0; + int i; + int numBytes = nNbBytesToWrite; + if (NULL == pDevHandle) { + return -1; + } + if (fragmentation_enabled == I2C_FRAGMENATATION_DISABLED && + nNbBytesToWrite > FRAGMENTSIZE_MAX) { + NXPLOG_TML_E( + "i2c_write() data larger than maximum I2C size,enable I2C " + "fragmentation"); + return -1; + } + while (numWrote < nNbBytesToWrite) { + if (fragmentation_enabled == I2C_FRAGMENTATION_ENABLED && + nNbBytesToWrite > FRAGMENTSIZE_MAX) { + if (nNbBytesToWrite - numWrote > FRAGMENTSIZE_MAX) { + numBytes = numWrote + FRAGMENTSIZE_MAX; + } else { + numBytes = nNbBytesToWrite; + } + } + ret = write((intptr_t)pDevHandle, pBuffer + numWrote, numBytes - numWrote); + if (ret > 0) { + numWrote += ret; + if (fragmentation_enabled == I2C_FRAGMENTATION_ENABLED && + numWrote < nNbBytesToWrite) { + usleep(500); + } + } else if (ret == 0) { + NXPLOG_TML_E("_i2c_write() EOF"); + return -1; + } else { + NXPLOG_TML_E("_i2c_write() errno : %x", errno); + if (errno == EINTR || errno == EAGAIN) { + continue; + } + return -1; + } + } + + return numWrote; +} + +/******************************************************************************* +** +** Function phTmlNfc_i2c_reset +** +** Description Reset PN54X device, using VEN pin +** +** Parameters pDevHandle - valid device handle +** level - reset level +** +** Returns 0 - reset operation success +** -1 - reset operation failure +** +*******************************************************************************/ +#define PN544_SET_PWR _IOW(0xe9, 0x01, unsigned int) +int phTmlNfc_i2c_reset(void* pDevHandle, long level) { + int ret; + NXPLOG_TML_D("phTmlNfc_i2c_reset(), VEN level %ld", level); + + if (NULL == pDevHandle) { + return -1; + } + + ret = ioctl((intptr_t)pDevHandle, PN544_SET_PWR, level); + if (level == 2 && ret == 0) { + bFwDnldFlag = true; + } else { + bFwDnldFlag = false; + } + return ret; +} + +/******************************************************************************* +** +** Function getDownloadFlag +** +** Description Returns the current mode +** +** Parameters none +** +** Returns Current mode download/NCI +*******************************************************************************/ +bool_t getDownloadFlag(void) { return bFwDnldFlag; } -- cgit v1.2.3