static void aud_ftm_tone_generator(void *pCtxt)
{
  int32  size, capacity;
  uint16  i, channels;
    int16   sample;
    Aud_FTM_DrvCtxt_T * pDrvCtxt = (Aud_FTM_DrvCtxt_T *)pCtxt;

    channels=pDrvCtxt->client_param.channel;

  do
      {
          DALSYS_EventWaitTimeout(pDrvCtxt->hReq_Data_Event, 500);   /* 500ms timeout */
          if( pDrvCtxt->bStart != TRUE ) break;

          /* determine if needing fillful new data */
          size=cbuf_data_size(&(pDrvCtxt->fifo_data_buf));
          capacity=cbuf_capacity(&(pDrvCtxt->fifo_data_buf));

        /* generate data */
        DALSYS_memset(pTmpBuf,0,capacity-size-4);

        for(i=0; i<((capacity-size-4)/sizeof(int16)); i++)
        {
          sample=audio_ftm_dtmf_tone_sample_gen(&(pDrvCtxt->dtmfGen) ,pDrvCtxt->nDTMF_Gain);
          *(pTmpBuf+i)=sample;
                if(channels == AUDIO_FTM_CHN_2)
                {
                   i++;
                   *(pTmpBuf+i)=sample;
                }
        }

        aud_ftm_cbuf_write (&(pDrvCtxt->fifo_data_buf),(uint8 *)pTmpBuf,(int32)(capacity-size-4));

      }while(1);

    pthread_exit(0);
}
/*==================================================================================================
  @brief FTM driver open

  This API can be used to open the FTM driver.

  @param DriverHdl:   Input -   handle created in Audio_FTM_Attach
         AccessMode:  Input -   Read/Write/RD_WR
         ShareMode:   Input -   Exclusive or Share
         pClientHdl:  Output -  point to the returned Open handle

  @return return code, AUDIO_FTM_SUCCESS on successful completion, error code otherwise
==================================================================================================*/
AUDIO_FTM_STS_T
audio_ftm_toneplay_open
(
    AUDIO_FTM_DRIVER_HANDLE_T pDriverContext ,  /* Input: driver handle */
    AUD_FTM_ACCESS_MODE_T AccessMode,           /* Input: Access mode */
    AUD_FTM_SHARE_MODE_T  ShareMode,            /* Input: Share mode */
    AUDIO_FTM_CLIENT_HANDLE_T * pClientContext  /* Output: client handle */
)
{
    Aud_FTM_DrvCtxt_T * pDrvCxt = (Aud_FTM_DrvCtxt_T *)pDriverContext;
    Aud_FTM_ClientCtxt_T * pOpenContext = NULL;
    AUDIO_FTM_STS_T  res;
    int16 i;
    uint32 dev_buf_size, fifo_buf_size;

    if (pDrvCxt == NULL)
    {
        DALSYS_Log_Err("%s: failed %d\n",__func__,__LINE__);
        return AUDIO_FTM_ERR_INVALID_PARAM;
    }

    DALSYS_SyncEnter(pDrvCxt->hClientSync);

    if((ShareMode == AUD_FTM_SHAREMODE_EXCLU ) && (DALSYS_atomic_read(&pDrvCxt->dwOpenCount) != 0))
        /* ShareMode = 0: exclusive mode; =FILE_SHARE_READ: read only; =FILE_SHARE_WRITE: write only */
    {
        DALSYS_SyncLeave(pDrvCxt->hClientSync);
        DALSYS_Log_Err("%s: failed %d\n",__func__,__LINE__);
        return AUDIO_FTM_ERROR;
    }

  if(DAL_SUCCESS != DALSYS_Malloc(sizeof(Aud_FTM_ClientCtxt_T), (void **)&pOpenContext))
    {
        DALSYS_Log_Err("%s: failed %d\n",__func__,__LINE__);
        DALSYS_SyncLeave(pDrvCxt->hClientSync);
        return AUDIO_FTM_ERR_MEM_ALLOC_FAIL;
    }

    if (pOpenContext == NULL)
    {
      DALSYS_SyncLeave(pDrvCxt->hClientSync);
        DALSYS_Log_Err("%s: failed %d\n",__func__,__LINE__);
      return AUDIO_FTM_ERR_MEM_ALLOC_FAIL;
    }
  DALSYS_memset(pOpenContext,0,sizeof(Aud_FTM_ClientCtxt_T));

    // Store device settings for future use
    pOpenContext->pDrvCtxt = pDrvCxt;
    pOpenContext->dwAccessCode = AccessMode;
    pOpenContext->dwShareMode = ShareMode;

  pOpenContext->dwClientID=DALSYS_atomic_read(&pDrvCxt->dwOpenCount);

  pDrvCxt->apClientCtxt[pOpenContext->dwClientID]=pOpenContext;

#ifdef MSM8960_ALSA
  pDrvCxt->pDevCtxt->read_write_flag = PCM_OUT;
#endif

  /***** open HW *****/
  DALSYS_Log_Info("%s: open hw\n",__func__);
  pDrvCxt->pDevCtxt->playbackdevice =
  pDrvCxt->pDevCtxt->pDrvCtxt->client_param.device;
  res=audio_ftm_hw_open(pDrvCxt->pDevCtxt);
  if(res != AUDIO_FTM_SUCCESS)
  {
    DALSYS_Log_Err("%s: failed %d\n",__func__,__LINE__);
    DALSYS_SyncLeave(pDrvCxt->hClientSync);
    return AUDIO_FTM_ERROR;
  }

    audio_ftm_hw_iocontrol(pDrvCxt->pDevCtxt, IOCTL_AUDIO_FTM_RX_DEV_BUF_SIZE, NULL, 0, &dev_buf_size, sizeof(dev_buf_size), NULL);
    pDrvCxt->nRx_blk_convey_samples=dev_buf_size/sizeof(int16);

  /********* init circular buf ********/
    fifo_buf_size=dev_buf_size*AUD_FTM_TONE_PLAY_FIFO_FACTOR+4;    // reserve 4 bytes

  DALSYS_Log_Info("%s: init buf\n",__func__);
  aud_ftm_cbuf_init(&(pDrvCxt->fifo_data_buf), fifo_buf_size);

  if(DAL_SUCCESS != DALSYS_Malloc(dev_buf_size*AUD_FTM_TONE_PLAY_FIFO_FACTOR, (void **)&pTmpBuf))  /* buffer for DTMF data producing */
  {
          DALSYS_SyncLeave(pDrvCxt->hClientSync);
      DALSYS_Log_Err(" pTmpBuf allocation fail\n");
      return DAL_ERROR;
    }
  DALSYS_memset(pTmpBuf,0,dev_buf_size*AUD_FTM_TONE_PLAY_FIFO_FACTOR);

  if(DAL_SUCCESS != DALSYS_Malloc(dev_buf_size, (void **)&pAud_ftm_rx_buf))  /* buffer for fetch data from FIFO and pass to low layer driver for consuming */
  {
          DALSYS_SyncLeave(pDrvCxt->hClientSync);
      DALSYS_Log_Err(" pAud_ftm_rx_buf allocation fail\n");
      return DAL_ERROR;
    }
  DALSYS_memset(pAud_ftm_rx_buf,0,dev_buf_size);

  /***** prefill the circular buffer with DTMF data *****/

  for(i=0; i<((dev_buf_size*AUD_FTM_TONE_PLAY_FIFO_FACTOR)/sizeof(int16)); i++)
  {
    *(pTmpBuf+i)=audio_ftm_dtmf_tone_sample_gen(&(pDrvCxt->dtmfGen),pDrvCxt->nDTMF_Gain);
  }
  aud_ftm_cbuf_write (&(pDrvCxt->fifo_data_buf),(uint8 *)pTmpBuf,(int32)(dev_buf_size*AUD_FTM_TONE_PLAY_FIFO_FACTOR));

    // Increase opened device counter
  AddRef(&pDrvCxt->dwOpenCount);
    pDrvCxt->bOpened=TRUE;

    DALSYS_SyncLeave(pDrvCxt->hClientSync);

    *pClientContext=  (AUDIO_FTM_CLIENT_HANDLE_T)pOpenContext;

    return AUDIO_FTM_SUCCESS;
}
AUDIO_FTM_STS_T
audio_ftm_toneplay_attach
(
    void *pParam,                                 /* Input: parameters  */
    AUDIO_FTM_DRIVER_HANDLE_T *pDriverHdl        /* Output: driver handle */
)
{
  /************* Context creation ***********/

  Aud_FTM_DevCtxt_T *pDeviceCtxt;
  Aud_FTM_DrvCtxt_T *pDriverCtxt;

    Aud_FTM_HW_INIT_PARAM_T hw_param;
    int16 freq1,freq2, sampling_freq;

    AUDIO_FTM_STS_T sts;

    if (g_bDriverInitialized)
  {
      DALSYS_Log_Err("%s: error: already initialized\n", __func__);
        return  AUDIO_FTM_ERROR;    //  already inited,
  }

  DALSYS_Log_Info("Attach TonePlay Driver\n");

    /****************** create context object ******************/

  if((DAL_SUCCESS != DALSYS_Malloc(sizeof(Aud_FTM_DevCtxt_T), (void **)&pDeviceCtxt)) ||
        (pDeviceCtxt == NULL))
    {
      DALSYS_Log_Err("Memory allocation fail\n");
        return AUDIO_FTM_ERR_MEM_ALLOC_FAIL;
    }

  DALSYS_memset(pDeviceCtxt,0,sizeof(Aud_FTM_DevCtxt_T));

  if((DAL_SUCCESS != DALSYS_Malloc(sizeof(Aud_FTM_DrvCtxt_T), (void **)&pDriverCtxt)) ||
        (pDriverCtxt == NULL))
    {
      DALSYS_Log_Err("Memory allocation fail\n");
                DALSYS_Free(pDeviceCtxt);
        return AUDIO_FTM_ERR_MEM_ALLOC_FAIL;
    }

  DALSYS_memset(pDriverCtxt,0,sizeof(Aud_FTM_DevCtxt_T));

    DALSYS_atomic_init(&pDriverCtxt->dwOpenCount);
    pDriverCtxt->pDevCtxt=pDeviceCtxt;
    pDeviceCtxt->pDrvCtxt=pDriverCtxt;

  /************* Create Critical Section ***********/

    if(DAL_SUCCESS != DALSYS_SyncCreate(DALSYS_SYNC_ATTR_RESOURCE,
        &(pDriverCtxt->hClientSync),
        NULL))
    {
      DALSYS_Log_Err("hClientSync creation fail\n");
        return AUDIO_FTM_ERROR;
    }

   if(DAL_SUCCESS != DALSYS_EventCreate(DALSYS_EVENT_ATTR_WORKLOOP_EVENT,       //Not used for work loops
                              &(pDriverCtxt->hReq_Data_Event),          //Return event handle
                              NULL))
   {
    DALSYS_Log_Err("%s: failed to create event\n", __func__);
    DALSYS_SyncLeave(pDriverCtxt->hClientSync);
    DALSYS_Free(pDriverCtxt->hClientSync);
    return AUDIO_FTM_ERROR;
   }

    /*************  hardware initialization ***********/

   DALSYS_memcpy((uint8*)&(pDriverCtxt->client_param),
                  (uint8*)pParam, sizeof(AUD_FTM_TONE_PLAY_PARAM_T));

   hw_param.inpath=AUDIO_FTM_IN_INVALID;
   hw_param.outpath=pDriverCtxt->client_param.path.outpath;
   hw_param.rate=AUDIO_FTM_PCM_RATE_8K;
   hw_param.width=AUDIO_FTM_BIT_WIDTH_16;
   hw_param.channel=AUDIO_FTM_CHN_1;
   hw_param.gain=pDriverCtxt->client_param.gain;
     hw_param.bLoopbackCase=FALSE;

   sts=aud_ftm_hw_init(pDeviceCtxt, &hw_param);
   if(sts != AUDIO_FTM_SUCCESS) {
      DALSYS_Log_Err("%s: failed to init hw\n", __func__);
        return AUDIO_FTM_ERROR;
   }

      /* Tone generator init */

    freq1=((AUD_FTM_TONE_PLAY_PARAM_T*)pParam)->dtmf_low;
    freq2=((AUD_FTM_TONE_PLAY_PARAM_T*)pParam)->dtmf_hi;
    sampling_freq=8000;

    audio_ftm_dtmf_tone_init(&(pDriverCtxt->dtmfGen),freq1,freq2,sampling_freq);
    pDriverCtxt->nDTMF_Gain = vol_map[3];

    /***** end of Init *****/

        pDriverCtxt->bOpened=FALSE;
      g_bDriverInitialized=TRUE;
    *pDriverHdl=(AUDIO_FTM_DRIVER_HANDLE_T)pDriverCtxt;

      return AUDIO_FTM_SUCCESS;

}
/** @brief Attaches to the device and creates a dal device
           handle.

    @param[in] pszArg       Char string.
    @param[in] DeviceId     Platform device id.
    @param[out] phDalDevice Pointer to pointer to device handle.
    
    @return          DAL_SUCCESS if successful, error otherwise.
  */
DALResult
I2C_DalI2C_Attach
(
   const char       *pszArg,
   DALDEVICEID       DeviceId,
   DalDeviceHandle **phDalDevice
)
{
  DALResult nErr;
  static DalI2cDrvCtxt *pDrvCtxt = NULL;
  uint32         uDrvCtxtSize;
  

  DalI2cClientCtxt *pclientCtxt =  NULL;

  if (NULL == pDrvCtxt) {
     /*
     nErr = DALSYS_GetDALPropertyHandleStr("/dev/buses/i2c", hPropI2C);
     if (nErr != DAL_SUCCESS) {
        return nErr;
     }
     nErr = DALSYS_GetPropertyValue(hPropI2C,"SW_DRV_NUM_DEVICES",0,&prop);
     if (nErr != DAL_SUCCESS) {
        return nErr;
     }
     */

     
     if ( 0 == uNumI2cBuses ) {
         return DAL_ERROR;
     }
     uDrvCtxtSize = sizeof(DalI2cDrvCtxt) + (uNumI2cBuses - 1) *
     sizeof(DalI2cDevCtxt);
     nErr = DALSYS_Malloc(uDrvCtxtSize, (void **)&pDrvCtxt);

     if ( nErr != DAL_SUCCESS ) {
        return nErr;
     }

     if ( NULL == pDrvCtxt ) {
        return DAL_ERROR;
     }
     DALSYS_memset(pDrvCtxt, 0, uDrvCtxtSize);
     pDrvCtxt->I2CDALVtbl.I2C_DriverInit = I2C_DalI2C_DriverInit;
     pDrvCtxt->I2CDALVtbl.I2C_DriverDeInit = I2C_DalI2C_DriverDeInit;
     pDrvCtxt->dwNumDev = uNumI2cBuses;
     pDrvCtxt->dwSizeDevCtxt = sizeof(DalI2cDevCtxt);

  }

  nErr = DALSYS_Malloc(sizeof(DalI2cClientCtxt), (void **)&pclientCtxt);

  *phDalDevice = NULL;

  if ((DAL_SUCCESS == nErr) && (NULL != pclientCtxt)) {
    DALSYS_memset(pclientCtxt,0,sizeof(DalI2cClientCtxt));

    nErr = DALFW_AttachToDevice(DeviceId,(DALDrvCtxt *)pDrvCtxt,
        (DALClientCtxt *)pclientCtxt);
    if (DAL_SUCCESS == nErr)
    {
      I2C_InitInterface(pclientCtxt);
      I2C_DalI2C_AddRef(&(pclientCtxt->DalI2CHandle));
      *phDalDevice = (DalDeviceHandle *)&(pclientCtxt->DalI2CHandle);
    }
  }
  return nErr;
}