Exemplo n.º 1
0
static ssize_t pn544_ven_store(struct device *dev, struct device_attribute *attr,
                               const char *buf, size_t count)
{
    int retval = 0;
    NFC_DEBUG("%s: enter pn544_ven_store\n", __func__);
    if ('0' != buf[0]) {
        retval = gpio_direction_output(NFC_1V8EN,1);
        if (retval) {
            pr_err("%s: Failed to setup nfc_ven gpio %d. Code: %d.",
                   __func__, NFC_1V8EN, retval);
        }
        ven_status = 1;

    } else {
        retval = gpio_direction_output(NFC_1V8EN,0);
        if (retval) {
            pr_err("%s: Failed to setup nfc_ven gpio %d. Code: %d.",
                   __func__, NFC_1V8EN, retval);
        }
        ven_status = 0;
    }

    NFC_DEBUG("%s: exit pn544_ven_store\n", __func__);
    return count;
}
Exemplo n.º 2
0
s8 nfcTxNBytes(const u8 *buf, u8 bufSize, u8 perform_collision_avoidance)
{
    s8 err = ERR_NONE;
    u8 regValue = 0;
    
    NFC_DEBUG("nfcTxNBytes(.buf=");
    NFC_DEBUG_HEX_DUMP(buf,bufSize);
    NFC_DEBUG(".bufSize=%hhx,.perform_collision_avoidance=%hhx)\n",
            bufSize, perform_collision_avoidance);

    err |= as3911ReadRegister(AS3911_REG_OP_CONTROL, &regValue);
    
    if (!(regValue & AS3911_REG_OP_CONTROL_tx_en))
    {
        /* RF field is off, perform initial RF collision avoidance. */
        u32 irqs = 0;
        
        err |= as3911EnableInterrupts(AS3911_IRQ_MASK_CAC | AS3911_IRQ_MASK_CAT);
        err |= as3911ExecuteCommand(AS3911_CMD_INITIAL_RF_COLLISION);
        irqs = as3911WaitForInterruptsTimed(AS3911_IRQ_MASK_CAC | AS3911_IRQ_MASK_CAT, NFC_RFCA_IRQ_TIMEOUT);
        err |= as3911DisableInterrupts(AS3911_IRQ_MASK_CAC | AS3911_IRQ_MASK_CAT);
        
        if (0 == irqs)
        {
            NFC_DEBUG("NFC_INITIAL_RFCA_IRQ_TIMEOUT expired\n");
            return ERR_INTERNAL;
        }
        else if (AS3911_IRQ_MASK_CAC & irqs)
        {
            return ERR_RF_COLLISION;
        }
    }
    
    /* Setup NRT timer for rf response RF collision timeout. */
    err |= as3911WriteRegister(AS3911_REG_NO_RESPONSE_TIMER1, RESPONSE_RFCA_NRT1);
    err |= as3911WriteRegister(AS3911_REG_NO_RESPONSE_TIMER2, RESPONSE_RFCA_NRT2);
    
    nfcPerformResponseCa = perform_collision_avoidance;
    as3911PrepareReceive(TRUE);
    err |= as3911TxNBytes(buf, bufSize, 0, AS3911_TX_FLAG_CRC);
    
    nfcRxBufferInPtr = nfcRxBuffer;
    nfcTaskStatus = NFC_TASK_WAIT_FOR_EON;

    if (ERR_NONE != err)
        return ERR_IO;
    else
        return ERR_NONE;
}
Exemplo n.º 3
0
static int pn544_dev_open(struct inode *inode, struct file *filp)
{
    struct pn544_dev *pn544_dev = container_of(filp->private_data,
                                  struct pn544_dev,
                                  pn544_device);

    NFC_DEBUG("%s:enter pn544_dev_open\n", __func__);

    filp->private_data = pn544_dev;

    pr_info("%s : %d,%d\n", __func__, imajor(inode), iminor(inode));

    NFC_DEBUG("%s:exit pn544_dev_open\n", __func__);

    return 0;
}
Exemplo n.º 4
0
s8 nfcStartInitialTargetRx()
{
    s8 err = ERR_NONE;
    
    NFC_DEBUG("nfcStartInitialTargetRx()\n");

    if (  (NFC_TASK_TRANSMITTING == nfcTaskStatus)
       || (NFC_TASK_RX_IN_PROGRESS == nfcTaskStatus))
       return ERR_BUSY;
       
    err |= as3911ExecuteCommand(AS3911_CMD_CLEAR_FIFO);
        
    /* Enter low power bitrate detection mode. */
    err |= as3911WriteRegister(AS3911_REG_MODE, 0x80);
        
    /* Turn off the chip. */
    err |= as3911ModifyRegister(AS3911_REG_OP_CONTROL,
        AS3911_REG_OP_CONTROL_en | AS3911_REG_OP_CONTROL_rx_en | AS3911_REG_OP_CONTROL_tx_en,
        0x00);
        
    if (ERR_NONE != err)
        return ERR_IO;
    
    nfcLowPowerMode = TRUE;
    nfcPerformResponseCa = TRUE;
    nfcRxBufferInPtr = nfcRxBuffer;
    nfcRxError = ERR_NONE;
    nfcTaskStatus = NFC_TASK_WAIT_FOR_EON;
    
    return ERR_NONE;
}
Exemplo n.º 5
0
s8 nfcDeinitialize()
{
    s8 err = ERR_NONE;
    u8 regOpControl = 0;

    NFC_DEBUG("nfcDeinitialize()\n");
                
    nfcTaskStatus = NFC_TASK_INACTIVE;

    err |= as3911ReadRegister(AS3911_REG_OP_CONTROL, &regOpControl);
    if (!(AS3911_REG_OP_CONTROL_en & regOpControl))
    {
        u32 oscIrqs = as3911GetInterrupt(AS3911_IRQ_MASK_OSC);
        as3911EnableInterrupts(AS3911_IRQ_MASK_OSC);
        
        err |= as3911ModifyRegister(AS3911_REG_OP_CONTROL,
            AS3911_REG_OP_CONTROL_en | AS3911_REG_OP_CONTROL_rx_en | AS3911_REG_OP_CONTROL_tx_en,
            AS3911_REG_OP_CONTROL_en | AS3911_REG_OP_CONTROL_rx_en);
                
        /* Wait for oscillators to start. */
        oscIrqs = as3911WaitForInterruptsTimed(AS3911_IRQ_MASK_OSC, NFC_OSC_IRQ_TIMEOUT);
        as3911DisableInterrupts(AS3911_IRQ_MASK_OSC);
                
        if (0 == oscIrqs)
        {
            NFC_DEBUG("NFC_OSC_IRQ_TIMEOUT expired\n");
            return ERR_INTERNAL;
        }
    }

    err |=  as3911SetBitrate(0,0);
	
    /* Restore old settings. */
    err |= as3911WriteRegister(AS3911_REG_FIELD_THRESHOLD, nfcSavedSettings.regFieldThreshold);
    err |= as3911WriteRegister(AS3911_REG_RX_CONF3, nfcSavedSettings.regRxConf3);
    err |= as3911WriteRegister(AS3911_REG_GPT_CONTROL, 0);

    /* Turn off reader field. */
    err |= as3911ModifyRegister(AS3911_REG_OP_CONTROL, AS3911_REG_OP_CONTROL_tx_en, 0);

    if (ERR_NONE != err)
        return ERR_IO;
    else
        return ERR_NONE;
}
Exemplo n.º 6
0
s8 nfcRxNBytes(u8 *buf, u8 bufsize, u8 *actlen)
{
    NFC_DEBUG("nfcRxNBytes( .bufSize=%hhx)\n");
    *actlen = 0;
    
    if (NFC_TASK_RX_DONE == nfcTaskStatus)
    {
        *actlen = nfcRxBufferInPtr - nfcRxBuffer - 2;
        memcpy(buf, nfcRxBuffer, *actlen);
        return nfcRxError;
    }

    return ERR_BUSY;
}
Exemplo n.º 7
0
static ssize_t pn544_dev_write(struct file *filp, const char __user *buf,
                               size_t count, loff_t *offset)
{
    struct pn544_dev  *pn544_dev;
    char tmp[MAX_BUFFER_SIZE];
    int ret;
    int calc =  0;

    pn544_dev = filp->private_data;

    if (count > MAX_BUFFER_SIZE)
        count = MAX_BUFFER_SIZE;

    if (copy_from_user(tmp, buf, count)) {
        pr_err("%s : failed to copy from user space\n", __func__);
        return -EFAULT;
    }

    NFC_DEBUG("%s : writing %zu bytes.\n", __func__, count);
    /* Write data */
    while(calc <3)
    {
        calc ++;
        ret = i2c_master_send(pn544_dev->client, tmp, count);
        if (ret != count)
        {
            pr_info("%s : send data try =%d returned %d\n", __func__,calc,ret);
            msleep(10);
            continue;
        }
        else
            break;
    }

    if (calc ==3) {
        pr_err("%s : i2c_master_send returned %d\n", __func__, ret);
        ret = -EIO;
    }

    return ret;
}
Exemplo n.º 8
0
s8 nfcSwitchToRx(u8 perform_collision_avoidance)
{
    u8 err = ERR_NONE;
    NFC_DEBUG("nfcSwitchToRx()");
    
    if (!(NFC_TASK_RX_DONE == nfcTaskStatus))
        return ERR_IO;
    
    /* Setup NRT timer for rf response RF collision timeout. */
    err |= as3911WriteRegister(AS3911_REG_NO_RESPONSE_TIMER1, RESPONSE_RFCA_NRT1);
    err |= as3911WriteRegister(AS3911_REG_NO_RESPONSE_TIMER2, RESPONSE_RFCA_NRT2);

    /* Prepare data reception. */
    nfcPerformResponseCa = perform_collision_avoidance;
    as3911PrepareReceive(TRUE);
    
    /* Enter low power bitrate detection mode. */
    err |= as3911WriteRegister(AS3911_REG_MODE, 0x80);

    /* Start the NRE timer. */
    err |= as3911ExecuteCommand(AS3911_CMD_START_NO_RESPONSE_TIMER);

    /* Disable the RF field manually. */
    err |= as3911ModifyRegister(AS3911_REG_OP_CONTROL, AS3911_REG_OP_CONTROL_tx_en, 0);
    
    nfcRxBufferInPtr = nfcRxBuffer;
    nfcTaskStatus = NFC_TASK_WAIT_FOR_EON;
    
    while (nfcTaskStatus != NFC_TASK_RX_DONE)
        err |= nfcReceptionTask();
    
    if (ERR_NONE != err)
        return ERR_IO;
    else
        return ERR_NONE;
}
Exemplo n.º 9
0
static ssize_t pn544_dev_read(struct file *filp, char __user *buf,
                              size_t count, loff_t *offset)
{
    struct pn544_dev *pn544_dev = filp->private_data;
    char tmp[MAX_BUFFER_SIZE];
    int ret, i;
    int calc =  0;

    if (count > MAX_BUFFER_SIZE)
        count = MAX_BUFFER_SIZE;

    NFC_DEBUG("%s : reading %zu bytes.\n", __func__, count);

    mutex_lock(&pn544_dev->read_mutex);

    wake_lock_timeout(&wlock_read, 1 * HZ);
    NFC_DEBUG("%s : start to gpio_get_value with got value: %d\n",
              __func__, gpio_get_value(pn544_dev->irq_gpio));
    if (!gpio_get_value(pn544_dev->irq_gpio)) {
        if (filp->f_flags & O_NONBLOCK) {
            NFC_DEBUG("flip->f_flags=%u\n",filp->f_flags);
            ret = -EAGAIN;
            goto fail;
        }

        pn544_dev->irq_enabled = true;
        NFC_DEBUG("%s : start to enable_irq.\n", __func__);
        enable_irq(pn544_dev->client->irq);
        NFC_DEBUG("%s : start to wait_event_interruptible.\n", __func__);
        ret = wait_event_interruptible(pn544_dev->read_wq,
                                       gpio_get_value(pn544_dev->irq_gpio));
        NFC_DEBUG("%s : end to pn544_disable_irq, with ret: %d.\n", __func__, ret);

        pn544_disable_irq(pn544_dev);

        if (ret)
            goto fail;

    }

    NFC_DEBUG("%s : start to i2c_master_recv.\n", __func__);

    /* Read data */
    while(calc <3)
    {
        calc ++;
        ret = i2c_master_recv(pn544_dev->client, tmp, count);
        if (ret < 0)
        {
            pr_info("%s : read data try =%d returned %d\n", __func__,calc,ret);
            msleep(10);
            continue;
        }
        else
            break;
    }

    if (calc ==3) {
        pr_err("%s : i2c_master_recv returned %d\n", __func__, ret);
        ret = -EIO;
    }

    mutex_unlock(&pn544_dev->read_mutex);

    NFC_DEBUG("%s : end to i2c_master_recv, with the ret: %d.\n", __func__, ret);

    for(i=0; i<count; i++)
    {
        NFC_DEBUG("%s : read %x.\n", __func__, tmp[i]);
    }

    if (ret < 0) {
        pr_err("%s: i2c_master_recv returned %d\n", __func__, ret);
        return ret;
    }
    if (ret > count) {
        pr_err("%s: received too many bytes from i2c (%d)\n",
               __func__, ret);
        return -EIO;
    }
    if (copy_to_user(buf, tmp, ret)) {
        pr_err("%s : failed to copy to user space\n", __func__);
        return -EFAULT;
    }

    return ret;

fail:
    mutex_unlock(&pn544_dev->read_mutex);

    return ret;
}
Exemplo n.º 10
0
static int check_pn544(struct i2c_client *client)
{
    int ret;
    int count =  0;
    int calc = 0;
    int check_pn544_result = 0;
    const char host_to_pn544[8] = {0x05, 0xF9, 0x04, 0x00, 0xC3, 0xe5};
    const char check_from_pn544[8] = {0x03,0xE6,0x17,0xA7};
    char pn544_to_host[8];
    const char cmd_fwdld_first[4] = {0x01, 0x00, 0x00};

    struct pn544_i2c_platform_data *platform_data;
    platform_data = client->dev.platform_data;

    NFC_DEBUG("------enter check pn544-----\n");
    for(count = 0; count < 3; count++)
    {
        ret = i2c_master_send(client,  &host_to_pn544, 6);

        NFC_DEBUG("%s:enter pn544 I2C\n", __func__);

        if (ret < 0)
        {
            pr_err("%s:pn544_i2c_write failed\n", __func__);
            msleep(10);
            continue;
        }
        pr_err("pn544_i2c_write: %x, %x, %x, %x, %x, %x \n", host_to_pn544[0],host_to_pn544[1],
               host_to_pn544[2],host_to_pn544[3],host_to_pn544[4],host_to_pn544[5]);

        ret =  i2c_master_recv(client, &pn544_to_host, 4);

        if (ret < 0)
        {
            pr_err("%s:pn544_i2c_read failed\n", __func__);
            msleep(10);
            continue;
        }

        pr_err("pn544_i2c_read: %x,%x,%x,%x \n", pn544_to_host[0],pn544_to_host[1],
               pn544_to_host[2],pn544_to_host[3]);

        if(!((pn544_to_host[0]== check_from_pn544[0])&&(pn544_to_host[1]== check_from_pn544[1])
                &&(pn544_to_host[2]== check_from_pn544[2])&&(pn544_to_host[3]== check_from_pn544[3])))
        {
            pr_err("%s : pn544 device check failed.\n", __func__);
            msleep(10);
            ret = -ENODEV;
            continue;
        }
        check_pn544_result = 1;
        break;
    }

    if ((1 == check_pn544_result) ||(pn544_to_host[0] == 0x51))
    {
        pr_err("%s, pn544 check successfully.\n", __func__);
        ret = 0;
        goto exit;
    }

    for(calc = 0; calc < 3; calc++)
    {
        pr_info("%s:enter fw download mode\n", __func__);
        gpio_set_value(platform_data->ven_gpio, 1);
        gpio_set_value(platform_data->firm_gpio, 1);
        msleep(20);
        gpio_set_value(platform_data->ven_gpio, 0);
        msleep(60);
        gpio_set_value(platform_data->ven_gpio, 1);
        msleep(20);

        pr_info("%s:send fw download cmd for check pn544\n", __func__);

        ret = i2c_master_send(client,  &cmd_fwdld_first, 3);
        if (ret < 0)
        {
            pr_err("%s:pn544_i2c_write download cmd failed:%d.\n", __func__,calc);
            continue;
        }
        pr_info("%s:exit firmware download for check pn544 successfully\n", __func__);
        gpio_set_value(platform_data->firm_gpio, 0);
        gpio_set_value(platform_data->ven_gpio, 1);
        msleep(20);
        gpio_set_value(platform_data->ven_gpio, 0);
        msleep(60);
        gpio_set_value(platform_data->ven_gpio, 1);
        msleep(20);
        break;

    }

exit:
    return ret;

}
Exemplo n.º 11
0
s8 nfcReceptionTask()
{
    s8 err = ERR_NONE;
    u32 irqs = 0;
    
    if (NFC_TASK_INACTIVE == nfcTaskStatus)
        return ERR_NONE;
        
    irqs = as3911GetInterrupt(AS3911_IRQ_MASK_RXS | AS3911_IRQ_MASK_RXE | AS3911_IRQ_MASK_FWL | AS3911_IRQ_MASK_NRE | AS3911_IRQ_MASK_NFCT | AS3911_IRQ_MASK_EON | AS3911_IRQ_MASK_EOF);
    
    if (AS3911_IRQ_MASK_EON & irqs)
    {
        if (NFC_TASK_WAIT_FOR_EON == nfcTaskStatus)
        {
            if (nfcLowPowerMode)
            {
                nfcLowPowerMode = FALSE;
                /* Clear oscillator on interrupt flag. */
                u32 oscIrqs = as3911GetInterrupt(AS3911_IRQ_MASK_OSC);
                as3911EnableInterrupts(AS3911_IRQ_MASK_OSC);
                
                err |= as3911ModifyRegister(AS3911_REG_OP_CONTROL,
                    AS3911_REG_OP_CONTROL_en | AS3911_REG_OP_CONTROL_rx_en | AS3911_REG_OP_CONTROL_tx_en,
                    AS3911_REG_OP_CONTROL_en | AS3911_REG_OP_CONTROL_rx_en);
                
                /* Wait for oscillators to start. */
                oscIrqs = as3911WaitForInterruptsTimed(AS3911_IRQ_MASK_OSC, NFC_OSC_IRQ_TIMEOUT);
                as3911DisableInterrupts(AS3911_IRQ_MASK_OSC);
                
                if (0 == oscIrqs)
                {
                    NFC_DEBUG("NFC_OSC_IRQ_TIMEOUT expired\n");
                    return ERR_INTERNAL;
                }
                
                /* Switch to normal target mode. */
                // err |= as3911WriteRegister(AS3911_REG_MODE, 0x88);
            }
            
            err |= as3911ExecuteCommand(AS3911_CMD_UNMASK_RECEIVE_DATA);
            
            /* The no response timer is stopped on an EON event. We therefore
            * restart the timer to be able to use it as a message timeout timer.
            * In addition to its NFC-P2P mode default usage as an external field on
            * timeout timer.
            */
            err |= as3911WriteRegister(AS3911_REG_NO_RESPONSE_TIMER1, TIMEOUT_NRT1);
            err |= as3911WriteRegister(AS3911_REG_NO_RESPONSE_TIMER2, TIMEOUT_NRT2);
            err |= as3911ExecuteCommand(AS3911_CMD_START_NO_RESPONSE_TIMER);
            
            nfcTaskStatus = NFC_TASK_WAIT_FOR_RXS;
        }
    }
    if (AS3911_IRQ_MASK_RXS & irqs)
    {
        nfcRxBufferInPtr = nfcRxBuffer;
        nfcTaskStatus = NFC_TASK_RX_IN_PROGRESS;
    }
    if (AS3911_IRQ_MASK_FWL & irqs)
    {
        err |= as3911ReadFifo(nfcRxBufferInPtr, NFC_FIFO_READ_SIZE);
        nfcRxBufferInPtr += NFC_FIFO_READ_SIZE;
    }
    if (AS3911_IRQ_MASK_RXE & irqs)
    {
        /* Reading the FIFO is postponed until the response collision avoidance has been performed. */
        nfcTaskStatus = NFC_TASK_WAIT_FOR_EOF;
    }
    if (AS3911_IRQ_MASK_NFCT & irqs)
    {
        nfcBitrateDetected = TRUE;
    }
    if (AS3911_IRQ_MASK_NRE & irqs)
    {
        if (  (NFC_TASK_WAIT_FOR_EON == nfcTaskStatus)
           || (NFC_TASK_WAIT_FOR_RXS == nfcTaskStatus))
        {
            nfcTaskStatus = NFC_TASK_RX_DONE;
            nfcRxError = ERR_TIMEOUT;
        }
    }
    if (AS3911_IRQ_MASK_EOF & irqs)
    {
        /* A bitrate detection event can only happen when we are in the bitrate
         * detection target mode. Thus, if such an event has happened during the
         * reception (the irq happens shortly after the RxS irq) we need to switch
         * back to normal nfc mode.
         */
        if (  (NFC_TASK_WAIT_FOR_EOF == nfcTaskStatus)
           && nfcBitrateDetected)
        {
            err |= as3911ExecuteCommand(AS3911_CMD_NORMAL_NFC_MODE);
        }
        nfcBitrateDetected = FALSE;
        
        if (  (NFC_TASK_WAIT_FOR_EOF == nfcTaskStatus)
           && nfcPerformResponseCa)
        {
            nfcPerformResponseCa = FALSE;
        
            err |= as3911EnableInterrupts(AS3911_IRQ_MASK_CAC | AS3911_IRQ_MASK_CAT);
            err |= as3911ExecuteCommand(AS3911_CMD_RESPONSE_RF_COLLISION_0);
            irqs = as3911WaitForInterruptsTimed(AS3911_IRQ_MASK_CAC | AS3911_IRQ_MASK_CAT, NFC_RFCA_IRQ_TIMEOUT);
            err |= as3911DisableInterrupts(AS3911_IRQ_MASK_CAC | AS3911_IRQ_MASK_CAT);
        
            if (0 == irqs)
            {
                NFC_DEBUG("NFC_RFCA_IRQ_TIMEOUT expired\n");
                nfcTaskStatus = NFC_TASK_RX_DONE;
                nfcRxError = ERR_INTERNAL;
            }
            else if (AS3911_IRQ_MASK_CAC & irqs)
            {
                nfcTaskStatus = NFC_TASK_RX_DONE;
                nfcRxError = ERR_RF_COLLISION;
            }
        }
        
        if (  (NFC_TASK_WAIT_FOR_RXS == nfcTaskStatus)
           || (NFC_TASK_RX_IN_PROGRESS == nfcTaskStatus))
        {
            nfcTaskStatus = NFC_TASK_RX_DONE;
            nfcRxError = ERR_TIMEOUT;
        }
        
        if (NFC_TASK_WAIT_FOR_EOF == nfcTaskStatus)
        {
            u8 fifoReadSize;
             
            err |= as3911ReadRegister(AS3911_REG_FIFO_RX_STATUS1, &fifoReadSize);
            as3911ReadFifo(nfcRxBufferInPtr, fifoReadSize);
            nfcRxBufferInPtr += fifoReadSize;
            nfcTaskStatus = NFC_TASK_RX_DONE;
            
            irqs = as3911GetInterrupt(AS3911_IRQ_MASK_CRC | AS3911_IRQ_MASK_PAR | AS3911_IRQ_MASK_ERR2 | AS3911_IRQ_MASK_ERR1);
            if (irqs & AS3911_IRQ_MASK_CRC)
                nfcRxError = ERR_CRC;
            else if (irqs & AS3911_IRQ_MASK_PAR)
                nfcRxError = ERR_PAR;
            else if ((irqs & AS3911_IRQ_MASK_ERR1) || (irqs & AS3911_IRQ_MASK_ERR2))
                nfcRxError = ERR_FRAMING;
            else if (0 != irqs)
                nfcRxError = ERR_FRAMING;
            else
            nfcRxError = ERR_NONE;

            
            /* Stop NRE timer via a clear fifo cmd. */
            as3911ExecuteCommand(AS3911_CMD_CLEAR_FIFO);
        
            /* Clear pending NRE timer events. */
            as3911GetInterrupt(AS3911_IRQ_MASK_NRE);
            irqs &= ~AS3911_IRQ_MASK_NRE;
        }
    }
    
    if (ERR_NONE != err)
        return ERR_IO;
    else
        return ERR_NONE;
}
Exemplo n.º 12
0
s8 nfcInitialize(u8 is_active, u8 is_initiator, u8 bitrate)
{
    s8 err = ERR_NONE;
    u8 regOpControl = 0;
    
    NFC_DEBUG("nfcInitialize(.is_active=%hhx,.is_initiator=%hhx,.bitrate=%hhx)\n",
            is_active, is_initiator, bitrate);
            
    /* Passive mode is currently not supported by this NFC module. */
    if (!is_active)
        return ERR_PARAM;
            
    err |= as3911ReadRegister(AS3911_REG_OP_CONTROL, &regOpControl);
    if (!(AS3911_REG_OP_CONTROL_en & regOpControl))
    {
        u32 oscIrqs = as3911GetInterrupt(AS3911_IRQ_MASK_OSC);
        as3911EnableInterrupts(AS3911_IRQ_MASK_OSC);
        
        err |= as3911ModifyRegister(AS3911_REG_OP_CONTROL,
            AS3911_REG_OP_CONTROL_en | AS3911_REG_OP_CONTROL_rx_en | AS3911_REG_OP_CONTROL_tx_en,
            AS3911_REG_OP_CONTROL_en | AS3911_REG_OP_CONTROL_rx_en);
                
        /* Wait for oscillators to start. */
        oscIrqs = as3911WaitForInterruptsTimed(AS3911_IRQ_MASK_OSC, NFC_OSC_IRQ_TIMEOUT);
        as3911DisableInterrupts(AS3911_IRQ_MASK_OSC);
                
        if (0 == oscIrqs)
        {
            NFC_DEBUG("NFC_OSC_IRQ_TIMEOUT expired\n");
            return ERR_INTERNAL;
        }
    }

    /* Stop ongoing operations. */
    err |= as3911ExecuteCommand(AS3911_CMD_CLEAR_FIFO);

    /* Enable receiver, turn off RF field. */
    err |= as3911ModifyRegister(
            AS3911_REG_OP_CONTROL,
            AS3911_REG_OP_CONTROL_rx_en | AS3911_REG_OP_CONTROL_tx_en,
            AS3911_REG_OP_CONTROL_rx_en);
    
    if (is_initiator)
        /* NFCIP1 active communication initiator mode. */
        err |= as3911WriteRegister(AS3911_REG_MODE, 0x00);
    else
        /* NFCIP1 active communication fixed bitrate target mode. */
        err |= as3911WriteRegister(AS3911_REG_MODE, 0x88);
        
    /* Peer detection threshold: 105mV
     * Collision Avoidance Threshold: 105mV
     */
    err |= as3911ReadRegister(AS3911_REG_FIELD_THRESHOLD, &nfcSavedSettings.regFieldThreshold);
    err |= as3911WriteRegister(AS3911_REG_FIELD_THRESHOLD, 0x11);
    /* Silicon v2 bug: we have to always receive crc bytes */
    err |= as3911ModifyRegister(AS3911_REG_AUX, AS3911_REG_AUX_crc_2_fifo, AS3911_REG_AUX_crc_2_fifo);
        
    /* Start the GPT after end of TX, EMV no response timer mode, no response timer set in 4096 fc intervalls. */
    err |= as3911WriteRegister(AS3911_REG_GPT_CONTROL, 0x63);
    /* The field is turned off 37.76µs after the end of the transmission. */
    err |= as3911WriteRegister(AS3911_REG_GPT1, 0x00);
    err |= as3911WriteRegister(AS3911_REG_GPT2, 0x40);

    /* Mask receive timer. */
    err |= as3911WriteRegister(AS3911_REG_MASK_RX_TIMER, 0x01);
        
    /* Reduce first stage gain for 106 kBit/s bitrate.
     */
    err |= as3911ReadRegister(AS3911_REG_RX_CONF3, &nfcSavedSettings.regRxConf3);
    if (0x00 == bitrate)
        err |= as3911ModifyRegister(AS3911_REG_RX_CONF3, 0xE0, 0xC0);
    else
        err |= as3911ModifyRegister(AS3911_REG_RX_CONF3, 0xE0, 0x00);
        
    if (bitrate > 0x02)
        return ERR_PARAM;
    err |= as3911SetBitrate(bitrate,bitrate);
    
    if (bitrate > 0x00)
    {
        /* Set to 25% AM modulation.
		 * modulation index: 25%
		 * a/b = 1.66666666
		 * a/b = b1.101010
		 */
        err |= as3911WriteRegister(AS3911_REG_AM_MOD_DEPTH_CONTROL, 0x54);
		err |= as3911CalibrateModulationDepth(NULL);
    }
    
    err |= as3911WriteRegister(AS3911_REG_NO_RESPONSE_TIMER1, TIMEOUT_NRT1);
    err |= as3911WriteRegister(AS3911_REG_NO_RESPONSE_TIMER2, TIMEOUT_NRT2);

    err |= as3911ClearInterrupts();
    err |= as3911EnableInterrupts(AS3911_IRQ_MASK_RXS | AS3911_IRQ_MASK_RXE | AS3911_IRQ_MASK_FWL | AS3911_IRQ_MASK_NRE | AS3911_IRQ_MASK_NFCT | AS3911_IRQ_MASK_EOF | AS3911_IRQ_MASK_EON | AS3911_IRQ_MASK_CRC | AS3911_IRQ_MASK_PAR | AS3911_IRQ_MASK_ERR2 | AS3911_IRQ_MASK_ERR1);

    if (is_initiator)
    {
        nfcTaskStatus = NFC_TASK_TRANSMITTING;
        nfcBitrateDetected = FALSE;
        nfcLowPowerMode = FALSE;
        nfcPerformResponseCa = FALSE;
        nfcRxBufferInPtr = nfcRxBuffer;
        nfcRxError = ERR_NONE;
    }
    else
    {
        nfcTaskStatus = NFC_TASK_INACTIVE;
        nfcBitrateDetected = FALSE;
        nfcLowPowerMode = FALSE;
        nfcPerformResponseCa = FALSE;
        nfcRxBufferInPtr = nfcRxBuffer;
        nfcRxError = ERR_NONE;
    }

    if (ERR_NONE != err)
        return ERR_IO;
    else
        return ERR_NONE;
}