---
 drivers/media/dvb/frontends/drx_driver.c | 1504 ++++++++++++++++++++++++++++++
 1 files changed, 1504 insertions(+), 0 deletions(-)
 create mode 100644 drivers/media/dvb/frontends/drx_driver.c

diff --git a/drivers/media/dvb/frontends/drx_driver.c 
b/drivers/media/dvb/frontends/drx_driver.c
new file mode 100644
index 0000000..1f58de7
--- /dev/null
+++ b/drivers/media/dvb/frontends/drx_driver.c
@@ -0,0 +1,1504 @@
+/*
+  Copyright (c), 2004-2005,2007-2010 Trident Microsystems, Inc.
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice,
+    this list of conditions and the following disclaimer.
+  * Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+       and/or other materials provided with the distribution.
+  * Neither the name of Trident Microsystems nor Hauppauge Computer Works
+    nor the names of its contributors may be used to endorse or promote
+       products derived from this software without specific prior written
+       permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+* \file $Id: drx_driver.c,v 1.40 2010/01/12 01:24:56 lfeng Exp $
+*
+* \brief Generic DRX functionality, DRX driver core.
+*
+*/
+
+/*------------------------------------------------------------------------------
+INCLUDE FILES
+------------------------------------------------------------------------------*/
+#include "drx_driver.h"
+#include "bsp_host.h"
+
+#define VERSION_FIXED 0
+#if     VERSION_FIXED
+#define VERSION_MAJOR 0
+#define VERSION_MINOR 0
+#define VERSION_PATCH 0
+#else
+#include "drx_driver_version.h"
+#endif
+
+/*------------------------------------------------------------------------------
+DEFINES
+------------------------------------------------------------------------------*/
+
+/*============================================================================*/
+/*=== MICROCODE RELATED DEFINES 
==============================================*/
+/*============================================================================*/
+
+/** \brief Magic word for checking correct Endianess of microcode data. */
+#ifndef DRX_UCODE_MAGIC_WORD
+#define DRX_UCODE_MAGIC_WORD         ((((u16_t)'H')<<8)+((u16_t)'L'))
+#endif
+
+/** \brief CRC flag in ucode header, flags field. */
+#ifndef DRX_UCODE_CRC_FLAG
+#define DRX_UCODE_CRC_FLAG           (0x0001)
+#endif
+
+/** \brief Compression flag in ucode header, flags field. */
+#ifndef DRX_UCODE_COMPRESSION_FLAG
+#define DRX_UCODE_COMPRESSION_FLAG   (0x0002)
+#endif
+
+/** \brief Maximum size of buffer used to verify the microcode.
+   Must be an even number. */
+#ifndef DRX_UCODE_MAX_BUF_SIZE
+#define DRX_UCODE_MAX_BUF_SIZE       (DRXDAP_MAX_RCHUNKSIZE)
+#endif
+#if DRX_UCODE_MAX_BUF_SIZE & 1
+#error DRX_UCODE_MAX_BUF_SIZE must be an even number
+#endif
+
+/*============================================================================*/
+/*=== CHANNEL SCAN RELATED DEFINES 
===========================================*/
+/*============================================================================*/
+
+/**
+* \brief Maximum progress indication.
+*
+* Progress indication will run from 0 upto DRX_SCAN_MAX_PROGRESS during scan.
+*
+*/
+#ifndef DRX_SCAN_MAX_PROGRESS
+#define DRX_SCAN_MAX_PROGRESS 1000
+#endif
+
+/*============================================================================*/
+/*=== MACROS 
=================================================================*/
+/*============================================================================*/
+
+#define DRX_ISPOWERDOWNMODE(mode) ((mode == DRX_POWER_MODE_9) || \
+                                       (mode == DRX_POWER_MODE_10) || \
+                                       (mode == DRX_POWER_MODE_11) || \
+                                       (mode == DRX_POWER_MODE_12) || \
+                                       (mode == DRX_POWER_MODE_13) || \
+                                       (mode == DRX_POWER_MODE_14) || \
+                                       (mode == DRX_POWER_MODE_15) || \
+                                       (mode == DRX_POWER_MODE_16) || \
+                                       (mode == DRX_POWER_DOWN))
+
+/*------------------------------------------------------------------------------
+GLOBAL VARIABLES
+------------------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------------------
+STRUCTURES
+------------------------------------------------------------------------------*/
+/** \brief  Structure of the microcode block headers */
+typedef struct {
+       u32_t addr;    /**<  Destination address of the data in this block */
+       u16_t size;    /**<  Size of the block data following this header 
counted in
+                       16 bits words */
+       u16_t flags;   /**<  Flags for this data block:
+                       - bit[0]= CRC on/off
+                       - bit[1]= compression on/off
+                       - bit[15..2]=reserved */
+       u16_t CRC;     /**<  CRC value of the data block, only valid if CRC 
flag is
+                       set. */
+} DRXUCodeBlockHdr_t, *pDRXUCodeBlockHdr_t;
+
+/*------------------------------------------------------------------------------
+FUNCTIONS
+------------------------------------------------------------------------------*/
+
+/*============================================================================*/
+/*============================================================================*/
+/*== Channel Scan Functions 
==================================================*/
+/*============================================================================*/
+/*============================================================================*/
+
+#ifndef DRX_EXCLUDE_SCAN
+
+/* Prototype of default scanning function */
+static DRXStatus_t
+ScanFunctionDefault(void                 *scanContext,
+                       DRXScanCommand_t     scanCommand,
+                       pDRXChannel_t        scanChannel,
+                       pBool_t              getNextChannel);
+
+/**
+* \brief Get pointer to scanning function.
+* \param demod:    Pointer to demodulator instance.
+* \return DRXScanFunc_t.
+*/
+static DRXScanFunc_t
+GetScanFunction(pDRXDemodInstance_t demod)
+{
+       pDRXCommonAttr_t commonAttr = (pDRXCommonAttr_t)(NULL);
+       DRXScanFunc_t    scanFunc   = (DRXScanFunc_t)(NULL);
+
+       /* get scan function from common attributes */
+       commonAttr  = (pDRXCommonAttr_t)demod->myCommonAttr;
+       scanFunc    = commonAttr->scanFunction;
+
+       if (scanFunc != NULL) {
+               /* return device-specific scan function if it's not NULL */
+               return scanFunc;
+       }
+       /* otherwise return default scan function in core driver */
+       return &ScanFunctionDefault;
+}
+
+/**
+* \brief Get Context pointer.
+* \param demod:    Pointer to demodulator instance.
+* \param scanContext: Context Pointer.
+* \return DRXScanFunc_t.
+*/
+void  *GetScanContext(pDRXDemodInstance_t  demod,
+                       void                 *scanContext)
+{
+       pDRXCommonAttr_t commonAttr = (pDRXCommonAttr_t)(NULL);
+
+       /* get scan function from common attributes */
+       commonAttr  = (pDRXCommonAttr_t) demod->myCommonAttr;
+       scanContext = commonAttr->scanContext;
+
+       if (scanContext == NULL) {
+               scanContext = (void *) demod;
+       }
+
+       return scanContext;
+}
+
+/**
+* \brief Wait for lock while scanning.
+* \param demod:    Pointer to demodulator instance.
+* \param lockStat: Pointer to bool indicating if end result is lock or not.
+* \return DRXStatus_t.
+* \retval DRX_STS_OK:    Success
+* \retval DRX_STS_ERROR: I2C failure or bsp function failure.
+*
+* Wait until timeout, desired lock or NEVER_LOCK.
+* Assume:
+* - lock function returns : at least DRX_NOT_LOCKED and a lock state
+*   higher than DRX_NOT_LOCKED.
+* - BSP has a clock function to retrieve a millisecond ticker value.
+* - BSP has a sleep function to enable sleep of n millisecond.
+*
+* In case DRX_NEVER_LOCK is returned the poll-wait will be aborted.
+*
+*/
+static DRXStatus_t
+ScanWaitForLock(pDRXDemodInstance_t demod,
+                       pBool_t             isLocked)
+{
+       Bool_t           doneWaiting        = FALSE;
+       DRXLockStatus_t  lockState          = DRX_NOT_LOCKED;
+       DRXLockStatus_t  desiredLockState   = DRX_NOT_LOCKED;
+       u32_t            timeoutValue       = 0;
+       u32_t            startTimeLockStage = 0;
+       u32_t            currentTime        = 0;
+       u32_t            timerValue         = 0;
+
+       *isLocked            = FALSE;
+       timeoutValue         = (u32_t) 
demod->myCommonAttr->scanDemodLockTimeout;
+       desiredLockState     = demod->myCommonAttr->scanDesiredLock;
+       startTimeLockStage   = DRXBSP_HST_Clock();
+
+       /* Start polling loop, checking for lock & timeout */
+       while (doneWaiting == FALSE)
+       {
+
+               if (DRX_Ctrl(demod, DRX_CTRL_LOCK_STATUS, &lockState) !=
+                                                       DRX_STS_OK) {
+                       return DRX_STS_ERROR;
+               }
+               currentTime = DRXBSP_HST_Clock();
+
+               timerValue = currentTime - startTimeLockStage;
+               if (lockState >= desiredLockState) {
+                       *isLocked = TRUE;
+                       doneWaiting = TRUE;
+               }  /* if (lockState >= desiredLockState) .. */
+               else if (lockState == DRX_NEVER_LOCK) {
+                       doneWaiting = TRUE;
+               }  /* if (lockState == DRX_NEVER_LOCK) .. */
+               else if (timerValue > timeoutValue) {
+                       /* lockState == DRX_NOT_LOCKED  and timeout */
+                       doneWaiting = TRUE;
+               }
+               else {
+                       if (DRXBSP_HST_Sleep(10) != DRX_STS_OK) {
+                       return DRX_STS_ERROR;
+                       }
+               }  /* if (timerValue > timeoutValue) .. */
+
+       } /* while */
+
+       return DRX_STS_OK;
+}
+
+/*============================================================================*/
+
+/**
+* \brief Determine next frequency to scan.
+* \param demod: Pointer to demodulator instance.
+* \param skip : Minimum frequency step to take.
+* \return DRXStatus_t.
+* \retval DRX_STS_OK:          Succes.
+* \retval DRX_STS_INVALID_ARG: Invalid frequency plan.
+*
+* Helper function for CtrlScanNext() function.
+* Compute next frequency & index in frequency plan.
+* Check if scan is ready.
+*
+*/
+static DRXStatus_t
+ScanPrepareNextScan (pDRXDemodInstance_t  demod,
+                       DRXFrequency_t       skip)
+{
+       pDRXCommonAttr_t     commonAttr        = (pDRXCommonAttr_t)(NULL);
+       u16_t                tableIndex        = 0;
+       u16_t                frequencyPlanSize = 0;
+       pDRXFrequencyPlan_t  frequencyPlan     = (pDRXFrequencyPlan_t)(NULL);
+       DRXFrequency_t       nextFrequency     = 0;
+       DRXFrequency_t       tunerMinFrequency = 0;
+       DRXFrequency_t       tunerMaxFrequency = 0;
+
+       commonAttr        = (pDRXCommonAttr_t)demod->myCommonAttr;
+       tableIndex        = commonAttr->scanFreqPlanIndex;
+       frequencyPlan     = commonAttr->scanParam->frequencyPlan;
+       nextFrequency     = commonAttr->scanNextFrequency;
+       tunerMinFrequency = commonAttr->tunerMinFreqRF;
+       tunerMaxFrequency = commonAttr->tunerMaxFreqRF;
+
+       do
+       {
+               /* Search next frequency to scan */
+
+               /* always take at least one step */
+               (commonAttr->scanChannelsScanned) ++;
+               nextFrequency += frequencyPlan[tableIndex].step;
+               skip -= frequencyPlan[tableIndex].step;
+
+               /* and then as many steps necessary to exceed 'skip'
+                without exceeding end of the band */
+               while ((skip > 0) &&
+                       (nextFrequency <= frequencyPlan[tableIndex].last))
+               {
+                       (commonAttr->scanChannelsScanned) ++;
+                       nextFrequency += frequencyPlan[tableIndex].step;
+                       skip -= frequencyPlan[tableIndex].step;
+               }
+               /* reset skip, in case we move to the next band later */
+               skip = 0;
+
+               if (nextFrequency > frequencyPlan[tableIndex].last) {
+                       /* reached end of this band */
+                       tableIndex++;
+                       frequencyPlanSize = 
commonAttr->scanParam->frequencyPlanSize;
+                       if (tableIndex >= frequencyPlanSize) {
+                               /* reached end of frequency plan */
+                               commonAttr->scanReady = TRUE;
+                       }
+                       else {
+                               nextFrequency = frequencyPlan[tableIndex].first;
+                       }
+               }
+               if (nextFrequency > (tunerMaxFrequency)) {
+                       /* reached end of tuner range */
+                       commonAttr->scanReady = TRUE;
+               }
+       } while((nextFrequency < tunerMinFrequency) &&
+                       (commonAttr->scanReady == FALSE));
+
+       /* Store new values */
+       commonAttr->scanFreqPlanIndex = tableIndex;
+       commonAttr->scanNextFrequency = nextFrequency;
+
+       return DRX_STS_OK;
+}
+
+/*============================================================================*/
+
+/**
+* \brief Default DTV scanning function.
+*
+* \param demod:          Pointer to demodulator instance.
+* \param scanCommand:    Scanning command: INIT, NEXT or STOP.
+* \param scanChannel:    Channel to check: frequency and bandwidth, others AUTO
+* \param getNextChannel: Return TRUE if next frequency is desired at next call
+*
+* \return DRXStatus_t.
+* \retval DRX_STS_OK:      Channel found, DRX_CTRL_GET_CHANNEL can be used
+*                             to retrieve channel parameters.
+* \retval DRX_STS_BUSY:    Channel not found (yet).
+* \retval DRX_STS_ERROR:   Something went wrong.
+*
+* scanChannel and getNextChannel will be NULL for INIT and STOP.
+*/
+static DRXStatus_t
+ScanFunctionDefault (void                 *scanContext,
+                       DRXScanCommand_t     scanCommand,
+                       pDRXChannel_t        scanChannel,
+                       pBool_t              getNextChannel)
+{
+       pDRXDemodInstance_t demod = NULL;
+       DRXStatus_t status   = DRX_STS_ERROR;
+       Bool_t      isLocked = FALSE;
+
+       demod = (pDRXDemodInstance_t) scanContext;
+
+       if (scanCommand != DRX_SCAN_COMMAND_NEXT) {
+               /* just return OK if not doing "scan next" */
+               return DRX_STS_OK;
+       }
+
+       *getNextChannel = FALSE;
+
+       status = DRX_Ctrl (demod, DRX_CTRL_SET_CHANNEL, scanChannel);
+       if (status != DRX_STS_OK) {
+               return (status);
+       }
+
+       status = ScanWaitForLock (demod, &isLocked);
+       if (status != DRX_STS_OK) {
+               return status;
+       }
+
+       /* done with this channel, move to next one */
+       *getNextChannel = TRUE;
+
+       if (isLocked == FALSE) {
+               /* no channel found */
+               return DRX_STS_BUSY;
+       }
+       /* channel found */
+       return DRX_STS_OK;
+}
+
+/*============================================================================*/
+
+/**
+* \brief Initialize for channel scan.
+* \param demod:     Pointer to demodulator instance.
+* \param scanParam: Pointer to scan parameters.
+* \return DRXStatus_t.
+* \retval DRX_STS_OK:          Initialized for scan.
+* \retval DRX_STS_ERROR:       No overlap between frequency plan and tuner
+*                              range.
+* \retval DRX_STS_INVALID_ARG: Wrong parameters.
+*
+* This function should be called before starting a complete channel scan.
+* It will prepare everything for a complete channel scan.
+* After calling this function the DRX_CTRL_SCAN_NEXT control function can be
+* used to perform the actual scanning. Scanning will start at the first
+* center frequency of the frequency plan that is within the tuner range.
+*
+*/
+static DRXStatus_t
+CtrlScanInit(pDRXDemodInstance_t  demod,
+               pDRXScanParam_t      scanParam)
+{
+       DRXStatus_t       status            = DRX_STS_ERROR;
+       pDRXCommonAttr_t  commonAttr        =(pDRXCommonAttr_t)(NULL);
+       DRXFrequency_t    maxTunerFreq      = 0;
+       DRXFrequency_t    minTunerFreq      = 0;
+       u16_t             nrChannelsInPlan  = 0;
+       u16_t             i                 = 0;
+       void              *scanContext      = NULL;
+
+       commonAttr              = (pDRXCommonAttr_t)demod->myCommonAttr;
+       commonAttr->scanActive  = TRUE;
+
+       /* invalidate a previous SCAN_INIT */
+       commonAttr->scanParam         = (pDRXScanParam_t)(NULL);
+       commonAttr->scanNextFrequency = 0;
+
+       /* Check parameters */
+       if (((demod->myTuner == NULL)          &&
+               (scanParam->numTries !=1))        ||
+
+               (scanParam == NULL)                ||
+               (scanParam->numTries == 0)         ||
+               (scanParam->frequencyPlan == NULL) ||
+               (scanParam->frequencyPlanSize == 0)
+               ) {
+               commonAttr->scanActive = FALSE;
+               return DRX_STS_INVALID_ARG;
+       }
+
+       /* Check frequency plan contents */
+       maxTunerFreq = commonAttr->tunerMaxFreqRF;
+       minTunerFreq = commonAttr->tunerMinFreqRF;
+       for(i = 0; i < (scanParam->frequencyPlanSize); i++) {
+               DRXFrequency_t width = 0;
+               DRXFrequency_t step      = scanParam->frequencyPlan[i].step;
+               DRXFrequency_t firstFreq = scanParam->frequencyPlan[i].first;
+               DRXFrequency_t lastFreq  = scanParam->frequencyPlan[i].last;
+               DRXFrequency_t minFreq = 0;
+               DRXFrequency_t maxFreq = 0;
+
+               if (step <= 0) {
+                       /* Step must be positive and non-zero */
+                       commonAttr->scanActive = FALSE;
+                       return DRX_STS_INVALID_ARG;
+               }
+
+               if (firstFreq > lastFreq) {
+                       /* First center frequency is higher than last center 
frequency */
+                       commonAttr->scanActive = FALSE;
+                       return DRX_STS_INVALID_ARG;
+               }
+
+               width = lastFreq - firstFreq;
+
+               if ((width % step) != 0) {
+                       /* Difference between last and first center frequency 
is not
+                       an integer number of steps */
+                       commonAttr->scanActive = FALSE;
+                       return DRX_STS_INVALID_ARG;
+               }
+
+               /* Check if frequency plan entry intersects with tuner range */
+               if (lastFreq >= minTunerFreq) {
+                       if (firstFreq <= maxTunerFreq) {
+                               if (firstFreq >= minTunerFreq) {
+                                       minFreq = firstFreq;
+                               }
+                               else {
+                                       DRXFrequency_t n = 0;
+
+                                       n = (minTunerFreq - firstFreq) / step;
+                                       if (((minTunerFreq - firstFreq) % step) 
!= 0) {
+                                               n++;
+                                       }
+                               minFreq = firstFreq + n*step;
+                               }
+
+                               if (lastFreq <= maxTunerFreq) {
+                                       maxFreq = lastFreq;
+                               }
+                               else {
+                                       DRXFrequency_t n=0;
+
+                                       n=(lastFreq - maxTunerFreq)/step;
+                                       if (((lastFreq - maxTunerFreq)%step) 
!=0) {
+                                               n++;
+                                       }
+                                       maxFreq = lastFreq - n*step;
+                               }
+                       }
+               }
+
+               /* Keep track of total number of channels within tuner range
+                in this frequency plan. */
+               if ((minFreq !=0) && (maxFreq != 0)) {
+                       nrChannelsInPlan += (u16_t)(((maxFreq-minFreq) / step) 
+1);
+
+                       /* Determine first frequency (within tuner range) to 
scan */
+                       if (commonAttr->scanNextFrequency == 0) {
+                               commonAttr->scanNextFrequency = minFreq;
+                               commonAttr->scanFreqPlanIndex = i;
+                       }
+               }
+
+       }/* for (...) */
+
+       if (nrChannelsInPlan == 0) {
+               /* Tuner range and frequency plan ranges do not overlap */
+               commonAttr->scanActive = FALSE;
+               return DRX_STS_ERROR;
+       }
+
+       /* Store parameters */
+       commonAttr->scanReady            = FALSE;
+       commonAttr->scanMaxChannels      = nrChannelsInPlan;
+       commonAttr->scanChannelsScanned  = 0;
+       commonAttr->scanParam            = scanParam; /* SCAN_NEXT is now 
allowed */
+
+       scanContext = GetScanContext(demod, scanContext);
+
+       status = (*(GetScanFunction(demod)))
+               (scanContext, DRX_SCAN_COMMAND_INIT, NULL, NULL);
+
+       commonAttr->scanActive = FALSE;
+
+       return DRX_STS_OK;
+}
+
+/*============================================================================*/
+
+/**
+* \brief Stop scanning.
+* \param demod:         Pointer to demodulator instance.
+* \return DRXStatus_t.
+* \retval DRX_STS_OK:          Scan stopped.
+* \retval DRX_STS_ERROR:       Something went wrong.
+* \retval DRX_STS_INVALID_ARG: Wrong parameters.
+*/
+static DRXStatus_t
+CtrlScanStop(pDRXDemodInstance_t  demod)
+{
+       DRXStatus_t       status         = DRX_STS_ERROR;
+       pDRXCommonAttr_t  commonAttr     = (pDRXCommonAttr_t) (NULL);
+       void              *scanContext   = NULL;
+
+       commonAttr              = (pDRXCommonAttr_t)demod->myCommonAttr;
+       commonAttr->scanActive  = TRUE;
+
+       if ((commonAttr->scanParam == NULL) ||
+               (commonAttr->scanMaxChannels == 0)) {
+               /* Scan was not running, just return OK */
+               commonAttr->scanActive = FALSE;
+               return DRX_STS_OK;
+       }
+
+       /* Call default or device-specific scanning stop function */
+       scanContext = GetScanContext(demod, scanContext);
+
+       status = (*(GetScanFunction(demod)))
+               (scanContext, DRX_SCAN_COMMAND_STOP, NULL, NULL);
+
+       /* All done, invalidate scan-init */
+       commonAttr->scanParam         = NULL;
+       commonAttr->scanMaxChannels   = 0;
+       commonAttr->scanActive        = FALSE;
+
+       return status;
+}
+
+/*============================================================================*/
+
+/**
+* \brief Scan for next channel.
+* \param demod:         Pointer to demodulator instance.
+* \param scanProgress:  Pointer to scan progress.
+* \return DRXStatus_t.
+* \retval DRX_STS_OK:          Channel found, DRX_CTRL_GET_CHANNEL can be used
+*                              to retrieve channel parameters.
+* \retval DRX_STS_BUSY:        Tried part of the channels, as specified in
+*                              numTries field of scan parameters. At least one
+*                              more call to DRX_CTRL_SCAN_NEXT is needed to
+*                              complete scanning.
+* \retval DRX_STS_READY:       Reached end of scan range.
+* \retval DRX_STS_ERROR:       Something went wrong.
+* \retval DRX_STS_INVALID_ARG: Wrong parameters. The scanProgress may be NULL.
+*
+* Progress indication will run from 0 upto DRX_SCAN_MAX_PROGRESS during scan.
+*
+*/
+static DRXStatus_t
+CtrlScanNext (pDRXDemodInstance_t  demod,
+               pu16_t               scanProgress)
+{
+       pDRXCommonAttr_t  commonAttr  = (pDRXCommonAttr_t)(NULL);
+       pBool_t           scanReady   = (pBool_t)(NULL);
+       u16_t             maxProgress = DRX_SCAN_MAX_PROGRESS;
+       u32_t             numTries    = 0;
+       u32_t             i           = 0;
+
+       commonAttr              = (pDRXCommonAttr_t)demod->myCommonAttr;
+
+       /* Check scan parameters */
+       if (scanProgress == NULL) {
+               commonAttr->scanActive = FALSE;
+               return DRX_STS_INVALID_ARG;
+       }
+
+       *scanProgress           = 0;
+       commonAttr->scanActive  = TRUE;
+       if ((commonAttr->scanParam == NULL) ||
+               (commonAttr->scanMaxChannels == 0)) {
+               /* CtrlScanInit() was not called succesfully before 
CtrlScanNext() */
+               commonAttr->scanActive = FALSE;
+               return DRX_STS_ERROR;
+       }
+
+       *scanProgress = (u16_t)(((commonAttr->scanChannelsScanned)*
+                               ((u32_t)(maxProgress))) /
+                               (commonAttr->scanMaxChannels));
+
+       /* Scan */
+       numTries    = commonAttr->scanParam->numTries;
+       scanReady   = &(commonAttr->scanReady);
+
+       for (i = 0; ((i < numTries) && ((*scanReady) == FALSE)); i++) {
+               DRXChannel_t         scanChannel    = { 0 };
+               DRXStatus_t          status         = DRX_STS_ERROR;
+               pDRXFrequencyPlan_t  freqPlan       = (pDRXFrequencyPlan_t) 
(NULL);
+               Bool_t               nextChannel    = FALSE;
+               void                 *scanContext   = NULL;
+
+               /* Next channel to scan */
+               freqPlan =
+                       
&(commonAttr->scanParam->frequencyPlan[commonAttr->scanFreqPlanIndex]);
+               scanChannel.frequency      = commonAttr->scanNextFrequency;
+               scanChannel.bandwidth      = freqPlan->bandwidth;
+               scanChannel.mirror         = DRX_MIRROR_AUTO;
+               scanChannel.constellation  = DRX_CONSTELLATION_AUTO;
+               scanChannel.hierarchy      = DRX_HIERARCHY_AUTO;
+               scanChannel.priority       = DRX_PRIORITY_HIGH;
+               scanChannel.coderate       = DRX_CODERATE_AUTO;
+               scanChannel.guard          = DRX_GUARD_AUTO;
+               scanChannel.fftmode        = DRX_FFTMODE_AUTO;
+               scanChannel.classification = DRX_CLASSIFICATION_AUTO;
+               scanChannel.symbolrate     = 0;
+               scanChannel.interleavemode = DRX_INTERLEAVEMODE_AUTO;
+               scanChannel.ldpc           = DRX_LDPC_AUTO;
+               scanChannel.carrier        = DRX_CARRIER_AUTO;
+               scanChannel.framemode      = DRX_FRAMEMODE_AUTO;
+               scanChannel.pilot          = DRX_PILOT_AUTO;
+
+               /* Call default or device-specific scanning function */
+               scanContext = GetScanContext(demod, scanContext);
+
+               status = (*(GetScanFunction(demod)))
+                       
(scanContext,DRX_SCAN_COMMAND_NEXT,&scanChannel,&nextChannel);
+
+               /* Proceed to next channel if requested */
+               if (nextChannel == TRUE) {
+                       DRXStatus_t nextStatus = DRX_STS_ERROR;
+                       DRXFrequency_t skip = 0;
+
+                       if (status == DRX_STS_OK) {
+                               /* a channel was found, so skip some frequency 
steps */
+                               skip = commonAttr->scanParam->skip;
+                       }
+                       nextStatus = ScanPrepareNextScan(demod, skip);
+
+                       /* keep track of progress */
+                       *scanProgress = 
(u16_t)(((commonAttr->scanChannelsScanned)*
+                                       ((u32_t)(maxProgress)))/
+                                       (commonAttr->scanMaxChannels));
+
+                       if (nextStatus != DRX_STS_OK) {
+                               commonAttr->scanActive = FALSE;
+                               return (nextStatus);
+                       }
+               }
+               if (status != DRX_STS_BUSY) {
+                       /* channel found or error */
+                       commonAttr->scanActive = FALSE;
+                       return status;
+               }
+       } /* for (i = 0; i < (... numTries); i++) */
+
+       if ((*scanReady) == TRUE) {
+               /* End of scan reached: call stop-scan, ignore any error */
+               CtrlScanStop(demod);
+               commonAttr->scanActive = FALSE;
+               return (DRX_STS_READY);
+       }
+
+       commonAttr->scanActive = FALSE;
+
+       return DRX_STS_BUSY;
+}
+
+#endif /* #ifndef DRX_EXCLUDE_SCAN */
+
+/*============================================================================*/
+
+/**
+* \brief Program tuner.
+* \param demod:         Pointer to demodulator instance.
+* \param tunerChannel:  Pointer to tuning parameters.
+* \return DRXStatus_t.
+* \retval DRX_STS_OK:          Tuner programmed successfully.
+* \retval DRX_STS_ERROR:       Something went wrong.
+* \retval DRX_STS_INVALID_ARG: Wrong parameters.
+*
+* tunerChannel passes parameters to program the tuner,
+* but also returns the actual RF and IF frequency from the tuner.
+*
+*/
+static DRXStatus_t
+CtrlProgramTuner(pDRXDemodInstance_t  demod,
+               pDRXChannel_t        channel)
+{
+       pDRXCommonAttr_t  commonAttr     = (pDRXCommonAttr_t)(NULL);
+       DRXStandard_t     standard       = DRX_STANDARD_UNKNOWN;
+       TUNERMode_t       tunerMode      = 0;
+       DRXStatus_t       status         = DRX_STS_ERROR;
+       DRXFrequency_t    ifFrequency    = 0;
+       Bool_t            tunerSlowMode  = FALSE;
+
+       /* can't tune without a tuner */
+       if (demod->myTuner == NULL) {
+               return DRX_STS_INVALID_ARG;
+       }
+
+       commonAttr = (pDRXCommonAttr_t) demod->myCommonAttr;
+
+       /* select analog or digital tuner mode based on current standard */
+       if (DRX_Ctrl(demod, DRX_CTRL_GET_STANDARD, &standard) != DRX_STS_OK) {
+               return DRX_STS_ERROR;
+       }
+
+       if (DRX_ISATVSTD(standard)) {
+               tunerMode |= TUNER_MODE_ANALOG;
+       }
+       else /* note: also for unknown standard */ {
+               tunerMode |= TUNER_MODE_DIGITAL;
+       }
+
+       /* select tuner bandwidth */
+       switch (channel->bandwidth) {
+       case DRX_BANDWIDTH_6MHZ:
+               tunerMode |= TUNER_MODE_6MHZ;
+               break;
+       case DRX_BANDWIDTH_7MHZ:
+               tunerMode |= TUNER_MODE_7MHZ;
+               break;
+       case DRX_BANDWIDTH_8MHZ:
+               tunerMode |= TUNER_MODE_8MHZ;
+               break;
+       default: /* note: also for unknown bandwidth */
+               return DRX_STS_INVALID_ARG;
+       }
+
+       DRX_GET_TUNERSLOWMODE (demod, tunerSlowMode);
+
+       /* select fast (switch) or slow (lock) tuner mode */
+       if (tunerSlowMode) {
+               tunerMode |= TUNER_MODE_LOCK;
+       }
+       else {
+               tunerMode |= TUNER_MODE_SWITCH;
+       }
+
+       if (commonAttr->tunerPortNr == 1) {
+               Bool_t      bridgeClosed = TRUE;
+               DRXStatus_t statusBridge = DRX_STS_ERROR;
+
+               statusBridge = DRX_Ctrl(demod, DRX_CTRL_I2C_BRIDGE, 
&bridgeClosed);
+               if (statusBridge != DRX_STS_OK) {
+                       return statusBridge;
+               }
+       }
+
+       status = DRXBSP_TUNER_SetFrequency(demod->myTuner,
+                                       tunerMode,
+                                       channel->frequency);
+
+       /* attempt restoring bridge before checking status of SetFrequency */
+       if (commonAttr->tunerPortNr == 1) {
+               Bool_t      bridgeClosed = FALSE;
+               DRXStatus_t statusBridge = DRX_STS_ERROR;
+
+               statusBridge = DRX_Ctrl(demod, DRX_CTRL_I2C_BRIDGE, 
&bridgeClosed);
+               if (statusBridge != DRX_STS_OK) {
+                       return statusBridge;
+               }
+       }
+
+       /* now check status of DRXBSP_TUNER_SetFrequency */
+       if (status != DRX_STS_OK) {
+               return status;
+       }
+
+       /* get actual RF and IF frequencies from tuner */
+       status = DRXBSP_TUNER_GetFrequency(demod->myTuner,
+                                       tunerMode,
+                                       &(channel->frequency),
+                                       &(ifFrequency));
+       if (status != DRX_STS_OK) {
+               return status;
+       }
+
+       /* update common attributes with information available from this 
function;
+               TODO: check if this is required and safe */
+       DRX_SET_INTERMEDIATEFREQ(demod, ifFrequency);
+
+       return DRX_STS_OK;
+}
+
+/*============================================================================*/
+
+/**
+* \brief function to do a register dump.
+* \param demod:            Pointer to demodulator instance.
+* \param registers:        Registers to dump.
+* \return DRXStatus_t.
+* \retval DRX_STS_OK:          Dump executed successfully.
+* \retval DRX_STS_ERROR:       Something went wrong.
+* \retval DRX_STS_INVALID_ARG: Wrong parameters.
+*
+*/
+DRXStatus_t CtrlDumpRegisters(pDRXDemodInstance_t  demod,
+                                pDRXRegDump_t        registers)
+{
+       u16_t i = 0;
+
+       if (registers == NULL) {
+               /* registers not supplied */
+               return DRX_STS_INVALID_ARG;
+       }
+
+       /* start dumping registers */
+       while (registers[i].address != 0) {
+               DRXStatus_t status = DRX_STS_ERROR;
+               u16_t       value  = 0;
+               u32_t       data   = 0;
+
+               status = demod->myAccessFunct->readReg16Func(
+                       demod->myI2CDevAddr, registers[i].address, &value, 0);
+
+               data = (u32_t)value;
+
+               if (status != DRX_STS_OK) {
+                       /* no breakouts;
+                       depending on device ID, some HW blocks might not be 
available */
+                       data |= ((u32_t)status) << 16;
+               }
+               registers[i].data = data;
+               i++;
+       }
+
+       /* all done, all OK (any errors are saved inside data) */
+       return DRX_STS_OK;
+}
+
+/*============================================================================*/
+/*============================================================================*/
+/*===Microcode related 
functions==============================================*/
+/*============================================================================*/
+/*============================================================================*/
+
+/**
+* \brief Read a 16 bits word, expects big endian data.
+* \param addr: Pointer to memory from which to read the 16 bits word.
+* \return u16_t The data read.
+*
+* This function takes care of the possible difference in endianness between the
+* host and the data contained in the microcode image file.
+*
+*/
+static u16_t
+UCodeRead16(pu8_t addr)
+{
+       /* Works fo any host processor */
+
+       u16_t word=0;
+
+       word = ((u16_t)addr[0]);
+       word <<= 8;
+       word |=((u16_t)addr[1]);
+
+       return word;
+}
+
+/*============================================================================*/
+
+/**
+* \brief Read a 32 bits word, expects big endian data.
+* \param addr: Pointer to memory from which to read the 32 bits word.
+* \return u32_t The data read.
+*
+* This function takes care of the possible difference in endianness between the
+* host and the data contained in the microcode image file.
+*
+*/
+static u32_t
+UCodeRead32(pu8_t addr)
+{
+       /* Works fo any host processor */
+
+       u32_t word=0;
+
+       word = ((u16_t)addr[0]);
+       word <<= 8;
+       word |= ((u16_t)addr[1]);
+       word <<= 8;
+       word |= ((u16_t)addr[2]);
+       word <<= 8;
+       word |= ((u16_t)addr[3]);
+
+       return word ;
+}
+
+/*============================================================================*/
+
+/**
+* \brief Compute CRC of block of microcode data.
+* \param blockData: Pointer to microcode data.
+* \param nrWords:   Size of microcode block (number of 16 bits words).
+* \return u16_t The computed CRC residu.
+*/
+static u16_t
+UCodeComputeCRC (pu8_t blockData, u16_t nrWords)
+{
+       u16_t i        = 0;
+       u16_t j        = 0;
+       u32_t CRCWord  = 0;
+       u32_t carry    = 0;
+
+       while (i < nrWords) {
+               CRCWord |= (u32_t) UCodeRead16(blockData);
+               for (j = 0; j < 16; j++) {
+                       CRCWord <<= 1;
+                       if (carry != 0) {
+                               CRCWord ^= 0x80050000UL;
+                       }
+                       carry = CRCWord & 0x80000000UL;
+               }
+               i++;
+               blockData+=(sizeof(u16_t));
+       }
+       return ((u16_t) (CRCWord >> 16));
+}
+
+/*============================================================================*/
+
+/**
+* \brief Handle microcode upload or verify.
+* \param devAddr: Address of device.
+* \param mcInfo:  Pointer to information about microcode data.
+* \param action:  Either UCODE_UPLOAD or UCODE_VERIFY
+* \return DRXStatus_t.
+* \retval DRX_STS_OK:
+*                    - In case of UCODE_UPLOAD: code is successfully uploaded.
+*                    - In case of UCODE_VERIFY: image on device is equal to
+*                      image provided to this control function.
+* \retval DRX_STS_ERROR:
+*                    - In case of UCODE_UPLOAD: I2C error.
+*                    - In case of UCODE_VERIFY: I2C error or image on device
+*                      is not equal to image provided to this control function.
+* \retval DRX_STS_INVALID_ARG:
+*                    - Invalid arguments.
+*                    - Provided image is corrupt
+*/
+static DRXStatus_t
+CtrlUCode(pDRXDemodInstance_t demod,
+       pDRXUCodeInfo_t  mcInfo,
+       DRXUCodeAction_t action)
+{
+       DRXStatus_t rc;
+       u16_t  i = 0;
+       u16_t  mcNrOfBlks = 0;
+       u16_t  mcMagicWord = 0;
+       pu8_t  mcData = (pu8_t)(NULL);
+       pI2CDeviceAddr_t devAddr = (pI2CDeviceAddr_t)(NULL);
+
+       devAddr = demod -> myI2CDevAddr;
+
+       /* Check arguments */
+       if ((mcInfo == NULL) ||
+               (mcInfo->mcData == NULL)) {
+               return DRX_STS_INVALID_ARG;
+       }
+
+       mcData = mcInfo->mcData;
+
+       /* Check data */
+       mcMagicWord = UCodeRead16(mcData);
+       mcData += sizeof(u16_t);
+       mcNrOfBlks = UCodeRead16(mcData);
+       mcData += sizeof(u16_t);
+
+       if ((mcMagicWord != DRX_UCODE_MAGIC_WORD) ||
+               (mcNrOfBlks == 0)) {
+               /* wrong endianess or wrong data ? */
+               return DRX_STS_INVALID_ARG;
+       }
+
+       /* Scan microcode blocks first for version info if uploading */
+       if (action == UCODE_UPLOAD) {
+               /* Clear version block */
+               DRX_SET_MCVERTYPE (demod, 0);
+               DRX_SET_MCDEV     (demod, 0);
+               DRX_SET_MCVERSION (demod, 0);
+               DRX_SET_MCPATCH   (demod, 0);
+               for (i = 0; i < mcNrOfBlks; i++) {
+                       DRXUCodeBlockHdr_t blockHdr;
+
+                       /* Process block header */
+                       blockHdr.addr = UCodeRead32(mcData);
+                       mcData += sizeof(u32_t);
+                       blockHdr.size = UCodeRead16(mcData);
+                       mcData += sizeof(u16_t);
+                       blockHdr.flags = UCodeRead16(mcData);
+                       mcData += sizeof(u16_t);
+                       blockHdr.CRC = UCodeRead16(mcData);
+                       mcData += sizeof(u16_t);
+
+                       if (blockHdr.flags & 0x8) {
+                               /* Aux block. Check type */
+                               pu8_t auxblk = mcInfo->mcData + blockHdr.addr;
+                               u16_t auxtype = UCodeRead16 (auxblk);
+                               if (DRX_ISMCVERTYPE (auxtype)) {
+                                       DRX_SET_MCVERTYPE (demod, UCodeRead16 
(auxblk));
+                                       auxblk += sizeof (u16_t);
+                                       DRX_SET_MCDEV     (demod, UCodeRead32 
(auxblk));
+                                       auxblk += sizeof (u32_t);
+                                       DRX_SET_MCVERSION (demod, UCodeRead32 
(auxblk));
+                                       auxblk += sizeof (u32_t);
+                                       DRX_SET_MCPATCH   (demod, UCodeRead32 
(auxblk));
+                               }
+                       }
+
+                       /* Next block */
+                       mcData += blockHdr.size * sizeof (u16_t);
+               }
+               /* After scanning, validate the microcode.
+                It is also valid if no validation control exists.
+               */
+               rc = DRX_Ctrl (demod, DRX_CTRL_VALIDATE_UCODE, NULL);
+               if (rc != DRX_STS_OK && rc != DRX_STS_FUNC_NOT_AVAILABLE) {
+                       return rc;
+               }
+
+               /* Restore data pointer */
+               mcData = mcInfo->mcData + 2 * sizeof(u16_t);
+               }
+
+       /* Process microcode blocks */
+       for(i = 0 ; i<mcNrOfBlks ; i++) {
+               DRXUCodeBlockHdr_t blockHdr;
+               u16_t mcBlockNrBytes = 0;
+
+               /* Process block header */
+               blockHdr.addr = UCodeRead32(mcData);
+               mcData += sizeof(u32_t);
+               blockHdr.size = UCodeRead16(mcData);
+               mcData += sizeof(u16_t);
+               blockHdr.flags = UCodeRead16(mcData);
+               mcData += sizeof(u16_t);
+               blockHdr.CRC = UCodeRead16(mcData);
+               mcData += sizeof(u16_t);
+
+               /* Check block header on:
+                - data larger than 64Kb
+                - if CRC enabled check CRC
+               */
+               if ((blockHdr.size > 0x7FFF) ||
+                       (((blockHdr.flags & DRX_UCODE_CRC_FLAG) != 0) &&
+                       (blockHdr.CRC != UCodeComputeCRC (mcData, 
blockHdr.size)))
+                       ) {
+                               /* Wrong data ! */
+                               return DRX_STS_INVALID_ARG;
+               }
+
+               mcBlockNrBytes = blockHdr.size * ((u16_t)sizeof(u16_t));
+
+               if (blockHdr.size != 0) {
+                       /* Perform the desired action */
+                       switch (action) {
+                       
/*================================================================*/
+                       case UCODE_UPLOAD : {
+                               /* Upload microcode */
+                               if (demod->myAccessFunct->writeBlockFunc(
+                                       devAddr,
+                                       (DRXaddr_t) blockHdr.addr,
+                                       mcBlockNrBytes,
+                                       mcData,
+                                       0x0000) != DRX_STS_OK) {
+                                       return (DRX_STS_ERROR);
+                               } /* if */
+                       };
+                       break;
+
+                       
/*================================================================*/
+                       case UCODE_VERIFY : {
+                               int         result = 0;
+                               u8_t        
mcDataBuffer[DRX_UCODE_MAX_BUF_SIZE];
+                               u32_t       bytesToCompare=0;
+                               u32_t       bytesLeftToCompare=0;
+                               DRXaddr_t   currAddr = (DRXaddr_t)0;
+                               pu8_t       currPtr =NULL;
+
+                               bytesLeftToCompare = mcBlockNrBytes;
+                               currAddr           = blockHdr.addr;
+                               currPtr            = mcData;
+
+                               while(bytesLeftToCompare != 0) {
+                                       if (bytesLeftToCompare > 
((u32_t)DRX_UCODE_MAX_BUF_SIZE)) {
+                                               bytesToCompare = 
((u32_t)DRX_UCODE_MAX_BUF_SIZE);
+                                       }
+                                       else {
+                                               bytesToCompare = 
bytesLeftToCompare;
+                                       }
+
+                                       if (demod->myAccessFunct->readBlockFunc(
+                                               devAddr,
+                                               currAddr,
+                                               (u16_t)bytesToCompare,
+                                               (pu8_t)mcDataBuffer,
+                                               0x0000) != DRX_STS_OK) {
+                                               return (DRX_STS_ERROR);
+                                       }
+
+                                       result = DRXBSP_HST_Memcmp(currPtr,
+                                               mcDataBuffer,
+                                               bytesToCompare);
+
+                                       if (result != 0) {
+                                               return DRX_STS_ERROR;
+                                       }
+
+                                       currAddr           += 
((DRXaddr_t)(bytesToCompare/2));
+                                       currPtr            = 
&(currPtr[bytesToCompare]);
+                                       bytesLeftToCompare -= 
((u32_t)bytesToCompare);
+                               } /* while(bytesToCompare > 
DRX_UCODE_MAX_BUF_SIZE) */
+                       };
+                       break;
+
+                       
/*================================================================*/
+                       default:
+                               return DRX_STS_INVALID_ARG;
+                               break;
+
+                       } /* switch (action) */
+               } /* if (blockHdr.size != 0) */
+
+               /* Next block */
+               mcData += mcBlockNrBytes;
+
+       } /* for(i = 0 ; i<mcNrOfBlks ; i++) */
+
+       return DRX_STS_OK;
+}
+
+/*============================================================================*/
+
+/**
+* \brief Build list of version information.
+* \param demod: A pointer to a demodulator instance.
+* \param versionList: Pointer to linked list of versions.
+* \return DRXStatus_t.
+* \retval DRX_STS_OK:          Version information stored in versionList
+* \retval DRX_STS_INVALID_ARG: Invalid arguments.
+*/
+static DRXStatus_t
+CtrlVersion(pDRXDemodInstance_t demod,
+       pDRXVersionList_t   *versionList)
+{
+       static char drxDriverCoreModuleName[]  = "Core driver";
+       static char drxDriverCoreVersionText[] =
+               DRX_VERSIONSTRING(VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH);
+
+       static DRXVersion_t drxDriverCoreVersion;
+       static DRXVersionList_t drxDriverCoreVersionList;
+
+       pDRXVersionList_t demodVersionList = (pDRXVersionList_t)(NULL);
+       DRXStatus_t returnStatus = DRX_STS_ERROR;
+
+       /* Check arguments */
+       if (versionList == NULL) {
+               return DRX_STS_INVALID_ARG;
+       }
+
+       /* Get version info list from demod */
+       returnStatus = (*(demod->myDemodFunct->ctrlFunc))(
+                               demod,
+                               DRX_CTRL_VERSION,
+                               (void *) &demodVersionList);
+
+       /* Always fill in the information of the driver SW . */
+       drxDriverCoreVersion.moduleType  = DRX_MODULE_DRIVERCORE;
+       drxDriverCoreVersion.moduleName  = drxDriverCoreModuleName;
+       drxDriverCoreVersion.vMajor      = VERSION_MAJOR;
+       drxDriverCoreVersion.vMinor      = VERSION_MINOR;
+       drxDriverCoreVersion.vPatch      = VERSION_PATCH;
+       drxDriverCoreVersion.vString     = drxDriverCoreVersionText;
+
+       drxDriverCoreVersionList.version = &drxDriverCoreVersion;
+       drxDriverCoreVersionList.next    = (pDRXVersionList_t)(NULL);
+
+       if ((returnStatus == DRX_STS_OK) && (demodVersionList != NULL)) {
+               /* Append versioninfo from driver to versioninfo from demod  */
+               /* Return version info in "bottom-up" order. This way, multiple
+                devices can be handled without using malloc. */
+               pDRXVersionList_t currentListElement = demodVersionList;
+               while (currentListElement->next != NULL) {
+                       currentListElement = currentListElement->next;
+               }
+               currentListElement->next = &drxDriverCoreVersionList;
+
+               *versionList = demodVersionList;
+       }
+       else {
+               /* Just return versioninfo from driver */
+               *versionList = &drxDriverCoreVersionList;
+       }
+
+       return DRX_STS_OK;
+}
+
+/*============================================================================*/
+/*============================================================================*/
+/*== Exported functions 
======================================================*/
+/*============================================================================*/
+/*============================================================================*/
+
+
+
+/**
+* \brief This function is obsolete.
+* \param demods: Don't care, parameter is ignored.
+* \return DRXStatus_t Return status.
+* \retval DRX_STS_OK: Initialization completed.
+*
+* This function is obsolete, prototype available for backward compatability.
+*
+*/
+
+DRXStatus_t
+DRX_Init(pDRXDemodInstance_t demods[])
+{
+       return DRX_STS_OK;
+}
+
+/*============================================================================*/
+
+/**
+* \brief This function is obsolete.
+* \return DRXStatus_t Return status.
+* \retval DRX_STS_OK: Terminated driver successful.
+*
+* This function is obsolete, prototype available for backward compatability.
+*
+*/
+
+DRXStatus_t
+DRX_Term(void)
+{
+       return DRX_STS_OK;
+}
+
+/*============================================================================*/
+
+/**
+* \brief Open a demodulator instance.
+* \param demod: A pointer to a demodulator instance.
+* \return DRXStatus_t Return status.
+* \retval DRX_STS_OK:          Opened demod instance with succes.
+* \retval DRX_STS_ERROR:       Driver not initialized or unable to initialize
+*                              demod.
+* \retval DRX_STS_INVALID_ARG: Demod instance has invalid content.
+*
+*/
+
+DRXStatus_t
+DRX_Open(pDRXDemodInstance_t demod)
+{
+       DRXStatus_t status = DRX_STS_OK;
+
+       if ((demod == NULL)               ||
+               (demod->myDemodFunct == NULL) ||
+               (demod->myCommonAttr == NULL) ||
+               (demod->myExtAttr == NULL)    ||
+               (demod->myI2CDevAddr == NULL) ||
+               (demod->myCommonAttr->isOpened == TRUE)) {
+               return (DRX_STS_INVALID_ARG);
+       }
+
+       status = (*(demod->myDemodFunct->openFunc))(demod);
+
+       if (status == DRX_STS_OK) {
+               demod->myCommonAttr->isOpened = TRUE;
+       }
+
+       return status;
+}
+
+/*============================================================================*/
+
+/**
+* \brief Close device.
+* \param demod: A pointer to a demodulator instance.
+* \return DRXStatus_t Return status.
+* \retval DRX_STS_OK:          Closed demod instance with succes.
+* \retval DRX_STS_ERROR:       Driver not initialized or error during close
+*                              demod.
+* \retval DRX_STS_INVALID_ARG: Demod instance has invalid content.
+*
+* Free resources occupied by device instance.
+* Put device into sleep mode.
+*/
+
+DRXStatus_t
+DRX_Close(pDRXDemodInstance_t demod)
+{
+       DRXStatus_t status = DRX_STS_OK;
+
+       if ((demod == NULL)               ||
+               (demod->myDemodFunct == NULL) ||
+               (demod->myCommonAttr == NULL) ||
+               (demod->myExtAttr == NULL)    ||
+               (demod->myI2CDevAddr == NULL) ||
+               (demod->myCommonAttr->isOpened == FALSE)) {
+               return DRX_STS_INVALID_ARG;
+       }
+
+       status = (*(demod->myDemodFunct->closeFunc))(demod);
+
+       DRX_SET_ISOPENED (demod, FALSE);
+
+       return status;
+}
+
+/*============================================================================*/
+
+/**
+* \brief Control the device.
+* \param demod:    A pointer to a demodulator instance.
+* \param ctrl:     Reference to desired control function.
+* \param ctrlData: Pointer to data structure for control function.
+* \return DRXStatus_t Return status.
+* \retval DRX_STS_OK:                 Control function completed successfully.
+* \retval DRX_STS_ERROR:              Driver not initialized or error during
+*                                     control demod.
+* \retval DRX_STS_INVALID_ARG:        Demod instance or ctrlData has invalid
+*                                     content.
+* \retval DRX_STS_FUNC_NOT_AVAILABLE: Specified control function is not
+*                                     available.
+*
+* Data needed or returned by the control function is stored in ctrlData.
+*
+*/
+
+DRXStatus_t
+DRX_Ctrl(pDRXDemodInstance_t demod, DRXCtrlIndex_t ctrl, void *ctrlData)
+{
+       DRXStatus_t status = DRX_STS_ERROR;
+
+       if ((demod               == NULL) ||
+               (demod->myDemodFunct == NULL) ||
+               (demod->myCommonAttr == NULL) ||
+               (demod->myExtAttr    == NULL) ||
+               (demod->myI2CDevAddr == NULL)
+               ) {
+               return (DRX_STS_INVALID_ARG);
+       }
+
+       if (((demod->myCommonAttr->isOpened == FALSE) &&
+               (ctrl != DRX_CTRL_PROBE_DEVICE) &&
+               (ctrl != DRX_CTRL_VERSION))
+               ) {
+               return (DRX_STS_INVALID_ARG);
+       }
+
+       if ((DRX_ISPOWERDOWNMODE(demod->myCommonAttr->currentPowerMode) &&
+               (ctrl != DRX_CTRL_POWER_MODE)   &&
+               (ctrl != DRX_CTRL_PROBE_DEVICE) &&
+               (ctrl != DRX_CTRL_NOP)          &&
+               (ctrl != DRX_CTRL_VERSION)
+               )
+               ) {
+               return DRX_STS_FUNC_NOT_AVAILABLE;
+       }
+
+       /* Fixed control functions */
+       switch (ctrl) {
+       
/*======================================================================*/
+       case DRX_CTRL_NOP:
+               /* No operation */
+               return DRX_STS_OK;
+               break;
+
+       
/*======================================================================*/
+       case DRX_CTRL_VERSION:
+               return CtrlVersion(demod, (pDRXVersionList_t *) ctrlData);
+               break;
+
+       
/*======================================================================*/
+       default :
+               /* Do nothing */
+               break;
+       }
+
+       /* Virtual functions */
+       /* First try calling function from derived class */
+       status = (*(demod->myDemodFunct->ctrlFunc))(demod, ctrl, ctrlData);
+       if (status == DRX_STS_FUNC_NOT_AVAILABLE) {
+               /* Now try calling a the base class function */
+               switch (ctrl) {
+               
/*===================================================================*/
+               case DRX_CTRL_LOAD_UCODE:
+                       return CtrlUCode (demod,
+                               (pDRXUCodeInfo_t) ctrlData,
+                               UCODE_UPLOAD);
+                       break;
+
+               
/*===================================================================*/
+               case DRX_CTRL_VERIFY_UCODE: {
+                       return CtrlUCode (demod,
+                               (pDRXUCodeInfo_t) ctrlData,
+                               UCODE_VERIFY);
+               }
+                       break;
+
+#ifndef DRX_EXCLUDE_SCAN
+               
/*===================================================================*/
+               case DRX_CTRL_SCAN_INIT: {
+                       return CtrlScanInit(demod, (pDRXScanParam_t) ctrlData);
+               }
+                       break;
+
+               
/*===================================================================*/
+               case DRX_CTRL_SCAN_NEXT: {
+                       return CtrlScanNext(demod, (pu16_t) ctrlData);
+               }
+                       break;
+
+               
/*===================================================================*/
+               case DRX_CTRL_SCAN_STOP: {
+                       return CtrlScanStop(demod);
+               }
+                       break;
+#endif /* #ifndef DRX_EXCLUDE_SCAN */
+
+               
/*===================================================================*/
+               case DRX_CTRL_PROGRAM_TUNER: {
+                       return CtrlProgramTuner(demod, (pDRXChannel_t) 
ctrlData);
+               }
+                       break;
+
+               
/*===================================================================*/
+               case DRX_CTRL_DUMP_REGISTERS: {
+                       return CtrlDumpRegisters(demod, (pDRXRegDump_t) 
ctrlData);
+               }
+                       break;
+
+               
/*===================================================================*/
+               default :
+                       return DRX_STS_FUNC_NOT_AVAILABLE;
+               }
+       }
+       else {
+               return (status);
+       }
+
+       return DRX_STS_OK;
+}
+
+
+/*============================================================================*/
+
+/* END OF FILE */
-- 
1.7.5.4

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to