diff options
Diffstat (limited to 'Linux_x86/phDal4Nfc_uart.c')
-rw-r--r-- | Linux_x86/phDal4Nfc_uart.c | 326 |
1 files changed, 326 insertions, 0 deletions
diff --git a/Linux_x86/phDal4Nfc_uart.c b/Linux_x86/phDal4Nfc_uart.c new file mode 100644 index 0000000..9d230f1 --- /dev/null +++ b/Linux_x86/phDal4Nfc_uart.c @@ -0,0 +1,326 @@ +/* + * Copyright (C) 2010 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. + */ + +/** + * \file phDalNfc_uart.c + * \brief DAL com port implementation for linux + * + * Project: Trusted NFC Linux Lignt + * + * $Date: 07 aug 2009 + * $Author: Jonathan roux + * $Revision: 1.0 $ + * + */ + +#include <unistd.h> +#include <fcntl.h> +#include <termios.h> +#include <sys/ioctl.h> +#include <sys/select.h> + +#include <phDal4Nfc_debug.h> +#include <phDal4Nfc_uart.h> +#include <phOsalNfc.h> +#include <phNfcStatus.h> +#if defined(ANDROID) +#include <string.h> +#endif + +typedef struct +{ + int nHandle; + char nOpened; + struct termios nIoConfigBackup; + struct termios nIoConfig; + +} phDal4Nfc_ComPortContext_t; + +/*----------------------------------------------------------------------------------- + COM PORT CONFIGURATION +------------------------------------------------------------------------------------*/ +#define DAL_BAUD_RATE B115200 + + + +/*----------------------------------------------------------------------------------- + VARIABLES +------------------------------------------------------------------------------------*/ +static phDal4Nfc_ComPortContext_t gComPortContext; + + + +/*----------------------------------------------------------------------------- + +FUNCTION: phDal4Nfc_uart_set_open_from_handle + +PURPOSE: Initialize internal variables + +-----------------------------------------------------------------------------*/ + +void phDal4Nfc_uart_initialize(void) +{ + memset(&gComPortContext, 0, sizeof(phDal4Nfc_ComPortContext_t)); +} + + +/*----------------------------------------------------------------------------- + +FUNCTION: phDal4Nfc_uart_set_open_from_handle + +PURPOSE: The application could have opened the link itself. So we just need + to get the handle and consider that the open operation has already + been done. + +-----------------------------------------------------------------------------*/ + +void phDal4Nfc_uart_set_open_from_handle(phHal_sHwReference_t * pDalHwContext) +{ + gComPortContext.nHandle = (int) pDalHwContext->p_board_driver; + DAL_ASSERT_STR(gComPortContext.nHandle >= 0, "Bad passed com port handle"); + gComPortContext.nOpened = 1; +} + +/*----------------------------------------------------------------------------- + +FUNCTION: phDal4Nfc_uart_is_opened + +PURPOSE: Returns if the link is opened or not. (0 = not opened; 1 = opened) + +-----------------------------------------------------------------------------*/ + +int phDal4Nfc_uart_is_opened(void) +{ + return gComPortContext.nOpened; +} + +/*----------------------------------------------------------------------------- + +FUNCTION: phDal4Nfc_uart_flush + +PURPOSE: Flushes the link ; clears the link buffers + +-----------------------------------------------------------------------------*/ + +void phDal4Nfc_uart_flush(void) +{ + int ret; + /* flushes the com port */ + ret = tcflush(gComPortContext.nHandle, TCIFLUSH); + DAL_ASSERT_STR(ret!=-1, "tcflush failed"); +} + +/*----------------------------------------------------------------------------- + +FUNCTION: phDal4Nfc_uart_close + +PURPOSE: Closes the link + +-----------------------------------------------------------------------------*/ + +void phDal4Nfc_uart_close(void) +{ + if (gComPortContext.nOpened == 1) + { + close(gComPortContext.nHandle); + gComPortContext.nHandle = 0; + gComPortContext.nOpened = 0; + } +} + +/*----------------------------------------------------------------------------- + +FUNCTION: phDal4Nfc_uart_close + +PURPOSE: Closes the link + +-----------------------------------------------------------------------------*/ + +NFCSTATUS phDal4Nfc_uart_open_and_configure(pphDal4Nfc_sConfig_t pConfig, void ** pLinkHandle) +{ + char * pComPort; + int nComStatus; + NFCSTATUS nfcret = NFCSTATUS_SUCCESS; + int ret; + + DAL_ASSERT_STR(gComPortContext.nOpened==0, "Trying to open but already done!"); + + switch(pConfig->nLinkType) + { + case ENUM_DAL_LINK_TYPE_COM1: + pComPort = "/dev/ttyS0"; + break; + case ENUM_DAL_LINK_TYPE_COM2: + pComPort = "/dev/ttyS1"; + break; + case ENUM_DAL_LINK_TYPE_COM3: + pComPort = "/dev/ttyS2"; + break; + case ENUM_DAL_LINK_TYPE_COM4: + pComPort = "/dev/ttyS3"; + break; + case ENUM_DAL_LINK_TYPE_COM5: + pComPort = "/dev/ttyS4"; + break; + case ENUM_DAL_LINK_TYPE_COM6: + pComPort = "/dev/ttyS5"; + break; + case ENUM_DAL_LINK_TYPE_COM7: + pComPort = "/dev/ttyS6"; + break; + case ENUM_DAL_LINK_TYPE_COM8: + pComPort = "/dev/ttyS7"; + break; + case ENUM_DAL_LINK_TYPE_USB: + pComPort = "/dev/ttyUSB0"; + break; + default: + return NFCSTATUS_INVALID_PARAMETER; + } + + /* open communication port handle */ + gComPortContext.nHandle = open(pComPort, O_RDWR | O_NOCTTY); + if (gComPortContext.nHandle < 0) + { + *pLinkHandle = NULL; + return PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_DEVICE); + } + + gComPortContext.nOpened = 1; + *pLinkHandle = (void*)gComPortContext.nHandle; + + /* + * Now configure the com port + */ + ret = tcgetattr(gComPortContext.nHandle, &gComPortContext.nIoConfigBackup); /* save the old io config */ + if (ret == -1) + { + /* tcgetattr failed -- it is likely that the provided port is invalid */ + *pLinkHandle = NULL; + return PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_DEVICE); + } + ret = fcntl(gComPortContext.nHandle, F_SETFL, 0); /* Makes the read blocking (default). */ + DAL_ASSERT_STR(ret != -1, "fcntl failed"); + /* Configures the io */ + memset((void *)&gComPortContext.nIoConfig, (int)0, (size_t)sizeof(struct termios)); + /* + BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed. + CRTSCTS : output hardware flow control (only used if the cable has + all necessary lines. See sect. 7 of Serial-HOWTO) + CS8 : 8n1 (8bit,no parity,1 stopbit) + CLOCAL : local connection, no modem contol + CREAD : enable receiving characters + */ + gComPortContext.nIoConfig.c_cflag = DAL_BAUD_RATE | CS8 | CLOCAL | CREAD; /* Control mode flags */ + gComPortContext.nIoConfig.c_iflag = IGNPAR; /* Input mode flags : IGNPAR Ignore parity errors */ + gComPortContext.nIoConfig.c_oflag = 0; /* Output mode flags */ + gComPortContext.nIoConfig.c_lflag = 0; /* Local mode flags. Read mode : non canonical, no echo */ + gComPortContext.nIoConfig.c_cc[VTIME] = 0; /* Control characters. No inter-character timer */ + gComPortContext.nIoConfig.c_cc[VMIN] = 1; /* Control characters. Read is blocking until X characters are read */ + + /* + TCSANOW Make changes now without waiting for data to complete + TCSADRAIN Wait until everything has been transmitted + TCSAFLUSH Flush input and output buffers and make the change + */ + ret = tcsetattr(gComPortContext.nHandle, TCSANOW, &gComPortContext.nIoConfig); + DAL_ASSERT_STR(ret != -1, "tcsetattr failed"); + + /* + On linux the DTR signal is set by default. That causes a problem for pn544 chip + because this signal is connected to "reset". So we clear it. (on windows it is cleared by default). + */ + ret = ioctl(gComPortContext.nHandle, TIOCMGET, &nComStatus); + DAL_ASSERT_STR(ret != -1, "ioctl TIOCMGET failed"); + nComStatus &= ~TIOCM_DTR; + ret = ioctl(gComPortContext.nHandle, TIOCMSET, &nComStatus); + DAL_ASSERT_STR(ret != -1, "ioctl TIOCMSET failed"); + DAL_DEBUG("Com port status=%d\n", nComStatus); + usleep(10000); /* Mandatory sleep so that the DTR line is ready before continuing */ + + return nfcret; +} + + +/*----------------------------------------------------------------------------- + +FUNCTION: phDal4Nfc_uart_read + +PURPOSE: Reads nNbBytesToRead bytes and writes them in pBuffer. + Returns the number of bytes really read or -1 in case of error. + +-----------------------------------------------------------------------------*/ + +int phDal4Nfc_uart_read(uint8_t * pBuffer, int nNbBytesToRead) +{ + fd_set rfds; + struct timeval tv; + int ret; + + DAL_ASSERT_STR(gComPortContext.nOpened == 1, "read called but not opened!"); + + FD_ZERO(&rfds); + FD_SET(gComPortContext.nHandle, &rfds); + + /* select will block for 10 sec */ + tv.tv_sec = 2; + tv.tv_usec = 0; + + ret = select(gComPortContext.nHandle + 1, &rfds, NULL, NULL, &tv); + + if (ret == -1) + return -1; + + if (ret) + return read(gComPortContext.nHandle, pBuffer, nNbBytesToRead); + + return 0; +} + +/*----------------------------------------------------------------------------- + +FUNCTION: phDal4Nfc_link_write + +PURPOSE: Writes nNbBytesToWrite bytes from pBuffer to the link + Returns the number of bytes that have been wrote to the interface or -1 in case of error. + +-----------------------------------------------------------------------------*/ + +int phDal4Nfc_uart_write(uint8_t * pBuffer, int nNbBytesToWrite) +{ + fd_set wfds; + struct timeval tv; + int ret; + + DAL_ASSERT_STR(gComPortContext.nOpened == 1, "write called but not opened!"); + + FD_ZERO(&wfds); + FD_SET(gComPortContext.nHandle, &wfds); + + /* select will block for 10 sec */ + tv.tv_sec = 2; + tv.tv_usec = 0; + + ret = select(gComPortContext.nHandle + 1, NULL, &wfds, NULL, &tv); + + if (ret == -1) + return -1; + + if (ret) + return write(gComPortContext.nHandle, pBuffer, nNbBytesToWrite); + + return 0; +} |