⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spi.cpp

📁 一个基于windows mobile 的GPS 接受IC 驱动程序。
💻 CPP
📖 第 1 页 / 共 4 页
字号:

//-----------------------------------------------------------------------------
//
//                  SPI_Deinit()
//
//  Set the GPIO to the lowest GPS  power level.
//  Set the GPIO to the lowest GPIO power level.
//  Set the SPI  to the lowest SPI  power level.
//  Deinit the ring buffers.
//  Deinit access to the ISR.
//  Deinit access to the hardware.
//
//-----------------------------------------------------------------------------

SPI_EXPORT BOOL
SPI_Deinit(DWORD hDeviceContext)
{
    GL_PRINT((MSG("SPI_Deinit(0x%x)/%d\n\r"),hDeviceContext,__LINE__));
    SPI_DEVICE_CONTEXT* pDev = getSpiDeviceContext(hDeviceContext);

    // Deinit the Isr
    SuspendThread(pDev->mIsrHandle);
    TerminateThread(pDev->mIsrHandle,0);

    // TODO:  do we need to CloseHandle() these???
    pDev->mIsrHandle = INVALID_HANDLE_VALUE;
    pDev->mhRxDone   = INVALID_HANDLE_VALUE;

	if (pDev->v_pGPIORegs) 
	{
		pDev->v_pGPIORegs = NULL;
	}
	if (pDev->v_pSPIRegs) 
	{
		pDev->v_pSPIRegs = NULL;
	}
	if (pDev->v_pClockRegs) 
	{
        pDev->v_pClockRegs->cken &= ~XLLP_CLKEN_SSP3;
		pDev->v_pClockRegs = NULL;
	}
	free(pDev);
    GL_PRINT((MSG("SPI_Deinit()/%d\n\r"),__LINE__));
	return TRUE;			
}

//-----------------------------------------------------------------------------
//
//                  SPI_Open()
//
//  Flush the ring buffers.
//  Don't touch GPIO.
//  Allow writing and reading.
//  Enable the interrupt.
//
//-----------------------------------------------------------------------------

SPI_EXPORT DWORD
SPI_Open(DWORD hDeviceContext, DWORD AccessCode, DWORD ShareMode)
{
    // GL_PRINT((TEXT("SPI_Open()/%d %s\n\r"), __LINE__, t_driverLabel));

    GL_ERROR((TEXT("SPI_Open()/%d %s\n\r"),
                                __LINE__, t_driverLabel));

    SPI_DEVICE_CONTEXT* pDev = getSpiDeviceContext(hDeviceContext);
    pDev->mbSignaledPower    = false;
    pDev->mbClosed           = false;
    spiDevClosed             = false;
    // clockSsp3Enable();               // TODO - add protection.

    ResumeThread(pDev->mIsrHandle);
    traceResume();
    pDev->closeTime_ = 0;
    pDev->openTime_  = *pGpsTimer;
    return (DWORD)pDev;
}

//-----------------------------------------------------------------------------
//
//                  SPI_Close()
//
//  Flush the ring buffers.
//
//-----------------------------------------------------------------------------

SPI_EXPORT BOOL
SPI_Close(DWORD hOpenContext)
{
    // Use GL_PRINT when testing with SPI_TEST.
    GL_PRINT((TEXT("SPI_Close()/%d %s\n\r"), __LINE__, t_driverLabel));

    // Use GL_ERROR normally.
    GL_ERROR((TEXT("SPI_Close()/%d %s\n\r"),
                                __LINE__, t_driverLabel));

    SPI_DEVICE_CONTEXT* pDev = getSpiDeviceContext(hOpenContext);
    SuspendThread(pDev->mIsrHandle);
    // clockSsp3Disable();              // TODO - add protection.
    if (!pDev->closeTime_)
    {
        pDev->closeTime_ = *pGpsTimer;
    }
    traceStats(pDev->closeTime_ - pDev->openTime_);
    return TRUE;
}

//-----------------------------------------------------------------------------
//
//                  SPI_PowerUp()
//
//-----------------------------------------------------------------------------

SPI_EXPORT void
SPI_PowerUp(DWORD hDeviceContext)
{
    GL_ERROR((TEXT("SPI_PowerUp()/%d\n\r"),__LINE__));
    sspConfig();
}

//-----------------------------------------------------------------------------
//
//                  SPI_PowerDown()
//
//  Flush the ring buffers.
//	Send the shut-down sequence to the GPS device.
//  Ignore all subsequent write calls.
//  Return error ERROR_PWR_INT upon reads.
//  Disable the interrupt.
//  Touch GPIO - set it to the lowest power consumption state.
//
//-----------------------------------------------------------------------------

SPI_EXPORT void
SPI_PowerDown(DWORD hDeviceContext)
{
    SPI_DEVICE_CONTEXT* pDev = getSpiDeviceContext(hDeviceContext);

    if (!pDev->closeTime_)
    {
        pDev->closeTime_ = *pGpsTimer;
    }
    GPS_GPIO_CONTROL control;
    control.value = 0;

#ifdef  GPS_GPIO_STANDBY_EXISTS         // {
    // Clear nSTANDBY/POWERON to cause Mantaray/Hammerhead to go into
    // low power standby mode.
    control.id    = GPS_GPIO_STANDBY;
    SPI_IOControl(hDeviceContext, GPS_IOCTL_CHIPSET_CONTROL,
                    reinterpret_cast<const PBYTE> (&control), sizeof(control),
                    0,0,0);
#endif // }  GPS_GPIO_STANDBY_EXISTS

#ifdef  GPS_GPIO_POWER_EXISTS         // {
    // Clear POWER to turn off Mantaray/Hammerhead VDD_CORE power supply.
    control.id    = GPS_GPIO_POWER;
    SPI_IOControl(hDeviceContext, GPS_IOCTL_CHIPSET_CONTROL,
                    reinterpret_cast<const PBYTE> (&control), sizeof(control),
                    0,0,0);
#endif // }  GPS_GPIO_POWER_EXISTS

    rb__RingBufferInit();
    pDev->mbClosed = true;
    spiDevClosed   = true;

    GL_ERROR((TEXT("SPI_PowerDown()/%d\n\r"),__LINE__));
}

//-----------------------------------------------------------------------------
//
//                  SPI_Read()
//
//  Read data from the queue.
//  If we had a power-down/up, then return ERROR_PWR_INT.
//
//-----------------------------------------------------------------------------

SPI_EXPORT DWORD
SPI_Read(DWORD hOpenContext, LPVOID pBuf, DWORD Count)
{
    DWORD startTime = *pGpsTimer;
    SPI_DEVICE_CONTEXT* pSpi = getSpiDeviceContext(hOpenContext);

    GL_PRINT((MSG("SPI_Read(%d)/%d  %d  %d {\n\r"),
                             Count,__LINE__,pSpi->mbClosed,pSpi->mbIsrAllow));
    if (pSpi->mbClosed)
    {
        GL_ERROR((TEXT("SPI_Read()/%d Signal Power %d\n\r"),
                                            __LINE__, pSpi->mbSignaledPower));
        if (!pSpi->mbSignaledPower)
        {
            // This code to send the error result only once isn't needed:
            pSpi->mbSignaledPower = true;

            // For safety, always return the power interrupted error code
            // until the next close/open cycle.
        }
        SetLastError(ERROR_PWRINT);
        return -1;
    }
    if (!pBuf /*|| !IsBadWritePtr(pBuf, Count)*/)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return -1;
    }

    // SuspendThread(pSpi->mIsrHandle);

    SetLastError(0);
#if 1
    DWORD result = rb__Dequeue((UINT8 *)pBuf, Count);
#else
    DWORD result = 0;

    for (int tries = 2; tries > 0; --tries)
    {
        if (!rb_TestRead())
        {
            Sleep(10);
            continue;
        }

        result = rb__Dequeue((UINT8 *)pBuf, Count);
        if (result) break;
    }
#endif
    // ResumeThread(pSpi->mIsrHandle);

    GL_PRINT((MSG("} SPI_Read()/%d %d\n\r"),__LINE__, result));

    STATS_READ(static_cast<unsigned short> (result),*pGpsTimer - startTime);
    return result;
}

//-----------------------------------------------------------------------------
//
//                  SPI_Write()
//
//  Write data into the queue.
//  If we had a power-down/up - ignore the write quietly.
//
//-----------------------------------------------------------------------------

SPI_EXPORT DWORD
SPI_Write(DWORD hOpenContext, LPCVOID pBuf, DWORD Count)
{
    DWORD startTime = *pGpsTimer;
    GL_PRINT((MSG("SPI_Write(%d)/%d {\n\r"), Count, __LINE__));

    SPI_DEVICE_CONTEXT* pSpi = getSpiDeviceContext(hOpenContext);
    SetLastError(0);
    if (pSpi->mbClosed)
    {
        GL_PRINT((MSG("SPI_Write()/%d\n\r"),__LINE__));
        return Count;           // Quietly ignore all writes.
    }

    if (!pBuf) //  || IsBadReadPtr(pBuf, Count))
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return -1;
    }

	// SuspendThread(pSpi->mIsrHandle);
    DWORD result = rb__Enqueue((const UINT8 *)pBuf, Count);

    // if (!rb_TestRead())
    // ResumeThread(pSpi->mIsrHandle);
	
    STATS_WRITE(static_cast<unsigned short> (result),*pGpsTimer - startTime);
    return result;
}

//-----------------------------------------------------------------------------
//
//                  SPI_Seek()
//
//-----------------------------------------------------------------------------

SPI_EXPORT DWORD
SPI_Seek(DWORD hOpenContext, long Amount, WORD Type)
{
    GL_PRINT((MSG("SPI_Seek()/%d\n\r"),__LINE__));
    SPI_DEVICE_CONTEXT* pSpi = getSpiDeviceContext(hOpenContext);
    SetLastError(0);
	return Amount;
}

//------------------------------------------------------------------------------
//
//      Handy Macros for commonly repeated code.
//
//  CASE(name)      --> case IOCTL_SERIAL_name: ioctlName = "name"
//  CHECK_IN(item)  --> make sure pBufIn and lenIn are OK compared to
//                      sizeof(item)
//  CHECK_OUT(item) --> make sure pBufIn, lenIn, and actualOut are OK
//                      compared to sizeof(item)
//  COPY_IN(item)   --> copy the pBufIn to item.
//  COPY_OUT(item)  --> copy the item to pBufIn.
//
//------------------------------------------------------------------------------

#define SET_ERR(e)    err = (e); errLine = __LINE__

#define CASE(name)    \
        case GPS_IOCTL_##name: \
            ioctlName = _T(#name)

#define CHECK_IN(item)   \
            if (sizeof(*item) != dwLenIn) \
            { \
                GL_ERROR((TEXT("SPI_IOCTL(%d)/%d inLength. expect %d\n\r"), \
                                        dwLenIn, __LINE__, sizeof(*item))); \
                SET_ERR(ERROR_BAD_LENGTH); \
                break; \
            }

#define CHECK_OUT(item)     \
            if (dwLenOut < sizeof(*item)) \
            { \
                GL_ERROR((TEXT("SPI_IOCTL(%d)/%d outLength. expect %d\n\r"), \
                                        dwLenOut, __LINE__, sizeof(*item))); \
                SET_ERR(ERROR_BAD_LENGTH); \
                break; \
            } \
            *pdwActualOut = sizeof(*item)

//-----------------------------------------------------------------------------
//
//                  SPI_IOControl()
//
//  REQUIRED - Set or get GPIO read/write.
//  OPTIONAL - MSISDN
//  OPTIONAL - CellID
//  OPTIONAL - Accurate GPS time
//  OPTIONAL - Radio status
//  OPTIONAL - Set PowerDown data
//
//-----------------------------------------------------------------------------

SPI_EXPORT BOOL
SPI_IOControl(DWORD  hOpenContext, DWORD dwCode,
              PBYTE  pBufIn,   DWORD dwLenIn,
              PBYTE  pBufOut,  DWORD dwLenOut, 
              PDWORD pdwActualOut)
{
    bool printError = true;
    int code = (dwCode - GPS_IOCTL_ZERO) >> 2;
    if (code <= GPS_INDEX_ZERO || code >= GPS_INDEX_MAX)
    {
        GL_PRINT((MSG("SPI_IOControl(0x%x,%%x,%d,%%x,%d,%%x)/%d Bad code %d err %d\n 0x%x\r"),
                dwCode,
                /* pBufIn, */  dwLenIn,
                /* pBufOut, */ dwLenOut,
                /* pdwActualOut, */
                __LINE__,
                code, ERROR_INVALID_PARAMETER, GPS_IOCTL_ZERO));
        SetLastError(ERROR_INVALID_PARAMETER);
        GL_ERROR((TEXT("SPI_IOControl(%x[%d])/%d bad IO code\n\r"),
                                                    dwCode, code, __LINE__));
        return FALSE;
    }

#if 0
    // Enable this debug when we start adding new commands.
    GL_PRINT((MSG("SPI_IOControl(%d,%x[%d],%x[%d],%x)/%d\n\r"),
            code,
            pBufIn, dwLenIn,
            pBufOut, dwLenOut,
            pdwActualOut, __LINE__));
#endif

    if (pBufIn && dwLenIn)
    {
        if (IsBadReadPtr(pBufIn, dwLenIn))
        {
            SetLastError(ERROR_INVALID_PARAMETER);
            GL_ERROR((TEXT("SPI_IOControl(%x[%d])/%d bad pBufIn\n\r"),
                                                pBufIn, dwLenIn, __LINE__));
            return -1;
        }
    }

    if (pBufOut && dwLenOut && pdwActualOut)
    {
        if (IsBadWritePtr(pBufOut, dwLenOut))
        {
            GL_ERROR((TEXT("SPI_IOControl(%x[%d])/%d bad pBufOut\n\r"),
                                                pBufOut, dwLenOut, __LINE__));
            SetLastError(ERROR_INVALID_PARAMETER);
            return -1;
        }
        if (IsBadWritePtr(pdwActualOut, sizeof(DWORD)))
        {
            GL_ERROR((TEXT("SPI_IOControl(%x[%d])/%d bad pdwActualOut\n\r"),
                                                pdwActualOut, __LINE__));
            SetLastError(ERROR_INVALID_PARAMETER);
            return -1;
        }
    }
    else if (pBufOut || dwLenOut || pdwActualOut)
    {
        GL_ERROR((TEXT("SPI_IOControl(%x,%d,%x)/%d missing param\n\r"),
                                pBufOut, dwLenOut, pdwActualOut, __LINE__));
        SetLastError(ERROR_INVALID_PARAMETER);
        return -1;
    }

    SPI_DEVICE_CONTEXT* pSpi      = getSpiDeviceContext(hOpenContext);
    const TCHAR* ioctlName        = _T("unknown");
    const TCHAR* structureInName  = (pBufIn ) ? _T("unknown") : _T("<null>");
    const TCHAR* structureOutName = (pBufOut) ? _T("unknown") : _T("<null>");

    DWORD err     = 0;
    int   errLine = 0;

    switch(dwCode)
    {

    CASE(CHIPSET_CONTROL);
    {
        const GPS_GPIO_CONTROL* gpioIn = (const GPS_GPIO_CONTROL *)pBufIn;
        GPS_GPIO_CONTROL* gpioOut = (GPS_GPIO_CONTROL *)pBufOut;
        if (pBufIn)
        {
            CHECK_IN(gpioIn);
            structureInName = _T("GPS_GPIO_CONTROL<in>");
        }
        if (pBufOut)
        {
            CHECK_OUT(gpioOut);
            structureOutName = _T("GPS_GPIO_CONTROL<out>");
        }

        printError = false;

        //----------------------------------------------------------------------
        //      [required] Set the GPIO.
        //----------------------------------------------------------------------
        if (pBufIn) switch(gpioIn->id)
        {
        case GPS_NONE:
        	break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -