diff src/cs/services/audio/audio_driver.c @ 0:92470e5d0b9e

src: partial import from FC Selenite
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 15 May 2020 01:28:16 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cs/services/audio/audio_driver.c	Fri May 15 01:28:16 2020 +0000
@@ -0,0 +1,810 @@
+/****************************************************************************/
+/*                                                                          */
+/*  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