Пример #1
0
/****************************************************************************
NAME 
  	configManagerUserDefinedTones

DESCRIPTION
  	Attempt to read the user configured tones, if data exists it will be in the following format:
    
    uint16 offset in array to user tone 1,
    uint16 offset in array to user tone ....,
    uint16 offset in array to user tone 8,
    uint16[] user tone data
    
    To play a particular tone it can be access via gVariableTones, e.g. to access tone 1
    
    theSink.audioData.gConfigTones->gVariableTones[0] + (uint16)*theSink.audioData.gConfigTones->gVariableTones[0]
    
    or to access tone 2

    theSink.audioData.gConfigTones->gVariableTones[0] + (uint16)*theSink.audioData.gConfigTones->gVariableTones[1]
    
    and so on
 
RETURNS
  	void
*/
static void configManagerUserDefinedTones( uint16 KeyLength ) 
{
    /* if the keyLength is zero there are no user tones so don't malloc any memory */
    if(KeyLength)
    {
        /* malloc only enough memory to hold the configured tone data */
        uint16 * configTone = mallocPanic(KeyLength * sizeof(uint16));
    
        /* retrieve pskey data up to predetermined max size */
        uint16 size_ps_key = ConfigRetrieve( theSink.config_id, PSKEY_CONFIG_TONES , configTone , KeyLength );
      
        CONF_DEBUG(("Co : Configurable Tones Malloc size [%x]\n", KeyLength )) ;
        
        /* is there any configurable tone data, if present update pointer to tone data */
        if (size_ps_key)
        {
            /* the data is in the form of 8 x uint16 audio note start offsets followed by the 
               up to 8 lots of tone data */
            theSink.conf1->gConfigTones.gVariableTones = (ringtone_note*)&configTone[0];
        
        }
        /* no user configured tone data is available, so free previous malloc as not in use */
        else
        {
            /* no need to waste memory */
        	freePanic(configTone);      
        }
    }
    /* no tone data available, ensure data pointer is null */
    else
    {
            theSink.conf1->gConfigTones.gVariableTones = NULL;
    }
}
Пример #2
0
/****************************************************************************
NAME 
  	configManagerButtonPatterns

DESCRIPTION
  	Read and configure any buttonpattern matches that exist
 
RETURNS

*/
static void configManagerButtonPatterns( void ) 
{  
      		/* Allocate enough memory to hold event configuration */
    button_pattern_config_type* config = (button_pattern_config_type*) mallocPanic(BM_NUM_BUTTON_MATCH_PATTERNS * sizeof(button_pattern_config_type));
   
    CONF_DEBUG(("Co: No Button Patterns - %d\n", BM_NUM_BUTTON_MATCH_PATTERNS));
   
        /* Now read in event configuration */
    if(config)
    {     
        if(ConfigRetrieve(theSink.config_id , PSKEY_BUTTON_PATTERN_CONFIG, config, BM_NUM_BUTTON_MATCH_PATTERNS * sizeof(button_pattern_config_type)))
        {
            uint16 n;
     
           /* Now we have the event configuration, map required events to system events */
            for(n = 0; n < BM_NUM_BUTTON_MATCH_PATTERNS ; n++)
            {	 
     	      CONF_DEBUG(("Co : AddPattern Ev[%x]\n", config[n].event )) ;
                        
          			   /* Map PIO button event to system events in specified states */
          	    buttonManagerAddPatternMapping ( theSink.theButtonsTask , config[n].event , config[n].pattern, n ) ;
            }
        }
        else
 	    {
 	      CONF_DEBUG(("Co: !EvLen\n")) ;
        }
        freePanic(config) ;
    }    
}
Пример #3
0
static void configManagerButtons( void )
{  
	/* Allocate enough memory to hold event configuration */
    event_config_type* configA = (event_config_type*) mallocPanic(BM_EVENTS_PER_PS_BLOCK * sizeof(event_config_type));
    event_config_type* configB = (event_config_type*) mallocPanic(BM_EVENTS_PER_PS_BLOCK * sizeof(event_config_type));
    event_config_type* configC = (event_config_type*) mallocPanic(BM_EVENTS_PER_PS_BLOCK * sizeof(event_config_type));
       
    uint16 n;
    uint8  i = 0;
 
    ConfigRetrieve(theSink.config_id , PSKEY_EVENTS_A, configA, BM_EVENTS_PER_PS_BLOCK * sizeof(event_config_type)) ;
    ConfigRetrieve(theSink.config_id , PSKEY_EVENTS_B, configB, BM_EVENTS_PER_PS_BLOCK * sizeof(event_config_type)) ; 
    ConfigRetrieve(theSink.config_id , PSKEY_EVENTS_C, configC, BM_EVENTS_PER_PS_BLOCK * sizeof(event_config_type)) ;  
  
        /* Now we have the event configuration, map required events to system events */
    for(n = 0; n < BM_EVENTS_PER_PS_BLOCK; n++)
    { 
        CONF_DEBUG(("Co : AddMap indexes [%u,%u] Ev[%x][%x][%x]\n", n, i, configA[n].event , configB[n].event, configC[n].event )) ;
                       
           /* check to see if a valid pio mask is present, this includes the upper 2 bits of the state
              info as these are being used for bc5 as vreg enable and charger detect */
        if ( (configA[n].pio_mask)||(configA[n].state_mask & 0xC000))
            buttonManagerAddMapping ( &configA[n], i++ ); 
               
        if ( (configB[n].pio_mask)||(configB[n].state_mask & 0xC000))
            buttonManagerAddMapping ( &configB[n], i++ ); 
        
        if ( (configC[n].pio_mask)||(configC[n].state_mask & 0xC000))
            buttonManagerAddMapping ( &configC[n], i++ );         
                                                                 
   	}
    
    freePanic(configA) ;
    freePanic(configB) ; 
    freePanic(configC) ; 
    
    /* perform an initial pio check to see if any pio changes need processing following the completion
       of the configuration ps key reading */
    BMCheckButtonsAfterReadingConfig();


}
Пример #4
0
/****************************************************************************
NAME    
    SetupPowerTable

DESCRIPTION
    Attempts to obtain a low power table from the Ps Key store.  If no table 
    (or an incomplete one) is found in Ps Keys then the default is used.
    
RETURNS
    void
*/
void SetupPowerTable( void )
{
    uint16 size_ps_key;
    power_table *PowerTable;
    
    /* obtain the size of memory in words required to hold the contents of the pskey */
    size_ps_key = PsFullRetrieve(PS_HFP_POWER_TABLE, NULL, 0);

    /* initialise user power table */
    theSink.user_power_table = 0;

    /* check whether any pskey data exists */    
    if (size_ps_key)
    {
        /* malloc storage for power table entries */ 
        PowerTable = (power_table*)mallocPanic(size_ps_key);
        
        /* attempt to retrieve all power table entries from ps */
        size_ps_key = PsFullRetrieve(PS_HFP_POWER_TABLE, PowerTable, ((sizeof(lp_power_table) * MAX_POWER_TABLE_ENTRIES) + sizeof(uint16)));
     
        /* sanity check the number of entried and length of pskey data to ensure entries are complete */
        if(size_ps_key == ((sizeof(lp_power_table)*PowerTable->normalEntries)+
                           (sizeof(lp_power_table)*PowerTable->SCOEntries)+
                           (sizeof(lp_power_table)*PowerTable->A2DPStreamEntries)+                                 
                           (sizeof(uint16)))
          )
        {   
            /* Use user defined power table */
            theSink.user_power_table = PowerTable;
            /* pskey format is correct */
            INIT_DEBUG(("User Power Table - Norm[%x] Sco[%x] Stream[%x]\n",PowerTable->normalEntries,PowerTable->SCOEntries,PowerTable->A2DPStreamEntries));
        }
        else
        {   /* No/incorrect power table defined in Ps Keys - use default table */
            freePanic(PowerTable);
            PowerTable = NULL;
            INIT_DEBUG(("No User Power Table\n"));
        }
    }
    
}
Пример #5
0
void configManagerInit( void )  
{ 
    
	/* use a memory allocation for the lengths data to reduce stack usage */
    lengths_config_type * keyLengths = mallocPanic(sizeof(lengths_config_type));
	
		/* Read key lengths */
    configManagerKeyLengths(keyLengths);			

        /* Allocate the memory required for the configuration data */
    InitConfigMemory(keyLengths);
    
  	    /* Read and configure the button translations */
  	configManagerButtonTranslations( );

        /* Read and configure the button durations */
  	configManagerButtonDurations( );
	
  	    /* Read the system event configuration and configure the buttons */
    configManagerButtons( );
    
    /*configures the pattern button events*/
    configManagerButtonPatterns( ) ;

        /*Read and configure the event tones*/
    configManagerEventTones( keyLengths->no_tones ) ;
        /* Read and configure the system features */
  	configManagerFeatureBlock( );	
                                                        
    /* Read and configure the automatic switch off time*/
    configManagerConfiguration( );

    /* Must happen between features and session data... */
    InitA2dp();  
 
    /* Read and configure the user defined tones */    
  	configManagerUserDefinedTones( keyLengths->userTonesLength );	

  	    /* Read and configure the LEDs */
    configManagerLEDS();
   
        /* Read and configure the voume settings */
  	configManagerVolume( );
 
  	    /* Read and configure the power management system */
  	configManagerPower( );
 
  	    /* Read and configure the radio parameters */
  	configManagerRadio();
   
        /* Read and configure the volume orientation, LED Disable state, and tts_language */
	configManagerReadSessionData ( ) ; 

    configManagerReadDspData();
	
        /* Read and configure the sniff sub-rate parameters */
	configManagerSetupSsr ( ) ; 
	
    configManagerEventTTSPhrases( keyLengths->no_tts ) ;

    configManagerVoicePromptsInit( keyLengths->no_vp , keyLengths->no_tts_languages );
 
#if defined (ENABLE_REMOTE) && defined (ENABLE_SOUNDBAR)
    /* Read the hid remote control key mapping. */
    configManagerHidkeyMap();
 #endif

    /* don't allocate memory for AT commands if they're not required */
    if (keyLengths->size_at_commands)
    {        
        InitConfigMemoryAtCommands(keyLengths->size_at_commands);
        configManagerAtCommands(keyLengths->size_at_commands + sizeof(config_block3_t) - 1);
    }
    
#ifdef ENABLE_FM
    /* read the fm configuration data */
    configManagerReadFmData();
    
#endif
    /* release the memory used for the lengths key */
    freePanic(keyLengths);
}
Пример #6
0
/****************************************************************************
NAME    
    A2dpRouteAudio
    
DESCRIPTION
    attempt to connect an audio connection from a2dp device via the passed in 
    deviceID

RETURNS
    
*/
void A2dpRouteAudio(uint8 Index, Sink sink)
{      
    AUD_DEBUG(("AudioA2dpRoute Index[%x] Sink[%x]\n", Index , (uint16) sink )) ;

    /* ensure sink is valid before attempting the connection */
    if(sink)
    {       
        a2dp_codec_settings * codec_settings;
            
        AUD_DEBUG(("AudioA2dpRoute Index[%d] DevId[%x]\n", Index , theSink.a2dp_link_data->device_id[Index] )) ;

        /* get the rate information for connection */
        codec_settings = A2dpCodecGetSettings(theSink.a2dp_link_data->device_id[Index], theSink.a2dp_link_data->stream_id[Index]);

            /* ensure stream is valid */
            if(codec_settings)
            {     
                AudioPluginFeatures features;
                AUDIO_MODE_T mode = AUDIO_MODE_CONNECTED;
                uint16 a2dp_gain = theSink.conf1->gVolMaps[ theSink.a2dp_link_data->gAvVolumeLevel[Index] ].A2dpGain;

                /* determine additional features applicable for this audio plugin */
                features.stereo = theSink.features.stereo;
                features.use_i2s_output = theSink.features.UseI2SOutputCapability;

                if (theSink.conf1->gVolMaps[ theSink.a2dp_link_data->gAvVolumeLevel[Index] ].A2dpGain == VOLUME_A2DP_MUTE_GAIN)
                {
                    mode = AUDIO_MODE_MUTE_SPEAKER;
                }
                else
                {
                    /* must take off 1 when passing to audio plugin if not mute; 0 = MUTE, 1 = Gain 0, 2 = Gain 1, etc. */
                    a2dp_gain--;
                }
                             
                /* initialise the AudioConnect extra parameters required to pass in additional codec information */
                theSink.a2dp_link_data->a2dp_audio_connect_params.packet_size = codec_settings->codecData.packet_size; /* Packet size retrieved from a2dp library */            
                theSink.a2dp_link_data->a2dp_audio_connect_params.content_protection = codec_settings->codecData.content_protection; /* content protection retrieved from a2dp library */            
                theSink.a2dp_link_data->a2dp_audio_connect_params.clock_mismatch = theSink.a2dp_link_data->clockMismatchRate[Index]; /* clock mismatch rate for this device */      
                theSink.a2dp_link_data->a2dp_audio_connect_params.mode_params = &theSink.a2dp_link_data->a2dp_audio_mode_params; /* EQ mode and Audio enhancements */
#ifdef INCLUDE_A2DP_EXTRA_CODECS                
#ifdef INCLUDE_FASTSTREAM                
                theSink.a2dp_link_data->a2dp_audio_connect_params.voice_rate = codec_settings->codecData.voice_rate; /* voice rate retrieved from a2dp library */
                theSink.a2dp_link_data->a2dp_audio_connect_params.bitpool = codec_settings->codecData.bitpool; /* bitpool retrieved from a2dp library */
                theSink.a2dp_link_data->a2dp_audio_connect_params.format = codec_settings->codecData.format; /* format retrieved from a2dp library */
#endif                   
#ifdef INCLUDE_APTX
                theSink.a2dp_link_data->a2dp_audio_connect_params.channel_mode  = codec_settings->channel_mode; /* aptX channel mode */ 
#endif
#ifdef INCLUDE_APTX_ACL_SPRINT
                theSink.a2dp_link_data->a2dp_audio_connect_params.aptx_sprint_params  = codec_settings->codecData.aptx_sprint_params; /* aptX LL params */ 
#endif
#endif  
#ifdef ENABLE_SOUNDBAR
                theSink.a2dp_link_data->seid[Index] = codec_settings->seid;
#endif /* ENABLE_SOUNDBAR */
#ifdef ENABLE_SUBWOOFER
                /* set the sub woofer link type prior to passing to audio connect */
                theSink.a2dp_link_data->a2dp_audio_connect_params.sub_woofer_type  = AUDIO_SUB_WOOFER_NONE;  
                theSink.a2dp_link_data->a2dp_audio_connect_params.sub_sink  = NULL;  
                
                /* bits inverted in dsp plugin */                
                sinkAudioSetEnhancement(MUSIC_CONFIG_SUB_WOOFER_BYPASS,TRUE);
#else
                /* no subwoofer support, set the sub woofer bypass bit in music config message sent o dsp */
                sinkAudioSetEnhancement(MUSIC_CONFIG_SUB_WOOFER_BYPASS,FALSE);
#endif          

                AUD_DEBUG(("AudioA2dpRoute Index[%d] DevId[%x] Gain[%x] Codec[%x] ClkMismatch[%x] EQ[%x] packet_size[%u]\n", 
                           Index , 
                           theSink.a2dp_link_data->device_id[Index],
                           a2dp_gain,
                           codec_settings->seid,
                           theSink.a2dp_link_data->a2dp_audio_connect_params.clock_mismatch,
                           (uint16)theSink.a2dp_link_data->a2dp_audio_connect_params.mode_params,
                           theSink.a2dp_link_data->a2dp_audio_connect_params.packet_size)) ;
                
                audioIndicateCodec( codec_settings->seid );

#ifdef ENABLE_SOUNDBAR
                /* Set the LE SCAN priority to Low since we are Streaming  It is possible 
                that we might be receiving less or no LE adverts when streaming is in progress*/
                InquirySetPriority(inquiry_low_priority);
#endif /*  ENABLE_SOUNDBAR */

                /* connect the audio via the audio plugin */    
                AudioConnect(   getA2dpPlugin(codec_settings->seid),
                                sink , 
                                AUDIO_SINK_AV ,
                                theSink.codec_task,
                                a2dp_gain, 
                                codec_settings->rate,
                                features ,
                                mode,
                                AUDIO_ROUTE_INTERNAL,
                                powerManagerGetLBIPM(), 
                                &theSink.a2dp_link_data->a2dp_audio_connect_params,
                                &theSink.task);
                                
                audioControlLowPowerCodecs (FALSE) ;


                /* caller responsible for freeing memory */
                freePanic(codec_settings);
                
#ifdef ENABLE_AVRCP
                if(theSink.features.avrcp_enabled)
                {    
                    /* any AVRCP commands should be targeted to the device which has A2DP audio routed */ 
                    sinkAvrcpSetActiveConnection(&theSink.a2dp_link_data->bd_addr[Index]);    
                }
#endif            
        }
            
        /* update the current sink being routed */            
        theSink.routed_audio = sink;
    }
}
Пример #7
0
/****************************************************************************
NAME    
    A2dpRouteAudio
    
DESCRIPTION
    attempt to connect an audio connection from a2dp device via the passed in 
    deviceID

RETURNS
    
*/
void A2dpRouteAudio(uint8 Index, Sink sink)
{      
    AUD_DEBUG(("AudioA2dpRoute Index[%x] Sink[%x]\n", Index , (uint16) sink )) ;

    /* ensure sink is valid before attempting the connection */
    if(sink)
    {       
        /* Use an instance of A2DP message structure for initial volume setting */
        AUDIO_PLUGIN_SET_VOLUME_A2DP_MSG_T volumeInitAudio;

        a2dp_codec_settings * codec_settings;
            
        AUD_DEBUG(("AudioA2dpRoute Index[%d] DevId[%x]\n", Index , theSink.a2dp_link_data->device_id[Index] )) ;

        /* get the rate information for connection */
        codec_settings = A2dpCodecGetSettings(theSink.a2dp_link_data->device_id[Index], theSink.a2dp_link_data->stream_id[Index]);

            /* ensure stream is valid */
            if(codec_settings)
            {     
                AUDIO_MODE_T mode = AUDIO_MODE_CONNECTED;
                int16 a2dp_gain_dB;
                /* determine additional features applicable for this audio plugin */
                /* Volume info is sent to DSP in dB units */
                a2dp_gain_dB = VolumeConvertStepsToDB(theSink.volume_levels->a2dp_volume[Index].masterVolume, &theSink.conf1->volume_config.volume_control_config, DSP_DB_SCALE);

                /* check for MUTE volume level and mute as appropriate */
				if (theSink.volume_levels->a2dp_volume[Index].masterVolume == VOLUME_A2DP_MUTE_GAIN)
                {
                    mode = AUDIO_MODE_MUTE_SPEAKER;
                }			
                             
                /* initialise the AudioConnect extra parameters required to pass in additional codec information */
				if (codec_settings->codecData.latency_reporting) /* latency reporting retrieved from a2dp library */
				{
					/* TODO: obtain settings from PS, probably based on codec type */
					theSink.a2dp_link_data->a2dp_audio_connect_params.latency.last = 150;
					theSink.a2dp_link_data->a2dp_audio_connect_params.latency.target = 150/5;
					theSink.a2dp_link_data->a2dp_audio_connect_params.latency.change = 10/5;
					theSink.a2dp_link_data->a2dp_audio_connect_params.latency.period = 500/100;			
				}

                theSink.a2dp_link_data->a2dp_audio_connect_params.packet_size = codec_settings->codecData.packet_size; /* Packet size retrieved from a2dp library */            
                theSink.a2dp_link_data->a2dp_audio_connect_params.content_protection = codec_settings->codecData.content_protection; /* content protection retrieved from a2dp library */            
                theSink.a2dp_link_data->a2dp_audio_connect_params.clock_mismatch = theSink.a2dp_link_data->clockMismatchRate[Index]; /* clock mismatch rate for this device */      
                theSink.a2dp_link_data->a2dp_audio_connect_params.mode_params = &theSink.a2dp_link_data->a2dp_audio_mode_params; /* EQ mode and Audio enhancements */
#ifdef INCLUDE_A2DP_EXTRA_CODECS                
#ifdef INCLUDE_FASTSTREAM                
                theSink.a2dp_link_data->a2dp_audio_connect_params.voice_rate = codec_settings->codecData.voice_rate; /* voice rate retrieved from a2dp library */
                theSink.a2dp_link_data->a2dp_audio_connect_params.bitpool = codec_settings->codecData.bitpool; /* bitpool retrieved from a2dp library */
                theSink.a2dp_link_data->a2dp_audio_connect_params.format = codec_settings->codecData.format; /* format retrieved from a2dp library */
#endif                   
#ifdef INCLUDE_APTX
                theSink.a2dp_link_data->a2dp_audio_connect_params.channel_mode  = codec_settings->channel_mode; /* aptX channel mode */ 
#endif
#ifdef INCLUDE_APTX_ACL_SPRINT
                theSink.a2dp_link_data->a2dp_audio_connect_params.aptx_sprint_params  = codec_settings->codecData.aptx_sprint_params; /* aptX LL params */ 
#endif
#endif  
#ifdef ENABLE_SOUNDBAR
                theSink.a2dp_link_data->seid[Index] = codec_settings->seid;
#endif /* ENABLE_SOUNDBAR */
#ifdef ENABLE_SUBWOOFER
                /* set the sub woofer link type prior to passing to audio connect */
                theSink.a2dp_link_data->a2dp_audio_connect_params.sub_woofer_type  = AUDIO_SUB_WOOFER_NONE;  
                theSink.a2dp_link_data->a2dp_audio_connect_params.sub_sink  = NULL;  
                
                /* bits inverted in dsp plugin */                
                sinkAudioSetEnhancement(MUSIC_CONFIG_SUB_WOOFER_BYPASS,TRUE);
#else
                /* no subwoofer support, set the sub woofer bypass bit in music config message sent o dsp */
                sinkAudioSetEnhancement(MUSIC_CONFIG_SUB_WOOFER_BYPASS,FALSE);
#endif          

                AUD_DEBUG(("AudioA2dpRoute Index[%d] DevId[%x] Gain[%x] Codec[%x] ClkMismatch[%x] EQ[%x] packet_size[%u]\n", 
                           Index , 
                           theSink.a2dp_link_data->device_id[Index],
                           a2dp_gain_dB,
                           codec_settings->seid,
                           theSink.a2dp_link_data->a2dp_audio_connect_params.clock_mismatch,
                           (uint16)theSink.a2dp_link_data->a2dp_audio_connect_params.mode_params,
                           theSink.a2dp_link_data->a2dp_audio_connect_params.packet_size)) ;
                
                audioIndicateCodec( codec_settings->seid );

#ifdef ENABLE_SOUNDBAR
                /* Set the LE SCAN priority to Low since we are Streaming  It is possible 
                that we might be receiving less or no LE adverts when streaming is in progress*/
                InquirySetPriority(inquiry_low_priority);
#endif /*  ENABLE_SOUNDBAR */

                /* We need to set A2DP volume info as the audio is in mute state after connection */ 
				volumeInitAudio.volume_type = theSink.conf1->volume_config.volume_control_config.volume_type;
                volumeInitAudio.codec_task = theSink.codec_task;
        		volumeInitAudio.master_gain = a2dp_gain_dB;
                volumeInitAudio.system_gain = theSink.conf1->volume_config.volume_control_config.system_volume;
        		volumeInitAudio.trim_gain_left = theSink.conf1->volume_config.volume_control_config.trim_volume_left;
        		volumeInitAudio.trim_gain_right= theSink.conf1->volume_config.volume_control_config.trim_volume_right;	
                volumeInitAudio.device_trim_master = theSink.conf1->volume_config.volume_control_config.device_trim_master;
                volumeInitAudio.device_trim_slave = theSink.conf1->volume_config.volume_control_config.device_trim_slave;
          		volumeInitAudio.tones_gain = VolumeConvertStepsToDB(((TonesGetToneVolume(FALSE) * theSink.conf1->volume_config.volume_control_config.no_of_steps)/VOLUME_NUM_VOICE_STEPS), &theSink.conf1->volume_config.volume_control_config, DSP_DB_SCALE);
                volumeInitAudio.mute_active = theSink.sink_enable_present;
                
                /* connect the audio via the audio plugin */    
  			    AudioConnect(getA2dpPlugin(codec_settings->seid),
                             sink , 
                             AUDIO_SINK_AV ,
                             theSink.codec_task,
                             volumeInitAudio.tones_gain, 
                             codec_settings->rate,
                             theSink.conf2->audio_routing_data.PluginFeatures ,
                             mode,
                             AUDIO_ROUTE_INTERNAL,
                             powerManagerGetLBIPM(), 
                             &theSink.a2dp_link_data->a2dp_audio_connect_params,
                             FALSE,
                             &theSink.task);
               
				AudioSetVolumeA2DP(&volumeInitAudio);

#ifdef ENABLE_SUBWOOFER
                /* set subwoofer volume level */
                updateSwatVolume(theSink.volume_levels->a2dp_volume[Index].masterVolume);

                SWAT_DEBUG(("SW : Send sample rate to Sub, rate is %ld\n",codec_settings->rate));
                
                /* send sample rate to sub */
                sendSampleRateToSub(codec_settings->rate);                        
#endif
                
                audioControlLowPowerCodecs (FALSE) ;

                /* caller responsible for freeing memory */
                freePanic(codec_settings);
                
#ifdef ENABLE_AVRCP
                if(theSink.features.avrcp_enabled)
                {    
                    UpdateAvrpcMessage_t * lUpdateMessage = mallocPanic ( sizeof(UpdateAvrpcMessage_t) ) ;        
                    lUpdateMessage->bd_addr = theSink.a2dp_link_data->bd_addr[Index];                            
                    /* any AVRCP commands should be targeted to the device which has A2DP audio routed */ 
                    MessageSend( &theSink.task, EventSysSetActiveAvrcpConnection, lUpdateMessage);
                }
#endif            
        }
            
        /* update the current sink being routed */            
        theSink.routed_audio = sink;
    }
}
Пример #8
0
/****************************************************************************
NAME	
	mapcHandleServiceSearchAttributeCfm
    
DESCRIPTION
    confirmation of the service search for MAP support, if successful the 
    app will progress and attempt to connect to the message access service
    
PARAMS
    @cfm message
    
RETURNS
	void
*/
void mapcHandleServiceSearchAttributeCfm( const CL_SDP_SERVICE_SEARCH_ATTRIBUTE_CFM_T *cfm)
{
    uint8 *rfcomm_channels;	
    uint8 size_rfcomm_channels = 1;
    uint8 channels_found = 0;
    mapcState *state = NULL;
    
    mapc_link_priority device_id = mapcGetLinkFromBdAddr( &cfm->bd_addr );
    
    /* ensure device_id has been correctly retrieved */
    if(device_id != mapc_invalid_link)
        state = &(theSink.rundata->mapc_data.state[device_id]);
    
    /* if the service search has been successful, parse returned entries */
    if(cfm->status == sdp_response_success)
    {
        MAPC_DEBUG(("MAPC:\tReceived SDP Response of length %d\n", cfm->size_attributes));
    
        rfcomm_channels = mallocPanic(size_rfcomm_channels * sizeof(uint8));
             
        /* parse all returned reports */
        if (SdpParseGetMultipleRfcommServerChannels(
                            cfm->size_attributes, 
                            (uint8*)cfm->attributes, 
                            1, 
                            &rfcomm_channels, 
                            &channels_found) )
        {
            /* If receiving multiple responses, the first record will be stored in this application */
            if(state)
            {
                state->masChannel   = rfcomm_channels[0];
                state->bdAddr       = cfm->bd_addr;
                state->device_state = mapc_sdp_searched;
    
                /* set the link security requirements */
                ConnectionSmSetSdpSecurityOut(TRUE, &cfm->bd_addr); 
                    
                ConnectionSmRegisterOutgoingService(&theSink.task, 
                                                    &cfm->bd_addr, 
                                                    protocol_rfcomm,
                                                    state->masChannel,
                                                    sec4_out_level_2);                
    
                /* attempt to connect the message access service */
                MapcMasConnectRequest( &theSink.task, &cfm->bd_addr, state->masChannel );
            }
        }
        /* no channels were found, there reset the state of this connection */
        else
        {
            if(state)
                state->device_state = mapc_state_idle;
            
            MAPC_DEBUG(("MAPC:NO Channels found\n"));   
        }
        /* ensure memory used in sdp record parsing is free'd */
        freePanic(rfcomm_channels);
    }
    /* the sdp record search was not successful, no further action needs to be taken */
    else
    {
        /* reset current connection state so that it can be reused */
        if(state)        
            state->device_state = mapc_state_idle;

        MAPC_DEBUG(("MAPC:SDP Search Failed. Status = %x, more = %x, error = %x \n", cfm->status, cfm->more_to_come, cfm->error_code));
        
    }
}
Пример #9
0
/****************************************************************************
NAME    
    sinkWriteEirData
    
DESCRIPTION
    Writes the local name, inquiry tx power and device UUIDs into device 
    EIR data

RETURNS
    void
*/
void sinkWriteEirData( CL_DM_LOCAL_NAME_COMPLETE_T *message )
{
    uint16 size_uuids = 0;
    uint16 size = 0;
    
    uint8 *eir = NULL;
    uint8 *p = NULL;
    
    /* Determine length of EIR data */
    size_uuids = SIZE_A2DP_UUIDS + SIZE_AVRCP_UUIDS + SIZE_PBAP_UUIDS + SIZE_HFP_UUIDS + SIZE_HSP_UUIDS;
    
    size = GetDeviceIdEirDataSize() + EIR_BLOCK_SIZE(EIR_DATA_SIZE_FULL(size_uuids) + EIR_DATA_SIZE_FULL(message->size_local_name) + EIR_DATA_SIZE_FULL(sizeof(uint8)));    
    
    /* Allocate space for EIR data */
    eir = (uint8 *)mallocPanic(size * sizeof(uint8));
    p = eir;    
    
    /* Device Id Record */
    p += WriteDeviceIdEirData( p );
    
    /* Inquiry Tx Field */
    *p++ = EIR_DATA_SIZE(sizeof(int8));
    *p++ = EIR_TYPE_INQUIRY_TX;
    *p++ = theSink.inquiry_tx;
    
    /* UUID16 field */
    *p++ = EIR_DATA_SIZE(size_uuids);
    *p++ = EIR_TYPE_UUID16_PARTIAL;

    if(theSink.features.EnableA2dpStreaming)
    {
        memmove(p, a2dp_uuids, sizeof(a2dp_uuids));
        p += sizeof(a2dp_uuids);
    }  
    
#ifdef ENABLE_AVRCP 
    if (theSink.features.avrcp_enabled)
    {
        memmove(p, avrcp_uuids, sizeof(avrcp_uuids));
        p += sizeof(avrcp_uuids);
    }
#endif      

#ifdef ENABLE_PBAP
    if (theSink.features.pbap_enabled)
    {
        memmove(p, pbap_uuids, sizeof(pbap_uuids));
        p += sizeof(pbap_uuids);
    }
#endif

    if(theSink.hfp_profiles & hfp_handsfree_all)
    {
        memmove(p, hfp_uuids, sizeof(hfp_uuids));
        p += sizeof(hfp_uuids);
    }
    if(theSink.hfp_profiles & hfp_headset_all)
    {
        memmove(p, hsp_uuids, sizeof(hsp_uuids));
        p += sizeof(hsp_uuids);
    }
    
    /* Device Name Field */
    *p++ = EIR_DATA_SIZE(message->size_local_name);  
    *p++ = EIR_TYPE_LOCAL_NAME_COMPLETE;
    memmove(p, message->local_name, message->size_local_name);
    p += message->size_local_name;
    
    /* NULL Termination */
    *p++ = 0x00; 
    
    /* Register and free EIR data */
    ConnectionWriteEirData(FALSE, size, eir);
    freePanic(eir);
}
Пример #10
0
/****************************************************************************
NAME    
    sinkPartyModeTrackChangeIndication
    
DESCRIPTION
    Called when AVRCP has detected a track change indication
    
RETURNS
    none
*/
void sinkPartyModeTrackChangeIndication(uint16 index)
{        
    /* check to see if this is an indication from the currently active device */
    if ((theSink.PartyModeEnabled)&&(theSink.features.PartyMode)&&(index == sinkAvrcpGetActiveConnection()))
    {
        PTY_DEBUG(("PTY: track change active dev\n"));
        
        if(!theSink.features.avrcp_enabled ||
           !theSink.features.EnableAvrcpAudioSwitching)
        {
            PTY_DEBUG(("PTY: ignore AVRCP in party mode\n"));
            return;
        }
        /*  check whether to changing the audio routing */
        else
        {
            /* get current audio status */
            audio_source_status * lAudioStatus = audioGetStatus(theSink.routed_audio);        
       
            /* ensure device is still streaming/playing */ 
            
            /* determine which device track change came from */
            if(BdaddrIsSame(&theSink.a2dp_link_data->bd_addr[a2dp_primary], &theSink.avrcp_link_data->bd_addr[index]))
            {
                /* track change on primary a2dp device, check it is still streaming and audio is routed */
                if(((theSink.avrcp_link_data->play_status[index] == avrcp_play_status_playing)||(theSink.avrcp_link_data->play_status[index] == avrcp_play_status_stopped)||(theSink.avrcp_link_data->play_status[index] == avrcp_play_status_paused))&&
                    (lAudioStatus->a2dpSinkPri == lAudioStatus->audio_routed)&&(lAudioStatus->a2dpStatePri == a2dp_stream_streaming))
                {
                    /* track change on a2dp primary is valid, check if a2dp secondary is paused */
                    if((lAudioStatus->a2dpStateSec == a2dp_stream_streaming)||(lAudioStatus->a2dpStateSec == a2dp_stream_open))
                    {
                        /* check avrcp play status is paused */        
                        if((theSink.rundata->partymode_pause.audio_source_secondary_paused)&&(theSink.avrcp_link_data->play_status[(index^1)] == avrcp_play_status_paused))
                        {
                            PTY_DEBUG(("PTY: track change route sec dis pri\n"));

                            /* disconnect primary device */                            
                            sinkPartyModeDisconnectAndResume(a2dp_primary, lAudioStatus);
                            /* reset paused flag */
                            theSink.rundata->partymode_pause.audio_source_secondary_paused = FALSE;
                        }
                    }
                }                     
            }
            else if(BdaddrIsSame(&theSink.a2dp_link_data->bd_addr[a2dp_secondary], &theSink.avrcp_link_data->bd_addr[index]))
            {
                /* track change on primary a2dp device, check it is still streaming and audio is routed */
                if(((theSink.avrcp_link_data->play_status[index] == avrcp_play_status_playing)||(theSink.avrcp_link_data->play_status[index] == avrcp_play_status_stopped)||(theSink.avrcp_link_data->play_status[index] == avrcp_play_status_paused))&&
                    (lAudioStatus->a2dpSinkSec == lAudioStatus->audio_routed)&&(lAudioStatus->a2dpStateSec == a2dp_stream_streaming))
                {
                    /* track change on a2dp primary is valid, check if a2dp secondary is paused */
                    if((lAudioStatus->a2dpStatePri == a2dp_stream_streaming)||(lAudioStatus->a2dpStatePri == a2dp_stream_open))
                    {
                        /* check avrcp play status is paused */        
                        if((theSink.rundata->partymode_pause.audio_source_primary_paused)&&(theSink.avrcp_link_data->play_status[(index^1)] == avrcp_play_status_paused))
                        {
                            PTY_DEBUG(("PTY: track change route pri dis sec\n"));
                            /* disconnect secondary device */                            
                            sinkPartyModeDisconnectAndResume(a2dp_secondary, lAudioStatus);
                            /* reset paused flag */
                            theSink.rundata->partymode_pause.audio_source_primary_paused = FALSE;
                        }
                    }
                }                     
                
            }
            /* free malloc'd status memory slot */
            freePanic(lAudioStatus);
        }
    }
    /* indication from device that isn't currently streaming audio, ignore */
    else
    {
        PTY_DEBUG(("PTY: track change ignored PTY[%d] index[%d] ActiveIdx[%d]\n",(theSink.PartyModeEnabled && theSink.features.PartyMode),index,sinkAvrcpGetActiveConnection()));
    }
}