svvitale / nxppy

Python wrapper for interfacing with the NXP EXPLORE-NFC shield for Raspberry Pi
MIT License
99 stars 34 forks source link

bug in nxp lib? #76

Open iceman1001 opened 6 years ago

iceman1001 commented 6 years ago

Please answer these questions as part of your new issue.

Which version of Python are you using?

v2.7

Which OS and version are you running?

PI

Is SPI enabled?

yes

Are you trying to read/write a Mifare Classic card? (This is currently unsupported)

no

There seems to be a bug in the NxpLib.

https://github.com/JohnMcLear/NXP-Raspberry-Pi-Card-Polling-Demo/blob/master/source/NxpRdLib_PublicRelease/comps/phbalReg/src/R_Pi_spi/phbalReg_R_Pi_spi.c#L319

The source here, seems to be using the same buffer TX and RX

spi.tx_buf = (unsigned long)pTxBuffer ; spi.rx_buf = (unsigned long)pTxBuffer ;

-- gdb trace.

Thread 1 "python" received signal SIGSEGV, Segmentation fault. 0x76aa47e8 in phbalReg_Stub_Exchange () from /home/pi/.local/lib/python2.7/site-packages/nxppy.so (gdb) bt

0 0x76aa47e8 in phbalReg_Stub_Exchange ()

from /home/pi/.local/lib/python2.7/site-packages/nxppy.so

1 0x76a9127c in phhalHw_Rc523_ReadRegister ()

from /home/pi/.local/lib/python2.7/site-packages/nxppy.so

2 0x76a8e2e0 in phhalHw_Rc523_FieldOff ()

from /home/pi/.local/lib/python2.7/site-packages/nxppy.so

3 0x76a7fad0 in Mifare_select (self=0x3d7368) at Mifare.c:289

4 0x0008be70 in PyEval_EvalFrameEx ()

5 0x00084494 in PyEval_EvalCodeEx ()

6 0x0008c8dc in PyEval_EvalFrameEx ()

7 0x0008c7d0 in PyEval_EvalFrameEx ()

8 0x0008c7d0 in PyEval_EvalFrameEx ()

9 0x00084494 in PyEval_EvalCodeEx ()

10 0x000841f8 in PyEval_EvalCode ()

11 0x000bd8b8 in ?? ()

Backtrace stopped: previous frame identical to this frame (corrupt stack?)

svvitale commented 6 years ago

@michaelneurohr, can you verify? I agree with @iceman1001 that this line looks fishy.

iceman1001 commented 6 years ago

Forget my link to JohnMcLer, that was me trying to find the method via google. Instead I extracted the source for NFC-Reader-Library-4.010-2.deb package.

phStatus_t phbalReg_Stub_Exchange(
                                  phbalReg_Stub_DataParams_t * pDataParams,
                                  uint16_t wOption,
                                  uint8_t * pTxBuffer,
                                  uint16_t wTxLength,
                                  uint16_t wRxBufSize,
                                  uint8_t * pRxBuffer,
                                  uint16_t * pRxLength
                                  )
{
    int ret = 0;
    size_t pos = 0;
    if( (pDataParams->bMultiRegRW == PH_ON) && ( pDataParams->wHalType != PHBAL_REG_HAL_HW_PN5180 ) )
    {
        //"Fast" bundled exchange for EMVCo compatibility -- only necessary for PN512/RC663 derivatives
        if( wTxLength < 1 )
        {
            return PH_ADD_COMPCODE(PH_ERR_INVALID_PARAMETER, PH_COMP_BAL);
        }
        if( ((pDataParams->wHalType == PHBAL_REG_HAL_HW_RC663)
                && ( (pTxBuffer[0] & 0x01) == 0x01 ))
            ||  ((pDataParams->wHalType == PHBAL_REG_HAL_HW_RC523)
                    && ( (pTxBuffer[0] & 0x80) == 0x80 )) )
        {
            //Perform a "MultiRegRead" exchange
            //This is a read operation
            ret = spi_transfer(pTxBuffer, pRxBuffer, wTxLength);
            if(ret)
            {
                return PH_ADD_COMPCODE(PH_ERR_INTERFACE_ERROR, PH_COMP_BAL);
            }

            if( pRxLength != NULL )
            {
                *pRxLength = wTxLength;
            }

            return PH_ERR_SUCCESS;
        }
        else if( (pDataParams->wHalType == PHBAL_REG_HAL_HW_RC663)
                && ( (pTxBuffer[0] & 0x01) == 0x00 ) )
        {
            //Perform a "MultiRegWrite" exchange
            if( (wTxLength % 2) != 0 )
            {
                return PH_ADD_COMPCODE(PH_ERR_INVALID_PARAMETER, PH_COMP_BAL);
            }

            while( pos < wTxLength )
            {
                ret = spi_transfer(pTxBuffer, NULL, 2);
                if(ret)
                {
                    return PH_ADD_COMPCODE(PH_ERR_INTERFACE_ERROR, PH_COMP_BAL);
                }

                pTxBuffer += 2;
                pos += 2;
            }

            if( pRxLength != NULL )
            {
                *pRxLength = 0;
            }

            return PH_ERR_SUCCESS;
        }
    }

    //Standard exchange
    if( pDataParams->wHalType == PHBAL_REG_HAL_HW_PN5180 )
    {
        //If PN5180, wait for busy line to be released
        ret = wait_not_busy();
        if(ret)
        {
            return PH_ADD_COMPCODE(PH_ERR_INTERNAL_ERROR, PH_COMP_BAL);
        }

        //Transmit first
        ret = spi_transfer(pTxBuffer, NULL, wTxLength);
        if(ret)
        {
            return PH_ADD_COMPCODE(PH_ERR_INTERFACE_ERROR, PH_COMP_BAL);
        }

        //Receive response
        if( pRxBuffer != NULL )
        {
            //Wait again
            ret = wait_not_busy();
            if(ret)
            {
                return PH_ADD_COMPCODE(PH_ERR_INTERNAL_ERROR, PH_COMP_BAL);
            }

            ret = spi_transfer(NULL, pRxBuffer, wRxBufSize);
            if(ret)
            {
                return PH_ADD_COMPCODE(PH_ERR_INTERFACE_ERROR, PH_COMP_BAL);
            }

            if( pRxLength != NULL )
            {
                *pRxLength = wRxBufSize;
            }
        }
    }
    else
    {
        //Transfer everything at once
        ret = spi_transfer(pTxBuffer, pRxBuffer, wTxLength);
        if(ret)
        {
            return PH_ADD_COMPCODE(PH_ERR_INTERFACE_ERROR, PH_COMP_BAL);
        }

        if( pRxLength != NULL )
        {
            *pRxLength = wTxLength;
        }
    }

    return PH_ERR_SUCCESS;
}
iceman1001 commented 6 years ago

The bug is triggered in my stress tests, when sending a select/write sequence in a loop with a sleep 1sec each iteration. It takes around 240-320 times before triggered. If the loop has a sleep for two seconds or more the loop can run to 3000 times at least.
Could it be spi transfer being called too fast?