//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//

#include <precomp.h>
#include <drvmsg.h>

#define CUSCAM_MSG_HEADER  _T("CUSCAM")

// Globals
CameraHal   oCameraIF[MAX_CAMERA_IP_HW];   // This is instance to handle Camera IF IP
CTX_CAMERA  oCtxCamera[MAX_CAMERA_IP_HW];  // This is logical context to control CAMERA module

extern CAM_CALLBACK_ARGS pfnCallbacks;      // Callback functions of Camera Capture Filter

static BUFFER_DESC    Video_Buffer;
static BUFFER_DESC    Still_Buffer;
static BUFFER_DESC    Preview_Buffer;

#define CAM_OFFSET_STEP     (8)

#define AlignSize(x, alignbyte) (alignbyte * (( x / alignbyte) + 1))


void Init_Context(UINT32 uCamID)
{
    oCtxCamera[uCamID].uCamID = uCamID;
    oCtxCamera[uCamID].pPreviewVirtAddr = 0;
    oCtxCamera[uCamID].pCodecVirtAddr = 0;
    oCtxCamera[uCamID].pCameraIF = &oCameraIF[uCamID];
    oCtxCamera[uCamID].pOccupantCam= NULL;
}

/**
 *
 *  Ths function will initialize specified Camera Interface IP(A,B,C)
 *  Allocate Device context and Mapped Virtual address of Physical SFR
 *
 */
PCTX_CAMERA CusCam_Initialize(UINT32 uCamID, DWORD dwMemBase, DWORD dwPhyIrq)
{
    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] ++%s()\r\n"), _T(__FUNCTION__)));
    DWORD dwError;

    Init_Context(uCamID);

    // Initialize Camera Interface IP
    dwError = oCameraIF[uCamID].Initialize(dwMemBase, dwPhyIrq);
    if(dwError != ERROR_CAMIF_SUCCESS)
    {
        SetLastError(dwError);
        return 0;
    }
    oCameraIF[uCamID].SetID(uCamID);
    // Create Additional Context for Post API
    CAM_initialize_context(uCamID, &oCameraIF[uCamID]);   // For Post API.
    CAM_initialize_post_power_context(uCamID);              // For Post Power Management

    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] --%s() return 0x%x\r\n"), _T(__FUNCTION__), &oCtxCamera[uCamID]));

    memset(&Video_Buffer , 0, sizeof(BUFFER_DESC));
    memset(&Still_Buffer , 0, sizeof(BUFFER_DESC));
    memset(&Preview_Buffer , 0, sizeof(BUFFER_DESC));
    return &oCtxCamera[uCamID];
}

void CusCam_Deinitialize(UINT32 uCamID)
{
    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] ++%s()\r\n"), _T(__FUNCTION__)));

    oCameraIF[uCamID].Deinitialize();

    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] --%s()\r\n"), _T(__FUNCTION__)));

}

/**
 *
 *   This function initialize camera module and the setting to use CAMERA
 *
 */
BOOL CusCam_CameraInitialize(CAMERA_MODULE_DESC CamModuleInfo, UINT32 uCamID)
{
    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] ++%s() uCalID = %d\r\n"), _T(__FUNCTION__),uCamID ));
    BOOL    retval = FALSE;

    if(oCameraIF[uCamID].CameraInitialize(CamModuleInfo) == ERROR_CAMIF_SUCCESS)
    {
            retval = TRUE;
            oCtxCamera[uCamID].PreviewState.status = STATUS_NOTSET;
            oCtxCamera[uCamID].StillState.status = STATUS_NOTSET;
            oCtxCamera[uCamID].VideoState.status = STATUS_NOTSET;

    }

    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] --%s()\r\n"), _T(__FUNCTION__)));

    return retval;
}

void CusCam_CameraDeinitialize(UINT32 uCamID)
{
    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] ++%s()\r\n"), _T(__FUNCTION__)));

    oCameraIF[uCamID].CameraDeinitialize();

    oCtxCamera[uCamID].pCameraIF->SetOperationMode(ABNORMAL_MODE);

    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] --%s()\r\n"), _T(__FUNCTION__)));
}

void CusCam_Reset(UINT32 uCamID)
{
    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] ++%s()\r\n"), _T(__FUNCTION__)));

    oCameraIF[uCamID].ModuleReset();

    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] --%s()\r\n"), _T(__FUNCTION__)));
}

CAMERA_POST_ERROR CusCam_SetPreviewSize(CAM_IMGTYPE_ARGS *args, UINT32 uCamID)
{
    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] ++%s(0x%x, %d)\r\n"), _T(__FUNCTION__), args, uCamID));
    if(oCtxCamera[uCamID].PreviewState.status == STATUS_RUNNING)
    {
        return ERROR_CAMIF_ALREADYRUNNING;
    }

    oCtxCamera[uCamID].PreviewState.status = STATUS_READY;
    oCtxCamera[uCamID].PreviewState.imgtype = args->imgtype;
    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] --%s()\r\n"), _T(__FUNCTION__)));
    return ERROR_CAMIF_SUCCESS;
}

CAMERA_POST_ERROR CusCam_SetStillSize(CAM_IMGTYPE_ARGS *args, UINT32 uCamID)
{
    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] ++%s(0x%x, %d)\r\n"), _T(__FUNCTION__), args, uCamID));
    if(oCtxCamera[uCamID].StillState.status == STATUS_RUNNING)
    {
        return ERROR_CAMIF_ALREADYRUNNING;
    }

    oCtxCamera[uCamID].StillState.status = STATUS_READY;
    oCtxCamera[uCamID].StillState.imgtype = args->imgtype;
    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] --CusCam_SetStillSize()\r\n")));

    return ERROR_CAMIF_SUCCESS;
}

CAMERA_POST_ERROR CusCam_SetVideoSize(CAM_IMGTYPE_ARGS *args, UINT32 uCamID)
{
    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] ++%s(0x%x, %d)\r\n"), _T(__FUNCTION__), args, uCamID));
    if(oCtxCamera[uCamID].VideoState.status == STATUS_RUNNING)
    {
        return ERROR_CAMIF_ALREADYRUNNING;
    }

    oCtxCamera[uCamID].VideoState.status = STATUS_READY;
    oCtxCamera[uCamID].VideoState.imgtype = args->imgtype;
    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] --%s()\r\n"),_T(__FUNCTION__)));
    return ERROR_CAMIF_SUCCESS;
}

CAMERA_POST_ERROR CusCam_StartPreview(CAM_START_ARGS *args, UINT32 uCamID)
{
    int size = 0;
    int yoffset = 0;
    int coffset = 0;

    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] ++%s(0x%x, %d)\r\n"), _T(__FUNCTION__), args, uCamID));

    CAMERA_STATE *CameraState = &oCtxCamera[uCamID].PreviewState;
    CameraHal * pCameraIF = oCtxCamera[uCamID].pCameraIF;

    if(CameraState->status != STATUS_READY)
    {
        return ERROR_CAMIF_ALREADYRUNNING;
    }


    CameraState->addrmode = args->mode;
    CameraState->imageSize = CameraState->CAM_BUFFER_INFO[0].size;
    CameraState->pingpongCount = VIDEO_PINGPONG_NUM;

//    pCameraIF->SetCameraFormat(PREVIEW_CAPTURE, CameraState->imgtype.width, CameraState->imgtype.height);
    pCameraIF->SetCameraSource(CameraState->imgtype.outputFormat);
    pCameraIF->SetOutputAddress(CameraState->CAM_BUFFER_INFO);

    pCameraIF->SetTargetRegister(CameraState->imgtype.width,
                                CameraState->imgtype.height,
                                CameraState->imgtype.outputFormat);

    pCameraIF->ThreadStart();
    CameraState->status = STATUS_RUNNING;

    pCameraIF->CaptureControl(TRUE);

    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] --%s()\r\n"), _T(__FUNCTION__)));

    return ERROR_CAMIF_SUCCESS;
}

DWORD   CusCam_GetPreviewFrame(PVOID pBufIn, UINT32 uCamID)
{
    DWORD   retAddr;
    int frame;
    CameraHal * pCameraIF = oCtxCamera[uCamID].pCameraIF;
    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] ++%s(0x%x, %d)\r\n"), _T(__FUNCTION__), pBufIn, uCamID));
    frame = pCameraIF->GetCurrentFrameNum();

    if(pBufIn != NULL)
    {
        memcpy(pBufIn, (PVOID)oCtxCamera[uCamID].PreviewState.CAM_BUFFER_INFO[frame].VirtAddr, oCtxCamera[uCamID].PreviewState.imageSize);
    }

    retAddr = (DWORD)oCtxCamera[uCamID].PreviewState.CAM_BUFFER_INFO[frame].VirtAddr;

    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] --%s()\r\n"), _T(__FUNCTION__)));

    return retAddr;
}

void CusCam_StopPreview(UINT32 uCamID)
{
    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] ++%s()\r\n"), _T(__FUNCTION__)));

    CameraHal * pCameraIF = oCtxCamera[uCamID].pCameraIF;

    pCameraIF->CaptureControl(FALSE);
    oCtxCamera[uCamID].PreviewState.status = STATUS_READY;
    pCameraIF->ThreadStop();
    oCtxCamera[uCamID].pCameraIF->CloseCMM();

    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] --%s()\r\n"), _T(__FUNCTION__)));
}

CAMERA_POST_ERROR CusCam_StartVideo(CAM_START_ARGS *args, UINT32 uCamID)
{
    int size = 0;
    int yoffset = 0;
    int coffset = 0;

    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] ++%s(0x%x, %d)\r\n"), _T(__FUNCTION__), args, uCamID));

    CAMERA_STATE *CameraState = &oCtxCamera[uCamID].VideoState;
    CameraHal * pCameraIF = oCtxCamera[uCamID].pCameraIF;

    if(CameraState->status != STATUS_READY)
    {
        return ERROR_CAMIF_ALREADYRUNNING;
    }


    CameraState->addrmode = args->mode;
    CameraState->imageSize = CameraState->CAM_BUFFER_INFO[0].size;
    CameraState->pingpongCount = VIDEO_PINGPONG_NUM;


//    pCameraIF->SetCameraFormat(VIDEO_CAPTURE, CameraState->imgtype.width, CameraState->imgtype.height);
    pCameraIF->SetCameraSource(CameraState->imgtype.outputFormat);
    pCameraIF->SetOutputAddress(CameraState->CAM_BUFFER_INFO);

    pCameraIF->SetTargetRegister(CameraState->imgtype.width,
                                CameraState->imgtype.height,
                                CameraState->imgtype.outputFormat);

    CameraState->status = STATUS_RUNNING;
    pCameraIF->ThreadStart();

    pCameraIF->CaptureControl(TRUE);


    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] --%s()\r\n"), _T(__FUNCTION__)));

    return ERROR_CAMIF_SUCCESS;
}

DWORD   CusCam_GetVideoFrame(PVOID pBufIn, UINT32 uCamID)
{
    DWORD   retAddr;
    int frame;
    CameraHal * pCameraIF = oCtxCamera[uCamID].pCameraIF;
    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] ++%s(0x%x, %d)\r\n"), _T(__FUNCTION__), pBufIn, uCamID));
    frame = pCameraIF->GetCurrentFrameNum();

    if(pBufIn != NULL)
    {
        memcpy(pBufIn, (PVOID)oCtxCamera[uCamID].VideoState.CAM_BUFFER_INFO[frame].VirtAddr, oCtxCamera[uCamID].VideoState.imageSize);
    }

    retAddr = (DWORD)oCtxCamera[uCamID].VideoState.CAM_BUFFER_INFO[frame].VirtAddr;

    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] --%s()\r\n"), _T(__FUNCTION__)));

    return retAddr;
}

void CusCam_StopVideo(UINT32 uCamID)
{
    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] ++%s()\r\n"), _T(__FUNCTION__)));

    CameraHal * pCameraIF = oCtxCamera[uCamID].pCameraIF;

    pCameraIF->CaptureControl(FALSE);
    oCtxCamera[uCamID].VideoState.status = STATUS_READY;
    pCameraIF->ThreadStop();
    oCtxCamera[uCamID].pCameraIF->CloseCMM();

    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] --%s()\r\n"), _T(__FUNCTION__)));
}

void CusCam_StopStillCut(UINT32 uCamID)
{
    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] ++%s()\r\n"), _T(__FUNCTION__)));

    CameraHal * pCameraIF = oCtxCamera[uCamID].pCameraIF;

    pCameraIF->CaptureControl(FALSE);
    oCtxCamera[uCamID].StillState.status = STATUS_READY;
    pCameraIF->ThreadStop();

    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] --%s()\r\n"), _T(__FUNCTION__)));
}

CAMERA_POST_ERROR CusCam_StillCut(CAM_STILLCUT_ARGS *args, UINT32 uCamID)
{
    int size = 0;
    int yoffset = 0;
    int coffset = 0;
    BOOL bPreviewFound = FALSE;
    BOOL bVideoCapFound = FALSE;
    DWORD dwPreviewIndex = 0;
    DWORD dwVideoIndex = 0;

    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[%s] ++%s(0x%x, %d)\r\n"), CUSCAM_MSG_HEADER, _T(__FUNCTION__), args, uCamID));

    CAMERA_STATE *CameraState = &oCtxCamera[uCamID].StillState;
    CAM_START_ARGS startArgs;

    CameraHal * pCameraIF = oCtxCamera[uCamID].pCameraIF;

    // we can not use video recording and stillcut at the same time.
    if(CameraState->status == STATUS_RUNNING || CameraState->status != STATUS_READY)
    {
        return ERROR_CAMIF_ALREADYRUNNING;
    }

    CameraState->addrmode = args->mode;
    CameraState->imageSize = CameraState->CAM_BUFFER_INFO[0].size;
    CameraState->pingpongCount = STILL_PINGPONG_NUM;

    // This will stop preview but if use 2 Camera Interface this code should not be need.
    // The use should restart preview if stop preview before capture the still image
    #if 0
    for(dwPreviewIndex = 0; dwPreviewIndex < MAX_CAMERA_IP_HW; dwPreviewIndex++)
    {
        if(oCameraIF[dwPreviewIndex].GetOperationMode() == PREVIEW_CAPTURE)
        {
            DBGMSG(CIF_FUNC && CIF_USR2,(_T("[%s] dwIndex=%d, GetOperationMode() returns %d\r\n"), CUSCAM_MSG_HEADER, dwPreviewIndex, oCameraIF[dwPreviewIndex].GetOperationMode()));
            bPreviewFound = TRUE;
            break;
        }
    }
    if(bPreviewFound)
    {
        CusCam_StopPreview(dwPreviewIndex);
        pCameraIF->SetOperationMode(STILL_CAPTURE);
    }
    #endif

    for(dwVideoIndex = 0; dwVideoIndex < MAX_CAMERA_IP_HW; dwVideoIndex++)
    {
        if(oCameraIF[dwVideoIndex].GetOperationMode() == VIDEO_CAPTURE)
        {
            DBGMSG(1,(_T("[%s] dwIndex=%d, GetOperationMode() returns %d\r\n"), CUSCAM_MSG_HEADER, dwVideoIndex, oCameraIF[dwVideoIndex].GetOperationMode()));
            bVideoCapFound = TRUE;
            break;
        }
    }
    if(bVideoCapFound)
    {
        CusCam_StopVideo(dwVideoIndex);
        pCameraIF->SetOperationMode(STILL_CAPTURE);

    }


//    pCameraIF->SetCameraFormat(STILL_CAPTURE, CameraState->imgtype.width, CameraState->imgtype.height);
    pCameraIF->SetCameraSource(CameraState->imgtype.outputFormat);
    pCameraIF->SetOutputAddress(CameraState->CAM_BUFFER_INFO);

    pCameraIF->SetTargetRegister(CameraState->imgtype.width,
                                CameraState->imgtype.height,
                                CameraState->imgtype.outputFormat);
    pCameraIF->ThreadStart();
    pCameraIF->CaptureControl(TRUE);

    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] %s() : Wait For Finish\r\n"), _T(__FUNCTION__)));
    pCameraIF->WaitForCaptureFinish();
    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] %s() : Wait For Finish Done\r\n"), _T(__FUNCTION__)));
    pCameraIF->ThreadStop();


    if(args->mode == MODE_MEM_COPY && args->buffer != NULL)
    {
        memcpy(args->buffer, (PVOID)CameraState->CAM_BUFFER_INFO[0].VirtAddr, CameraState->imageSize);
    }
    else
    {
    args->directBuffer.physicalAddr = (DWORD)CameraState->CAM_BUFFER_INFO[0].pY;
    args->directBuffer.virtualAddr = (DWORD)CameraState->CAM_BUFFER_INFO[0].VirtAddr;;
    }

    if(pfnCallbacks.dwCameraDriverContext != 0)
    {
        pfnCallbacks.pfnCameraHandleStillFrame(pfnCallbacks.dwCameraDriverContext);
    }

#if 0
    // if we stopped preview, then rerun preview automatically
    if(bPreviewFound)
    {
        DBGMSG(CIF_FUNC && CIF_USR2,(TEXT("bPreviewFound\r\n")));
        pCameraIF->SetOperationMode(PREVIEW_CAPTURE);
        startArgs.mode = oCtxCamera[dwPreviewIndex].PreviewState.addrmode;
        CusCam_StartPreview(&startArgs, dwPreviewIndex);
    }
#endif
    if(bVideoCapFound)
    {
        DBGMSG(CIF_FUNC && CIF_USR2,(TEXT("bVideoCapFound\r\n")));

        pCameraIF->SetOperationMode(VIDEO_CAPTURE);
        startArgs.mode = oCtxCamera[dwVideoIndex].VideoState.addrmode;
        CusCam_StartVideo(&startArgs, dwVideoIndex);
    }

    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] --%s()\r\n"), _T(__FUNCTION__)));

    return ERROR_CAMIF_SUCCESS;
}


DWORD CusCam_JPEGStillCut(CAM_STILLCUT_ARGS *args, UINT32 uCamID)
{
    int size = 0;
    int yoffset = 0;
    int coffset = 0;
    BOOL bPreviewFound = FALSE;
    BOOL bVideoCapFound = FALSE;
    DWORD dwPreviewIndex = 0;
    DWORD dwVideoIndex = 0;

    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[%s] ++%s(0x%x, %d)\r\n"), CUSCAM_MSG_HEADER, _T(__FUNCTION__), args, uCamID));

    CAMERA_STATE *CameraState = &oCtxCamera[uCamID].StillState;
    CAM_START_ARGS startArgs;

    CameraHal * pCameraIF = oCtxCamera[uCamID].pCameraIF;

    // we can not use video recording and stillcut at the same time.
    if(CameraState->status == STATUS_RUNNING || CameraState->status != STATUS_READY)
    {
        return ERROR_CAMIF_ALREADYRUNNING;
    }


    CameraState->addrmode = args->mode;
    CameraState->imageSize = CameraState->CAM_BUFFER_INFO[0].size;
    CameraState->pingpongCount = STILL_PINGPONG_NUM;


    // This will stop preview but if use 2 Camera Interface this code should not be need.
    // The use should restart preview if stop preview before capture the still image
    for(dwPreviewIndex = 0; dwPreviewIndex < MAX_CAMERA_IP_HW; dwPreviewIndex++)
    {
        if(oCameraIF[dwPreviewIndex].GetOperationMode() == PREVIEW_CAPTURE)
        {
            DBGMSG(CIF_FUNC && CIF_USR2,(_T("[%s] dwIndex=%d, GetOperationMode() returns %d\r\n"), CUSCAM_MSG_HEADER, dwPreviewIndex, oCameraIF[dwPreviewIndex].GetOperationMode()));
            bPreviewFound = TRUE;
            break;
        }
    }
    if(bPreviewFound)
        CusCam_StopPreview(dwPreviewIndex);

    for(dwVideoIndex = 0; dwVideoIndex < MAX_CAMERA_IP_HW; dwVideoIndex++)
    {
        if(oCameraIF[dwVideoIndex].GetOperationMode() == VIDEO_CAPTURE)
        {
            DBGMSG(1,(_T("[%s] dwIndex=%d, GetOperationMode() returns %d\r\n"), CUSCAM_MSG_HEADER, dwVideoIndex, oCameraIF[dwVideoIndex].GetOperationMode()));
            bVideoCapFound = TRUE;
            break;
        }
    }
    if(bVideoCapFound)
        CusCam_StopVideo(dwVideoIndex);

//    pCameraIF->SetCameraFormat(STILL_CAPTURE, CameraState->imgtype.width, CameraState->imgtype.height);
    pCameraIF->SetCameraSource(CameraState->imgtype.outputFormat);
    pCameraIF->SetOutputAddress(CameraState->CAM_BUFFER_INFO);

    pCameraIF->SetTargetRegister(CameraState->imgtype.width,
                                CameraState->imgtype.height,
                                CameraState->imgtype.outputFormat);
    pCameraIF->ThreadStart();
    pCameraIF->CaptureControl(TRUE);

    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] %s() : Wait For Finish\r\n"), _T(__FUNCTION__)));
    pCameraIF->WaitForCaptureFinish();
    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] %s() : Wait For Finish Done\r\n"), _T(__FUNCTION__)));
    pCameraIF->ThreadStop();

    if(args->mode == MODE_MEM_COPY && args->buffer != NULL)
    {
        memcpy(args->buffer, (PVOID)CameraState->CAM_BUFFER_INFO[0].VirtAddr, CameraState->imageSize);
    }
    else
    {
    args->directBuffer.physicalAddr = (DWORD)CameraState->CAM_BUFFER_INFO[0].pY;
    args->directBuffer.virtualAddr = (DWORD)CameraState->CAM_BUFFER_INFO[0].VirtAddr;;
    }

    if(pfnCallbacks.dwCameraDriverContext != 0)
    {
        pfnCallbacks.pfnCameraHandleStillFrame(pfnCallbacks.dwCameraDriverContext);
    }


    // if we stopped preview, then rerun preview automatically
    if(bPreviewFound)
    {
        DBGMSG(CIF_FUNC && CIF_USR2,(TEXT("bPreviewFound\r\n")));
        startArgs.mode = oCtxCamera[dwPreviewIndex].PreviewState.addrmode;
        CusCam_StartPreview(&startArgs, dwPreviewIndex);
    }

    if(bVideoCapFound)
    {
        DBGMSG(CIF_FUNC && CIF_USR2,(TEXT("bVideoCapFound\r\n")));
        startArgs.mode = oCtxCamera[dwVideoIndex].VideoState.addrmode;
        CusCam_StartVideo(&startArgs, dwVideoIndex);
    }



    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] --%s()\r\n"), _T(__FUNCTION__)));

    return pCameraIF->m_Size_Capture_Data;
}


// Todo Move to CustomCamera
int CusCam_CameraSetFormat(UINT32 width, UINT32 height, CAM_IMG_FORMAT format, int BufferType, UINT32 uCamID)
{
    CAM_IMGTYPE_ARGS ImgInfo;
    ImgInfo.imgtype.width = width;
    ImgInfo.imgtype.height = height;
    ImgInfo.imgtype.outputFormat = format;
    ImgInfo.imgtype.outputOrder = 0;
    ImgInfo.imgtype.outputPlane = 0;

    DBGMSG(CIF_FUNC && CIF_USR2,(TEXT("%s ++%s()\n"), CUSCAM_MSG_HEADER, _T(__FUNCTION__)));
    if(BufferType == VIDEO_CAPTURE)
    {
        Video_Buffer.Width = width;
        Video_Buffer.Height = height;
        Video_Buffer.Format = format;
        CusCam_SetVideoSize(&ImgInfo, uCamID);
    }
    else if(BufferType == STILL_CAPTURE)
    {
        Still_Buffer.Width = width;
        Still_Buffer.Height = height;
        Still_Buffer.Format = format;
        CusCam_SetStillSize(&ImgInfo, uCamID);
    }
    else if(BufferType == PREVIEW_CAPTURE)
    {
        Preview_Buffer.Width = width;
        Preview_Buffer.Height = height;
        Preview_Buffer.Format = format;
        CusCam_SetPreviewSize(&ImgInfo, uCamID);
    }
    else
    {
        return FALSE;
    }
    DBGMSG(CIF_FUNC && CIF_USR2,(TEXT("%s --%s()\n"), CUSCAM_MSG_HEADER, _T(__FUNCTION__)));
    return TRUE;
}


int CusCam_CameraReleaseBuffer(int BufferType, UINT32 uCamID) // Release DMA buffer
{
    int i =0;
    DBGMSG(CIF_FUNC && CIF_USR2,(TEXT("%s ++%s(%d, %d)\n"), CUSCAM_MSG_HEADER, _T(__FUNCTION__), BufferType, uCamID));
    if(BufferType == VIDEO_CAPTURE)
    {
        for(i=0;i<MAX_PINGPONG_NUM;i++)
        {
            if(Video_Buffer.vBufAddr[i] != 0)
            {
                oCtxCamera[uCamID].pCameraIF->FreeOutputDMABuffer(Video_Buffer.vBufAddr[i]);
                Video_Buffer.vBufAddr[i] = 0;
            }
        }

    }
    else if(BufferType == STILL_CAPTURE)
    {
        for(i=0;i<MAX_PINGPONG_NUM;i++)
        {
            if(Still_Buffer.vBufAddr[i] != 0)
            {
                oCtxCamera[uCamID].pCameraIF->FreeOutputDMABuffer(Still_Buffer.vBufAddr[i]);
                Still_Buffer.vBufAddr[i] = 0;
            }
        }

    }
    else if(BufferType == PREVIEW_CAPTURE)
    {
        for(i=0;i<MAX_PINGPONG_NUM;i++)
        {
            if(Preview_Buffer.vBufAddr[i] != 0)
            {
                oCtxCamera[uCamID].pCameraIF->FreeOutputDMABuffer(Preview_Buffer.vBufAddr[i]);
                Preview_Buffer.vBufAddr[i] = 0;

            }
        }

    }
    return TRUE;
}

int CusCam_CameraPrepareBuffer(P_CAMERA_DMA_BUFFER_INFO pBufInfo, int BufferType, UINT32 uCamID)        // allocate DMA buffer
{
    int i,size;
    int sizeY,sizeC;
    DWORD dwVir,dwPhy;
    DBGMSG(CIF_FUNC && CIF_USR2,(TEXT("%s ++%s(0x%x, %d, %d)\n"), CUSCAM_MSG_HEADER, _T(__FUNCTION__), pBufInfo, BufferType, uCamID));
    CAMERA_STATE *CameraState;

    oCtxCamera[uCamID].pCameraIF->OpenCMM();

    if(BufferType == VIDEO_CAPTURE)
    {
        CameraState = &oCtxCamera[uCamID].VideoState;

        size = oCtxCamera[uCamID].pCameraIF->CalculateBufferSize(Video_Buffer.Width, Video_Buffer.Height, Video_Buffer.Format);
        Video_Buffer.FrameSize = size;
        Video_Buffer.Size = size * MAX_PINGPONG_NUM;
        DBGMSG(CIF_FUNC && CIF_USR2,(TEXT("Video_Buffer.Width=%d Video_Buffer.Height=%d Video_Buffer.Size=%d  Video_Buffer.Format=%d\n"),Video_Buffer.Width, Video_Buffer.Height, Video_Buffer.Size, Video_Buffer.Format));
/*
        if(Video_Buffer.Size > CAPTURE_BUFFER_SIZE)
        {
            ERRMSG((TEXT("Video size is larger than buffer size\n")));
            return FALSE;
        }
*/
        for(i=0;i<MAX_PINGPONG_NUM;i++)
        {
            if(i%2 == 0)
            {
                oCtxCamera[uCamID].pCameraIF->AllocOutputDMABuffer(Video_Buffer.FrameSize, DRAM_1, &dwPhy, &dwVir);
                Video_Buffer.vBufAddr[i] = dwVir;
            }
            else
            {
                oCtxCamera[uCamID].pCameraIF->AllocOutputDMABuffer(Video_Buffer.FrameSize, DRAM_1, &dwPhy, &dwVir);
                Video_Buffer.vBufAddr[i] = dwVir;
            }

            pBufInfo[i].VirtAddr = (DWORD)dwVir;
            pBufInfo[i].size = Video_Buffer.FrameSize;
            pBufInfo[i].pY = (DWORD*)(DWORD)(dwPhy);
        }

        if(CAM_FORMAT_YV12 == Video_Buffer.Format)
        {
            sizeY = Video_Buffer.Width*Video_Buffer.Height;
            sizeC = Video_Buffer.Width*Video_Buffer.Height/4;
            for(i=0;i<MAX_PINGPONG_NUM;i++)
            {
                pBufInfo[i].pCr = (DWORD*)((DWORD)pBufInfo[i].pY + sizeY);
                pBufInfo[i].pCb = (DWORD*)((DWORD)pBufInfo[i].pCr + sizeC);
            }
        }
        if( CAM_FORMAT_YCBYCR422_3PLANE == Video_Buffer.Format )
        {
            sizeY = Video_Buffer.Width*Video_Buffer.Height;
            sizeC = Video_Buffer.Width*Video_Buffer.Height/2;
            for(i=0;i<MAX_PINGPONG_NUM;i++)
            {
                pBufInfo[i].pCr = (DWORD*)((DWORD)pBufInfo[i].pY + sizeY);
                pBufInfo[i].pCb = (DWORD*)((DWORD)pBufInfo[i].pCr + sizeC);
            }
        }
        else if(CAM_FORMAT_YCBYCR422_2PLANE == Video_Buffer.Format )
        {
            sizeY = Video_Buffer.Width*Video_Buffer.Height;
            sizeC = Video_Buffer.Width*Video_Buffer.Height/2;
            for(i=0;i<MAX_PINGPONG_NUM;i++)
            {
                pBufInfo[i].pCr = (DWORD*)((DWORD)pBufInfo[i].pY + sizeY);
                pBufInfo[i].pCb = (DWORD*)((DWORD)pBufInfo[i].pY + sizeY);
            }

        }
        if(CAM_FORMAT_NV12 == Video_Buffer.Format ||
           CAM_FORMAT_NV12_WEAVE == Video_Buffer.Format)
        {
            sizeY = AlignSize(Video_Buffer.Width*Video_Buffer.Height, 0x4000);
            sizeC = AlignSize(Video_Buffer.Width*Video_Buffer.Height/2, 0x4000);
            for(i=0;i<MAX_PINGPONG_NUM;i++)
            {
                pBufInfo[i].pCr = (DWORD*)((DWORD)pBufInfo[i].pY + sizeY);
                pBufInfo[i].pCb = (DWORD*)((DWORD)pBufInfo[i].pY + sizeY);  // 2 Planes
            }
            /*
            AlignedWidth = AlignSize(Video_Buffer.Width, 128);
            AlignedYHeight = AlignSize(Video_Buffer.Height, 32);
            AlignedCbHeight = AlignSize(Video_Buffer.Height/2, 32);

            sizeY = AlignSize(AlignedWidth*AlignedYHeight, 64*1024);
            sizeC = AlignSize(AlignedWidth*AlignedCbHeight, 64*1024);
            for(i=0;i<MAX_PINGPONG_NUM;i++)
            {
                pBufInfo[i].pCr = (DWORD*)((DWORD)pBufInfo[i].pY + sizeY);
                pBufInfo[i].pCb = (DWORD*)((DWORD)pBufInfo[i].pY + sizeY);  // 2 Planes
            }
            */
        }

        for(i=0;i<MAX_PINGPONG_NUM;i++)
        {
            memcpy(&(CameraState->CAM_BUFFER_INFO[i]), &pBufInfo[i],sizeof(CAMERA_DMA_BUFFER_INFO));
        }

    }
    else if(BufferType == STILL_CAPTURE)
    {

        CameraState = &oCtxCamera[uCamID].StillState;

        size = oCtxCamera[uCamID].pCameraIF->CalculateBufferSize(Still_Buffer.Width, Still_Buffer.Height, Still_Buffer.Format);
        Still_Buffer.FrameSize = size;
        Still_Buffer.Size = size;
        DBGMSG(CIF_FUNC && CIF_USR2,(TEXT("Still_Buffer.Width=%d Still_Buffer.Height=%d Still_Buffer.Size=%d  Still_Buffer.Format=%d\n"),Still_Buffer.Width, Still_Buffer.Height, Still_Buffer.Size, Still_Buffer.Format));


        if(Still_Buffer.Size > CAPTURE_BUFFER_SIZE)
        {
            ERRMSG((TEXT("Still size is larger than buffer size\n")));
            return FALSE;
        }

        oCtxCamera[uCamID].pCameraIF->AllocOutputDMABuffer(Still_Buffer.FrameSize, DRAM_1, &dwPhy, &dwVir);
            pBufInfo[0].VirtAddr = (DWORD)dwVir;
            pBufInfo[0].size = Still_Buffer.FrameSize;
            pBufInfo[0].pY = (DWORD*)(DWORD)(dwPhy);

        Still_Buffer.vBufAddr[0] = dwVir;
        Still_Buffer.vBufAddr[1] = 0;
        Still_Buffer.vBufAddr[2] = 0;
        Still_Buffer.vBufAddr[3] = 0;


        if(CAM_FORMAT_YV12 == Still_Buffer.Format)
        {
            sizeY = Still_Buffer.Width*Still_Buffer.Height;
            sizeC = Still_Buffer.Width*Still_Buffer.Height/4;
            pBufInfo[0].pCr = (DWORD*)((DWORD)pBufInfo[0].pY + sizeY);
            pBufInfo[0].pCb = (DWORD*)((DWORD)pBufInfo[0].pCr + sizeC);

        }
        if( CAM_FORMAT_YCBYCR422_3PLANE == Still_Buffer.Format )
        {
            sizeY = Still_Buffer.Width*Still_Buffer.Height;
            sizeC = Still_Buffer.Width*Still_Buffer.Height/2;
            for(i=0;i<MAX_PINGPONG_NUM;i++)
            {
                pBufInfo[i].pCr = (DWORD*)((DWORD)pBufInfo[i].pY + sizeY);
                pBufInfo[i].pCb = (DWORD*)((DWORD)pBufInfo[i].pCr + sizeC);
            }
        }
        else if(CAM_FORMAT_YCBYCR422_2PLANE == Still_Buffer.Format )
        {
            sizeY = Still_Buffer.Width*Still_Buffer.Height;
            sizeC = Still_Buffer.Width*Still_Buffer.Height/2;
            for(i=0;i<MAX_PINGPONG_NUM;i++)
            {
                pBufInfo[i].pCr = (DWORD*)((DWORD)pBufInfo[i].pY + sizeY);
                pBufInfo[i].pCb = (DWORD*)((DWORD)pBufInfo[i].pY + sizeY);
            }

        }
        if(CAM_FORMAT_NV12 == Still_Buffer.Format || CAM_FORMAT_NV12_WEAVE == Still_Buffer.Format)
        {
            sizeY = Still_Buffer.Width*Still_Buffer.Height;
            sizeC = Still_Buffer.Width*Still_Buffer.Height/2;

            sizeY = AlignSize(Still_Buffer.Width*Still_Buffer.Height, 0x4000);
            sizeC = AlignSize(Still_Buffer.Width*Still_Buffer.Height/2, 0x4000);

            pBufInfo[0].pCb = (DWORD*)((DWORD)pBufInfo[0].pY + sizeY);
            pBufInfo[0].pCr = (DWORD*)((DWORD)pBufInfo[0].pY + sizeY);  // 2 Planes
        }


            for(i=0;i<MAX_PINGPONG_NUM;i++)
            {
            memcpy(&(CameraState->CAM_BUFFER_INFO[i]), &pBufInfo[0],sizeof(CAMERA_DMA_BUFFER_INFO));
        }

    }
    else if(BufferType == PREVIEW_CAPTURE)
    {
        CameraState = &oCtxCamera[uCamID].PreviewState;
//add by jerry
//		Preview_Buffer.Width = 2048;
//		Preview_Buffer.Height = 1536;
//----
        size = oCtxCamera[uCamID].pCameraIF->CalculateBufferSize(Preview_Buffer.Width, Preview_Buffer.Height, Preview_Buffer.Format);

	RETAILMSG(1, (TEXT("[preview] width = %d,height = %d,format = %d\r\n"),Preview_Buffer.Width, Preview_Buffer.Height, Preview_Buffer.Format));

        Preview_Buffer.FrameSize = size;
        Preview_Buffer.Size = size * MAX_PINGPONG_NUM;
        DBGMSG(CIF_FUNC && CIF_USR2,(TEXT("Preview_Buffer.Width=%d Preview_Buffer.Height=%d Preview_Buffer.Size=%d Preview_Buffer.Format=%d\n"),Preview_Buffer.Width, Preview_Buffer.Height, Preview_Buffer.Size, Preview_Buffer.Format));
/*
        if(Preview_Buffer.Size > PREVIEW_BUFFER_SIZE)
        {
            ERRMSG((TEXT("Preview size is larger than buffer size\n")));
            return FALSE;
        }
*/
        for(i=0;i<MAX_PINGPONG_NUM;i++)
        {
            if(i%2 == 0)
            {
                oCtxCamera[uCamID].pCameraIF->AllocOutputDMABuffer(Preview_Buffer.FrameSize, DRAM_1, &dwPhy, &dwVir);
                Preview_Buffer.vBufAddr[i] = dwVir;
            }
            else
            {
                oCtxCamera[uCamID].pCameraIF->AllocOutputDMABuffer(Preview_Buffer.FrameSize, DRAM_1, &dwPhy, &dwVir);
                Preview_Buffer.vBufAddr[i] = dwVir;
            }

            pBufInfo[i].VirtAddr = (DWORD)dwVir;
            pBufInfo[i].size = Preview_Buffer.FrameSize;
            pBufInfo[i].pY = (DWORD*)(DWORD)(dwPhy);
        }

        if(CAM_FORMAT_YV12 == Preview_Buffer.Format)
        {
            sizeY = Preview_Buffer.Width*Preview_Buffer.Height;
            sizeC = Preview_Buffer.Width*Preview_Buffer.Height/4;
            for(i=0;i<MAX_PINGPONG_NUM;i++)
            {
                pBufInfo[i].pCr = (DWORD*)((DWORD)pBufInfo[i].pY + sizeY);
                pBufInfo[i].pCb = (DWORD*)((DWORD)pBufInfo[i].pCr + sizeC);
            }
        }
        if( CAM_FORMAT_YCBYCR422_3PLANE == Preview_Buffer.Format )
        {
            sizeY = Preview_Buffer.Width*Preview_Buffer.Height;
            sizeC = Preview_Buffer.Width*Preview_Buffer.Height/2;
            for(i=0;i<MAX_PINGPONG_NUM;i++)
            {
                pBufInfo[i].pCr = (DWORD*)((DWORD)pBufInfo[i].pY + sizeY);
                pBufInfo[i].pCb = (DWORD*)((DWORD)pBufInfo[i].pCr + sizeC);
            }
        }
        else if(CAM_FORMAT_YCBYCR422_2PLANE == Preview_Buffer.Format )
        {
            sizeY = Preview_Buffer.Width*Preview_Buffer.Height;
            sizeC = Preview_Buffer.Width*Preview_Buffer.Height/2;
            for(i=0;i<MAX_PINGPONG_NUM;i++)
            {
                pBufInfo[i].pCr = (DWORD*)((DWORD)pBufInfo[i].pY + sizeY);
                pBufInfo[i].pCb = (DWORD*)((DWORD)pBufInfo[i].pY + sizeY);
            }

        }
        if(CAM_FORMAT_NV12 == Preview_Buffer.Format ||
           CAM_FORMAT_NV12_WEAVE == Preview_Buffer.Format)
        {
            sizeY = Preview_Buffer.Width*Preview_Buffer.Height;
            sizeC = Preview_Buffer.Width*Preview_Buffer.Height/2;

            sizeY = AlignSize(Preview_Buffer.Width*Preview_Buffer.Height, 0x4000);
            sizeC = AlignSize(Preview_Buffer.Width*Preview_Buffer.Height/2, 0x4000);

            for(i=0;i<MAX_PINGPONG_NUM;i++)
            {
                pBufInfo[i].pCr = (DWORD*)((DWORD)pBufInfo[i].pY + sizeY);
                pBufInfo[i].pCb = (DWORD*)((DWORD)pBufInfo[i].pY + sizeY);  // 2 Planes
            }
        }

        for(i=0;i<MAX_PINGPONG_NUM;i++)
        {
            memcpy(&(CameraState->CAM_BUFFER_INFO[i]), &pBufInfo[i],sizeof(CAMERA_DMA_BUFFER_INFO));
        }

    }
    else
    {
        return FALSE;
    }

    DBGMSG(CIF_FUNC && CIF_USR2,(TEXT("%s --%s()\n"), CUSCAM_MSG_HEADER, _T(__FUNCTION__)));
    return TRUE;
}

// For All device, this callback point is shared.
DWORD CusCam_SetCallback(CAM_CALLBACK_ARGS *pArgs)
{
    return (DWORD)memcpy(&pfnCallbacks, pArgs, sizeof(CAM_CALLBACK_ARGS));
}

DWORD CusCam_GetCurrentFrameNum(UINT32 uCamID)
{
    CameraHal * pCameraIF = oCtxCamera[uCamID].pCameraIF;

    return pCameraIF->GetCurrentFrameNum();
}

DWORD CusCam_SetOperationMode(CAMIF_OPERATION_MODE mode, UINT32 uCamID)
{
    if(mode==VIDEO_CAPTURE ||mode==STILL_CAPTURE || mode==PREVIEW_CAPTURE)
    {
        oCtxCamera[uCamID].pCameraIF->SetOperationMode(mode);
        DBGMSG(CIF_FUNC && CIF_USR2,(TEXT(" CusCam_SetOperationMode : 0x%x\r\n"),mode));
        return TRUE;
    }
    else
    {
        DBGMSG(CIF_FUNC && CIF_USR2,(TEXT(" CusCam_SetOperationMode : 0x%x\r\n"),mode));
        oCtxCamera[uCamID].pCameraIF->SetOperationMode(ABNORMAL_MODE);
        return FALSE;
    }
}

DWORD CusCam_Zoom(DWORD ZoomRatio, UINT32 uCamID)
{
    MODULE_DESCRIPTOR moduleValue;
    UINT32 offsetValueWidth,offsetValueHeight;

    oCtxCamera[uCamID].pCameraIF->GetModuleDesc(&moduleValue);

    offsetValueWidth = (ZoomRatio+1) * CAM_OFFSET_STEP; // TODO: Need to calculate accureately
    offsetValueHeight = (int)(offsetValueWidth * (moduleValue.SourceVSize/(float)moduleValue.SourceHSize));
    offsetValueHeight = (offsetValueHeight<<1)>>1;

    if( offsetValueWidth*2 > (moduleValue.SourceHSize-16) || offsetValueHeight*2 > (moduleValue.SourceVSize-8) )
    {
        return FALSE;
    }

    oCtxCamera[uCamID].pCameraIF->SetOffsetRegister(offsetValueWidth, offsetValueWidth, offsetValueHeight, offsetValueHeight);

    DBGMSG(CIF_FUNC && CIF_USR2,(TEXT("[CAM] offsetValueWidth=%d   offsetValueHeight=%d\n"),offsetValueWidth,offsetValueHeight));

    if(oCtxCamera[uCamID].pCameraIF->GetOperationMode() == PREVIEW_CAPTURE)
    {
        oCtxCamera[uCamID].pCameraIF->SetScaler(Preview_Buffer.Width, Preview_Buffer.Height);
    }
    else if(oCtxCamera[uCamID].pCameraIF->GetOperationMode() == VIDEO_CAPTURE)
    {
        oCtxCamera[uCamID].pCameraIF->SetScaler(Video_Buffer.Width, Video_Buffer.Height);
    }
    else if(oCtxCamera[uCamID].pCameraIF->GetOperationMode() == STILL_CAPTURE)
    {
        oCtxCamera[uCamID].pCameraIF->SetScaler(Still_Buffer.Width, Still_Buffer.Height);
    }

    return TRUE;

}


BOOL CusCam_PowerDown(UINT32 uCamID)
{
    DBGMSG(CIF_FUNC && CIF_USR2,(TEXT("[CUSCAM] CusCam_PowerDown CamID = %d\r\n"),uCamID));
    if(oCtxCamera[uCamID].PreviewState.status == STATUS_RUNNING ||
            oCtxCamera[uCamID].VideoState.status == STATUS_RUNNING ||
            oCtxCamera[uCamID].StillState.status == STATUS_RUNNING )
    {
        oCtxCamera[uCamID].pCameraIF->DeInitSensor();
    }



    if(oCtxCamera[uCamID].PreviewState.status == STATUS_RUNNING)
    {
        DBGMSG(CIF_FUNC && CIF_USR2,(TEXT("[CUSCAM] CusCam_PowerDown PREVIEW = %d\r\n"),uCamID));
        CusCam_StopPreview(uCamID);
        oCtxCamera[uCamID].PreviewState.bWakeUp = TRUE;
    }
    if(oCtxCamera[uCamID].VideoState.status == STATUS_RUNNING)
    {
        DBGMSG(CIF_FUNC && CIF_USR2,(TEXT("[CUSCAM] CusCam_PowerDown Video = %d\r\n"),uCamID));
        CusCam_StopVideo(uCamID);
        oCtxCamera[uCamID].VideoState.bWakeUp = TRUE;
    }

    if(oCtxCamera[uCamID].StillState.status == STATUS_RUNNING)
    {
        DBGMSG(CIF_FUNC && CIF_USR2,(TEXT("[CUSCAM] CusCam_PowerDown Still = %d\r\n"),uCamID));
        CusCam_StopStillCut(uCamID);
        oCtxCamera[uCamID].StillState.bWakeUp = TRUE;
    }
    return TRUE;
}

BOOL CusCam_PowerUp(UINT32 uCamID)
{
    DBGMSG(CIF_FUNC && CIF_USR2,(TEXT("[CUSCAM] CusCam_PowerUp CamID = %d\r\n"),uCamID));

    CAM_START_ARGS arg;
    if(oCtxCamera[uCamID].PreviewState.bWakeUp == TRUE ||
            oCtxCamera[uCamID].VideoState.bWakeUp == TRUE ||
            oCtxCamera[uCamID].StillState.bWakeUp == TRUE )
    {
        oCtxCamera[uCamID].pCameraIF->InitSensor();
    }

    if(oCtxCamera[uCamID].PreviewState.bWakeUp == TRUE)
    {
        DBGMSG(CIF_FUNC && CIF_USR2,(TEXT("[CUSCAM] CusCam_PowerUp PREVIEW = %d\r\n"),uCamID));
        arg.mode = oCtxCamera[uCamID].PreviewState.addrmode;
        CusCam_StartPreview( &arg ,uCamID);
        oCtxCamera[uCamID].PreviewState.bWakeUp = FALSE;
    }
    if(oCtxCamera[uCamID].VideoState.bWakeUp == TRUE)
    {
        DBGMSG(CIF_FUNC && CIF_USR2,(TEXT("[CUSCAM] CusCam_PowerUp Video = %d\r\n"),uCamID));
        arg.mode = oCtxCamera[uCamID].VideoState.addrmode;
        CusCam_StartVideo( &arg ,uCamID);
        oCtxCamera[uCamID].VideoState.bWakeUp = FALSE;
    }
    if(oCtxCamera[uCamID].StillState.bWakeUp == TRUE)
    {
        DBGMSG(CIF_FUNC && CIF_USR2,(TEXT("[CUSCAM] CusCam_PowerUp Still = %d\r\n"),uCamID));
        arg.mode = oCtxCamera[uCamID].StillState.addrmode;
        CusCam_StopStillCut(uCamID);
        oCtxCamera[uCamID].StillState.bWakeUp = FALSE;
    }
    return TRUE;
}



BOOL CAM_Resource_API_Proc(
    PHW_OPEN_INFO pOpenHead,
    DWORD dwCode,
    PBYTE pBufIn,
    DWORD dwLenIn,
    PBYTE pBufOut,
    DWORD dwLenOut,
    PDWORD pdwActualOut
    )
{
    BOOL bRet = TRUE;
    PHW_INDEP_INFO  pCAMHead = pOpenHead->pCamHead;
    PCTX_CAMERA pCtxCamera = pCAMHead->pCtxCamera;

    if(IOCTL_CAM_RSC_REQUEST == dwCode)
    {
        if(pCtxCamera->pOccupantCam == NULL)
     {
         pCtxCamera->pOccupantCam = pOpenHead;
         DEBUGMSG(CAM_ZONE_IOCTL,(TEXT("[CAM]CAM_Resource_API_Proc(): OpenContext[0x%x] has resource CAM%d\n"), (DWORD)pOpenHead, pCtxCamera->uCamID));
         return TRUE;
     }
     else if(pCtxCamera->pOccupantCam == pOpenHead)
     {
         //ERRMSG((TEXT("[CAM]CAM_Resource_API_Proc(): OpenContext[0x%x] already has resource CAM%d\n"), (DWORD)pOpenHead, pCtxCamera->uCamID));
         return TRUE;
     }
     else
     {
         ERRMSG((TEXT("[CAM]CAM_Resource_API_Proc(): Resource CAM%d is occupied by other OpenContext\n"), pCtxCamera->uCamID));
         return FALSE;
     }
    }
    else if(IOCTL_CAM_RSC_RELEASE== dwCode)
    {
        if(pCtxCamera->pOccupantCam == NULL)
     {
         ERRMSG((TEXT("[CAM]CAM_Resource_API_Proc(): Resource CAM%d is already released\n"), pCtxCamera->uCamID));
         return TRUE;
     }
     else if(pCtxCamera->pOccupantCam == pOpenHead)
     {
            pCtxCamera->pOccupantCam = NULL;
         DEBUGMSG(CAM_ZONE_IOCTL,(TEXT("[CAM]CAM_Resource_API_Proc(): Resource CAM%d is released\n"), pCtxCamera->uCamID));
         return TRUE;
     }
     else
     {
         ERRMSG((TEXT("[CAM]CAM_Resource_API_Proc(): Resource CAM%d is occupied by other OpenContext\n"), pCtxCamera->uCamID));
         return FALSE;
     }
    }
    else
    {
        ERRMSG((TEXT("[CAM]CAM_Resource_API_Proc(): Invalid IOCTL code\n")));
     return FALSE;
    }

}


BOOL CAM_Camera_API_Proc(
    PHW_OPEN_INFO pOpenHead,
    DWORD dwCode,
    PBYTE pBufIn,
    DWORD dwLenIn,
    PBYTE pBufOut,
    DWORD dwLenOut,
    PDWORD pdwActualOut
    )
{
    BOOL bRet = TRUE;
    DWORD dwErr;
    PHW_INDEP_INFO  pCAMHead = pOpenHead->pCamHead;
    PCTX_CAMERA  pCtxCamera = pCAMHead->pCtxCamera;
    UINT32 uCamID = pCtxCamera->uCamID;
    PVOID pMarshalledInBuf = NULL;
    PVOID pMarshalledOutBuf = NULL;

    DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] ++%s()\n\r"), _T(__FUNCTION__)));

    if(pCtxCamera->pOccupantCam != pOpenHead)
    {
         ERRMSG((TEXT("[CAM]CAM_Camera_API_Proc(): dwCode:0x%08x, No access, OpenContext 0x%08x already has resource CAM%d\n"), dwCode, (DWORD)pCtxCamera->pOccupantCam, pCtxCamera->uCamID));
         return FALSE;
    }


    //--------------------------------
    // Processing IOCTL for post Processor
    //--------------------------------
    switch(dwCode)
    {
        case IOCTL_CAM_INIT:
            // In : Camera Port(A, B, MIPI, DMA)
            if(!pBufIn || dwLenIn < sizeof(CAMERA_MODULE_DESC))
            {
                ERRMSG((TEXT("dwCode:0x%x, Invalid Buffer : pBufIn:0x%x, dwLenIn:%d(Mustbe size of CAMIF_INPUTPORT)\n"), dwCode, pBufIn, dwLenIn));
                bRet = FALSE;
                break;
            }

            if(!CusCam_CameraInitialize(*(CAMERA_MODULE_DESC *)pBufIn, pCtxCamera->uCamID))
            {
                CusCam_CameraDeinitialize(pCtxCamera->uCamID);
                bRet=FALSE;
            }
            break;

        case IOCTL_CAM_DEINIT:
            CusCam_CameraDeinitialize(pCtxCamera->uCamID);
            break;

        case IOCTL_CAM_RESET:
            CusCam_Reset(pCtxCamera->uCamID);
            break;

        case IOCTL_CAM_PREVIEW_START:
            if(CusCam_StartPreview((PCAM_START_ARGS)pBufIn, pCtxCamera->uCamID) != ERROR_CAMIF_SUCCESS)
            {
                bRet = FALSE;
            }
            break;
        case IOCTL_CAM_PREVIEW_GETFRAME:
            // In : Virtual Address of Target Preview Frame Buffer in Client(Filter Driver)
            // Out : Virtual Address of Source Preview Frame Buffer in Raw Camera Driver
            if(!pBufIn)
            {
                ERRMSG((TEXT("dwCode:0x%x, Invalid Buffer : pBufIn:0x%x, dwLenIn:%d(Mustbe size of DWORD)\n"), dwCode, pBufIn, dwLenIn));
                bRet = FALSE;
                break;
            }
            if(!pBufOut || dwLenOut < sizeof(DWORD))
            {
                ERRMSG((TEXT("Invalid Buffer : pBufOut:0x%x, dwLenOut:%d\n"), pBufOut, dwLenOut));
                bRet = FALSE;
                break;
            }

            (*(LPDWORD)pBufOut) = CusCam_GetPreviewFrame((PVOID)pBufIn, pCtxCamera->uCamID);
            if(*pBufOut == 0)
            {
                bRet = FALSE;
            }

            break;

        case IOCTL_CAM_PREVIEW_STOP:
            CusCam_StopPreview(pCtxCamera->uCamID);
            break;

        case IOCTL_CAM_STILLCUT:
            // In : PCAM_STILLCUT_ARGS
            // Out : none
            // Current API does not allow still capture in video capturing.
            // Video capturing should be stopped before starting still capture.
            // The application should control these sequence.
            DBGMSG(CIF_FUNC && CIF_USR2,(_T("[CAM] IOCTL_CAM_STILLCUT\n\r")));

            dwErr = CusCam_StillCut((PCAM_STILLCUT_ARGS)pBufIn, pCtxCamera->uCamID);

            if( dwErr != ERROR_CAMIF_SUCCESS)
            {
                ERRMSG((TEXT("%s(): IoCode:0x%x, errCode:0x%x\n"), _T(__FUNCTION__), dwCode, dwErr));
                bRet = FALSE;
            }
            break;

        case IOCTL_CAM_STILL_STOP:
            CusCam_StopStillCut(pCtxCamera->uCamID);
            break;

        case IOCTL_CAM_JPEGSTILLCUT:
            // In : PCAM_STILLCUT_ARGS
            // Out : none
            // Current API does not allow still capture in video capturing.
            // Video capturing should be stopped before starting still capture.
            // The application should control these sequence.

            if(!pBufOut || dwLenOut < sizeof(DWORD))
            {
                ERRMSG((TEXT("Invalid Buffer : pBufOut:0x%x, dwLenOut:%d\n"), pBufOut, dwLenOut));
                bRet = FALSE;
                break;
            }

            (*(LPDWORD)pBufOut) = CusCam_JPEGStillCut((PCAM_STILLCUT_ARGS)pBufIn, pCtxCamera->uCamID);

            DBGMSG(CIF_FUNC && CIF_USR2,(TEXT("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n(*(LPDWORD)pBufOut) = %d\r\n"),(*(LPDWORD)pBufOut)));
            if((*(LPDWORD)pBufOut) == 0)
            {
                bRet = FALSE;
            }
            break;

        case IOCTL_CAM_VIDEO_START:
            dwErr = CusCam_StartVideo((PCAM_START_ARGS)pBufIn, pCtxCamera->uCamID);
            if( dwErr != ERROR_CAMIF_SUCCESS)
            {
                ERRMSG((TEXT("%s(): IoCode:0x%x, errCode:0x%x\n"), _T(__FUNCTION__), dwCode, dwErr));
                bRet = FALSE;
            }
            break;

        case IOCTL_CAM_VIDEO_GETFRAME:
            // In : Virtual Address of Target Video Frame Buffer in Client(Filter Driver)
            // Out : Virtual Address of Source Video Frame Buffer in Raw Camera Driver
            if(!pBufIn)
            {
                ERRMSG((TEXT("dwCode:0x%x, Invalid Buffer : pBufIn:0x%x, dwLenIn:%d(Mustbe size of DWORD)\n"), dwCode, pBufIn, dwLenIn));
                bRet = FALSE;
                break;
            }

            if(!pBufOut || dwLenOut < sizeof(DWORD))
            {
                ERRMSG((TEXT("Invalid Buffer : pBufOut:0x%x, dwLenOut:%d\n"), pBufOut, dwLenOut));
                bRet = FALSE;
                break;
            }

            (*(LPDWORD)pBufOut) = CusCam_GetVideoFrame((PVOID)pBufIn, pCtxCamera->uCamID);
            if(*pBufOut == 0)
            {
                bRet = FALSE;
            }

            break;

        case IOCTL_CAM_VIDEO_STOP:
            CusCam_StopVideo(pCtxCamera->uCamID);
            break;

        case IOCTL_CAM_SET_PREVIEWSOURCE:

            break;

        case IOCTL_CAM_SET_STILLSOURCE:

            break;

        case IOCTL_CAM_SET_VIDEOSOURCE:

            break;

        // Just Context Parameter Change
        case IOCTL_CAM_SET_PREVIEWSIZE:
            if(CusCam_SetPreviewSize((PCAM_IMGTYPE_ARGS)pBufIn, pCtxCamera->uCamID) != ERROR_CAMIF_SUCCESS)
            {
                bRet = FALSE;
            }
            break;
        // Just Context Parameter Change
        case IOCTL_CAM_SET_STILLSIZE:
            if(CusCam_SetStillSize((PCAM_IMGTYPE_ARGS)pBufIn, pCtxCamera->uCamID) != ERROR_CAMIF_SUCCESS)
            {
                bRet = FALSE;
            }
            break;
        // Just Context Parameter Change
        case IOCTL_CAM_SET_VIDEOSIZE:
            if(CusCam_SetVideoSize((PCAM_IMGTYPE_ARGS)pBufIn, pCtxCamera->uCamID) != ERROR_CAMIF_SUCCESS)
            {
                bRet = FALSE;
            }
            break;

        case IOCTL_CAM_SET_PROPERTY:
            break;

        case IOCTL_CAM_GET_ERROR:
            break;

        case IOCTL_CAM_SETCALLBACK:
            // In : CAM_CALLBACK_ARGS
            // Out : Copied Destination's Buffer address
            CAM_CALLBACK_ARGS *pArg;

            DBGMSG(CIF_FUNC && CIF_USR2, (_T("[CAM] %s() : IOCTL_CAM_SETCALLBACK\n\r"), _T(__FUNCTION__)));

            if(!pBufIn || dwLenIn < sizeof(CAM_CALLBACK_ARGS))
            {
                ERRMSG((TEXT("dwCode:0x%x, Invalid Buffer : pBufIn:0x%x, dwLenIn:%d(Mustbe size of CAM_CALLBACK_ARGS)\n"), dwCode, pBufIn, dwLenIn));
                bRet = FALSE;
                break;
            }
            if(!pBufOut || dwLenOut < sizeof(DWORD))
            {
                ERRMSG((TEXT("dwCode:0x%x, Invalid Buffer : pBufOut:0x%x, dwLenOut:%d(Mustbe size of DWORD)\n"), dwCode, pBufOut, dwLenOut));
                bRet = FALSE;
                break;
            }

            pArg = (CAM_CALLBACK_ARGS *)pBufIn;

            (*(LPDWORD)pBufOut) = CusCam_SetCallback(pArg);
            if(*pBufOut == 0)
            {
                bRet = FALSE;
            }
            break;

        case IOCTL_CAM_INIT_SENSOR:
            DBGMSG(CIF_FUNC && CIF_USR2, (_T("[%s] %s - IOCTL_CAM_INIT_SENSOR\r\n"), CUSCAM_MSG_HEADER, _T(__FUNCTION__)));

		RETAILMSG(1, (TEXT("IOCTL_CAM_INIT_SENSOR = 0x%x\r\n"),IOCTL_CAM_INIT_SENSOR));
            CAMERA_POST_ERROR ErrorRet;
            ErrorRet = pCtxCamera->pCameraIF->InitSensor();
            if(ErrorRet != ERROR_CAMIF_SUCCESS)
                bRet=FALSE;

            break;

        case IOCTL_CAM_DEINIT_SENSOR:
            DBGMSG(CIF_FUNC && CIF_USR2, (_T("[%s] %s - IOCTL_CAM_DEINIT_SENSOR\r\n"), CUSCAM_MSG_HEADER, _T(__FUNCTION__)));

            pCtxCamera->pCameraIF->DeInitSensor();
            break;

        case IOCTL_CAM_GETCURRENTFRAMENUM:
        {
            // In : NULL
            // Out : DWORD
            DWORD CurrentFrame;
            DBGMSG(CIF_FUNC && CIF_USR2, (_T("[CAM] %s() : IOCTL_CAM_GETCURRENTFRAMENUM\n\r"), _T(__FUNCTION__)));

            if(!pBufOut || dwLenOut < sizeof(DWORD))
            {
                ERRMSG((TEXT("dwCode:0x%x, Invalid Buffer : pBufOut:0x%x, dwLenOut:%d(Mustbe size of DWORD)\n"), dwCode, pBufOut, dwLenOut));
                bRet = FALSE;
                break;
            }

            CurrentFrame = CusCam_GetCurrentFrameNum(pCtxCamera->uCamID);
            DBGMSG(CIF_FUNC && CIF_USR2,(TEXT("Frame:%d\n"), CurrentFrame));
            (*(LPDWORD)pBufOut) = CurrentFrame;

            if(*pBufOut > MAX_PINGPONG_NUM - 1)
            {
                ERRMSG((TEXT("Invalid FrameNumber : pBufOut%d\n"), *pBufOut));
                bRet = FALSE;
            }
            if(pBufIn && dwLenIn == sizeof(DWORD))
            {
                DBGMSG(CIF_FUNC && CIF_USR2,(TEXT("Inputted Size .. So return Size value... : %d\n"), pCtxCamera->pCameraIF->m_Size_Capture_Data));
                 (*(LPDWORD)pBufIn) = pCtxCamera->pCameraIF->m_Size_Capture_Data;
            }

        }
        break;

        case IOCTL_CAM_PREPAREBUFFER:
        {
            // In : BUFFER_DESC
            // Out : P_CAMERA_DMA_BUFFER_INFO
            BUFFER_DESC *pArgs;

            DBGMSG(CIF_FUNC && CIF_USR2, (_T("[CAM] %s() : IOCTL_CAM_PREPAREBUFFER\n\r"), _T(__FUNCTION__)));

            if(!pBufIn || dwLenIn < sizeof(BUFFER_DESC))
            {
                ERRMSG((TEXT("Invalid Buffer : pBufIn:0x%x, dwLenIn:%d\n"), pBufIn, dwLenIn));
                bRet = FALSE;
                break;
            }

            pArgs = (BUFFER_DESC *)pBufIn;

            CusCam_CameraSetFormat(pArgs->Width, pArgs->Height, pArgs->Format, pArgs->Type, uCamID);

            if(!pBufOut || dwLenOut < sizeof(CAMERA_DMA_BUFFER_INFO))
            {
                ERRMSG((TEXT("Invalid Buffer : pBufOut:0x%x, dwLenOut:%d\n"), pBufOut, dwLenOut));
                bRet = FALSE;
                break;
            }

            bRet = CusCam_CameraPrepareBuffer((P_CAMERA_DMA_BUFFER_INFO)pBufOut, pArgs->Type, uCamID);
        }
        break;
        case IOCTL_CAM_RELEASEBUFFER:
        {
            // In : BUFFER_DESC
            // Out : P_CAMERA_DMA_BUFFER_INFO
            int BufferType;

            DBGMSG(CIF_FUNC && CIF_USR2, (_T("[CAM] %s() : IOCTL_CAM_RELEASEBUFFER\n\r"), _T(__FUNCTION__)));

            if(!pBufIn || dwLenIn < sizeof(int))
            {
                ERRMSG((TEXT("Invalid Buffer : pBufIn:0x%x, dwLenIn:%d\n"), pBufIn, dwLenIn));
                bRet = FALSE;
                break;
            }

            BufferType = (*(LPDWORD)pBufIn);

            bRet = CusCam_CameraReleaseBuffer(BufferType, uCamID); // Release DMA buffer

        }
        break;

        case IOCTL_CAM_SET_OPERATIONMODE:
        {
            // In : CAMIF_OPERATION_MODE
            // Out : none
            CAMIF_OPERATION_MODE pArgs;
            DBGMSG(CIF_FUNC && CIF_USR2, (_T("[CAM] %s() : IOCTL_CAM_SET_OPERATIONMODE\n\r"), _T(__FUNCTION__)));

            if(!pBufIn || dwLenIn < sizeof(CAMIF_OPERATION_MODE))
            {
                ERRMSG((TEXT("Invalid Buffer : pBufIn:0x%x, dwLenIn:%d\n"), pBufIn, dwLenIn));
                bRet = FALSE;
                break;
            }
            pArgs = (CAMIF_OPERATION_MODE) *pBufIn;

            bRet = CusCam_SetOperationMode(pArgs, pCtxCamera->uCamID);
        }
        break;
        case IOCTL_CAM_SET_REGISTER:
        {
        }
        break;

        case IOCTL_CAM_IMAGE_EFFECT_ON:
        {
            // In : DWORD //ENUM IMAGE_EFFECT
            // Out : None
            if(!pBufIn || dwLenIn < sizeof(DWORD))
            {
                ERRMSG((TEXT("dwCode:0x%x, Invalid Buffer : pBufIn:0x%x, dwLenIn:%d(Mustbe size of DWORD)\n"), dwCode, pBufIn, dwLenIn));
                bRet = FALSE;
                break;
            }

            pCtxCamera->pCameraIF->ImageEffectOn(*pBufIn);
        }
        break;

        case IOCTL_CAM_IMAGE_EFFECT_OFF:
        {
            pCtxCamera->pCameraIF->ImageEffectOff();

        }
        break;

        case IOCTL_CAM_CAPTURECONTROL:
        {
            // In : DWORD
            // Out : none
            if(!pBufIn || dwLenIn < sizeof(DWORD))
            {
                ERRMSG((TEXT("dwCode:0x%x, Invalid Buffer : pBufIn:0x%x, dwLenIn:%d(Mustbe size of DWORD)\n"), dwCode, pBufIn, dwLenIn));
                bRet = FALSE;
                break;
            }

            pCtxCamera->pCameraIF->CaptureControl(*pBufIn);
        }
        break;

        case IOCTL_CAM_ZOOM:
        {
            // In : DWORD -> ZoomRatio
            // Out : none
            DBGMSG(CIF_FUNC && CIF_USR2, (_T("[CAM] %s() : IOCTL_CAM_ZOOM\n\r"), _T(__FUNCTION__)));

            if(!pBufIn || dwLenIn < sizeof(DWORD))
            {
                ERRMSG((TEXT("Invalid Buffer : pBufIn:0x%x, dwLenIn:%d\n"), pBufIn, dwLenIn));
                bRet = FALSE;
                break;
            }

            bRet = CusCam_Zoom(*pBufIn, pCtxCamera->uCamID);
        }
        break;

        // This IOCTL will turn on/off CameraInterface IP clock, does not include Camera Module Main Clock
        case IOCTL_CAM_CLOCK_ONOFF:
        {
            // In : DWORD -> On/Off
            // Out : none
            DBGMSG(CIF_FUNC && CIF_USR2, (_T("[CAM] %s() : IOCTL_CAM_CLOCK_ONOFF\n\r"), _T(__FUNCTION__)));

            if(!pBufIn || dwLenIn < sizeof(DWORD))
            {
                ERRMSG((TEXT("Invalid Buffer : pBufIn:0x%x, dwLenIn:%d\n"), pBufIn, dwLenIn));
                bRet = FALSE;
                break;
            }

            pCtxCamera->pCameraIF->SetCamIFClockOn(*pBufIn);
        }
        break;

        case IOCTL_CAM_SET_PCLK:
        {
            // In : DWORD -> Clock frequency(in MHz)
            // Out : none
            DBGMSG(CIF_FUNC && CIF_USR2, (_T("[CAM] %s() : IOCTL_CAM_SET_PCLK\n\r"), _T(__FUNCTION__)));

            if(!pBufIn || dwLenIn < sizeof(DWORD))
            {
                ERRMSG((TEXT("Invalid Buffer : pBufIn:0x%x, dwLenIn:%d\n"), pBufIn, dwLenIn));
                bRet = FALSE;
                break;
            }

            pCtxCamera->pCameraIF->SetPixelClock( *(reinterpret_cast<DWORD *>(pBufIn)));
        }
        break;

        case IOCTL_CAM_SET_DMA_PARAMETER:
        {
            // In : CAM_DMA_PARAMETER_ARGS
            // Out : DWORD -> ErrorCode (OK, Illegal Value)
            DBGMSG(CIF_FUNC && CIF_USR2, (_T("[CAM] %s() : IOCTL_CAM_SET_DMA_PARAMETER\n\r"), _T(__FUNCTION__)));

            if(!pBufIn || dwLenIn < sizeof(CAM_DMA_PARAMETER_ARGS))
            {
                ERRMSG((TEXT("Invalid Buffer : pBufIn:0x%x, dwLenIn:%d\n"), pBufIn, dwLenIn));
                bRet = FALSE;
                break;
            }
#if _WIN32_WCE >= 600
            if(FAILED(CeOpenCallerBuffer(&pMarshalledInBuf, pBufIn, dwLenIn, ARG_I_PTR, TRUE)))
            {
                ERRMSG((TEXT("[CAM] %s() : Invalid Buffers: CeOpenCallerBuffer failed for IN buf.\r\n"), _T(__FUNCTION__)));
                bRet = FALSE;
                break;
            }
#else
            pMarshalledInBuf = new CAM_DMA_PARAMETER_ARGS;
            if(pMarshalledInBuf == NULL)
            {
                ERRMSG((TEXT("Memory is not enough try\n")));
                bRet = FALSE;
                break;
            }
            memcpy(pMarshalledInBuf, pBufIn, sizeof(CAM_DMA_PARAMETER_ARGS));
#endif
//            pCtxCamera->pCameraIF->SetDMARegister(static_cast<CAM_DMA_PARAMETER_ARGS *>(pMarshalledInBuf));
#if _WIN32_WCE >= 600
            if(FAILED(CeCloseCallerBuffer(pMarshalledInBuf, pBufIn, dwLenIn, ARG_I_PTR)))
            {
                ERRMSG((TEXT("IIC_IOControl: CeCloseCallerBuffer failed in IOCTL_IIC_READ for IN buf.\r\n")));
                bRet = FALSE;
                break;
            }
#else
            delete pMarshalledInBuf;
#endif

        }
        break;


        default:    // This is filtered above switch statement
            bRet = FALSE;
            break;
    }

    DBGMSG(CIF_FUNC && CIF_USR2, (_T("[CAM] --%s(): ret:%d\n\r"), _T(__FUNCTION__), bRet));

    return bRet;
}

