view src/cs/services/audio/audio_driver.c @ 275:79cfefc1e2b4

audio mode load: gracefully handle mode files of wrong AEC version Unfortunately our change of enabling L1_NEW_AEC (which is necessary in order to bring our Calypso ARM fw into match with the underlying DSP reality) brings along a change in the audio mode file binary format and file size - all those new tunable AEC parameters do need to be stored somewhere, after all. But we already have existing mode files in the old format, and setting AEC config to garbage when loading old audio modes (which is what would happen without the present change) is not an appealing proposition. The solution implemented in the present change is as follows: the audio mode loading code checks the file size, and if it differs from the active version of T_AUDIO_MODE, the T_AUDIO_AEC_CFG structure is cleared - set to the default (disabled AEC) for the compiled type of AEC. We got lucky in that this varying T_AUDIO_AEC_CFG structure sits at the end of T_AUDIO_MODE!
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 30 Jul 2021 02:55:48 +0000
parents 4e78acac3d88
children
line wrap: on
line source

/****************************************************************************/
/*                                                                          */
/*  File Name:  audio_driver.c                                              */
/*                                                                          */
/*  Purpose:  This file contains all the functions used to manage the       */
/*            driver.                                                       */
/*                                                                          */
/*  Version   0.1                                                           */
/*                                                                          */
/*  Date        Modification                                                */
/*  ------------------------------------                                    */
/*  09 December 2002  Create                                                */
/*                                                                          */
/*  Author   Frederic Turgis                                                */
/*                                                                          */
/* (C) Copyright 2002 by Texas Instruments Incorporated, All Rights Reserved*/
/****************************************************************************/

#include "rv/rv_defined_swe.h"
#ifdef RVM_AUDIO_MAIN_SWE
#ifndef _WINDOWS
    #include "config/swconfig.cfg"
	#include "config/sys.cfg"
	#include "config/chipset.cfg"
#endif

  #include "l1_confg.h"
  #include "rvf/rvf_api.h"
  #include "rv/rv_general.h"
  #include "rvm/rvm_gen.h"
  #include "audio/audio_features_i.h"
  #include "audio/audio_api.h"
  #include "audio/audio_env_i.h"
  #include "audio/audio_ffs_i.h"
  #include "audio/audio_structs_i.h"
  #include "audio/audio_macro_i.h"
  #include "rvf/rvf_target.h"
  #include "audio/audio_const_i.h"
  #include "audio/audio_var_i.h"
  #include "audio/audio_error_hdlr_i.h"
  #include "audio/audio_messages_i.h"
  
  #ifndef _WINDOWS
    // include the usefull L1 header
    #define BOOL_FLAG
    #define CHAR_FLAG
    #include "l1_types.h"
    #include "cust_os.h"
    #include "l1audio_cust.h"
    #include "l1audio_msgty.h"
    #include "l1audio_signa.h"
    #include "l1_signa.h"
  #else
    // include the usefull L1 header
    #define BOOL_FLAG
    #define CHAR_FLAG
    #include "l1_types.h"
    #include "l1audio_const.h"
    #include "l1audio_cust.h"
    #include "l1audio_defty.h"
    #include "l1audio_msgty.h"
    #include "l1audio_signa.h"
    #include "l1_const.h"
    #include "l1_defty.h"
    #include "l1_msgty.h"
    #include "l1_signa.h"
    #include "l1_varex.h"
	#include "audio/tests/audio_test.h"
  #endif

#if (L1_AUDIO_DRIVER)
  #if (L1_VOICE_MEMO_AMR)
    extern T_AUDIO_RET audio_driver_vm_amr_play_manager (T_RV_HDR *p_message, T_AUDIO_DRIVER_SESSION *p_session);
    extern T_AUDIO_RET audio_driver_vm_amr_record_manager (T_RV_HDR *p_message, T_AUDIO_DRIVER_SESSION *p_session);
    extern T_AUDIO_RET audio_driver_midi_manager (T_RV_HDR *p_message, T_AUDIO_DRIVER_SESSION *p_session);
  #endif

  UINT8 audio_driver_message_switch(T_RV_HDR *p_message);
  void audio_driver_send_status (T_AUDIO_RET status,
                                 UINT8 status_type,
                                 UINT8 channel_id,
                                 T_RV_RETURN return_path);
  void audio_driver_init_send_status (T_AUDIO_RET status,
                                      UINT8 session_id,
                                      UINT8 channel_id,
                                      T_RV_RETURN return_path);
  void audio_driver_manager(T_RV_HDR *p_message);
  T_AUDIO_RET audio_driver_get_play_buffer(UINT8 channel_id, UINT8 **pp_buffer);
  T_AUDIO_RET audio_driver_play_buffer(UINT8 channel_id, UINT8 *p_buffer);

  UINT8 audio_driver_message_switch(T_RV_HDR *p_message)
  {
    switch (p_message->msg_id)
    {
      case AUDIO_DRIVER_START_SESSION:
      case AUDIO_DRIVER_STOP_SESSION:
      case AUDIO_DRIVER_FREE_SESSION:
        return(AUDIO_DRIVER_SWITCH);
      break;
    #if (L1_VOICE_MEMO_AMR)
      case AUDIO_DRIVER_INIT_VM_AMR_RECORD_SESSION:
      case MMI_VM_AMR_RECORD_START_CON:
      case MMI_VM_AMR_RECORD_STOP_CON:
        return(AUDIO_DRIVER_VM_AMR_RECORD_SESSION_SWITCH);
      break;
      case AUDIO_DRIVER_INIT_VM_AMR_PLAY_SESSION:
      case MMI_VM_AMR_PLAY_START_CON:
      case MMI_VM_AMR_PLAY_STOP_CON:
        return(AUDIO_DRIVER_VM_AMR_PLAY_SESSION_SWITCH);
      break;
    #endif
    #if (L1_MIDI == 1)
      case AUDIO_DRIVER_INIT_MIDI_SESSION:
      case MMI_MIDI_START_CON:
      case MMI_MIDI_STOP_CON:
        return(AUDIO_DRIVER_MIDI_SESSION_SWITCH);
      break;
    #endif
      default:
        return(AUDIO_DRIVER_NONE);
      break;
    } // switch
  }

  void audio_driver_send_status (T_AUDIO_RET status,
                                 UINT8       status_type,
                                 UINT8       channel_id,
                                 T_RV_RETURN return_path)
  {
    T_AUDIO_DRIVER_STATUS *p_send_message;
    T_RVF_MB_STATUS mb_status = RVF_RED;

    while (mb_status == RVF_RED)
    {
      // allocate the message buffer
      mb_status = rvf_get_buf (p_audio_gbl_var->mb_external,
                               sizeof (T_AUDIO_DRIVER_STATUS),
                               (T_RVF_BUFFER **) (&p_send_message));

      // If insufficient resources, then report a memory error and abort.
      // and wait until more ressource is given
      if (mb_status == RVF_RED)
      {
        audio_driver_error_trace(AUDIO_ENTITY_NO_MEMORY);
        rvf_delay(RVF_MS_TO_TICKS(1000));
      }
    }

    // fill the header of the message + parameters
    p_send_message->os_hdr.msg_id = AUDIO_DRIVER_STATUS_MSG;
    p_send_message->status      = status;
    p_send_message->status_type = status_type;
    p_send_message->channel_id  = channel_id;

    // send message or call callback
    if (return_path.callback_func == NULL)
      rvf_send_msg (return_path.addr_id, p_send_message);
    else
    {
      (*return_path.callback_func)((void *)(p_send_message));
	    rvf_free_buf((T_RVF_BUFFER *)p_send_message);
    }
  }

  void audio_driver_init_send_status (T_AUDIO_RET status,
                                      UINT8       session_id,
                                      UINT8       channel_id,
                                      T_RV_RETURN return_path)
  {
    T_AUDIO_DRIVER_INIT_STATUS *p_send_message;
    T_RVF_MB_STATUS mb_status = RVF_RED;

    while (mb_status == RVF_RED)
    {
      // allocate the message buffer
      mb_status = rvf_get_buf (p_audio_gbl_var->mb_external,
                               sizeof (T_AUDIO_DRIVER_INIT_STATUS),
                               (T_RVF_BUFFER **) (&p_send_message));

      // If insufficient resources, then report a memory error and abort.
      // and wait until more ressource is given
      if (mb_status == RVF_RED)
      {
        audio_driver_error_trace(AUDIO_ENTITY_NO_MEMORY);
        rvf_delay(RVF_MS_TO_TICKS(1000));
      }
    }

    // fill the header of the message
    p_send_message->os_hdr.msg_id = AUDIO_DRIVER_INIT_STATUS_MSG;

    // fill the status parameters
    p_send_message->status      = status;
    p_send_message->session_id  = session_id;
    p_send_message->channel_id  = channel_id;

    // send message or call callback
    if (return_path.callback_func == NULL)
      rvf_send_msg (return_path.addr_id, p_send_message);
    else
    {
      (*return_path.callback_func)((void *)(p_send_message));
	    rvf_free_buf((T_RVF_BUFFER *)p_send_message);
    }
  }

  void audio_driver_manager(T_RV_HDR *p_message)
  {
    T_AUDIO_DRIVER_SESSION *p_session;
    T_AUDIO_DRIVER_PARAMETER *driver_parameter;
    T_RV_RETURN return_path;
    T_RVF_MB_STATUS mb_status;
    UINT8 session_id, channel_id, state, j;

    // initialize return_path to default values
    return_path.callback_func=NULL;
    return_path.addr_id=0;

    // find state + extract information:channel_id or session_id + driver_parameter
    switch (p_message->msg_id)
    {
      // start/stop session messages have channel_id so we know the driver_session
      case AUDIO_DRIVER_START_SESSION:
      case AUDIO_DRIVER_STOP_SESSION:
      case AUDIO_DRIVER_FREE_SESSION:
        channel_id = ((T_AUDIO_DRIVER_HANDLE_SESSION *)p_message)->channel_id;
        p_session  = &(p_audio_gbl_var->audio_driver_session[channel_id]);
        state      = p_session->session_info.state;
        if (p_message->msg_id != AUDIO_DRIVER_STOP_SESSION)
          return_path = ((T_AUDIO_DRIVER_HANDLE_SESSION *)p_message)->return_path;
        else
          return_path = p_session->session_req.return_path;
      break;
      // messages which contain only session_id, must look for it in ACTIVE driver_session
      default:
      {
        switch (p_message->msg_id)
        {
        #if (L1_VOICE_MEMO_AMR)
          case AUDIO_DRIVER_INIT_VM_AMR_RECORD_SESSION:
            session_id       = AUDIO_VM_AMR_RECORD_SESSION_ID;
            driver_parameter = &(((T_AUDIO_DRIVER_INIT_VM_AMR_RECORD_SESSION *)p_message)->driver_parameter);
            return_path      = ((T_AUDIO_DRIVER_INIT_VM_AMR_RECORD_SESSION *)p_message)->return_path;
          break;
          case AUDIO_DRIVER_INIT_VM_AMR_PLAY_SESSION:
            session_id       = AUDIO_VM_AMR_PLAY_SESSION_ID;
            driver_parameter = & (((T_AUDIO_DRIVER_INIT_VM_AMR_PLAY_SESSION *)p_message)->driver_parameter);
            return_path      = ((T_AUDIO_DRIVER_INIT_VM_AMR_PLAY_SESSION *)p_message)->return_path;
          break;
          case MMI_VM_AMR_RECORD_START_CON:
          case MMI_VM_AMR_RECORD_STOP_CON:
            session_id = AUDIO_VM_AMR_RECORD_SESSION_ID;
          break;
          case MMI_VM_AMR_PLAY_START_CON:
          case MMI_VM_AMR_PLAY_STOP_CON:
            session_id = AUDIO_VM_AMR_PLAY_SESSION_ID;
          break;
        #endif
        #if (L1_MIDI == 1)
          case AUDIO_DRIVER_INIT_MIDI_SESSION:
            session_id       = AUDIO_MIDI_SESSION_ID;
            driver_parameter = &(((T_AUDIO_DRIVER_INIT_MIDI_SESSION *)p_message)->driver_parameter);
            return_path      = ((T_AUDIO_DRIVER_INIT_MIDI_SESSION *)p_message)->return_path;
          break;
          case MMI_MIDI_START_CON:
          case MMI_MIDI_STOP_CON:
            session_id = AUDIO_MIDI_SESSION_ID;
          break;
        #endif
        }

        // initialize channel_id to browse all driver channels
        channel_id = 0;
        state = AUDIO_DRIVER_CHANNEL_WAIT_INIT;

        // look for an active session, which session_id matches the one from the message
        while ( (channel_id < AUDIO_DRIVER_MAX_CHANNEL)&&
                ((p_audio_gbl_var->audio_driver_session[channel_id].session_info.state == AUDIO_DRIVER_CHANNEL_WAIT_INIT)||
                (p_audio_gbl_var->audio_driver_session[channel_id].session_req.session_id != session_id)) )
        {
          channel_id++;
        }
        // if channel_id < MAX_CHANNEL, we found an active channel so we can derive channel_id + state
        if (channel_id < AUDIO_DRIVER_MAX_CHANNEL)
        {
          p_session = &(p_audio_gbl_var->audio_driver_session[channel_id]);
          state = p_session->session_info.state;
          return_path = p_session->session_req.return_path;
        }
      }
      break; // default
    }

    switch (state)
    {
      case AUDIO_DRIVER_CHANNEL_WAIT_INIT:
      {
        switch (p_message->msg_id)
        {
        #if (L1_VOICE_MEMO_AMR)
          case AUDIO_DRIVER_INIT_VM_AMR_RECORD_SESSION:
          case AUDIO_DRIVER_INIT_VM_AMR_PLAY_SESSION:
        #endif
        #if (L1_MIDI == 1)
          case AUDIO_DRIVER_INIT_MIDI_SESSION:
        #endif
          {
            T_AUDIO_RET result;

            // Find a free channel
            channel_id = 0;
            while ( (p_audio_gbl_var->audio_driver_session[channel_id].session_info.state != AUDIO_DRIVER_CHANNEL_WAIT_INIT) &&
                    (channel_id < AUDIO_DRIVER_MAX_CHANNEL) )
              channel_id++;

            if (channel_id == AUDIO_DRIVER_MAX_CHANNEL)
            {
              AUDIO_SEND_TRACE("no driver channel available", RV_TRACE_LEVEL_DEBUG_LOW);
              audio_driver_init_send_status(AUDIO_ERROR, session_id, channel_id, return_path);
              return;
            }

            AUDIO_SEND_TRACE_PARAM("AUDIO DRIVER: open channel", channel_id, RV_TRACE_LEVEL_DEBUG_LOW);

            // get session descriptor and fill REQ parameters
            p_session = &(p_audio_gbl_var->audio_driver_session[channel_id]);
            p_session->session_req.session_id     = session_id;
            p_session->session_req.size           = driver_parameter->buffer_size << 1;// we request 16-bit words buffers
            p_session->session_req.nb_buffer      = driver_parameter->nb_buffer;
            // fill return_path parameters, may be used if next message is STOP_SESSION
            p_session->session_req.return_path.callback_func = return_path.callback_func;
            p_session->session_req.return_path.addr_id = return_path.addr_id;

            /************************************************************/
            /* the driver must allocate the RAM buffers pointer         */
            /************************************************************/
            mb_status = rvf_get_buf (p_audio_gbl_var->mb_internal,
                                     sizeof(T_AUDIO_DRIVER_BUFFER_INFO)*p_session->session_req.nb_buffer,
                                     (T_RVF_BUFFER **) (&p_session->session_info.buffer));

            // If insufficient resources, then report a memory error and abort.
            if (mb_status == RVF_RED)
            {
              audio_driver_error_trace(AUDIO_ENTITY_NO_MEMORY);
              audio_driver_init_send_status(AUDIO_ERROR, session_id, channel_id, return_path);
              return;
            }

            /************************************************************/
            /* the driver must allocate the RAM buffers                 */
            /************************************************************/
            for (j = 0; j < p_session->session_req.nb_buffer; j++)
            {
              mb_status = rvf_get_buf (p_audio_gbl_var->mb_audio_ffs,
                                       p_session->session_req.size,
                                       (T_RVF_BUFFER **) (&p_session->session_info.buffer[j].p_start_pointer));

              // If insufficient resources, then report a memory error and abort.
              if (mb_status == RVF_RED)
              {
                UINT8 i;
                // free already allocated buffers + buffer pointer
                if (j > 0)
                {
                  for (i = j - 1; i >= 0; i--)
                    rvf_free_buf((T_RVF_BUFFER *)p_session->session_info.buffer[i].p_start_pointer);
                }
                rvf_free_buf((T_RVF_BUFFER *)p_session->session_info.buffer);
                audio_driver_error_trace(AUDIO_ENTITY_NO_MEMORY);
                audio_driver_init_send_status(AUDIO_ERROR, session_id, channel_id, return_path);
                return;
              }

              // initialize parameters
              p_session->session_info.buffer[j].size = p_session->session_req.size;

              AUDIO_SEND_TRACE_PARAM("AUDIO DRIVER: allocate buffer",
                p_session->session_info.buffer[j].p_start_pointer, RV_TRACE_LEVEL_DEBUG_LOW);
            }

            // info parameters (state must be changed before driver specific functions call
            p_session->session_info.index_l1     = 0;
            p_session->session_info.index_appli  = 0;
            p_session->session_info.stop_request = 0;

            // conversion of parameters + prepare l1 start message
            switch(p_message->msg_id)
            {
            #if (L1_VOICE_MEMO_AMR)
              case AUDIO_DRIVER_INIT_VM_AMR_RECORD_SESSION:
                result=audio_driver_vm_amr_record_manager(p_message,p_session);
              break;
              case AUDIO_DRIVER_INIT_VM_AMR_PLAY_SESSION:
                result=audio_driver_vm_amr_play_manager(p_message,p_session);
              break;
            #endif
            #if (L1_MIDI == 1)
              case AUDIO_DRIVER_INIT_MIDI_SESSION:
                result=audio_driver_midi_manager(p_message,p_session);
              break;
            #endif
            }

            // check L1 msg allocation was successfull
            if (result != AUDIO_OK)
            {
              AUDIO_SEND_TRACE("AUDIO DRIVER MANAGER: L1 msg allocation failed", RV_TRACE_LEVEL_DEBUG_LOW);
              audio_driver_init_send_status(AUDIO_ERROR, session_id, channel_id, return_path);
              return;
            }

            // state (must be changed after driver specific functions calls)
            p_session->session_info.state = AUDIO_DRIVER_CHANNEL_WAIT_START;

            audio_driver_init_send_status(AUDIO_OK, session_id, channel_id, return_path);
          } //case AUDIO_DRIVER_INIT_..._SESSION:
          break;
          case AUDIO_DRIVER_START_SESSION:
            audio_driver_error_trace(AUDIO_ERROR_START_EVENT);
            audio_driver_send_status(AUDIO_ERROR, AUDIO_START_STATUS, channel_id, return_path);
          break;
          case AUDIO_DRIVER_STOP_SESSION:
            audio_driver_error_trace(AUDIO_ERROR_STOP_EVENT);
            audio_driver_send_status(AUDIO_ERROR, AUDIO_STOP_STATUS, channel_id, return_path);
          break;
          case AUDIO_DRIVER_FREE_SESSION:
            audio_driver_error_trace(AUDIO_ERROR_FREE_EVENT);
            audio_driver_send_status(AUDIO_ERROR, AUDIO_FREE_STATUS, channel_id, return_path);
          break;
        } // switch (p_message->msg_id)
      } //case AUDIO_DRIVER_CHANNEL_WAIT_INIT:
      break;
      case AUDIO_DRIVER_CHANNEL_WAIT_START:
      {
        switch (p_message->msg_id)
        {
          case AUDIO_DRIVER_START_SESSION:
          {
            T_AUDIO_RET result;

            // fill notification parameters
            p_session->session_req.return_path.callback_func = return_path.callback_func;
            p_session->session_req.return_path.addr_id = return_path.addr_id;

            // send l1 message
            switch(p_session->session_req.session_id)
            {
            #if (L1_VOICE_MEMO_AMR)
              case AUDIO_VM_AMR_RECORD_SESSION_ID:
                result=audio_driver_vm_amr_record_manager(p_message,p_session);
              break;
              case AUDIO_VM_AMR_PLAY_SESSION_ID:
                result=audio_driver_vm_amr_play_manager(p_message,p_session);
              break;
            #endif
            #if (L1_MIDI == 1)
              case AUDIO_MIDI_SESSION_ID:
                result=audio_driver_midi_manager(p_message,p_session);
              break;
            #endif
            }

            if (result != AUDIO_OK)
            {
              audio_driver_error_trace(AUDIO_ERROR_L1_START_EVENT);
              audio_driver_send_status(AUDIO_ERROR, AUDIO_START_STATUS, channel_id, return_path);
              return;
            }

            // change state
            p_session->session_info.state = AUDIO_DRIVER_CHANNEL_WAIT_START_CON;
          }
          break;
          case AUDIO_DRIVER_STOP_SESSION:
          {
            // deallocate buffers
            for(j=0; j<p_session->session_req.nb_buffer; j++)
            {
              mb_status=rvf_free_buf((T_RVF_BUFFER *)(p_session->session_info.buffer[j].p_start_pointer));

              AUDIO_SEND_TRACE_PARAM("AUDIO DRIVER MANAGER: deallocate buffer",
                j, RV_TRACE_LEVEL_DEBUG_LOW);

              if (mb_status != RVF_GREEN)
                AUDIO_SEND_TRACE_PARAM("can't deallocate buffer", j, RV_TRACE_LEVEL_ERROR);
            }

            // Deallocate buffers pointer
            rvf_free_buf((T_RVF_BUFFER *)p_session->session_info.buffer);

            // deallocate l1 message
            audio_deallocate_l1_message(p_session->session_req.p_l1_send_message);

            // send status OK
            audio_driver_send_status(AUDIO_OK,AUDIO_STOP_STATUS,channel_id,return_path);

            // change state
            p_session->session_info.state=AUDIO_DRIVER_CHANNEL_WAIT_INIT;
          }
          break;
        #if (L1_VOICE_MEMO_AMR)
          case AUDIO_DRIVER_INIT_VM_AMR_RECORD_SESSION:
          case AUDIO_DRIVER_INIT_VM_AMR_PLAY_SESSION:
        #endif
        #if (L1_MIDI == 1)
          case AUDIO_DRIVER_INIT_MIDI_SESSION:
        #endif
            audio_driver_error_trace(AUDIO_ERROR_INIT_EVENT);
            audio_driver_init_send_status(AUDIO_ERROR, session_id, 0, return_path);
          break;
          case AUDIO_DRIVER_FREE_SESSION:
            audio_driver_error_trace(AUDIO_ERROR_FREE_EVENT);
            audio_driver_send_status(AUDIO_ERROR, AUDIO_FREE_STATUS, channel_id, return_path);
          break;
        } // switch
      } //case AUDIO_DRIVER_CHANNEL_WAIT_START:
      break;
      case AUDIO_DRIVER_CHANNEL_WAIT_START_CON:
      {
        switch (p_message->msg_id)
        {
        #if (L1_VOICE_MEMO_AMR)
          case MMI_VM_AMR_RECORD_START_CON:
          case MMI_VM_AMR_PLAY_START_CON:
        #endif
        #if (L1_MIDI == 1)
          case MMI_MIDI_START_CON:
        #endif
            // change state
            p_session->session_info.state = AUDIO_DRIVER_CHANNEL_WAIT_STOP;
          break;
          case AUDIO_DRIVER_STOP_SESSION:
            // change state
            p_session->session_info.state = AUDIO_DRIVER_CHANNEL_WAIT_START_CON_TO_STOP;
          break;
        #if (L1_VOICE_MEMO_AMR)
          case AUDIO_DRIVER_INIT_VM_AMR_RECORD_SESSION:
          case AUDIO_DRIVER_INIT_VM_AMR_PLAY_SESSION:
        #endif
        #if (L1_MIDI == 1)
          case AUDIO_DRIVER_INIT_MIDI_SESSION:
        #endif
            audio_driver_error_trace(AUDIO_ERROR_INIT_EVENT);
            audio_driver_init_send_status(AUDIO_ERROR, session_id, channel_id, return_path);
          break;
          case AUDIO_DRIVER_START_SESSION:
            audio_driver_error_trace(AUDIO_ERROR_START_EVENT);
            audio_driver_send_status(AUDIO_ERROR, AUDIO_START_STATUS, channel_id, return_path);
          break;
          case AUDIO_DRIVER_FREE_SESSION:
            audio_driver_error_trace(AUDIO_ERROR_FREE_EVENT);
            audio_driver_send_status(AUDIO_ERROR, AUDIO_FREE_STATUS, channel_id, return_path);
          break;
        } // switch
      } //case AUDIO_DRIVER_CHANNEL_WAIT_START_CON:
      break;
      case AUDIO_DRIVER_CHANNEL_WAIT_STOP:
      {
        switch (p_message->msg_id)
        {
          case AUDIO_DRIVER_STOP_SESSION:
          {
            // 1st stop request
            if (p_session->session_info.stop_request == 0)
            {
              T_AUDIO_RET result;

              // send l1 message STOP_REQ
              switch(p_session->session_req.session_id)
              {
              #if (L1_VOICE_MEMO_AMR)
                case AUDIO_VM_AMR_RECORD_SESSION_ID:
                  result=audio_driver_vm_amr_record_manager(p_message,p_session);
                break;
                case AUDIO_VM_AMR_PLAY_SESSION_ID:
                  result=audio_driver_vm_amr_play_manager(p_message,p_session);
                break;
              #endif
              #if (L1_MIDI == 1)
                case AUDIO_MIDI_SESSION_ID:
                  result=audio_driver_midi_manager(p_message,p_session);
                break;
              #endif
              }

              // allocate or send L1 msg went wrong
              if (result != AUDIO_OK)
              {
                audio_driver_error_trace(AUDIO_ERROR_L1_STOP_EVENT);
                audio_driver_send_status(AUDIO_ERROR, AUDIO_STOP_STATUS, channel_id, return_path);
                return;
              }

              // STOP has been requested, no longer accept it
              p_session->session_info.stop_request = 1;
            }
            else
            {
              audio_driver_error_trace(AUDIO_ERROR_STOP_EVENT);
              audio_driver_send_status(AUDIO_ERROR, AUDIO_STOP_STATUS, channel_id, return_path);
            }
          }
          break;
        #if (L1_VOICE_MEMO_AMR)
          case MMI_VM_AMR_RECORD_STOP_CON:
          {
            // send last notification
            T_AUDIO_DRIVER_LAST_NOTIFICATION *p_status_message;

            // Allocate the Riviera buffer
            mb_status = RVF_RED;
            while (mb_status == RVF_RED)
            {
              mb_status = rvf_get_buf (p_audio_gbl_var->mb_internal,
                                       sizeof (T_AUDIO_DRIVER_LAST_NOTIFICATION),
                                       (T_RVF_BUFFER **) (&p_status_message));
              // If insufficient resources, then report a memory error and abort.
              if (mb_status == RVF_RED)
              {
                // the memory is insufficient to continue the non regression test
                audio_driver_error_trace(AUDIO_ENTITY_NO_MEMORY);
                rvf_delay(RVF_MS_TO_TICKS(1000));
              }
            }

            // Fill the message ID
            p_status_message->header.msg_id = AUDIO_DRIVER_LAST_NOTIFICATION_MSG;

            // fill parameters
            p_status_message->channel_id = channel_id;
            p_status_message->recorded_size = ((T_MMI_VM_AMR_RECORD_CON *)p_message)->recorded_size - SC_VM_AMR_END_MASK_SIZE;
            p_status_message->p_buffer   =
              (UINT16 *)p_session->session_info.buffer[p_session->session_info.index_l1].p_start_pointer;

            if (return_path.callback_func == NULL)
              rvf_send_msg (return_path.addr_id, p_status_message);
            else
            {
              // call the callback function
              (*(return_path.callback_func))((void *)(p_status_message));
              rvf_free_buf((T_RVF_BUFFER *)p_status_message);
            }

            // change state
            p_session->session_info.state = AUDIO_DRIVER_CHANNEL_WAIT_FREE;
          }
          break;
        #endif // #if (L1_VOICE_MEMO_AMR)
        #if (L1_VOICE_MEMO_AMR)
          case MMI_VM_AMR_PLAY_STOP_CON:
        #endif
        #if (L1_MIDI == 1)
          case MMI_MIDI_STOP_CON:
        #endif
          {
            // deallocate buffers
            for (j = 0; j < p_session->session_req.nb_buffer; j++)
            {
              mb_status = rvf_free_buf ((T_RVF_BUFFER *) (p_session->session_info.buffer[j].p_start_pointer));

              AUDIO_SEND_TRACE_PARAM("AUDIO DRIVER MANAGER: deallocate buffer", j, RV_TRACE_LEVEL_DEBUG_LOW);

              if (mb_status != RVF_GREEN)
                AUDIO_SEND_TRACE_PARAM("can't deallocate buffer", j, RV_TRACE_LEVEL_ERROR);
            }
            // Deallocate buffers pointer
            rvf_free_buf((T_RVF_BUFFER *)p_session->session_info.buffer);

            audio_driver_send_status (AUDIO_OK, AUDIO_STOP_STATUS, channel_id,
                                      return_path);
            // change state
            p_session->session_info.state = AUDIO_DRIVER_CHANNEL_WAIT_INIT;
          }
          break;
        #if (L1_VOICE_MEMO_AMR)
          case AUDIO_DRIVER_INIT_VM_AMR_RECORD_SESSION:
          case AUDIO_DRIVER_INIT_VM_AMR_PLAY_SESSION:
        #endif
        #if (L1_MIDI == 1)
          case AUDIO_DRIVER_INIT_MIDI_SESSION:
        #endif
            audio_driver_error_trace(AUDIO_ERROR_INIT_EVENT);
            audio_driver_init_send_status(AUDIO_ERROR, session_id, channel_id, return_path);
          break;
          case AUDIO_DRIVER_START_SESSION:
            audio_driver_error_trace(AUDIO_ERROR_START_EVENT);
            audio_driver_send_status(AUDIO_ERROR, AUDIO_START_STATUS, channel_id, return_path);
          break;
          case AUDIO_DRIVER_FREE_SESSION:
            audio_driver_error_trace(AUDIO_ERROR_FREE_EVENT);
            audio_driver_send_status(AUDIO_ERROR, AUDIO_FREE_STATUS, channel_id, return_path);
          break;
        } //switch
      } //case AUDIO_DRIVER_CHANNEL_WAIT_STOP:
      break;
      case AUDIO_DRIVER_CHANNEL_WAIT_START_CON_TO_STOP:
      {
        T_AUDIO_RET result = AUDIO_OK;
        switch (p_message->msg_id)
        {
        #if (L1_VOICE_MEMO_AMR)
          case AUDIO_DRIVER_INIT_VM_AMR_RECORD_SESSION:
          case AUDIO_DRIVER_INIT_VM_AMR_PLAY_SESSION:
        #endif
        #if (L1_MIDI == 1)
          case AUDIO_DRIVER_INIT_MIDI_SESSION:
        #endif
            audio_driver_error_trace(AUDIO_ERROR_INIT_EVENT);
            audio_driver_init_send_status(AUDIO_ERROR, session_id, channel_id, return_path);
            return;
          break;
          case AUDIO_DRIVER_START_SESSION:
            audio_driver_error_trace(AUDIO_ERROR_START_EVENT);
            audio_driver_send_status(AUDIO_ERROR, AUDIO_START_STATUS, channel_id, return_path);
            return;
          break;
          case AUDIO_DRIVER_STOP_SESSION:
            audio_driver_error_trace(AUDIO_ERROR_STOP_EVENT);
            audio_driver_send_status(AUDIO_ERROR, AUDIO_STOP_STATUS, channel_id, return_path);
            return;
          break;
          case AUDIO_DRIVER_FREE_SESSION:
            audio_driver_error_trace(AUDIO_ERROR_FREE_EVENT);
            audio_driver_send_status(AUDIO_ERROR, AUDIO_FREE_STATUS, channel_id, return_path);
            return;
          break;
        #if (L1_VOICE_MEMO_AMR)
          case MMI_VM_AMR_RECORD_START_CON:
            // send L1 stop msg
            result=audio_driver_vm_amr_record_manager(p_message, p_session);
          break;
          case MMI_VM_AMR_PLAY_START_CON:
            // send L1 stop msg
            result=audio_driver_vm_amr_play_manager(p_message, p_session);
          break;
        #endif
        #if (L1_MIDI == 1)
          case MMI_MIDI_START_CON:
            // send L1 stop msg
            result=audio_driver_midi_manager(p_message,p_session);
          break;
        #endif
        }

        if (result != AUDIO_OK)
        {
          audio_driver_send_status(AUDIO_ERROR, AUDIO_STOP_STATUS, channel_id, return_path);
          return;
        }
        else
        {
          // next state should be WAIT_STOP_CON, which is WAIT_STOP + stop_request == 1
          p_session->session_info.stop_request = 1;
          // change state
          p_session->session_info.state = AUDIO_DRIVER_CHANNEL_WAIT_STOP;
        }
      }
      break;
      case AUDIO_DRIVER_CHANNEL_WAIT_FREE:
      {
        switch (p_message->msg_id)
        {
          case AUDIO_DRIVER_FREE_SESSION:
          {
            // deallocate buffers
            for (j = 0; j < p_session->session_req.nb_buffer; j++)
            {
              mb_status = rvf_free_buf ((T_RVF_BUFFER *) (p_session->session_info.buffer[j].p_start_pointer));

              AUDIO_SEND_TRACE_PARAM("AUDIO DRIVER MANAGER: deallocate buffer", j, RV_TRACE_LEVEL_DEBUG_LOW);

              if (mb_status != RVF_GREEN)
                AUDIO_SEND_TRACE_PARAM("can't deallocate buffer", j, RV_TRACE_LEVEL_ERROR);
            }
            // Deallocate buffers pointer
            rvf_free_buf((T_RVF_BUFFER *)p_session->session_info.buffer);

            audio_driver_send_status (AUDIO_OK, AUDIO_FREE_STATUS, channel_id,
                                      return_path);

            // change state
            p_session->session_info.state = AUDIO_DRIVER_CHANNEL_WAIT_INIT;
          }
          break;
        #if (L1_VOICE_MEMO_AMR)
          case AUDIO_DRIVER_INIT_VM_AMR_RECORD_SESSION:
          case AUDIO_DRIVER_INIT_VM_AMR_PLAY_SESSION:
        #endif
        #if (L1_MIDI == 1)
          case AUDIO_DRIVER_INIT_MIDI_SESSION:
        #endif
            audio_driver_error_trace(AUDIO_ERROR_INIT_EVENT);
            audio_driver_init_send_status(AUDIO_ERROR, session_id, channel_id, return_path);
          break;
          case AUDIO_DRIVER_START_SESSION:
            audio_driver_error_trace(AUDIO_ERROR_START_EVENT);
            audio_driver_send_status(AUDIO_ERROR, AUDIO_START_STATUS, channel_id, return_path);
          break;
          case AUDIO_DRIVER_STOP_SESSION:
            audio_driver_error_trace(AUDIO_ERROR_STOP_EVENT);
            audio_driver_send_status(AUDIO_ERROR, AUDIO_STOP_STATUS, channel_id, return_path);
          break;
        } // switch
      }
      break;
    }
  }
#endif // (L1_AUDIO_DRIVER)

#endif // #ifdef RVM_AUDIO_MAIN_SWE