FreeCalypso > hg > fc-magnetite
diff src/cs/services/Audio/audio_ffs.c @ 0:945cf7f506b2
src/cs: chipsetsw import from tcs211-fcmodem
binary blobs and LCD demo files have been excluded,
all line endings are LF only
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 25 Sep 2016 22:50:11 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cs/services/Audio/audio_ffs.c Sun Sep 25 22:50:11 2016 +0000 @@ -0,0 +1,1437 @@ +/****************************************************************************/ +/* */ +/* Name audio_ffs.c */ +/* */ +/* Function this file contains the AUDIO ffs function: */ +/* */ +/* */ +/* Version 0.1 */ +/* */ +/* Date Modification */ +/* ------------------------------------ */ +/* 18 May 2001 Create */ +/* */ +/* Author Francois Mazard - Stephanie Gerthoux */ +/* */ +/* (C) Copyright 2001 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" + #if (MELODY_E1) || (MELODY_E2) || (VOICE_MEMO) + #include "rvf/rvf_api.h" + #include "rv/rv_general.h" + #include "rvm/rvm_gen.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" + + /* include the usefull L1 header */ + #define BOOL_FLAG + #define CHAR_FLAG + #include "l1_types.h" + #include "l1audio_cust.h" + #include "l1audio_const.h" + #include "l1audio_msgty.h" + #include "l1audio_signa.h" + + #include "ffs/ffs_api.h" + + + /********************************************************************************/ + /* */ + /* Function Name: audio_ffs_manager */ + /* */ + /* Purpose: This function is called to manage the FFS request from the */ + /* audio entity */ + /* */ + /* Input Parameters: */ + /* message from the audio entity */ + /* */ + /* Output Parameters: */ + /* None. */ + /* */ + /* Note: */ + /* None. */ + /* */ + /* Revision History: */ + /* None. */ + /* */ + /********************************************************************************/ + void audio_ffs_manager (T_RV_HDR *p_message) + { + UINT8 j, active_task, index_ffs, index_l1, *p_buffer, channel_id; + T_AUDIO_FFS_SESSION *p_session; + T_RV_HDR *p_send_message; + T_RVF_MB_STATUS mb_status; + BOOLEAN loop_mode; + #ifndef _WINDOWS + UINT16 voice_memo_size, *p_scan; + #else + UINT16 i; + UINT8 *p_mem; + #endif + UINT16 buffer_size; + T_FFS_SIZE size; + T_RV_RET status; + + switch (p_message->msg_id) + { + case AUDIO_FFS_FLASH_2_RAM_START_REQ: + { + AUDIO_SEND_TRACE_PARAM("AUDIO FFS MANAGER: flash to RAM session_id", + ((T_AUDIO_FFS_FLASH_2_RAM_START *)p_message)->session_id, RV_TRACE_LEVEL_DEBUG_LOW); + + /* Find a free channel */ + channel_id = 0; + while ( (p_audio_gbl_var->audio_ffs_session[channel_id].session_req.valid_channel) && + (channel_id < AUDIO_FFS_MAX_CHANNEL) ) + channel_id++; + + AUDIO_SEND_TRACE_PARAM("AUDIO FFS MANAGER: open channel", + channel_id, RV_TRACE_LEVEL_DEBUG_LOW); + + p_session = + &(p_audio_gbl_var->audio_ffs_session[channel_id]); + + /* fill the request structure corresponding to the session id */ + p_session->session_req.audio_ffs_fd = + ((T_AUDIO_FFS_FLASH_2_RAM_START *)p_message)->audio_ffs_fd; + p_session->session_req.size = + ((T_AUDIO_FFS_FLASH_2_RAM_START *)p_message)->initial_size; + p_session->session_req.loop_mode = + ((T_AUDIO_FFS_FLASH_2_RAM_START *)p_message)->loop; + p_session->session_req.session_id = + ((T_AUDIO_FFS_FLASH_2_RAM_START *)p_message)->session_id; + + /************************************************************/ + /* the FFS must download the 2 first buffers to the RAM */ + /************************************************************/ + for (j=0; j<2; j++) + { + /* allocate the first buffer */ + p_session->session_info.buffer[j].size = + p_session->session_req.size; + + mb_status = rvf_get_buf (p_audio_gbl_var->mb_audio_ffs, + p_session->session_info.buffer[j].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) + { + audio_ffs_error_trace(AUDIO_ENTITY_NO_MEMORY); + } + + AUDIO_SEND_TRACE_PARAM("AUDIO FFS MANAGER: allocate buffer", + j, RV_TRACE_LEVEL_DEBUG_LOW); + + /* intialize the stop pointer */ + p_session->session_info.buffer[j].p_stop_pointer = + p_session->session_info.buffer[j].p_start_pointer + + (p_session->session_info.buffer[j].size); + + /* Fill the buffer j while it isn't full in case of the loop back mode activated */ + loop_mode = TRUE; + buffer_size = p_session->session_info.buffer[j].size; + p_buffer = (UINT8 *)p_session->session_info.buffer[j].p_start_pointer; + while ( (p_buffer < p_session->session_info.buffer[j].p_stop_pointer) && + (loop_mode) ) + { + loop_mode = p_session->session_req.loop_mode; + + #ifndef _WINDOWS + size = ffs_read(p_session->session_req.audio_ffs_fd, + p_buffer, + buffer_size); + #else + size = buffer_size; + p_mem = p_buffer; + for (i=0; i<size; i++) + { + *p_mem = (UINT8)i; + p_mem++; + } + #endif + + AUDIO_SEND_TRACE_PARAM("AUDIO FFS MANAGER: ffs_read size", + size, RV_TRACE_LEVEL_DEBUG_LOW); + + buffer_size -= size; + p_buffer += size; + + if (buffer_size != 0) + { + #ifndef _WINDOWS + /* reset the FFS pointer */ + ffs_seek(p_session->session_req.audio_ffs_fd, + 0, + FFS_SEEK_SET); + #endif + } + } /* while */ + } /* for (j=0; j<2; j++) */ + + /* initialize the cust_get_pointer state machine */ + p_session->session_info.cust_get_pointer_state = AUDIO_CUST_GET_POINTER_INIT; + + /* inform the L1 to use the buffer 0 */ + p_session->session_info.index_l1 = 0; + + /* inform the FFS downloader to fill the buffer 0 when the L1 doesn't used */ + p_session->session_info.index_ffs = 0; + + p_session->session_req.session_mode = + AUDIO_FFS_FLASH_2_RAM_SESSION; + + /* a new session is valid now */ + p_session->session_req.valid_channel = TRUE; + + /* Active the downloader if it is not already activated */ + active_task = 0; + for (j=0; j<AUDIO_FFS_MAX_CHANNEL; j++) + { + if ( p_audio_gbl_var->audio_ffs_session[j].session_req.valid_channel ) + { + active_task++; + } + } + AUDIO_SEND_TRACE_PARAM("AUDIO FFS MANAGER: active session", + active_task, RV_TRACE_LEVEL_DEBUG_LOW); + if (active_task == 1) + { + AUDIO_SEND_TRACE("AUDIO FFS MANAGER: start FFS DOWNLOADER", RV_TRACE_LEVEL_DEBUG_LOW); + + /* Active asap the FFS downloader */ + rvf_start_timer(AUDIO_FFS_TIMER, AUDIO_FFS_ACTIVE_NOW, AUDIO_FFS_ONE_SHOT_TIMER); + } + + /* Send the message to confirm that the first buffer is downloaded */ + /* allocate the message buffer */ + mb_status = rvf_get_buf (p_audio_gbl_var->mb_internal, + sizeof (T_AUDIO_FFS_INIT), + (T_RVF_BUFFER **) (&p_send_message)); + + /* If insufficient resources, then report a memory error and abort. */ + if (mb_status == RVF_RED) + { + audio_ffs_error_trace(AUDIO_ENTITY_NO_MEMORY); + } + + /* fill the header of the message */ + ((T_AUDIO_FFS_INIT*)(p_send_message))->os_hdr.msg_id = AUDIO_FFS_INIT_DONE; + + /* fill the status parameters */ + ((T_AUDIO_FFS_INIT *)(p_send_message))->session_id = + ((T_AUDIO_FFS_FLASH_2_RAM_START *)p_message)->session_id; + ((T_AUDIO_FFS_INIT *)(p_send_message))->channel_id = + channel_id; + + + /* send the message to the AUDIO entity */ + rvf_send_msg (p_audio_gbl_var->addrId, + p_send_message); + break; + } + case AUDIO_FFS_RAM_2_FLASH_START_REQ: + { + AUDIO_SEND_TRACE_PARAM("AUDIO FFS MANAGER: RAM to flash session_id", + ((T_AUDIO_FFS_RAM_2_FLASH_START *)p_message)->session_id, RV_TRACE_LEVEL_DEBUG_LOW); + + /* Find a free channel */ + channel_id = 0; + while ( (p_audio_gbl_var->audio_ffs_session[channel_id].session_req.valid_channel) && + (channel_id < AUDIO_FFS_MAX_CHANNEL) ) + channel_id++; + + AUDIO_SEND_TRACE_PARAM("AUDIO FFS MANAGER: open channel", + channel_id, RV_TRACE_LEVEL_DEBUG_LOW); + + p_session = + &(p_audio_gbl_var->audio_ffs_session[channel_id]); + + /* fill the request structure corresponding to the session id */ + p_session->session_req.size = + ((T_AUDIO_FFS_RAM_2_FLASH_START *)p_message)->initial_size; + p_session->session_req.loop_mode = FALSE; + p_session->session_req.audio_ffs_fd = + ((T_AUDIO_FFS_RAM_2_FLASH_START *)p_message)->audio_ffs_fd; + p_session->session_req.session_mode = + AUDIO_FFS_RAM_2_FLASH_SESSION; + p_session->session_req.session_id = + ((T_AUDIO_FFS_RAM_2_FLASH_START *)p_message)->session_id; + + /********************* TO BE COMPLETED **********************/ + /* the FFS must allocate the first buffer to the RAM */ + /************************************************************/ + for (j=0; j<2; 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) + { + audio_ffs_error_trace(AUDIO_ENTITY_NO_MEMORY); + } + + AUDIO_SEND_TRACE_PARAM("AUDIO FFS MANAGER: allocate buffer", + j, RV_TRACE_LEVEL_DEBUG_LOW); + + /* Copy the initial size */ + p_session->session_info.buffer[j].size = p_session->session_req.size; + } + + /* initialize the cust_get_pointer state machine */ + p_session->session_info.cust_get_pointer_state = AUDIO_CUST_GET_POINTER_INIT; + + /* inform the L1 to use the buffer 0 */ + p_session->session_info.index_l1 = 0; + + /* inform the FFS downloader to read the buffer 0 when the L1 doesn't used */ + p_session->session_info.index_ffs = 0; + + /* a new session is valid now */ + p_session->session_req.valid_channel = TRUE; + + /* Active the downloader if it is not already activated */ + active_task = 0; + for (j=0; j<AUDIO_FFS_MAX_CHANNEL; j++) + { + if ( p_audio_gbl_var->audio_ffs_session[j].session_req.valid_channel) + { + active_task++; + } + } + AUDIO_SEND_TRACE_PARAM("AUDIO FFS MANAGER: active session", + active_task, RV_TRACE_LEVEL_DEBUG_LOW); + + if (active_task == 1) + { + AUDIO_SEND_TRACE("AUDIO FFS MANAGER: start FFS DOWNLOADER", RV_TRACE_LEVEL_DEBUG_LOW); + + /* Active asap the FFS downloader */ + rvf_start_timer(AUDIO_FFS_TIMER, AUDIO_FFS_ACTIVE_NOW, AUDIO_FFS_ONE_SHOT_TIMER); + } + /* Send the message to confirm that the first buffer is allocated */ + /* allocate the message buffer */ + mb_status = rvf_get_buf (p_audio_gbl_var->mb_internal, + sizeof (T_AUDIO_FFS_INIT), + (T_RVF_BUFFER **) (&p_send_message)); + + /* If insufficient resources, then report a memory error and abort. */ + if (mb_status == RVF_RED) + { + audio_ffs_error_trace(AUDIO_ENTITY_NO_MEMORY); + } + + /* fill the header of the message */ + ((T_AUDIO_FFS_INIT*)(p_send_message))->os_hdr.msg_id = AUDIO_FFS_INIT_DONE; + + /* fill the status parameters */ + ((T_AUDIO_FFS_INIT *)(p_send_message))->session_id = + ((T_AUDIO_FFS_RAM_2_FLASH_START *)p_message)->session_id; + ((T_AUDIO_FFS_INIT *)(p_send_message))->channel_id = + channel_id; + + /* send the message to the AUDIO entity */ + rvf_send_msg (p_audio_gbl_var->addrId, + p_send_message); + + break; + } + + case AUDIO_FFS_STOP_REQ: + { + /* Find a channel corresponding to this session */ + channel_id = 0; + while ( (p_audio_gbl_var->audio_ffs_session[channel_id].session_req.session_id + != ((T_AUDIO_FFS_STOP_REQ *)p_message)->session_id) && + (channel_id < AUDIO_FFS_MAX_CHANNEL) ) + channel_id++; + + p_session = &(p_audio_gbl_var->audio_ffs_session[channel_id]); + + AUDIO_SEND_TRACE_PARAM("AUDIO FFS MANAGER: stop session_id", + ((T_AUDIO_FFS_STOP_REQ *)p_message)->session_id, RV_TRACE_LEVEL_DEBUG_LOW); + AUDIO_SEND_TRACE_PARAM("AUDIO FFS MANAGER: close channel", + channel_id, RV_TRACE_LEVEL_DEBUG_LOW); + + /* the task is stopped */ + p_session->session_req.valid_channel = FALSE; + + /* the stop process depends on the session_mode and sometimes the session_id */ + #if (VOICE_MEMO) + if ( (p_session->session_req.session_mode == AUDIO_FFS_RAM_2_FLASH_SESSION) && + (((T_AUDIO_FFS_STOP_REQ *)p_message)->session_id == AUDIO_FFS_SESSION_VM_RECORD) ) + { + index_l1 = p_session->session_info.index_l1; + index_ffs = p_session->session_info.index_ffs; + + if (index_ffs != index_l1) + /* There's two buffers to save: one full (index_ffs) and one not full (index_l1) */ + { + AUDIO_SEND_TRACE("AUDIO FFS MANAGER: end of VM record session with index_l1<>index_ffs", RV_TRACE_LEVEL_DEBUG_LOW); + + #ifndef _WINDOWS + /* save the full buffer */ + if ((ffs_write (p_session->session_req.audio_ffs_fd, + p_session->session_info.buffer[index_ffs].p_start_pointer, + p_session->session_req.size)) < EFFS_OK) + { + audio_ffs_error_trace(AUDIO_ENTITY_FILE_NO_SAVED); + } + + /* save a part of the buffer pointed by the L1 */ + voice_memo_size = 2; + p_scan = (UINT16 *)(p_session->session_info.buffer[index_l1].p_start_pointer); + while ( (*p_scan++) != SC_VM_END_MASK ) + { + voice_memo_size += 2; + } + + if ((ffs_write (p_session->session_req.audio_ffs_fd, + p_session->session_info.buffer[index_l1].p_start_pointer, + voice_memo_size)) < EFFS_OK) + { + audio_ffs_error_trace(AUDIO_ENTITY_FILE_NO_SAVED); + } + #endif + } + else + /* 1 buffer (not full) needs to be saved */ + { + AUDIO_SEND_TRACE("AUDIO FFS MANAGER: end of VM record session with index_l1==index_ffs", RV_TRACE_LEVEL_DEBUG_LOW); + #ifndef _WINDOWS + voice_memo_size = 2; + p_scan = (UINT16*)(p_session->session_info.buffer[index_l1].p_start_pointer); + while ( (*p_scan++) != SC_VM_END_MASK ) + { + voice_memo_size += 2; + } + + if ((ffs_write (p_session->session_req.audio_ffs_fd, + p_session->session_info.buffer[index_l1].p_start_pointer, + voice_memo_size)) < EFFS_OK) + { + audio_ffs_error_trace(AUDIO_ENTITY_FILE_NO_SAVED); + } + #endif + } /* index_ffs != index_l1 */ + } + #endif /* VOICE_MEMO */ + /* deallocate the buffers */ + for (j=0; j<AUDIO_MAX_FFS_BUFFER_PER_SESSION; j++) + { + status = rvf_free_buf ( (T_RVF_BUFFER *)(p_session->session_info.buffer[j].p_start_pointer) ); + if (status != RVF_GREEN) + { + AUDIO_SEND_TRACE(" wrong buffer deallocated ", + RV_TRACE_LEVEL_ERROR); + } + AUDIO_SEND_TRACE_PARAM("AUDIO FFS MANAGER: deallocate buffer", + j, RV_TRACE_LEVEL_DEBUG_LOW); + } + + /* Close the FFS file */ + #ifndef _WINDOWS + if ( ffs_close(p_session->session_req.audio_ffs_fd) != EFFS_OK ) + { + audio_ffs_error_trace(AUDIO_ENTITY_FILE_NO_CLOSE); + } + #endif + + /* Send the message to confirm that the session is stopped */ + /* allocate the message buffer */ + mb_status = rvf_get_buf (p_audio_gbl_var->mb_internal, + sizeof (T_AUDIO_FFS_STOP_CON), + (T_RVF_BUFFER **)(&p_send_message)); + + /* If insufficient resources, then report a memory error and abort. */ + if (mb_status == RVF_RED) + { + audio_ffs_error_trace(AUDIO_ENTITY_NO_MEMORY); + } + + /* fill the header of the message */ + ((T_AUDIO_FFS_STOP_CON*)(p_send_message))->os_hdr.msg_id = AUDIO_FFS_STOP_CON; + + /* fill the status parameters */ + ((T_AUDIO_FFS_STOP_CON*)(p_send_message))->session_id = + ((T_AUDIO_FFS_STOP_REQ *)p_message)->session_id; + + /* send the message to the AUDIO entity */ + rvf_send_msg (p_audio_gbl_var->addrId, + p_send_message); + break; + } + } /* switch (p_message) */ + } + + /********************************************************************************/ + /* */ + /* Function Name: audio_ffs_downloader */ + /* */ + /* Purpose: This function is called to download the melody, voice memo data */ + /* between the RAM and the FLASH. */ + /* */ + /* Input Parameters: */ + /* None. */ + /* */ + /* Output Parameters: */ + /* None. */ + /* */ + /* Note: */ + /* None. */ + /* */ + /* Revision History: */ + /* None. */ + /* */ + /********************************************************************************/ + void audio_ffs_downloader(void) + { + UINT8 i, index_ffs, index_l1, *p_buffer; + T_AUDIO_FFS_SESSION *p_session; + UINT16 buffer_size; + T_FFS_SIZE size = 0; + BOOLEAN loop_mode, active_session; + + /* Scan all session in order to know which is valid */ + active_session = FALSE; + for (i=0; i<AUDIO_FFS_MAX_CHANNEL; i++) + { + p_session = &(p_audio_gbl_var->audio_ffs_session[i]); + if (p_session->session_req.valid_channel) + { + /* a session is valid */ + active_session = TRUE; + + index_l1 = p_session->session_info.index_l1; + index_ffs = p_session->session_info.index_ffs; + + if (index_l1 != index_ffs) + /* It's time to download a new buffer for the L1 */ + { + AUDIO_SEND_TRACE_PARAM("AUDIO FFS DOWNLOADER: index_l1", + index_l1, RV_TRACE_LEVEL_DEBUG_LOW); + AUDIO_SEND_TRACE_PARAM("AUDIO FFS DOWNLOADER: index_ffs", + index_ffs, RV_TRACE_LEVEL_DEBUG_LOW); + + switch (p_session->session_req.session_mode) + { + case AUDIO_FFS_FLASH_2_RAM_SESSION: + { + AUDIO_SEND_TRACE("AUDIO FFS DOWNLOADER: FLASH to RAM", RV_TRACE_LEVEL_DEBUG_LOW); + + /* Fill the buffer 0 while it isn't full in case of the loop back mode activated */ + loop_mode = TRUE; + buffer_size = p_session->session_info.buffer[index_ffs].size; + p_buffer = (UINT8 *)p_session->session_info.buffer[index_ffs].p_start_pointer; + while ( (p_buffer < p_session->session_info.buffer[index_ffs].p_stop_pointer) && + (loop_mode) ) + { + loop_mode = p_session->session_req.loop_mode; + + #ifndef _WINDOWS + size = ffs_read(p_session->session_req.audio_ffs_fd, + p_buffer, + buffer_size); + #endif + + AUDIO_SEND_TRACE_PARAM("AUDIO FFS MANAGER: ffs_read size", + size, RV_TRACE_LEVEL_DEBUG_LOW); + + buffer_size -= size; + p_buffer += size; + + if (buffer_size != 0) + { + #ifndef _WINDOWS + /* reset the FFS pointer */ + ffs_seek(p_session->session_req.audio_ffs_fd, + 0, + FFS_SEEK_SET); + #endif + } + } /* while */ + break; + } + + case AUDIO_FFS_RAM_2_FLASH_SESSION: + { + AUDIO_SEND_TRACE("AUDIO FFS DOWNLOADER: RAM to FLASH", RV_TRACE_LEVEL_DEBUG_LOW); + + /* save the full buffer */ + #ifndef _WINDOWS + if ((ffs_write (p_session->session_req.audio_ffs_fd, + p_session->session_info.buffer[index_ffs].p_start_pointer, + p_session->session_req.size)) < EFFS_OK) + { + audio_ffs_error_trace(AUDIO_ENTITY_FILE_NO_SAVED); + } + #endif + break; + } + } /* switch (p_session->session_req.session_mode) */ + + /* update the ffs buffer index */ + p_session->session_info.index_ffs++; + if (p_session->session_info.index_ffs == AUDIO_MAX_FFS_BUFFER_PER_SESSION) + { + p_session->session_info.index_ffs = 0; + } + } /* (p_session->session_info.index_l1 != p_session->session_info.index_l1) */ + } /* valid session */ + } /* for (i=0; i<AUDIO_FFS_MAX_CHANNEL; i++) */ + + /* Activate or not the Timer the next time */ + if (active_session) + { + rvf_start_timer(AUDIO_FFS_TIMER, AUDIO_FFS_TIME_OUT, AUDIO_FFS_ONE_SHOT_TIMER); + } + else + { + AUDIO_SEND_TRACE("AUDIO FFS DOWNLOADER: stop", RV_TRACE_LEVEL_DEBUG_LOW); + /* Stop asap the FFS downloader */ + rvf_stop_timer(AUDIO_FFS_TIMER); + } + } + #endif /* MELODY_E1 || MELODY_E2 || VOICE_MEMO */ + +#if (L1_VOICE_MEMO_AMR) + T_AUDIO_RET audio_convert_to_mms(UINT8 *p_buffer, UINT16 *buffer_size, UINT8 *previous_type, UINT8 *size_left) + { + UINT8 rxtx_type, frame_header, data_size; + UINT8 frame_type, quality; + UINT8 *ptr_final, *ptr_mms; + + ptr_mms = p_buffer; + ptr_final = ptr_mms + *buffer_size; + + /* sample is shared among the 2 buffers */ + if (*size_left > 0) + { + UINT8 i; + + switch (*previous_type) + { + case AUDIO_VM_AMR_RXTX_SID_FIRST: + /* set data bits to 0 */ + for (i = 0; i < *size_left; i++) + *(ptr_mms + i) = 0; + /* set Mode Indication */ + *(ptr_mms + *size_left - 1) = AUDIO_MMS_MODE_INDICATION; + break; + case AUDIO_VM_AMR_RXTX_SID_UPDATE: + //case AUDIO_VM_AMR_RXTX_SID_BAD: + *(ptr_mms + *size_left - 1) |= AUDIO_MMS_STI_BIT | AUDIO_MMS_MODE_INDICATION; + break; + } + ptr_mms += *size_left; + } + *size_left = 0; + + while (ptr_mms < ptr_final) + { + /* read header */ + frame_header = *ptr_mms; + + /* if end_mask, stop */ + if (frame_header == SC_VM_AMR_END_MASK) + { + *buffer_size = (ptr_mms - p_buffer); + return AUDIO_OK; + } + + /* reset header */ + *ptr_mms = 0; + + rxtx_type = (frame_header & SC_RX_TX_TYPE_MASK); + *previous_type = rxtx_type; + switch (rxtx_type) + { + case AUDIO_VM_AMR_RXTX_SPEECH_GOOD: + //case AUDIO_VM_AMR_RXTX_SPEECH_BAD: + { + /* FT + data_size */ + frame_type = frame_header & SC_CHAN_TYPE_MASK; + switch (frame_type) + { + case AUDIO_VM_AMR_SPEECH_475: + data_size = AUDIO_VM_AMR_SPEECH_475_DATA_SIZE; + break; + case AUDIO_VM_AMR_SPEECH_515: + data_size = AUDIO_VM_AMR_SPEECH_515_DATA_SIZE; + break; + case AUDIO_VM_AMR_SPEECH_59: + data_size = AUDIO_VM_AMR_SPEECH_590_DATA_SIZE; + break; + case AUDIO_VM_AMR_SPEECH_67: + data_size = AUDIO_VM_AMR_SPEECH_670_DATA_SIZE; + break; + case AUDIO_VM_AMR_SPEECH_74: + data_size = AUDIO_VM_AMR_SPEECH_740_DATA_SIZE; + break; + case AUDIO_VM_AMR_SPEECH_795: + data_size = AUDIO_VM_AMR_SPEECH_795_DATA_SIZE; + break; + case AUDIO_VM_AMR_SPEECH_102: + data_size = AUDIO_VM_AMR_SPEECH_102_DATA_SIZE; + break; + case AUDIO_VM_AMR_SPEECH_122: + data_size = AUDIO_VM_AMR_SPEECH_122_DATA_SIZE; + break; + } + /* Q */ + //if (rxtx_type == AUDIO_VM_AMR_RXTX_SPEECH_GOOD) + quality = AUDIO_MMS_GOOD_QUALITY; + //else + // quality = AUDIO_MMS_BAD_QUALITY; + } + break; + case AUDIO_VM_AMR_RXTX_SID_FIRST: + case AUDIO_VM_AMR_RXTX_SID_UPDATE: + //case AUDIO_VM_AMR_RXTX_SID_BAD: + { + /* FT, data_size, Q */ + frame_type = AUDIO_MMS_SID_FRAME_TYPE; + data_size = AUDIO_VM_AMR_SID_DATA_SIZE; + //if ((rxtx_type == AUDIO_VM_AMR_RXTX_SID_FIRST)|| + // (rxtx_type == AUDIO_VM_AMR_RXTX_SID_UPDATE)) + //{ + quality = AUDIO_MMS_GOOD_QUALITY; + //} + //else + // quality = AUDIO_MMS_BAD_QUALITY; + + /* data, STI, Mode indication */ + if (rxtx_type == AUDIO_VM_AMR_RXTX_SID_FIRST) + { + UINT8 data, i; + + /* number of bytes to set to 0 */ + data = ((ptr_final - ptr_mms) >= (data_size + 1)) ? (data_size) : (ptr_final - ptr_mms - 1); + + /* set data bits to 0 */ + for (i = 0; i < data; i++) + *(ptr_mms + 1 + i) = 0; + + /* set Mode indication */ + if ((ptr_final - ptr_mms) >= (data_size + 1)) + *(ptr_mms + data_size) = AUDIO_MMS_MODE_INDICATION; + + } + /* SID_UPDATE */ + else + { + /* set STI bit to 1 + Mode indication */ + if ((ptr_final - ptr_mms) >= (data_size + 1)) + *(ptr_mms + data_size) |= AUDIO_MMS_STI_BIT | AUDIO_MMS_MODE_INDICATION; + } + } + break; + case AUDIO_VM_AMR_RXTX_NO_DATA: + frame_type = AUDIO_MMS_NO_DATA_FRAME_TYPE; + data_size = AUDIO_VM_AMR_NO_DATA_DATA_SIZE; + quality = AUDIO_MMS_GOOD_QUALITY; + break; + default: + { + AUDIO_SEND_TRACE_PARAM("AUDIO MEMORY MANAGER: convert to MMS, header not recognized", frame_header, RV_TRACE_LEVEL_DEBUG_LOW); + return AUDIO_ERROR; + } + } + /* write header */ + *(ptr_mms)++ |= (frame_type << AUDIO_MMS_FRAME_TYPE_SHIFT) | (quality << AUDIO_MMS_QUALITY_SHIFT); + + /* write data, check we are not at the end of the buffer */ + if ((ptr_final - ptr_mms) < data_size) + { + *size_left = data_size - (ptr_final - ptr_mms); + data_size = ptr_final - ptr_mms; + } + ptr_mms += data_size; + } + *buffer_size = (ptr_final - p_buffer); + return AUDIO_OK; + } + + T_AUDIO_RET audio_convert_from_mms(UINT8 *p_buffer, UINT16 buffer_size, UINT8 *previous_type, UINT8 *size_left) + { + UINT8 frame_header, data_size; + UINT8 frame_type, quality; + UINT8 *ptr_final, *ptr_mms; + + ptr_mms = p_buffer; + ptr_final = ptr_mms + buffer_size; + + /* a sample is split between 2 RAM buffers */ + if (*size_left > 0) + { + /* if SID sample, remove STI and mode indication */ + if (*previous_type == AUDIO_MMS_SID_FRAME_TYPE) + { + *(ptr_mms + *size_left - 1) &= (~(AUDIO_MMS_STI_BIT | AUDIO_MMS_MODE_INDICATION)); + } + ptr_mms += *size_left; + *size_left = 0; + } + + while (ptr_mms < ptr_final) + { + /* read header */ + frame_header = *ptr_mms; + + /* reset header */ + *ptr_mms = 0; + + /* FT and Q */ + frame_type = (frame_header & AUDIO_MMS_FRAME_TYPE_MASK) >> AUDIO_MMS_FRAME_TYPE_SHIFT; + quality = (frame_header & AUDIO_MMS_QUALITY_MASK) >> AUDIO_MMS_QUALITY_SHIFT; + *previous_type = frame_type; + + /* Identify sample */ + if (frame_type < AUDIO_MMS_SID_FRAME_TYPE) + { + /* speech good or bad */ + *ptr_mms |= frame_type; + if (quality == AUDIO_MMS_GOOD_QUALITY) + *ptr_mms |= AUDIO_VM_AMR_RXTX_SPEECH_GOOD; + else + *ptr_mms |= AUDIO_VM_AMR_RXTX_SPEECH_BAD; + + switch (frame_type) + { + case AUDIO_VM_AMR_SPEECH_475: + data_size = AUDIO_VM_AMR_SPEECH_475_DATA_SIZE; + break; + case AUDIO_VM_AMR_SPEECH_515: + data_size = AUDIO_VM_AMR_SPEECH_515_DATA_SIZE; + break; + case AUDIO_VM_AMR_SPEECH_59: + data_size = AUDIO_VM_AMR_SPEECH_590_DATA_SIZE; + break; + case AUDIO_VM_AMR_SPEECH_67: + data_size = AUDIO_VM_AMR_SPEECH_670_DATA_SIZE; + break; + case AUDIO_VM_AMR_SPEECH_74: + data_size = AUDIO_VM_AMR_SPEECH_740_DATA_SIZE; + break; + case AUDIO_VM_AMR_SPEECH_795: + data_size = AUDIO_VM_AMR_SPEECH_795_DATA_SIZE; + break; + case AUDIO_VM_AMR_SPEECH_102: + data_size = AUDIO_VM_AMR_SPEECH_102_DATA_SIZE; + break; + case AUDIO_VM_AMR_SPEECH_122: + data_size = AUDIO_VM_AMR_SPEECH_122_DATA_SIZE; + break; + } + } + else if (frame_type == AUDIO_MMS_SID_FRAME_TYPE) + { + data_size = AUDIO_VM_AMR_SID_DATA_SIZE; + /* SID_BAD */ + if (quality == AUDIO_MMS_BAD_QUALITY) + *ptr_mms |= AUDIO_VM_AMR_RXTX_SID_BAD; + /* SID_FIRST or SID_UPDATE */ + else + { + if (*previous_type == AUDIO_MMS_NO_DATA_FRAME_TYPE) + *ptr_mms |= AUDIO_VM_AMR_RXTX_SID_UPDATE; + else + *ptr_mms |= AUDIO_VM_AMR_RXTX_SID_FIRST; + /* try to remove STI + mode indication if sample not split between 2 buffers */ + if ((ptr_final - ptr_mms) >= (data_size + 1)) + *(ptr_mms + data_size) &= (~(AUDIO_MMS_STI_BIT | AUDIO_MMS_MODE_INDICATION)); + } + } + else if (frame_type == AUDIO_MMS_NO_DATA_FRAME_TYPE) + { + data_size = AUDIO_VM_AMR_NO_DATA_DATA_SIZE; + *ptr_mms |= AUDIO_VM_AMR_RXTX_NO_DATA; + } + else + { + AUDIO_SEND_TRACE_PARAM("AUDIO MEMORY MANAGER: convert from MMS, header not recognized", frame_header, RV_TRACE_LEVEL_DEBUG_LOW); + return AUDIO_ERROR; + } + + /* pass header */ + ptr_mms++; + + /* write data, check we are not at the end of the buffer */ + if ((ptr_final - ptr_mms) < data_size) + { + *size_left = data_size - (ptr_final - ptr_mms); + data_size = ptr_final - ptr_mms; + } + ptr_mms += data_size; + } + return AUDIO_OK; + } +#endif + +#if (AUDIO_RAM_MANAGER) + /* try to copy "size" bytes from audio_ram_fd to dest_buffer, returns bytes copied (0 to size) */ + INT16 ram_read(T_AUDIO_MEM_SESSION *p_session, UINT8 *dest_buffer, UINT16 size) + { + UINT16 i; + + /* check how many bytes there are in audio_ram_fd */ + if (size > p_session->session_req.audio_ram_size) + size = p_session->session_req.audio_ram_size; + /* copy byte by byte */ + for (i = 0; i < size; i++) + *dest_buffer++ = *(p_session->session_req.audio_ram_fd)++; + /* update audio_ram_fd size */ + p_session->session_req.audio_ram_size -= size; + return size; + } + + /* copy "size" bytes from src_buffer to audio_ram_fd, does not check size */ + INT16 ram_write(T_AUDIO_MEM_SESSION *p_session, UINT8 *src_buffer, UINT16 size) + { + UINT16 i; + + /* copy byte by byte */ + for (i = 0; i < size; i++) + *(p_session->session_req.audio_ram_fd)++ = *src_buffer++; + return size; + } +#endif + +#if (AUDIO_MEM_MANAGER) + void audio_mem_send_status(T_AUDIO_RET status, UINT8 channel_id, UINT8 status_type, + T_RV_RETURN return_path) + { + /* status_type START or STOP, status AUDIO_OK or AUDIO_ERROR */ + T_AUDIO_MEM_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_MEM_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_mem_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_MEM_STATUS_MSG; + + /* fill the status parameters */ + p_send_message->status = status; + p_send_message->channel_id = channel_id; + p_send_message->status_type = status_type; + + /* 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_mem_send_record_status(UINT8 channel_id, UINT32 recorded_size, T_RV_RETURN return_path) + { + /* status_type START or STOP, status AUDIO_OK or AUDIO_ERROR */ + T_AUDIO_MEM_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_MEM_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_mem_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_MEM_STATUS_MSG; + + /* fill the status parameters */ + p_send_message->status = AUDIO_OK; + p_send_message->channel_id = channel_id; + p_send_message->status_type = AUDIO_STOP_STATUS; + p_send_message->recorded_size = recorded_size; + + /* 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_mem_manager (T_RV_HDR *p_message) + { + UINT8 channel_id, session_id, state; + UINT8 mem_channel_id; + T_RV_RETURN return_path; + T_AUDIO_MEM_SESSION *p_session; + + /* get channel_id from messages */ + switch (p_message->msg_id) + { + case AUDIO_MEM_START_REQ: + channel_id = ((T_AUDIO_MEM_START *)p_message)->channel_id; + session_id = ((T_AUDIO_MEM_START *)p_message)->session_id; + break; + case AUDIO_MEM_STOP_REQ: + channel_id = ((T_AUDIO_MEM_STOP *)p_message)->channel_id; + break; + case AUDIO_DRIVER_NOTIFICATION_MSG: + channel_id = ((T_AUDIO_DRIVER_NOTIFICATION *)p_message)->channel_id; + break; + case AUDIO_DRIVER_LAST_NOTIFICATION_MSG: + channel_id = ((T_AUDIO_DRIVER_NOTIFICATION *)p_message)->channel_id; + break; + case AUDIO_DRIVER_STATUS_MSG: + channel_id = ((T_AUDIO_DRIVER_STATUS *)p_message)->channel_id; + break; + } + + /* Init mem_channel_id to browse all mem channels and find channel_id */ + /* state will stay IDLE if no mem channel is found */ + mem_channel_id = 0; + state = AUDIO_MEM_IDLE; + + /* look for an ACTIVE session, which channel_id matches the one from the message */ + while ( (mem_channel_id < AUDIO_MEM_MAX_CHANNEL)&& + ((p_audio_gbl_var->audio_mem_session[mem_channel_id].session_info.state == AUDIO_MEM_IDLE)|| + (p_audio_gbl_var->audio_mem_session[mem_channel_id].session_req.channel_id != channel_id)) ) + { + mem_channel_id++; + } + + /* if mem_channel_id < MAX_CHANNEL, we found an active channel so we can derive state */ + if (mem_channel_id < AUDIO_MEM_MAX_CHANNEL) + { + p_session = &(p_audio_gbl_var->audio_mem_session[mem_channel_id]); + state = p_session->session_info.state; + } + + switch (state) + { + case AUDIO_MEM_IDLE: + { + /* requester return_path (currently is Riviera Audio) */ + return_path.callback_func = NULL; + return_path.addr_id = p_audio_gbl_var->addrId; + + switch (p_message->msg_id) + { + case AUDIO_MEM_START_REQ: + { + /* find free MEM channel i.e. state = AUDIO_MEM_IDLE */ + mem_channel_id = 0; + while ( (p_audio_gbl_var->audio_mem_session[mem_channel_id].session_info.state != AUDIO_MEM_IDLE) && + (mem_channel_id < AUDIO_MEM_MAX_CHANNEL) ) + mem_channel_id++; + + if (mem_channel_id == AUDIO_MEM_MAX_CHANNEL) + { + AUDIO_SEND_TRACE("AUDIO MEMORY MANAGER: no memory channel available", RV_TRACE_LEVEL_DEBUG_LOW); + audio_mem_send_status(AUDIO_ERROR, channel_id, AUDIO_START_STATUS, return_path); + return; + } + + /* get MEM session */ + p_session = &(p_audio_gbl_var->audio_mem_session[mem_channel_id]); + + /* fill parameters */ + p_session->session_req.channel_id = channel_id; + p_session->session_req.session_id = session_id; + #if (AUDIO_NEW_FFS_MANAGER) + p_session->session_req.audio_ffs_fd = + ((T_AUDIO_MEM_START *)p_message)->audio_ffs_fd; + #endif + #if (AUDIO_RAM_MANAGER) + p_session->session_req.audio_ram_fd = + ((T_AUDIO_MEM_START *)p_message)->audio_ram_fd; + p_session->session_req.audio_ram_size = + ((T_AUDIO_MEM_START *)p_message)->audio_ram_size; + #endif + p_session->session_req.size = + ((T_AUDIO_MEM_START *)p_message)->size;// temporary RAM buffer size + + /* parameters for notification handling */ + p_session->session_info.size_left = 0; + p_session->session_info.previous_type = AUDIO_VM_AMR_RXTX_SPEECH_GOOD; + p_session->session_info.stop_req_allowed = TRUE; + + /* initialization phase for play sessions */ + switch (session_id) + { + case AUDIO_VM_AMR_PLAY_SESSION_ID: + { + UINT8 *play_buffer;// temporary RAM buffer to fill + INT16 size_read; + + /* fill all buffers in advance */ + while (audio_driver_get_play_buffer(channel_id, &play_buffer) == AUDIO_OK) + { + #if (AUDIO_NEW_FFS_MANAGER) + /* write from FLASH to RAM buffer */ + if (p_session->session_req.audio_ffs_fd != NULL) + { + /* copy from Flash "size" bytes into play_buffer */ + size_read = ffs_read(p_session->session_req.audio_ffs_fd, + play_buffer, + p_session->session_req.size); + + /* wrong read */ + if (size_read < EFFS_OK) + { + if ( ffs_close(p_session->session_req.audio_ffs_fd) != EFFS_OK ) + audio_mem_error_trace(AUDIO_ENTITY_FILE_NO_CLOSE); + AUDIO_SEND_TRACE("AUDIO MEMORY MANAGER INIT: FFS PLAY READ failed", RV_TRACE_LEVEL_DEBUG_LOW); + audio_mem_send_status(AUDIO_ERROR, channel_id, AUDIO_START_STATUS, return_path); + return; + } + } + #endif + #if (AUDIO_RAM_MANAGER) + /* write from RAM to RAM buffer */ + if (p_session->session_req.audio_ram_fd != NULL) + { + /* copy from RAM "size" bytes into play_buffer */ + size_read = ram_read(p_session, play_buffer, p_session->session_req.size); + } + #endif + + /* convert to MMS */ + if (audio_convert_from_mms(play_buffer, size_read, + &(p_session->session_info.previous_type), + &(p_session->session_info.size_left)) != AUDIO_OK) + { + AUDIO_SEND_TRACE("AUDIO MEMORY MANAGER INIT: wrong MMS format", RV_TRACE_LEVEL_DEBUG_LOW); + size_read = 0;// will fill buffer with END_MASK and stop task + } + + /* last buffer already, put END_MASK */ + if ( ((UINT16)size_read) < p_session->session_req.size ) + { + UINT16 i; + + if (p_session->session_info.size_left != 0) + AUDIO_SEND_TRACE_PARAM("AUDIO MEMORY DOWNLOADER: MMS PLAY file incomplete", + p_session->session_info.size_left, RV_TRACE_LEVEL_DEBUG_LOW); + for (i = size_read; i < p_session->session_req.size; i++) + *(play_buffer + i) = SC_VM_AMR_END_MASK; + } + + AUDIO_SEND_TRACE_PARAM("AUDIO MEMORY DOWNLOADER: size read", size_read, RV_TRACE_LEVEL_DEBUG_LOW); + + audio_driver_play_buffer(channel_id, play_buffer); + } + + }// case AUDIO_VM_AMR_PLAY_SESSION_ID + break; + }// switch (session_id) + + audio_driver_start_session(channel_id, return_path); + + p_session->session_info.state = AUDIO_MEM_WAIT_NOTIFICATION_OR_STOP; + } + break; //case AUDIO_MEM_START_REQ: + case AUDIO_MEM_STOP_REQ: + audio_mem_error_trace(AUDIO_ERROR_STOP_EVENT); + break; + } + } // case AUDIO_MEM_IDLE: + break; + case AUDIO_MEM_WAIT_NOTIFICATION_OR_STOP: + { + /* requester return_path (currently is Riviera Audio) */ + return_path.callback_func = NULL; + return_path.addr_id = p_audio_gbl_var->addrId; + + switch (p_message->msg_id) + { + case AUDIO_DRIVER_NOTIFICATION_MSG: + { + switch (p_session->session_req.session_id) + { + case AUDIO_VM_AMR_RECORD_SESSION_ID: + { + UINT16 record_buffer_size; + + /* default is session_req.size but can be less if we find END_MASK */ + record_buffer_size = p_session->session_req.size; + + /* convert to MMS, update record_buffer_size if END_MASK is found */ + audio_convert_to_mms((UINT8 *)((T_AUDIO_DRIVER_NOTIFICATION *)p_message)->p_buffer, + &record_buffer_size, + &(p_session->session_info.previous_type), + &(p_session->session_info.size_left)); + + #if (AUDIO_NEW_FFS_MANAGER) + if (p_session->session_req.audio_ffs_fd != NULL) + { + if ((ffs_write (p_session->session_req.audio_ffs_fd, + (UINT8 *)((T_AUDIO_DRIVER_NOTIFICATION *)p_message)->p_buffer, + record_buffer_size)) < EFFS_OK) + { + AUDIO_SEND_TRACE("AUDIO MEMORY MANAGER: FFS RECORD WRITE FAILED", RV_TRACE_LEVEL_DEBUG_LOW); + } + } + #endif + #if (AUDIO_RAM_MANAGER) + if (p_session->session_req.audio_ram_fd != NULL) + { + ram_write (p_session, + (UINT8 *)((T_AUDIO_DRIVER_NOTIFICATION *)p_message)->p_buffer, + record_buffer_size); + } + #endif + + AUDIO_SEND_TRACE_PARAM("AUDIO MEMORY MANAGER: RAM to MEMORY", record_buffer_size, RV_TRACE_LEVEL_DEBUG_LOW);//DEBUG + } + break; + case AUDIO_VM_AMR_PLAY_SESSION_ID: + { + UINT8 *play_buffer; + INT16 size_read; + + /* try to get a buffer */ + if (audio_driver_get_play_buffer(channel_id, &play_buffer) == AUDIO_OK) + { + #if (AUDIO_NEW_FFS_MANAGER) + if (p_session->session_req.audio_ffs_fd != NULL) + { + size_read = ffs_read(p_session->session_req.audio_ffs_fd, + play_buffer, + p_session->session_req.size); + /* wrong read */ + if (size_read < EFFS_OK) + { + AUDIO_SEND_TRACE("AUDIO MEMORY MANAGER: FFS PLAY READ FAILED", RV_TRACE_LEVEL_DEBUG_LOW); + size_read = 0;// will put END_MASK in whole buffer so stops play + } + } + #endif + #if (AUDIO_RAM_MANAGER) + if (p_session->session_req.audio_ram_fd != NULL) + { + size_read = ram_read(p_session, play_buffer, p_session->session_req.size); + } + #endif + + if (audio_convert_from_mms(play_buffer, size_read, + &(p_session->session_info.previous_type), + &(p_session->session_info.size_left)) != AUDIO_OK) + { + AUDIO_SEND_TRACE("AUDIO MEMORY DOWNLOADER: wrong MMS format", RV_TRACE_LEVEL_DEBUG_LOW); + size_read = 0;// will fill buffer with END_MASK + } + + /* last buffer, put END_MASK */ + if ( ((UINT16)size_read) < p_session->session_req.size ) + { + UINT16 i; + + if (p_session->session_info.size_left != 0) + AUDIO_SEND_TRACE_PARAM("AUDIO MEMORY MANAGER: MMS PLAY file incomplete", + p_session->session_info.size_left, RV_TRACE_LEVEL_DEBUG_LOW); + for (i = size_read; i < p_session->session_req.size; i++) + *(play_buffer + i) = SC_VM_AMR_END_MASK; + } + + audio_driver_play_buffer(channel_id, play_buffer); + + if (size_read > 0) + { + AUDIO_SEND_TRACE_PARAM("AUDIO MEMORY MANAGER: MEMORY to RAM", size_read, RV_TRACE_LEVEL_DEBUG_LOW);//DEBUG + } + else + { + AUDIO_SEND_TRACE("AUDIO MEMORY MANAGER: buffer not used", RV_TRACE_LEVEL_DEBUG_LOW);//DEBUG + } + } // if (audio_driver_get_play_buffer(channel_id, &p_buffer) == AUDIO_OK) + else + AUDIO_SEND_TRACE("AUDIO MEMORY MANAGER: no buffer available", RV_TRACE_LEVEL_DEBUG_LOW);//DEBUG + } + break; + } + } + break; + case AUDIO_DRIVER_LAST_NOTIFICATION_MSG: + { + UINT16 record_buffer_size; + + record_buffer_size = p_session->session_req.size; + + audio_convert_to_mms((UINT8 *)((T_AUDIO_DRIVER_NOTIFICATION *)p_message)->p_buffer, + &record_buffer_size, + &(p_session->session_info.previous_type), + &(p_session->session_info.size_left)); + + #if (AUDIO_NEW_FFS_MANAGER) + if (p_session->session_req.audio_ffs_fd != NULL) + { + if ((ffs_write (p_session->session_req.audio_ffs_fd, + (UINT8 *)((T_AUDIO_DRIVER_NOTIFICATION *)p_message)->p_buffer, + record_buffer_size)) < EFFS_OK) + { + AUDIO_SEND_TRACE("AUDIO MEMORY MANAGER: FFS RECORD WRITE FAILED", RV_TRACE_LEVEL_DEBUG_LOW); + } + } + #endif + #if (AUDIO_RAM_MANAGER) + if (p_session->session_req.audio_ram_fd != NULL) + { + if ((ram_write (p_session, + (UINT8 *)((T_AUDIO_DRIVER_NOTIFICATION *)p_message)->p_buffer, + record_buffer_size)) < 0) + { + AUDIO_SEND_TRACE("AUDIO MEMORY MANAGER: RAM RECORD WRITE FAILED", RV_TRACE_LEVEL_DEBUG_LOW); + } + } + #endif + + /* recorded_size */ + AUDIO_SEND_TRACE_PARAM("AUDIO MEMORY MANAGER: last RAM to MEMORY", record_buffer_size, RV_TRACE_LEVEL_DEBUG_LOW); + AUDIO_SEND_TRACE_PARAM("AUDIO MEMORY MANAGER: size recorded", + ((T_AUDIO_DRIVER_LAST_NOTIFICATION *)p_message)->recorded_size, RV_TRACE_LEVEL_DEBUG_LOW); + p_session->session_info.recorded_size = ((T_AUDIO_DRIVER_LAST_NOTIFICATION *)p_message)->recorded_size; + + /* stop must no longer be accepted as it is an automatic stop */ + p_session->session_info.stop_req_allowed = FALSE; + + /* MEM return_path */ + return_path.callback_func = NULL; + return_path.addr_id = p_audio_gbl_var->addrId; + + audio_driver_free_session(channel_id, return_path); + } + break; + case AUDIO_DRIVER_STATUS_MSG: + { + /* STOP OK for play */ + /* FREE OK for record */ + if ( ( (((T_AUDIO_DRIVER_STATUS *)p_message)->status_type == AUDIO_STOP_STATUS) && + (((T_AUDIO_DRIVER_STATUS *)p_message)->status == AUDIO_OK)) || + ( (((T_AUDIO_DRIVER_STATUS *)p_message)->status_type == AUDIO_FREE_STATUS) && + (((T_AUDIO_DRIVER_STATUS *)p_message)->status == AUDIO_OK)) ) + { + #if (AUDIO_NEW_FFS_MANAGER) + if (p_session->session_req.audio_ffs_fd != NULL) + { + if ( ffs_close(p_session->session_req.audio_ffs_fd) != EFFS_OK ) + { + audio_ffs_error_trace(AUDIO_ENTITY_FILE_NO_CLOSE); + } + AUDIO_SEND_TRACE_PARAM("AUDIO MEMORY MANAGER: close FFS file for mem channel:", mem_channel_id, RV_TRACE_LEVEL_DEBUG_LOW); + } + #endif + + if (((T_AUDIO_DRIVER_STATUS *)p_message)->status_type == AUDIO_FREE_STATUS) + audio_mem_send_record_status(channel_id, p_session->session_info.recorded_size, return_path); + else + audio_mem_send_status(AUDIO_OK, channel_id, AUDIO_STOP_STATUS, return_path); + + p_session->session_info.state = AUDIO_MEM_IDLE; + } + } //case AUDIO_DRIVER_STATUS_MSG: + break; + case AUDIO_MEM_STOP_REQ: + { + /* check stop req is allowed i.e. no previous stop req, nor automatic stop */ + if (p_session->session_info.stop_req_allowed == TRUE) + { + p_session->session_info.stop_req_allowed = FALSE; + + audio_driver_stop_session(channel_id); + } + else + { + audio_mem_error_trace(AUDIO_ERROR_STOP_EVENT); + //audio_mem_send_status(AUDIO_ERROR, channel_id, AUDIO_STOP_STATUS, return_path); + } + } + break; + case AUDIO_MEM_START_REQ: + audio_mem_error_trace(AUDIO_ERROR_START_EVENT); + //audio_mem_send_status(AUDIO_ERROR, channel_id, AUDIO_START_STATUS, return_path); + break; + }//switch (p_message->msg_id) + } //case AUDIO_MEM_WAIT_NOTIFICATION_OR_STOP: + break; + } // switch(state) + } + + UINT8 audio_mem_message_switch(T_RV_HDR *p_message) + { + UINT8 channel_id; + UINT8 mem_channel_id = 0; + + /* MEM START and STOP */ + if ((p_message->msg_id == AUDIO_MEM_START_REQ)|| + (p_message->msg_id == AUDIO_MEM_STOP_REQ)) + return 1; + + /* For other messages, we must check channel_id is really handled by MEM + and not by other managers such as streaming or UART */ + if (p_message->msg_id == AUDIO_DRIVER_STATUS_MSG) + channel_id = ((T_AUDIO_DRIVER_STATUS *)p_message)->channel_id; + + if (p_message->msg_id == AUDIO_DRIVER_NOTIFICATION_MSG) + channel_id = ((T_AUDIO_DRIVER_NOTIFICATION *)p_message)->channel_id; + + if (p_message->msg_id == AUDIO_DRIVER_LAST_NOTIFICATION_MSG) + channel_id = ((T_AUDIO_DRIVER_NOTIFICATION *)p_message)->channel_id; + + /* find active MEM session handling channel_id */ + while ( (mem_channel_id < AUDIO_MEM_MAX_CHANNEL) && + ((p_audio_gbl_var->audio_mem_session[mem_channel_id].session_info.state == AUDIO_MEM_IDLE)|| + (p_audio_gbl_var->audio_mem_session[mem_channel_id].session_req.channel_id != channel_id))) + { + mem_channel_id++; + } + + if (mem_channel_id == AUDIO_MEM_MAX_CHANNEL) + return 0; + else + return 1; + } +#endif // AUDIO_MEM_MANAGER + +#endif /* RVM_AUDIO_MAIN_SWE */ +