Esempio n. 1
0
/****************************************************************************
 Register the service record corresponding to the specified profile
*/
void aghfpRegisterServiceRecord(AGHFP *aghfp, aghfp_profile profile, uint8 chan)
{
	uint16 length;
	uint8 *service_record = 0;


	if (supportedProfileIsHsp(profile))
	{
		/* Create a copy of the service record that we can modify */
		length = sizeof(aghfp_hsp_service_record);
		service_record = (uint8 *)PanicUnlessMalloc(length);
		memcpy(service_record, aghfp_hsp_service_record, length);
	}
	else if (supportedProfileIsHfp(profile))
	{
		/* Create a copy of the service record that we can modify */
		length = sizeof(aghfp_hfp_service_record);
		service_record = (uint8 *)PanicUnlessMalloc(length);
		memcpy(service_record, aghfp_hfp_service_record, length);

		/* Insert the supported features into the service record */
		if (!insertHfpSupportedFeatures(service_record, service_record + length, aghfp->supported_profile))
		{
			/* Failed to insert the supported features into the service record */
			MAKE_AGHFP_MESSAGE(AGHFP_INTERNAL_SDP_REGISTER_CFM);
			message->status = aghfp_fail;
			MessageSend(&aghfp->task, AGHFP_INTERNAL_SDP_REGISTER_CFM, message);

			/* Free the allocated memory */
			free(service_record);
			return;
		}
	}
	else
	{
		/* Unknown profile, send an error */
		MAKE_AGHFP_MESSAGE(AGHFP_INTERNAL_SDP_REGISTER_CFM);
		message->status = aghfp_fail;
		MessageSend(&aghfp->task, AGHFP_INTERNAL_SDP_REGISTER_CFM, message);
		return;
	}

	if (!insertRfcommServerChannel(service_record, service_record + length, chan))
	{
		/* If we fail to insert the rfcomm channel return an error to the app */
		MAKE_AGHFP_MESSAGE(AGHFP_INTERNAL_SDP_REGISTER_CFM);
		message->status = aghfp_fail;
		MessageSend(&aghfp->task, AGHFP_INTERNAL_SDP_REGISTER_CFM, message);

		/* Free the allocated memory */
		free(service_record);
	}
	else
	{
		/* Send the service record to the connection lib to be registered with BlueStack */
		ConnectionRegisterServiceRecord(&aghfp->task, length, service_record);
	}
}
void aghfpHandleCmerReqParse(Task task, const struct aghfpHandleCmerReqParse *data)
{
	MAKE_AGHFP_MESSAGE(AGHFP_INTERNAL_AT_CMER_REQ);
    message->mode = data->mode;
    message->ind = data->ind;
    MessageSend(task, AGHFP_INTERNAL_AT_CMER_REQ, message);
}
void aghfpHandleCopsFormatParse(Task task, const struct aghfpHandleCopsFormatParse *data)
{
	MAKE_AGHFP_MESSAGE(AGHFP_INTERNAL_NETWORK_OPERATOR_FORMAT_REQ);
	message->mode = data->mode;
	message->format = data->format;
	MessageSend(task, AGHFP_INTERNAL_NETWORK_OPERATOR_FORMAT_REQ, message);
}
Esempio n. 4
0
/****************************************************************************
 Service search has completed, check it has succeeded and get the required
 attributes from the returned list.
*/
void aghfpHandleServiceSearchAttributeCfm(AGHFP *aghfp, const CL_SDP_SERVICE_SEARCH_ATTRIBUTE_CFM_T *cfm)
{
	/* Check the outcome of the service search */
	if (cfm->status == sdp_response_success)
	{
		uint16 sdp_data = 0;

		if (getRfcommChannelNumber(cfm->attributes,
			cfm->attributes + cfm->size_attributes,
			&sdp_data))
		{
			/* We have an rfcomm channel we can proceed with the connection establishment */
			MAKE_AGHFP_MESSAGE(AGHFP_INTERNAL_RFCOMM_CONNECT_REQ);
			message->addr = cfm->bd_addr;
			message->rfc_channel = sdp_data;
			MessageSend(&aghfp->task, AGHFP_INTERNAL_RFCOMM_CONNECT_REQ, message);
		}
		else
		{
			/*  We have received data we don't know what to do with.
				This shouldn't happen since we're issuing the search and should
				know what we're looking for so for the moment just ignore.
			*/
		}
	}
	else
	{
		/* If we have an established SLC the rfcomm sink will be valid. */
		if (!aghfp->rfcomm_sink)
		{
			/* Tell the app the connection attempt has failed. */
			aghfpSendSlcConnectCfmToApp(aghfp_connect_sdp_fail, aghfp);
		}
	}
}
/****************************************************************************
	Enables AG to reject a new call/terminate an existing call.
*/
void AghfpCallTerminate (AGHFP *aghfp, bool keep_sink)
{
	MAKE_AGHFP_MESSAGE(AGHFP_INTERNAL_CALL_MGR_TERMINATE_REQ);
	message->keep_sink = keep_sink;
	
	MessageSend(&aghfp->task, AGHFP_INTERNAL_CALL_MGR_TERMINATE_REQ, message);
}
void aghfpHandleAvailableCodecs(Task task, const struct aghfpHandleAvailableCodecs *availableCodecs)
{
	/* Immediately extract the data. Once we return from this
	   function the data is lost, so parse now. */
	uint16 num_of_entries = availableCodecs->codecs.count;
	uint16 counter1;
	struct value_aghfpHandleAvailableCodecs_codecs value;

	MAKE_AGHFP_MESSAGE(AGHFP_INTERNAL_CODEC_NEGOTIATION_REQ);
	
	AGHFP_DEBUG(("aghfpHandleCodecNegotiationReq\n"));

	if(num_of_entries > AGHFP_MAX_NUM_CODECS)
	{
		AGHFP_DEBUG(("Warning HF specified more codecs than AG can handle. Only considering the first %d\n", AGHFP_MAX_NUM_CODECS));
		num_of_entries = AGHFP_MAX_NUM_CODECS;
	}

	message->num_codecs = num_of_entries;

	for (counter1 = 0; counter1 < num_of_entries; counter1++)
	{
		/* Get the next Codec ID. */
		value = get_aghfpHandleAvailableCodecs_codecs(&availableCodecs->codecs, counter1);

		message->codec_uuids[counter1] = value.codec;
	}

	MessageSend(task, AGHFP_INTERNAL_CODEC_NEGOTIATION_REQ, message);
}
Esempio n. 7
0
/****************************************************************************
	Outcome of SDP service register request.
*/
void aghfpHandleSdpRegisterCfm(AGHFP *aghfp, const CL_SDP_REGISTER_CFM_T *cfm)
{
	MAKE_AGHFP_MESSAGE(AGHFP_INTERNAL_SDP_REGISTER_CFM);

	/* Check the outcome of the register request */
	if (cfm->status == success)
	{
		/* Set status to success */
		message->status = aghfp_success;

		/* Store the service handle */
		aghfp->sdp_record_handle = cfm->service_handle;
	}
	else
	{
		/* Set status to fail */
		message->status = aghfp_fail;

		/* Reset the service handle */
		aghfp->sdp_record_handle = 0;
	}

	/* Send the message */
	MessageSend(&aghfp->task, AGHFP_INTERNAL_SDP_REGISTER_CFM, message);
}
/****************************************************************************
	Enables AG to setup a call to a HS/HF device.
*/
void AghfpCallCreate (AGHFP *aghfp, aghfp_call_type call_type, bool in_band)
{
	MAKE_AGHFP_MESSAGE(AGHFP_INTERNAL_CALL_MGR_CREATE_REQ);
	message->call_type = call_type;
	message->in_band = in_band;
	
	MessageSend(&aghfp->task, AGHFP_INTERNAL_CALL_MGR_CREATE_REQ, message);
}
static void sendCallTerminateIndToApp (AGHFP *aghfp, aghfp_call_terminate_status status)
{
	MAKE_AGHFP_MESSAGE(AGHFP_CALL_MGR_TERMINATE_IND);
	message->aghfp = aghfp;
	message->status = status;
	message->audio_sink = aghfp->audio_sink;
	MessageSend(aghfp->client_task, AGHFP_CALL_MGR_TERMINATE_IND, message);
}
static void sendCallCreateWaitingIndToApp (AGHFP *aghfp)
{
	if (aghfp->call_params.call_type == aghfp_call_type_incoming )
	{
		MAKE_AGHFP_MESSAGE(AGHFP_CALL_MGR_CREATE_WAITING_RESPONSE_IND);
		message->aghfp = aghfp;
		message->audio_sink = aghfp->audio_sink;
		MessageSend(aghfp->client_task, AGHFP_CALL_MGR_CREATE_WAITING_RESPONSE_IND, message);
	}
	else if (aghfp->call_params.call_type == aghfp_call_type_outgoing )
	{
		MAKE_AGHFP_MESSAGE(AGHFP_CALL_MGR_CREATE_ALERTING_REMOTE_IND);
		message->aghfp = aghfp;
		message->audio_sink = aghfp->audio_sink;
		MessageSend(aghfp->client_task, AGHFP_CALL_MGR_CREATE_ALERTING_REMOTE_IND, message);
	}
}
/* Inform the app of the status of the audio (Synchronous) disconnection */
static void sendAudioDisconnectIndToApp(AGHFP *aghfp, aghfp_audio_disconnect_status status)
{
	MAKE_AGHFP_MESSAGE(AGHFP_AUDIO_DISCONNECT_IND);
	message->aghfp = aghfp;
    message->status = status;
	
	MessageSend(aghfp->client_task, AGHFP_AUDIO_DISCONNECT_IND, message);
}
void aghfpSendCsrFeatureNegotiationReqInd(AGHFP * aghfp)
{
    MAKE_AGHFP_MESSAGE(AGHFP_CSR_FEATURE_NEGOTIATION_REQ_IND);
    
    message->aghfp = aghfp ;

	/* Prompt the app to negotiate the codec */
	MessageSend(aghfp->client_task, AGHFP_CSR_FEATURE_NEGOTIATION_REQ_IND, message);
}
void aghfpHandleFeatureNegotiation(Task task, const struct aghfpHandleFeatureNegotiation * feature )
{
    AGHFP * aghfp = (AGHFP *)task ;
    
    MAKE_AGHFP_MESSAGE(AGHFP_CSR_FEATURE_NEGOTIATION_IND) ;
    
    message->aghfp = aghfp ;
    message->indicator = feature->ind ;
    message->value = feature->val ;
    
    MessageSend ( aghfp->client_task , AGHFP_CSR_FEATURE_NEGOTIATION_IND , message ) ;
}
Esempio n. 14
0
/****************************************************************************
	Notification of an incoming rfcomm connection, pass this up to the app
	to decide whether to accept this or not.
*/
void aghfpHandleRfcommConnectInd(AGHFP *aghfp, const CL_RFCOMM_CONNECT_IND_T *ind)
{
	/* Ask the app whether to accept this connection or not */
	MAKE_AGHFP_MESSAGE(AGHFP_SLC_CONNECT_IND);
	message->bd_addr = ind->bd_addr;
	message->aghfp = aghfp;
	MessageSend(aghfp->client_task, AGHFP_SLC_CONNECT_IND, message);

	/* Update the local state to indicate we're in the middle of connecting. */
	aghfpSetState(aghfp, aghfp_slc_connecting);
    
    /* Store the sink */
    aghfp->rfcomm_sink = ind->sink;
}
void aghfpHandleChldParse(Task task, const struct aghfpHandleChldParse *data)
{
	MAKE_AGHFP_MESSAGE(AGHFP_INTERNAL_CALL_HOLD_REQ);
    message->action = (uint16)(*data->cmd.data - '0');
    if ( data->cmd.length>1 )
    {
        (void)UtilGetNumber(data->cmd.data+1,data->cmd.data+data->cmd.length-1, &message->index);
    }
    else
    {
        message->index = 0;
    }
    MessageSend(task, AGHFP_INTERNAL_CALL_HOLD_REQ, message);
}
void aghfpHandleCindStatusReqParse(Task task)
{
    AGHFP *aghfp = (AGHFP *) task;
    if(aghfp->cind_poll_client)
    {
        MAKE_AGHFP_MESSAGE(AGHFP_CALL_INDICATIONS_STATUS_REQUEST_IND);
        message->aghfp = aghfp;
        MessageSend(aghfp->client_task, AGHFP_CALL_INDICATIONS_STATUS_REQUEST_IND, message);
    }
    else
    {
        MessageSend(task, AGHFP_INTERNAL_AT_CIND_STATUS_REQ, NULL);
    }
}
void aghfpHandleReponseCSRSupportedFeatures(Task task , const struct aghfpHandleReponseCSRSupportedFeatures * features )
{
    AGHFP * aghfp = (AGHFP *)task ;
        
    MAKE_AGHFP_MESSAGE(AGHFP_CSR_SUPPORTED_FEATURES_IND);
    
    message->aghfp      = aghfp ;
    message->callerName = features->callerName;
	message->rawText    = features->rawText;
	message->smsInd     = features->smsInd;
	message->battLevel  = features->battLevel;
	message->pwrSource  = features->pwrSource;
	message->codecs     = features->codecs;    
    
    MessageSend ( aghfp->client_task , AGHFP_CSR_SUPPORTED_FEATURES_IND , message );
}
/*
	Handle Codec Connection request from the HF (AT+BCC).
	This function performs the the actual actions of handling the AT+BCC (once the audio params have been
	obtained from the app, i.e. after aghfpHandleWbsCodecConReq() and ).
*/
static void aghfpHandleWbsCodecConReqProcessing(AGHFP *aghfp)
{
	/* Are we supporting WBS */
	if (aghfp->use_wbs)
	{
		/* OK to initiate WBS Codec Negotiation. */
	
		/* Send OK */
		aghfpSendOk(aghfp);
	
		/* If we haven't negotiatied a codec we need to do so.
		   If we have, we're gonna go ahead and use it here. */
		if (aghfp->use_codec == 0)
		{
			/* Start codec negotiation with HF. */
			if (aghfpWbsStartCodecNegotiation(aghfp, aghfp_negotiate_audio_at_hf))
			{
				aghfp->audio_connection_state = aghfp_audio_codec_connect;
			}
		}
		else
		{
			if (!aghfpCallManagerActiveNotComplete(aghfp))
			{
				MAKE_AGHFP_MESSAGE(AGHFP_INTERNAL_AUDIO_CONNECT_REQ);
				AGHFP_DEBUG(("	  Normal Audio Connection\n"));
				
				message->audio_params = aghfp->audio_params;
				message->packet_type = aghfp->audio_packet_type;
				MessageSend(&aghfp->task, AGHFP_INTERNAL_AUDIO_CONNECT_REQ, message);
			}
			else
			{
				/* Save the audio packet type for Call Manager */
				aghfpStoreAudioParams(aghfp, aghfp->audio_packet_type, &aghfp->audio_params);
				
				/* Answer the call again now that the WBS negotiation is complete. */
				aghfpManageCall(aghfp, CallEventAnswer, CallFlagOpenAudio);
			}
		}
	}
	else
	{
		/* WBS not supported, send ERROR. */
		aghfpSendError(aghfp);
	}
}
/****************************************************************************
	Enables AG to setup a call to a HS/HF device, creating an audio connection in the process.
*/
void AghfpCallCreateAudio (AGHFP *aghfp, aghfp_call_type call_type, bool in_band, sync_pkt_type packet_type, const aghfp_audio_params *audio_params)
{
	MAKE_AGHFP_MESSAGE(AGHFP_INTERNAL_CALL_MGR_CREATE_WITH_AUDIO_REQ);
	message->call_type = call_type;
	message->in_band = in_band;
	message->packet_type = packet_type;
	
	if (audio_params)
	{
		message->audio_params = *audio_params;
	}
	else
	{
		message->audio_params = *aghfpGetDefaultAudioParams(packet_type);
	}
	
	MessageSend(&aghfp->task, AGHFP_INTERNAL_CALL_MGR_CREATE_WITH_AUDIO_REQ, message);
}
void AghfpStartAudioAfterAppCodecNegotiation(AGHFP * aghfp)
{
	if (!aghfpCallManagerActiveNotComplete(aghfp))
	{
		MAKE_AGHFP_MESSAGE(AGHFP_INTERNAL_AUDIO_CONNECT_REQ);
		AGHFP_DEBUG(("	  Normal Audio Connection\n"));
		
		/* Assume that the audio parameters have been previously stored using aghfpStoreAudioParams() */
		message->audio_params = aghfp->audio_params;
		message->packet_type = aghfp->audio_packet_type;
		
		MessageSend(&aghfp->task, AGHFP_INTERNAL_AUDIO_CONNECT_REQ, message);
	}
	else
	{
		/* Answer the call again now that the WBS negotiation is complete. */
		aghfpManageCall(aghfp, CallEventAnswer, CallFlagOpenAudio);
	}
}
/****************************************************************************
NAME	
	aghfpHandleSyncConnectInd

DESCRIPTION
	Incoming audio notification, accept if we recognise the sink reject
	otherwise.

RETURNS
	void
*/
void aghfpHandleSyncConnectInd(AGHFP *aghfp, const CL_DM_SYNC_CONNECT_IND_T *ind)
{
    uint16 i=0;
    uint16 my_audio = 0;
    uint16 num_sinks = 5;
    tp_bdaddr tp_addr = { {TYPED_BDADDR_PUBLIC, { 0, 0, 0 }}, TRANSPORT_BREDR_ACL};

    /* Sink array to store the sinks on the acl. */
    Sink *all_sinks = (Sink *)PanicNull(calloc(num_sinks, sizeof(Sink))); 

    tp_addr.taddr.addr = ind->bd_addr;

    if(StreamSinksFromBdAddr(&num_sinks, all_sinks, &tp_addr))
    {
        for (i=0; i<num_sinks; i++)
        {
            /* Make sure this profile instance owns the unlerlying sink */
            if (all_sinks[i] && all_sinks[i] == aghfp->rfcomm_sink)
            {
                my_audio = 1;
                break;
            }
        }
    }

    free(all_sinks);    

    /* If this is our audio connection then ask the app, otherwise reject outright */
    if (my_audio)
    {
        MAKE_AGHFP_MESSAGE(AGHFP_AUDIO_CONNECT_IND);
    	message->aghfp = aghfp;
		message->bd_addr = ind->bd_addr;
    	MessageSend(aghfp->client_task, AGHFP_AUDIO_CONNECT_IND, message);

        aghfp->audio_connection_state = aghfp_audio_accepting;
    }
    else
    {
        ConnectionSyncConnectResponse(&aghfp->task, &ind->bd_addr, FALSE, 0);
    }
}
void aghfpSendCallCreateCfmToApp (AGHFP *aghfp, aghfp_call_create_status status)
{
	MAKE_AGHFP_MESSAGE(AGHFP_CALL_MGR_CREATE_CFM);
	message->aghfp = aghfp;
	message->status = status;
    message->link_type = aghfp->link_type;
	message->audio_sink = aghfp->audio_sink;
    message->rx_bandwidth = aghfp->rx_bandwidth;
    message->tx_bandwidth = aghfp->tx_bandwidth;

	/* Let the application know if a WBS codec is required. */
    if ((aghfp->use_wbs) && (aghfp->use_codec > 0))
    {
	    message->using_wbs = TRUE;
	    message ->wbs_codec = aghfp->use_codec;
    }
    else
	    message->using_wbs = FALSE;
	
	MessageSend(aghfp->client_task, AGHFP_CALL_MGR_CREATE_CFM, message);
}
/* Inform the app of the status of the audio (Synchronous) connection */
void sendAudioConnectCfmToApp(AGHFP *aghfp, aghfp_audio_connect_status status, hci_status cl_status)
{
	MAKE_AGHFP_MESSAGE(AGHFP_AUDIO_CONNECT_CFM);
	message->aghfp = aghfp;
    message->status = status;
	message->cl_status = cl_status;
    message->audio_sink = aghfp->audio_sink;
    message->rx_bandwidth = aghfp->rx_bandwidth;
    message->tx_bandwidth = aghfp->tx_bandwidth;
    message->link_type = aghfp->link_type;
	
    if ((aghfp->use_wbs) && (aghfp->use_codec > 0))
    {
	    message->using_wbs = TRUE;
	    message ->wbs_codec = aghfp->use_codec;
    }
    else
	    message->using_wbs = FALSE;
	
	MessageSend(aghfp->client_task, AGHFP_AUDIO_CONNECT_CFM, message);
}
void aghfpHandleBtrhSetStatusParse(Task task, const struct aghfpHandleBtrhSetStatusParse *data)
{
	MAKE_AGHFP_MESSAGE(AGHFP_INTERNAL_SET_RESPONSE_HOLD_STATUS_REQ);
	message->cmd = data->cmd;
	MessageSend(task, AGHFP_INTERNAL_SET_RESPONSE_HOLD_STATUS_REQ, message);
}
/* HF has sent us AT+BRSF=xxx, informing us of its supported features. Pass this
   message on to the profile handler. */
void aghfpHandleBrsfReqParse(Task task, const struct aghfpHandleBrsfReqParse *data)
{
	MAKE_AGHFP_MESSAGE(AGHFP_INTERNAL_AT_BRSF_REQ);
    message->hf_supported_features = data->supportedFeatures;
    MessageSend(task, AGHFP_INTERNAL_AT_BRSF_REQ, message);
}
/* HS has sent us AT+CKPD=xxx command */
void aghfpHandleCkpdParse(Task task, const struct aghfpHandleCkpdParse *data)
{
	MAKE_AGHFP_MESSAGE(AGHFP_INTERNAL_AT_CKPD_CMD);
    message->keycode = data->keycode;
    MessageSend(task, AGHFP_INTERNAL_AT_CKPD_CMD, message);
}
void aghfpHandleWbsCodecNegotiation(Task task, const struct aghfpHandleWbsCodecNegotiation *codec)
{
	MAKE_AGHFP_MESSAGE(AGHFP_INTERNAL_WBS_CODEC_NEGOTIATE_REQ);
	message->codec_id = codec->codec;
	MessageSend(task, AGHFP_INTERNAL_WBS_CODEC_NEGOTIATE_REQ, message);
}
void aghfpHandleBiaParse(Task task, const struct aghfpHandleBiaParse *data)
{
    struct sequence indicators = data->indicators;
    uint16 i, indicator_idx=0;    
    bool success = TRUE;
    
    MAKE_AGHFP_MESSAGE(AGHFP_INTERNAL_INDICATORS_ACTIVATION_REQ);
    
    /* By default we don't update the indicator state */
    message->service=indicator_ignore;
    message->signal=indicator_ignore;
    message->roam=indicator_ignore;
    message->battchg=indicator_ignore;
    
    AGHFP_DEBUG(("aghfpHandleBiaParse - Parsing\n"));
    
    for(i=0; i<indicators.length; i++)
    {
        AGHFP_DEBUG(("%c", (char)indicators.data[i]));
        if(indicators.data[i] == ',' || indicators.data[i] == ';')
        {
            /* If this is a comma move on (break if more indicators specified than we support) */
            AGHFP_DEBUG(("+ "));
            if(++indicator_idx > 6)
                break;
        }
        else if(indicators.data[i] == ' ' || indicators.data[i] =='\t')
        {
            /* Ignore whitespace */
            AGHFP_DEBUG(("- "));
        }
        else if(indicators.data[i] == '0' || indicators.data[i] == '1')
        {
            AGHFP_DEBUG(("m "));
            
            /* Matched a valid value */
            switch(indicator_idx)
            {
                /* This corresponds to the order we list our indicators to the HF */
                case 0:
                    message->service = indicators.data[i]-0x30;
                break;
                case 4:
                    message->signal = indicators.data[i]-0x30;
                break;
                case 5:
                    message->roam = indicators.data[i]-0x30;
                break;
                case 6:
                    message->battchg = indicators.data[i]-0x30;
                break;
                default:
                    /* Ignore call, call_setup and call_held - always on */
                break;
            }
        }
        else
        {
            /* Improperly formatted command - ERROR */
            success = FALSE;
            break;
        }
    }
    
    if(success)
    {
        AGHFP_DEBUG(("\nOK\n"));
        MessageSend(task, AGHFP_INTERNAL_INDICATORS_ACTIVATION_REQ, message);
    }
    else
    {
        AGHFP_DEBUG(("\nERROR\n"));
        free(message);
        aghfpSendError((AGHFP *)task);
    }
}
void aghfpHandleVgsParse(Task task, const struct aghfpHandleVgsParse *data)
{
	MAKE_AGHFP_MESSAGE(AGHFP_INTERNAL_SYNC_SPEAKER_VOLUME);
	message->volume = data->volume;
	MessageSend(task, AGHFP_INTERNAL_SYNC_SPEAKER_VOLUME, message);
}
void aghfpHandleVgmParse(Task task, const struct aghfpHandleVgmParse *data)
{
	MAKE_AGHFP_MESSAGE(AGHFP_INTERNAL_SYNC_MIC_GAIN);
	message->gain = data->gain;
	MessageSend(task, AGHFP_INTERNAL_SYNC_MIC_GAIN, message);
}