Home | History | Annotate | Download | only in Linux_x86
      1 /*
      2  * Copyright (C) 2010 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  * \file phDalNfc_i2c.c
     19  * \brief DAL I2C port implementation for linux
     20  *
     21  * Project: Trusted NFC Linux
     22  *
     23  */
     24 
     25 #define LOG_TAG "NFC_i2c"
     26 #include <utils/Log.h>
     27 
     28 #include <stdlib.h>
     29 #include <unistd.h>
     30 #include <fcntl.h>
     31 #include <termios.h>
     32 #include <sys/ioctl.h>
     33 #include <sys/select.h>
     34 
     35 #include <phDal4Nfc_debug.h>
     36 #include <phDal4Nfc_i2c.h>
     37 #include <phOsalNfc.h>
     38 #include <phNfcStatus.h>
     39 #if defined(ANDROID)
     40 #include <string.h>
     41 #endif
     42 
     43 #include <linux/pn544.h>
     44 
     45 typedef struct
     46 {
     47    int  nHandle;
     48    char nOpened;
     49 
     50 } phDal4Nfc_I2cPortContext_t;
     51 
     52 
     53 /*-----------------------------------------------------------------------------------
     54                                       VARIABLES
     55 ------------------------------------------------------------------------------------*/
     56 static phDal4Nfc_I2cPortContext_t gI2cPortContext;
     57 
     58 
     59 
     60 /*-----------------------------------------------------------------------------
     61 
     62 FUNCTION: phDal4Nfc_i2c_set_open_from_handle
     63 
     64 PURPOSE:  Initialize internal variables
     65 
     66 -----------------------------------------------------------------------------*/
     67 
     68 void phDal4Nfc_i2c_initialize(void)
     69 {
     70    memset(&gI2cPortContext, 0, sizeof(phDal4Nfc_I2cPortContext_t));
     71 }
     72 
     73 
     74 /*-----------------------------------------------------------------------------
     75 
     76 FUNCTION: phDal4Nfc_i2c_set_open_from_handle
     77 
     78 PURPOSE:  The application could have opened the link itself. So we just need
     79           to get the handle and consider that the open operation has already
     80           been done.
     81 
     82 -----------------------------------------------------------------------------*/
     83 
     84 void phDal4Nfc_i2c_set_open_from_handle(phHal_sHwReference_t * pDalHwContext)
     85 {
     86    gI2cPortContext.nHandle = (int) pDalHwContext->p_board_driver;
     87    DAL_ASSERT_STR(gI2cPortContext.nHandle >= 0, "Bad passed com port handle");
     88    gI2cPortContext.nOpened = 1;
     89 }
     90 
     91 /*-----------------------------------------------------------------------------
     92 
     93 FUNCTION: phDal4Nfc_i2c_is_opened
     94 
     95 PURPOSE:  Returns if the link is opened or not. (0 = not opened; 1 = opened)
     96 
     97 -----------------------------------------------------------------------------*/
     98 
     99 int phDal4Nfc_i2c_is_opened(void)
    100 {
    101    return gI2cPortContext.nOpened;
    102 }
    103 
    104 /*-----------------------------------------------------------------------------
    105 
    106 FUNCTION: phDal4Nfc_i2c_flush
    107 
    108 PURPOSE:  Flushes the link ; clears the link buffers
    109 
    110 -----------------------------------------------------------------------------*/
    111 
    112 void phDal4Nfc_i2c_flush(void)
    113 {
    114    /* Nothing to do (driver has no internal buffers) */
    115 }
    116 
    117 /*-----------------------------------------------------------------------------
    118 
    119 FUNCTION: phDal4Nfc_i2c_close
    120 
    121 PURPOSE:  Closes the link
    122 
    123 -----------------------------------------------------------------------------*/
    124 
    125 void phDal4Nfc_i2c_close(void)
    126 {
    127    DAL_PRINT("Closing port\n");
    128    if (gI2cPortContext.nOpened == 1)
    129    {
    130       close(gI2cPortContext.nHandle);
    131       gI2cPortContext.nHandle = 0;
    132       gI2cPortContext.nOpened = 0;
    133    }
    134 }
    135 
    136 /*-----------------------------------------------------------------------------
    137 
    138 FUNCTION: phDal4Nfc_i2c_open_and_configure
    139 
    140 PURPOSE:  Closes the link
    141 
    142 -----------------------------------------------------------------------------*/
    143 
    144 NFCSTATUS phDal4Nfc_i2c_open_and_configure(pphDal4Nfc_sConfig_t pConfig, void ** pLinkHandle)
    145 {
    146    char *       pComPort;
    147 
    148    DAL_ASSERT_STR(gI2cPortContext.nOpened==0, "Trying to open but already done!");
    149 
    150    switch(pConfig->nLinkType)
    151    {
    152        case ENUM_DAL_LINK_TYPE_I2C:
    153           pComPort = "/dev/pn544";
    154           break;
    155        default:
    156           DAL_DEBUG("Open failed: unknown type %d\n", pConfig->nLinkType);
    157           return NFCSTATUS_INVALID_PARAMETER;
    158    }
    159 
    160    DAL_DEBUG("Opening port=%s\n", pComPort);
    161 
    162    /* open port */
    163    gI2cPortContext.nHandle = open(pComPort, O_RDWR | O_NOCTTY);
    164    if (gI2cPortContext.nHandle < 0)
    165    {
    166        DAL_DEBUG("Open failed: open() returned %d\n", gI2cPortContext.nHandle);
    167       *pLinkHandle = NULL;
    168       return PHNFCSTVAL(CID_NFC_DAL, NFCSTATUS_INVALID_DEVICE);
    169    }
    170 
    171    gI2cPortContext.nOpened = 1;
    172    *pLinkHandle = (void*)gI2cPortContext.nHandle;
    173 
    174    DAL_PRINT("Open succeed\n");
    175 
    176    return NFCSTATUS_SUCCESS;
    177 }
    178 
    179 
    180 /*-----------------------------------------------------------------------------
    181 
    182 FUNCTION: phDal4Nfc_i2c_read
    183 
    184 PURPOSE:  Reads nNbBytesToRead bytes and writes them in pBuffer.
    185           Returns the number of bytes really read or -1 in case of error.
    186 
    187 -----------------------------------------------------------------------------*/
    188 
    189 int phDal4Nfc_i2c_read(uint8_t * pBuffer, int nNbBytesToRead)
    190 {
    191    int ret;
    192    DAL_ASSERT_STR(gI2cPortContext.nOpened == 1, "read called but not opened!");
    193 
    194    DAL_DEBUG("Reading %d bytes\n", nNbBytesToRead);
    195    ret = read(gI2cPortContext.nHandle, pBuffer, nNbBytesToRead);
    196    if (ret < 0)
    197    {
    198       DAL_DEBUG("Read failed: read() returned %d\n", ret);
    199    }
    200    else
    201    {
    202       DAL_DEBUG("Read succeed (%d bytes)\n", ret);
    203    }
    204    return ret;
    205 }
    206 
    207 /*-----------------------------------------------------------------------------
    208 
    209 FUNCTION: phDal4Nfc_i2c_write
    210 
    211 PURPOSE:  Writes nNbBytesToWrite bytes from pBuffer to the link
    212           Returns the number of bytes that have been wrote to the interface or -1 in case of error.
    213 
    214 -----------------------------------------------------------------------------*/
    215 
    216 int phDal4Nfc_i2c_write(uint8_t * pBuffer, int nNbBytesToWrite)
    217 {
    218    int ret;
    219    DAL_ASSERT_STR(gI2cPortContext.nOpened == 1, "write called but not opened!");
    220 
    221    DAL_DEBUG("Writing %d bytes\n", nNbBytesToWrite);
    222    ret = write(gI2cPortContext.nHandle, pBuffer, nNbBytesToWrite);
    223    if (ret < 0)
    224    {
    225       DAL_DEBUG("Write failed: write() returned %d \n", ret);
    226    }
    227    else
    228    {
    229       DAL_DEBUG("Write succeed (%d bytes)\n", ret);
    230    }
    231    return ret;
    232 }
    233 
    234 
    235 /*-----------------------------------------------------------------------------
    236 
    237 FUNCTION: phDal4Nfc_i2c_reset
    238 
    239 PURPOSE:  Reset the PN544, using the VEN pin
    240 
    241 -----------------------------------------------------------------------------*/
    242 int phDal4Nfc_i2c_reset(long level)
    243 {
    244    int ret = NFCSTATUS_SUCCESS;
    245 
    246    DAL_DEBUG("phDal4Nfc_i2c_reset, VEN level = %ld",level);
    247 
    248    ret = ioctl(gI2cPortContext.nHandle, PN544_SET_PWR, level);
    249 
    250    /* HACK to increase reset time
    251     * TODO: move this to kernel
    252     */
    253    if (level == 0) {
    254        LOGW("sleeping a little longer...");
    255        usleep(50000);
    256    } else {
    257        usleep(10000);
    258    }
    259 
    260    return ret;
    261 }
    262 
    263 
    264 
    265 
    266 
    267