/****************************************************************************
NAME    
    hfpHandleSetActiveIndicatorsReq

DESCRIPTION
    Handle request to set active indicators from the app

AT INDICATION
    +BIA=

RETURNS
    void
*/
void hfpHandleSetActiveIndicatorsReq(hfp_link_data* link)
{
    if(hfpLinkIsHfp106(link))
    {
        static const char atCmd[] = {'A','T','+','B','I','A','='};
        static const char atCmdSeparator[] = {'0',','};
        static const char atEnd[] = {'0','\r','\0'};
        
        /* 'AT+BIA=' takes 7 chars, two chars for each indicator plus one more for '\0' */
        uint16 size_bia = sizeof(atCmd) + (link->ag_supported_indicators.num_indicators * sizeof(atCmdSeparator)) + 1;
        char *bia;
        char *p;
        
        bia = (char*)malloc(size_bia * sizeof(char));
        
        if(bia)
        {
            uint16 i;
            /* Add "AT+BIA=" */
            memmove(bia, atCmd, sizeof(atCmd));
            /* Fill in default value for all indicators "0,"*/
            for(p = bia + sizeof(atCmd); p < bia + size_bia - sizeof(atEnd); p += sizeof(atCmdSeparator))
                memmove(p, atCmdSeparator, sizeof(atCmdSeparator));
            /* Add "0\r\0" */
            memmove(p, atEnd, sizeof(atEnd));
            
            /* set p to point to the first indicator position in the command */
            p = bia + sizeof(atCmd);
            
            /* If app requested to turn indicators off/on update the message with char '0' or '1' */
            hfpUpdateIndicatorsCommand(p, link->ag_supported_indicators.indicator_idxs.service,         theHfp->optional_indicators.service        );
            hfpUpdateIndicatorsCommand(p, link->ag_supported_indicators.indicator_idxs.signal_strength, theHfp->optional_indicators.signal_strength);
            hfpUpdateIndicatorsCommand(p, link->ag_supported_indicators.indicator_idxs.roaming_status,  theHfp->optional_indicators.roaming_status );
            hfpUpdateIndicatorsCommand(p, link->ag_supported_indicators.indicator_idxs.battery_charge,  theHfp->optional_indicators.battery_charge );
            
            /* Make sure mandatory indicators are all on */
            hfpUpdateIndicatorsCommand(p, link->ag_supported_indicators.indicator_idxs.call,             hfp_indicator_on);
            hfpUpdateIndicatorsCommand(p, link->ag_supported_indicators.indicator_idxs.call_setup,       hfp_indicator_on);
            hfpUpdateIndicatorsCommand(p, link->ag_supported_indicators.indicator_idxs.call_hold_status, hfp_indicator_on);
            hfpUpdateIndicatorsCommand(p, link->ag_supported_indicators.indicator_idxs.extra_call_setup, hfp_indicator_on);
            
            /* Make sure any extra indicators the app cares about are on */
            for(i=0; i < link->ag_supported_indicators.num_extra_indicator_idxs; i++)
                hfpUpdateIndicatorsCommand(p, link->ag_supported_indicators.extra_indicator_idxs[i], hfp_indicator_on);
            
            /* Send the command */
            hfpSendAtCmd(link, strlen(bia), bia, hfpBiaCmdPending);
            free(bia);
        }
        else
        {
            HFP_DEBUG(("BIA malloc failed\n")) ;
        }
    }
    else
    {
        /* Skip on the CMEE */
        hfpSendCommonInternalMessage(HFP_INTERNAL_AT_CMEE_REQ, link);
    }
}
/*
	Handle internal Disable Indicators
*/
void hfpCsrMofifyIndicatorsDisableReq(HFP *hfp)
{
	switch (hfp->state)
	{
	case hfpInitialising:
	case hfpReady:
	case hfpSlcConnecting:
		/* SLC not connected, return an error */
		hfpSendCsrModifyIndicatorsCfm(hfp, hfp_csr_no_slc);
		break;
	case hfpSlcConnected:
	case hfpIncomingCallEstablish:
	case hfpOutgoingCallEstablish:
	case hfpOutgoingCallAlerting:
	case hfpActiveCall:
		{
			/* SLC connected, send the command */
			char cmd[20];
				
			/* Create the AT cmd we're sending */
			sprintf(cmd, "AT+CSR=0\r");
		
			/* Send the AT cmd over the air */
			hfpSendAtCmd(&hfp->task, strlen(cmd), cmd);
			break;
		}
	default:
		HFP_DEBUG(("Unknown State [0x%x]\n", hfp->state));
		break;
	}
}
/****************************************************************************
NAME    
    hfpHandleVgsRequest

DESCRIPTION
    Send a volume gain update to the AG.

RETURNS
    void
*/
void hfpHandleVgsRequest(hfp_link_data* link, uint8 gain)
{
    /* Don't send anything to AG if gain already set */
    if(link->at_vol_setting != gain)
    {
        /* Store the latest volume setting requested by the client */
        link->at_vol_setting = (gain > HFP_MAX_GAIN) ? HFP_MAX_GAIN : gain;
        
        /*
            Don't send another AT command if one is pending, the volume is read
            from the link data when the VGS is sent so just updating the volume
            stored in the link is enough. This prevents us from sending AT+VGS 
            to the AG repeatedly for rapid volume changes. 
        */
        if (!link->at_vol_pending)
        {
            char *vgs = "AT+VGS=00\r";
            
            /* Set the pending mask */
            link->at_vol_pending = TRUE;
            
            /* Send the AT cmd over the air */
            hfpSendAtCmd(link, strlen(vgs), vgs, hfpVgsCmdPending);
        }
    }
}
Example #4
0
/****************************************************************************
NAME    
    hfpHandleCmerRequest

DESCRIPTION
    Send AT+CMER to the AG.

RETURNS
    void
*/
static void hfpHandleCmerRequest(hfp_link_data* link)
{
    const char* cmer = "AT+CMER=3, 0, 0, 1\r";

    /* Send the AT cmd over the air */
    hfpSendAtCmd(link, strlen(cmer), cmer, hfpCmerCmdPending);
}
void hfpHandleFeatureNegotiationRes ( HFP * hfp , HFP_INTERNAL_CSR_FEATURE_NEGOTIATION_RES_T * msg )
{
    static const char atCmd[] = {'A','T','+','C','S','R','F','N','=','('};
	static const char atEnd[] = {')','\r'};
	char *atStr;
	uint16 atLen = sizeof(atCmd) + sizeof(atEnd) + 3 ; /*one for the indicator, 1 for the comma, 1 for the value*/ 
	
	atStr = (char*)malloc(atLen);
	
	if (atStr)
	{
		uint16 used = sizeof(atCmd);
		memmove(atStr, atCmd, sizeof(atCmd));
		
        
        used += sprintf(&atStr[used], "%d", msg->indicator);
	
    	atStr[used] = ',';
		used++;
	
    	used += sprintf(&atStr[used], "%d", msg->value);
	
    	memmove(&atStr[used], atEnd, sizeof(atEnd));
		
		used+= sizeof(atEnd) ;

		hfpSendAtCmd(&hfp->task, used, atStr);		
		free(atStr);
	}
	else
	{
	   HFP_DEBUG(("malloc failed\n")) ;
	}
}
Example #6
0
/****************************************************************************
NAME    
    hfpHandleCindReadRequest

DESCRIPTION
    Send AT+CIND? to the AG.

RETURNS
    void
*/
static void hfpHandleCindReadRequest(hfp_link_data* link)
{
    char cind_read[] = "AT+CIND?\r";

    /* Send the AT cmd over the air */
    hfpSendAtCmd(link, stringLen(cind_read), cind_read, hfpCindReadCmdPending);
}
/*
	Handle internal Get SMS request.
*/
void hfpHandleCsrGetSmsReq(HFP *hfp, HFP_INTERNAL_CSR_GET_SMS_REQ_T *msg)
{
	switch (hfp->state)
	{
	case hfpInitialising:
	case hfpReady:
	case hfpSlcConnecting:
		/* SLC not connected, return an error */
		hfpSendCsrSmsCfm(hfp, hfp_csr_no_slc, 0, NULL);
		break;
	case hfpSlcConnected:
	case hfpIncomingCallEstablish:
	case hfpOutgoingCallEstablish:
	case hfpOutgoingCallAlerting:
	case hfpActiveCall:
		{
			/* SLC connected, send the command */
			char cmd[20];
				
			/* Create the AT cmd we're sending */
			sprintf(cmd, "AT+CSRGETSMS=%d\r", msg->index);
		
			/* Send the AT cmd over the air */
			hfpSendAtCmd(&hfp->task, strlen(cmd), cmd);
			break;
		}
	default:
		HFP_DEBUG(("Unknown State [0x%x]\n", hfp->state));
		break;
	}
}
Example #8
0
/****************************************************************************
NAME    
    hfpHandleBacRequest

DESCRIPTION
    Send AT+BAC= to the AG.

RETURNS
    void
*/
void hfpHandleBacRequest(hfp_link_data* link)
{
    /* Safety check against misbehaving AGs; only proceed if the AG supports Codec Negotiation. */
    if(agFeatureEnabled(link, AG_CODEC_NEGOTIATION) && hfFeatureEnabled(HFP_CODEC_NEGOTIATION))
    {
        char   bac_req[20];
        uint16 check_bit;
        
        /* Create a local copy of HF supported codecs */
        hfp_wbs_codec_mask supported_codecs = theHfp->wbs_codec_mask;
        
        /* Start the AT+BAC command */
        uint8  char_idx = sprintf(bac_req, "AT+BAC=");
        
        /* Run through all bits of supported codec mask until no more set */
        for(check_bit=1; supported_codecs > 0; check_bit <<= 1)
        {
            /* Check if bit is set in the codec mask */
            if(supported_codecs & check_bit)
            {
                /* Convert this bit to codec ID and put into AT+BAC */
                char_idx += sprintf(&bac_req[char_idx], "%d,", hfpWbsCodecMaskToCodecId(supported_codecs & check_bit));
           }
            /* Clear this bit in supported codecs */
            supported_codecs &= ~(supported_codecs & check_bit);
        }
        
        /* Replace last ',' with '\r' */
        sprintf(&bac_req[char_idx-1], "\r");
        
        /* Send the AT cmd over the air */
        hfpSendAtCmd(link, char_idx, bac_req, hfpBacCmdPending);
    }
}
/*
	Handle CSR Supported Features request.
*/
void hfpHandleCsrSupportedFeaturesReq(HFP *hfp, HFP_INTERNAL_CSR_SUPPORTED_FEATURES_REQ_T *msg)
{
	switch (hfp->state)
	{
	case hfpInitialising:
	case hfpReady:
	case hfpSlcConnecting:
		/* SLC not connected, return an error */
		hfpSendCsrSupportedFeaturesCfm(hfp, hfp_csr_no_slc, FALSE, FALSE, FALSE, FALSE, FALSE , 0 );
		break;
	case hfpSlcConnected:
	case hfpIncomingCallEstablish:
	case hfpOutgoingCallEstablish:
	case hfpOutgoingCallAlerting:
	case hfpActiveCall:
		{
			/* SLC connected, send the command */
			char cmd[22];
				
			/* Create the AT cmd we're sending */
			sprintf(cmd, "AT+CSRSF=%d,%d,%d,%d,%d,%d\r", (msg->callerName?1:0), (msg->rawText?1:0),
										(msg->smsInd?1:0), (msg->battLevel?1:0), (msg->pwrSource?1:0) , msg->codecs);
										
		
			/* Send the AT cmd over the air */
			hfpSendAtCmd(&hfp->task, strlen(cmd), cmd);
          	hfp->use_csr2csr = TRUE;
            
			break;
		}
	default:
		HFP_DEBUG(("Unknown State [0x%x]\n", hfp->state));
		break;
	}
}
/****************************************************************************
NAME    
    hfpHandleSubscriberNumberGetReq

DESCRIPTION
    Request subscriber number information from the AG.

RETURNS
    void
*/
void hfpHandleSubscriberNumberGetReq(hfp_link_data* link)
{
    char cnum[] = "AT+CNUM\r";

    /* Send the AT cmd over the air */
    hfpSendAtCmd(link, strlen(cnum), cnum, hfpCnumCmdPending);
}
Example #11
0
/****************************************************************************
NAME    
    hfpHandleChldStatusRequest

DESCRIPTION
    Send AT+CHLD=? to the AG.

RETURNS
    void
*/
static void hfpHandleChldStatusRequest(hfp_link_data* link)
{
    const char* chld = "AT+CHLD=?\r";
    
    /* Only send this if both sides support TWC, otherwise SLC is complete */
    if (hfFeatureEnabled(HFP_THREE_WAY_CALLING) && agFeatureEnabled(link, AG_THREE_WAY_CALLING))
        hfpSendAtCmd(link, strlen(chld), chld, hfpChldStatusCmdPending);
}
/****************************************************************************
NAME	
	hfpHandleDtmfRequest

DESCRIPTION
	HAndle a request to send a DTMF tone to the AG.

RETURNS
	void
*/
void hfpHandleDtmfRequest(HFP *hfp, const HFP_INTERNAL_AT_VTS_REQ_T *req)
{
	char dtmf[20];
	sprintf(dtmf, "AT+VTS=%c\r", req->dtmf);

	/* Send the AT cmd over the air */
	hfpSendAtCmd(&hfp->task, strlen(dtmf), dtmf);
}
Example #13
0
/****************************************************************************
NAME    
    hfpHandleBrsfRequest

DESCRIPTION
    Send AT+BRSF to the AG.

RETURNS
    void
*/
void hfpHandleBrsfRequest(hfp_link_data* link)
{
    char brsf[15];

    /* Create the AT cmd we're sending */
    sprintf(brsf, "AT+BRSF=%d\r", theHfp->hf_supported_features);

    /* Send the AT cmd over the air */
    hfpSendAtCmd(link, strlen(brsf), brsf, hfpBrsfCmdPending);
}
/****************************************************************************
NAME    
    hfpSendChldCmd

DESCRIPTION
    Send AT+CHLD=action to the AG. If both AG and HF support ECC then this
    can also be used to send AT+CHLD=action call_idx.

RETURNS
    void
*/
bool hfpSendChldCmd(HFP_INTERNAL_AT_CHLD_REQ_T* req)
{
    hfp_link_data* link    = req->link;
    hfp_chld_action action = req->action;
    uint16 call_idx        = req->index;
    hfp_at_cmd pending_cmd = hfpCmdPending;
    
    char chld[12];
    
    /* Make sure this link is valid and in a valid state for the requested action */
    if(hfpCheckCallActionState(link, action, call_idx, &pending_cmd))
    {
        /* Check HF and AG both support TWC */
        if (hfFeatureEnabled(HFP_THREE_WAY_CALLING) && agFeatureEnabled(link, AG_THREE_WAY_CALLING))
        {
            if(call_idx)
            {
                /* Check HF and AG both support ECC */
                if(hfFeatureEnabled(HFP_ENHANCED_CALL_CONTROL) && agFeatureEnabled(link, AG_ENHANCED_CALL_CONTROL))
                {
                    /* Send ECC CHLD with index */
                    sprintf(chld, "AT+CHLD=%d%d\r", action, call_idx);
                    hfpSendAtCmd(link, strlen(chld), chld, pending_cmd);
                    return TRUE;
                }
            }
            else
            {
                /* Send normal CHLD */
                sprintf(chld, "AT+CHLD=%d\r", action);
                hfpSendAtCmd(link, strlen(chld), chld, pending_cmd);
                return TRUE;
            }
        }
    }
    
    return FALSE;
}
/****************************************************************************
NAME    
    hfpHandleVgsInd

DESCRIPTION
    Send the VGM request to the AG.

RETURNS
    void
*/
void hfpHandleVgmRequest(hfp_link_data* link, uint8 gain)
{
    char vgm[11];

    strcpy(vgm, "AT+VGM=00\r");
    gain = (gain > HFP_MAX_GAIN) ? HFP_MAX_GAIN : gain;
 
    /* Create the AT cmd we're sending */
    vgm[7] = '0' + gain / 10;
    vgm[8] = '0' + gain % 10;
     
    /* Send the AT cmd over the air */
    hfpSendAtCmd(link, strlen(vgm), vgm, hfpCmdPending);
}
/****************************************************************************
NAME	
	hfpHandleNrEcDisable

DESCRIPTION
	Send a request to the AG to disable its Noise Reduction (NR) and Echo
	Cancellation (EC) capabilities.

RETURNS
	void
*/
void hfpHandleNrEcDisable(HFP *hfp)
{
	/* Only send the AT cmd if the AG and HFP support this functionality */
	if ((hfp->agSupportedFeatures & AG_NREC_FUNCTION) &&
		(hfp->hfpSupportedFeatures & HFP_NREC_FUNCTION))
	{
		static const char nrec[] = "AT+NREC=0\r";

		/* Send the AT cmd over the air */
		hfpSendAtCmd(&hfp->task, strlen(nrec), nrec);
	}
	else
		/* Send an error */
		sendNrecCfmToApp(hfp, hfp_fail);
}
/****************************************************************************
NAME    
    hfpHandleCallWaitingNotificationEnable

DESCRIPTION
    Enable call waiting notifications from the AG.

RETURNS
    void
*/
bool hfpHandleCallWaitingNotificationEnable(const HFP_INTERNAL_AT_CCWA_REQ_T *req)
{
    hfp_link_data* link = req->link;
    
    /* Only send this message if the AG and HF support this functionality */
    if (hfFeatureEnabled(HFP_THREE_WAY_CALLING) && agFeatureEnabled(link, AG_THREE_WAY_CALLING))
    {
        /* Send the AT cmd over the air */
        char ccwa_en[11];
        sprintf(ccwa_en, "AT+CCWA=%d\r", req->enable);
        hfpSendAtCmd(link, strlen(ccwa_en), ccwa_en, hfpCcwaCmdPending);
        return TRUE;
    }
    return FALSE;
}
/****************************************************************************
NAME    
    hfpHandleBtrhHoldReq

DESCRIPTION
    Request to AG to perform a response and hold action.

RETURNS
    void
*/
bool hfpHandleBtrhReq(HFP_INTERNAL_AT_BTRH_REQ_T* req)
{
    hfp_link_data*  link   = req->link;
    hfp_btrh_action action = req->action;
    bool action_is_valid   = FALSE;
    hfp_at_cmd pending_cmd = hfpCmdPending;
    
    /* Check action is valid for link */
    switch(action)
    {
        case hfp_hold_incoming_call:
            if(link->ag_call_state == hfp_call_state_incoming)
            {
                pending_cmd = hfpBtrhZeroCmdPending;
                action_is_valid = TRUE;
            }
        break;
        case hfp_accept_held_incoming_call:
            if(link->ag_call_state == hfp_call_state_incoming_held)
            {
                pending_cmd = hfpBtrhOneCmdPending;
                action_is_valid = TRUE;
            }
        break;
        case hfp_reject_held_incoming_call:
            if(link->ag_call_state == hfp_call_state_incoming_held)
            {
                pending_cmd = hfpBtrhTwoCmdPending;
                action_is_valid = TRUE;
            }
        break;
        default:
        break;
    }
    
    if(action_is_valid)
    {
        /* Send the AT command over the air */
        char btrh[11];
        sprintf(btrh, "AT+BTRH=%d\r", action);
        hfpSendAtCmd(link, strlen(btrh), btrh, pending_cmd);
    }

    return action_is_valid;
}
bool hfpHandleCallerIdEnableReq(const HFP_INTERNAL_AT_CLIP_REQ_T *req)
{
    /* Make sure the local device supports caller id */
    if(hfFeatureEnabled(HFP_CLI_PRESENTATION))
    {
        char *caller_id;

        if (req->enable)
            caller_id = "AT+CLIP=1\r";
        else
            caller_id = "AT+CLIP=0\r";

        /* Send the AT cmd over the air */
        hfpSendAtCmd(req->link, strlen(caller_id), caller_id, hfpClipCmdPending);
        return TRUE;
    }
    return FALSE;
}
/*
	Handle CSR Modify Indicators Request
	
	NOTE: If number of valid indicators becomes more than 99, then the size calculation will need to be modified
*/
void hfpHandleCsrModIndsReq(HFP *hfp, HFP_INTERNAL_CSR_MOD_INDS_REQ_T *msg)
{
	static const char atCmd[] = {'A','T','+','C','S','R','='};
	static const char atEnd[] = {'\r'};
	char *atStr;
	uint16 atLen = sizeof(atCmd) + (msg->size_indicators * (3+2+1)) + msg->size_indicators + sizeof(atEnd); /* size = (,) + 2 for ind + 1 for val */ 
	
	atStr = (char*)malloc(atLen);
	
	if (atStr)
	{
		uint16 used = sizeof(atCmd);
		uint16 cnt;
		memmove(atStr, atCmd, sizeof(atCmd));
		
		for (cnt = 0; cnt < msg->size_indicators; cnt++)
		{
			if (cnt > 0)
			{
				atStr[used] = ',';
				used++;
			}
			atStr[used] = '(';
			used++;
			used += sprintf(&atStr[used], "%d", msg->indicators[cnt].indicator);
			atStr[used] = ',';
			used++;
			used += sprintf(&atStr[used], "%d", msg->indicators[cnt].value);
			atStr[used] = ')';
			used++;
			
		}
		memmove(&atStr[used], atEnd, sizeof(atEnd));
		used++;

		hfpSendAtCmd(&hfp->task, used, atStr);		
		free(atStr);
	}
	else
	{
		hfpSendCsrModifyIndicatorsCfm(hfp, hfp_csr_mod_ind_no_mem);
	}
	free(msg->indicators);
}
/*
	Handle CSR Power Source Request
*/
void hfpHandleCsrPowerSourceReq(HFP *hfp, HFP_INTERNAL_CSR_POWER_SOURCE_REQ_T *msg)
{
	if (msg->pwr_status > hfp_csr_pwr_rep_external)
	{
		HFP_DEBUG(("hfpHandleCsrSupportedFeaturesAck : Invalid Power Status parameter\n"));
		return;
	}
	
	switch (hfp->state)
	{
	case hfpInitialising:
	case hfpReady:
	case hfpSlcConnecting:
		/* SLC not connected, Do Nothing */
		break;
	case hfpSlcConnected:
	case hfpIncomingCallEstablish:
	case hfpOutgoingCallEstablish:
	case hfpOutgoingCallAlerting:
	case hfpActiveCall:
		{
			/* SLC connected, send the command */
			char cmd[15];
				
			/* Create the AT cmd we're sending */
			sprintf(cmd, "AT+CSRPWR=%d\r", msg->pwr_status);
		
			/* Send the AT cmd over the air */
			hfpSendAtCmd(&hfp->task, strlen(cmd), cmd);
			break;
		}
	default:
		HFP_DEBUG(("Unknown State [0x%x]\n", hfp->state));
		break;
	}
}
Example #22
0
/****************************************************************************
NAME    
    hfpProfileHandler

DESCRIPTION
    All messages for this profile lib are handled by this function

RETURNS
    void
*/
void hfpProfileHandler(Task task, MessageId id, Message message)
{
    if(!theHfp->initialised)
    {
        /* Initialisation messages */
        if(id >= HFP_MSG_BASE && id < HFP_INTERNAL_TOP)
        {
            switch(id)
            {
                case HFP_INTERNAL_SDP_REGISTER_REQ:
                    PRINT(("HFP_INTERNAL_SDP_REGISTER_REQ\n"));
                    hfpRegisterServiceRecord( ((HFP_INTERNAL_SDP_REGISTER_REQ_T *)message)->service );
                break;
                
                default:
                     /* Panic in debug and ignore in release lib variants */  
                    goto hfp_prim_error;
            }
        }
        else if(id >= CL_MESSAGE_BASE && id < CL_MESSAGE_TOP)
        {
            switch (id)
            {
                case CL_DM_SYNC_REGISTER_CFM:
                    PRINT(("CL_DM_SYNC_REGISTER_CFM\n"));
                    /* Ignore this silently */
                break;
                
                case CL_RFCOMM_REGISTER_CFM:
                    PRINT(("CL_RFCOMM_REGISTER_CFM\n"));
                    hfpInitRfcommRegisterCfm((CL_RFCOMM_REGISTER_CFM_T *) message);
                break;
                
                case CL_SDP_REGISTER_CFM:
                    PRINT(("CL_SDP_REGISTER_CFM\n"));
                    hfpInitSdpRegisterCfm((CL_SDP_REGISTER_CFM_T *) message);
                break;
                
                default:
                     /* Panic in debug and ignore in release lib variants */  
                    goto cl_prim_error;
                break;
            }
        }
        else
        {
            /* Panic in debug and ignore in release lib variants */  
            goto sys_prim_error;
        }
    }
    else
    {
        /* Run time messages */
        if(id == HFP_INTERNAL_SDP_REGISTER_REQ)
        {
            /* 
               This message does not conform to the common structure,
               also its sent from inside the lib only so we know service
               is valid. 
            */
            PRINT(("HFP_INTERNAL_SDP_REGISTER_REQ\n"));
            hfpRegisterServiceRecord( ((HFP_INTERNAL_SDP_REGISTER_REQ_T *)message)->service );
        }
        else if(id >= HFP_MSG_BASE && id < HFP_INTERNAL_TOP)
        {
            hfp_link_data* link = NULL;
            bool success = FALSE;
            
            /* Try and obtain the link for this message */
            if(message)
                link = ((HFP_COMMON_INTERNAL_MESSAGE_T*)message)->link;
            else
                link = hfpGetLinkFromTimeoutMessage(id);
            
            if(link)
            {
                switch(link->ag_slc_state)
                {
                    /* 
                       In theory audio connect should only happen once SLC is complete, 
                       however in practice some AG's will open SCO before completing the
                       SLC so we should be able to handle it. 
                    */
                    case hfp_slc_searching:
                    case hfp_slc_incoming:
                    case hfp_slc_outgoing:
                    case hfp_slc_connected:
                        switch(id)
                        {
                            case HFP_INTERNAL_AUDIO_CONNECT_RES:
                                PRINT(("HFP_INTERNAL_AUDIO_CONNECT_RES\n"));
                                hfpHandleAudioConnectRes((HFP_INTERNAL_AUDIO_CONNECT_RES_T*)message);
                                success = TRUE;
                            break;
                            
                            case HFP_RFCOMM_LINK_LOSS_RECONNECT_LINK_0_IND:
                            case HFP_RFCOMM_LINK_LOSS_RECONNECT_LINK_1_IND:
                                PRINT(("HFP_RFCOMM_LINK_LOSS_RECONNECT\n"));
                                hfpHandleRfcommLinkLossReconnect(link);
                                success = TRUE;
                            break;
                            
                            case HFP_RFCOMM_LINK_LOSS_TIMEOUT_LINK_0_IND:
                            case HFP_RFCOMM_LINK_LOSS_TIMEOUT_LINK_1_IND:
                                PRINT(("HFP_RFCOMM_LINK_LOSS_TIMEOUT\n"));
                                hfpHandleRfcommLinkLossTimeout(link);
                                success = TRUE;
                            break;
                                
                            case HFP_INTERNAL_SLC_DISCONNECT_REQ:
                                PRINT(("HFP_INTERNAL_SLC_DISCONNECT_REQ\n"));
                                hfpHandleDisconnectRequest(link);
                                success = TRUE;
                            break;
                            
                            default:
                            break;
                        }
                    break;
                    
                    /*
                       AT commands/requests that are valid once SLC is completed
                    */
                    case hfp_slc_complete:
                        if(hfpLinkIsHfp(link))
                        {
                            /* Messages valid for HFP in this state */
                            switch(id)
                            {
                                case HFP_INTERNAL_AT_BTRH_STATUS_REQ:
                                    PRINT(("HFP_INTERNAL_AT_BTRH_STATUS_REQ\n"));
                                    hfpHandleBtrhStatusReq(link);
                                    success = TRUE;
                                break;
                                
                                case HFP_INTERNAL_AT_BAC_REQ:
                                    PRINT(("HFP_INTERNAL_AT_BAC_REQ\n"));
                                    /* Only allowed if we are an HFP device */
                                    hfpHandleBacRequest(link);
                                    success = TRUE;
                                break;
                                
                                case HFP_INTERNAL_AT_CLIP_REQ:
                                    PRINT(("HFP_INTERNAL_AT_CLIP_REQ\n"));
                                    success = hfpHandleCallerIdEnableReq((HFP_INTERNAL_AT_CLIP_REQ_T*)message);
                                break;
                        
                                case HFP_INTERNAL_AT_ANSWER_REQ:
                                    PRINT(("HFP_INTERNAL_AT_ANSWER_REQ\n"));
                                    success = hfpHandleAnswerCall((HFP_INTERNAL_AT_ANSWER_REQ_T*)message);
                                break;
                                
                                case HFP_INTERNAL_AT_TERMINATE_REQ:
                                    PRINT(("HFP_INTERNAL_AT_TERMINATE_REQ\n"));
                                    success = hfpHandleTerminateCall(link, hfpChupCmdPending);
                                break;
                                
                                case HFP_INTERNAL_AT_CLCC_REQ:
                                    PRINT(("HFP_INTERNAL_AT_CLCC_REQ\n"));
                                    success = hfpHandleCurrentCallsGetReq(link);
                                break;
                                
                                case HFP_INTERNAL_AT_CHLD_REQ:
                                    PRINT(("HFP_INTERNAL_AT_CHLD_REQ\n"));
                                    success = hfpSendChldCmd((HFP_INTERNAL_AT_CHLD_REQ_T*)message);
                                break;
                                
                                case HFP_INTERNAL_AT_BTRH_REQ:
                                    PRINT(("HFP_INTERNAL_AT_BTRH_REQ\n"));
                                    success = hfpHandleBtrhReq((HFP_INTERNAL_AT_BTRH_REQ_T*)message);
                                break;
                        
                                case HFP_INTERNAL_AT_BLDN_REQ:
                                    PRINT(("HFP_INTERNAL_AT_BLDN_REQ\n"));
                                    hfpHandleLastNumberRedial(link);
                                    success = TRUE;
                                break;
                                
                                case HFP_INTERNAL_AT_ATD_NUMBER_REQ:
                                    PRINT(("HFP_INTERNAL_AT_ATD_NUMBER_REQ\n"));
                                    hfpHandleDialNumberRequest((HFP_INTERNAL_AT_ATD_NUMBER_REQ_T*)message);
                                    success = TRUE;
                                break;
                                
                                case HFP_INTERNAL_AT_ATD_MEMORY_REQ:
                                    PRINT(("HFP_INTERNAL_AT_ATD_MEMORY_REQ\n"));
                                    hfpHandleDialMemoryRequest((HFP_INTERNAL_AT_ATD_MEMORY_REQ_T*)message);
                                    success = TRUE;
                                break;
                                
                                case HFP_INTERNAL_AT_BVRA_REQ:
                                    PRINT(("HFP_INTERNAL_AT_BVRA_REQ\n"));
                                    success = hfpHandleVoiceRecognitionEnable((HFP_INTERNAL_AT_BVRA_REQ_T*)message);
                                break;
                                
                                case HFP_INTERNAL_AT_NREC_REQ:
                                    PRINT(("HFP_INTERNAL_AT_NREC_REQ\n"));
                                    hfpHandleNrEcDisable(link);
                                    success = TRUE;
                                break;
                                
                                case HFP_INTERNAL_AT_BIA_REQ:
                                    PRINT(("HFP_INTERNAL_AT_BIA_REQ\n"));
                                    hfpHandleSetActiveIndicatorsReq(link);
                                    success = TRUE;
                                break;
                                
                                case HFP_INTERNAL_AT_CMEE_REQ:
                                    PRINT(("HFP_INTERNAL_AT_CMEE_REQ\n"));
                                    hfpHandleExtendedErrorReq(link);
                                    success = TRUE;
                                break;
                                
                                case HFP_INTERNAL_AT_CNUM_REQ:
                                    PRINT(("HFP_INTERNAL_AT_CNUM_REQ\n"));
                                    hfpHandleSubscriberNumberGetReq(link);
                                    success = TRUE;
                                break;
                                
                                case HFP_INTERNAL_AT_BINP_REQ:
                                    PRINT(("HFP_INTERNAL_AT_BINP_REQ\n"));
                                    success = hfpHandleGetVoiceTagReq(link);
                                break;
                                
                                case HFP_INTERNAL_AT_VTS_REQ:
                                    PRINT(("HFP_INTERNAL_AT_VTS_REQ\n"));
                                    hfpHandleDtmfRequest((HFP_INTERNAL_AT_VTS_REQ_T*)message);
                                    success = TRUE;
                                break;
                                
                                case HFP_INTERNAL_AT_COPS_REQ:
                                    PRINT(("HFP_INTERNAL_AT_COPS_REQ\n"));
                                    hfpHandleNetworkOperatorReq(link);
                                    success = TRUE;
                                break;
                                
                                case HFP_INTERNAL_AT_CCWA_REQ:
                                    PRINT(("HFP_INTERNAL_AT_CCWA_REQ\n"));
                                    success = hfpHandleCallWaitingNotificationEnable((HFP_INTERNAL_AT_CCWA_REQ_T*)message);
                                break;
                                
                                case HFP_INTERNAL_AT_CMD_REQ:
                                {
                                    HFP_INTERNAL_AT_CMD_REQ_T* req = (HFP_INTERNAL_AT_CMD_REQ_T*)message;
                                    PRINT(("HFP_INTERNAL_AT_CMD_REQ\n"));
                                    if(!req->size_cmd) break;
                                    hfpSendAtCmd(req->link, req->size_cmd, req->cmd, hfpAtCmdPending);
                                    success = TRUE;
                                }
                                break;
                                
                                case HFP_INTERNAL_CSR_SUPPORTED_FEATURES_REQ:
                                    PRINT(("HFP_INTERNAL_CSR_SUPPORTED_FEATURES_REQ\n"));
                                    hfpCsrFeaturesReq(link);
                                    success = TRUE;
                                break;
                                
                                case HFP_INTERNAL_CSR_BATTERY_LEVEL_REQ:
                                    PRINT(("HFP_INTERNAL_CSR_BATTERY_LEVEL_REQ\n"));
                                    hfpCsrFeaturesHandleBatteryLevelReq((HFP_INTERNAL_CSR_BATTERY_LEVEL_REQ_T*)message);
                                    success = TRUE;
                                break;
                                
                                case HFP_INTERNAL_CSR_POWER_SOURCE_REQ:
                                    PRINT(("HFP_INTERNAL_CSR_POWER_SOURCE_REQ\n"));
                                    hfpCsrFeaturesHandlePowerSourceReq((HFP_INTERNAL_CSR_POWER_SOURCE_REQ_T*)message);
                                    success = TRUE;
                                break;
                                
                                case HFP_INTERNAL_CSR_GET_SMS_REQ:
                                    PRINT(("HFP_INTERNAL_CSR_GET_SMS_REQ\n"));
                                    success = hfpHandleCsrGetSmsReq((HFP_INTERNAL_CSR_GET_SMS_REQ_T*)message);
                                break;
                                
                                case HFP_INTERNAL_WAIT_AT_TIMEOUT_LINK_0_IND:
                                case HFP_INTERNAL_WAIT_AT_TIMEOUT_LINK_1_IND:
                                    PRINT(("HFP_INTERNAL_WAIT_AT_TIMEOUT_IND\n"));
                                    hfpHandleWaitAtTimeout(link);
                                    success = TRUE;
                                break;
                                
                                case HFP_INTERNAL_SLC_DISCONNECT_REQ:
                                    PRINT(("HFP_INTERNAL_SLC_DISCONNECT_REQ\n"));
                                    hfpHandleDisconnectRequest(link);
                                    success = TRUE;
                                break;
                        
                                case HFP_INTERNAL_AUDIO_CONNECT_REQ:
                                    PRINT(("HFP_INTERNAL_AUDIO_CONNECT_REQ\n"));
                                    hfpHandleAudioConnectReq((HFP_INTERNAL_AUDIO_CONNECT_REQ_T*)message);
                                    success = TRUE;
                                break;
                        
                                case HFP_INTERNAL_AUDIO_CONNECT_RES:
                                    PRINT(("HFP_INTERNAL_AUDIO_CONNECT_RES\n"));
                                    hfpHandleAudioConnectRes((HFP_INTERNAL_AUDIO_CONNECT_RES_T*)message);
                                    success = TRUE;
                                break;
                        
                                case HFP_INTERNAL_AUDIO_TRANSFER_REQ:
                                    PRINT(("HFP_INTERNAL_AUDIO_TRANSFER_REQ\n"));
                                    hfpHandleAudioTransferReq((HFP_INTERNAL_AUDIO_TRANSFER_REQ_T*)message);
                                    success = TRUE;
                                break;
                                
                                case HFP_INTERNAL_AUDIO_DISCONNECT_REQ:
                                    PRINT(("HFP_INTERNAL_AUDIO_DISCONNECT_REQ\n"));
                                    hfpHandleAudioDisconnectReq(link);
                                    success = TRUE;
                                break;
                                
                                default:
                                break;
                            }
                        }
                        else if(hfpLinkIsHsp(link))
                        {
                            /* Messages valid for HSP in this state */
                            switch(id)
                            {
                                case HFP_INTERNAL_AT_ANSWER_REQ:
                                    PRINT(("HFP_INTERNAL_AT_ANSWER_REQ\n"));
                                    success = hfpHandleAnswerHspCall((HFP_INTERNAL_AT_ANSWER_REQ_T*)message);
                                break;
                                
                                case HFP_INTERNAL_AT_TERMINATE_REQ:
                                    PRINT(("HFP_INTERNAL_AT_TERMINATE_REQ\n"));
                                    success = hfpHandleTerminateHspCall(link);
                                break;
                                
                                case HFP_INTERNAL_AT_BVRA_REQ:
                                    PRINT(("HFP_INTERNAL_AT_BVRA_REQ\n"));
                                    success = hfpHandleHspVoiceRecognitionEnable((HFP_INTERNAL_AT_BVRA_REQ_T*) message);
                                break;
                                
                                case HFP_INTERNAL_AT_CMD_REQ:
                                {
                                    HFP_INTERNAL_AT_CMD_REQ_T* req = (HFP_INTERNAL_AT_CMD_REQ_T*)message;
                                    PRINT(("HFP_INTERNAL_AT_CMD_REQ\n"));
                                    hfpSendAtCmd(req->link, req->size_cmd, req->cmd, hfpAtCmdPending);
                                }
                                break;
                                
                                case HFP_INTERNAL_WAIT_AT_TIMEOUT_LINK_0_IND:
                                case HFP_INTERNAL_WAIT_AT_TIMEOUT_LINK_1_IND:
                                    PRINT(("HFP_INTERNAL_WAIT_AT_TIMEOUT_IND\n"));
                                    hfpHandleWaitAtTimeout(link);
                                    success = TRUE;
                                break;
                                
                                case HFP_INTERNAL_SLC_DISCONNECT_REQ:
                                    PRINT(("HFP_INTERNAL_SLC_DISCONNECT_REQ\n"));
                                    hfpHandleDisconnectRequest(link);
                                    success = TRUE;
                                break;
                        
                                case HFP_INTERNAL_AUDIO_CONNECT_REQ:
                                    PRINT(("HFP_INTERNAL_AUDIO_CONNECT_REQ\n"));
                                    hfpSendHsButtonPress(link, hfpCmdPending);
                                    success = TRUE;
                                break;
                        
                                case HFP_INTERNAL_AUDIO_CONNECT_RES:
                                    PRINT(("HFP_INTERNAL_AUDIO_CONNECT_RES\n"));
                                    hfpHandleAudioConnectRes((HFP_INTERNAL_AUDIO_CONNECT_RES_T*)message);
                                    success = TRUE;
                                break;
                        
                                case HFP_INTERNAL_AUDIO_TRANSFER_REQ:
                                    PRINT(("HFP_INTERNAL_AUDIO_TRANSFER_REQ\n"));
                                    hfpHandleAudioTransferReq((HFP_INTERNAL_AUDIO_TRANSFER_REQ_T*)message);
                                    success = TRUE;
                                break;
                                
                                case HFP_INTERNAL_AUDIO_DISCONNECT_REQ:
                                    PRINT(("HFP_INTERNAL_AUDIO_DISCONNECT_REQ\n"));
                                    hfpHandleAudioDisconnectReq(link);
                                    success = TRUE;
                                break;
                                
                                case HFP_INTERNAL_HS_INCOMING_TIMEOUT_LINK_0_IND:
                                case HFP_INTERNAL_HS_INCOMING_TIMEOUT_LINK_1_IND:
                                    PRINT(("HFP_INTERNAL_HS_INCOMING_TIMEOUT_IND\n"));
                                    hfpHandleCallIncomingTimeout(link);
                                    success = TRUE;
                                break;
                                
                                case HFP_INTERNAL_AT_CKPD_REQ:
                                    PRINT(("HFP_INTERNAL_AT_CKPD_REQ\n"));
                                    hfpSendHsButtonPress(link, hfpCkpdCmdPending);
                                    success = TRUE;
                                break;
                                
                                default:
                                break;
                            }
                        }
                    break;
                    
                    /* 
                       No internal messages valid in these states 
                    */
                    case hfp_slc_idle:
                    case hfp_slc_disabled:
                    default:
                    break;
                }
            }
            
            if(!success)
            {
                MessageId cfm_id = HFP_NO_CFM;
                
                PRINT(("Link %X, SLC state %X\n", (uint16)link, link ? link->ag_slc_state : 0));
                
                /* Either the link is NULL or link state was invalid. */
                switch (id)
                {
                    case HFP_RFCOMM_LINK_LOSS_RECONNECT_LINK_0_IND:
                    case HFP_RFCOMM_LINK_LOSS_RECONNECT_LINK_1_IND:
                        PRINT(("HFP_RFCOMM_LINK_LOSS_RECONNECT\n"));
                        goto hfp_prim_error;
                    break;
                    
                    case HFP_RFCOMM_LINK_LOSS_TIMEOUT_LINK_0_IND:
                    case HFP_RFCOMM_LINK_LOSS_TIMEOUT_LINK_1_IND:
                        PRINT(("HFP_RFCOMM_LINK_LOSS_TIMEOUT\n"));
                        goto hfp_prim_error;
                    break;

                    case HFP_INTERNAL_AT_BAC_REQ:
                        PRINT(("HFP_INTERNAL_AT_BAC_REQ\n"));
                        /* Ignore this silently */
                    break;
                    
                    case HFP_INTERNAL_AT_BTRH_STATUS_REQ:
                        PRINT(("HFP_INTERNAL_AT_BTRH_STATUS_REQ\n"));
                        /* Internal request failed, ignore */
                    break;
                    
                    case HFP_INTERNAL_AT_CLIP_REQ:
                        PRINT(("HFP_INTERNAL_AT_CLIP_REQ\n"));
#ifndef HFP_MIN_CFM
                        cfm_id = HFP_CALLER_ID_ENABLE_CFM;
#endif
                    break;
                    
                    case HFP_INTERNAL_AT_ANSWER_REQ:
                        PRINT(("HFP_INTERNAL_AT_ANSWER_REQ\n"));
#ifndef HFP_MIN_CFM
                        cfm_id = HFP_CALL_ANSWER_CFM;
#endif
                    break;
                    
                    case HFP_INTERNAL_AT_TERMINATE_REQ:
                        PRINT(("HFP_INTERNAL_AT_TERMINATE_REQ\n"));
#ifndef HFP_MIN_CFM
                        cfm_id = hfpHandleChupAtAck(link);
#endif
                    break;
                    
                    case HFP_INTERNAL_AT_BLDN_REQ:
                        PRINT(("HFP_INTERNAL_AT_BLDN_REQ"));
                        cfm_id = HFP_DIAL_LAST_NUMBER_CFM;
                    break;
                    
                    case HFP_INTERNAL_AT_ATD_NUMBER_REQ:
                        PRINT(("HFP_INTERNAL_AT_ATD_NUMBER_REQ"));
                        cfm_id = HFP_DIAL_NUMBER_CFM;
                    break;
                    
                    case HFP_INTERNAL_AT_ATD_MEMORY_REQ:
                        PRINT(("HFP_INTERNAL_AT_ATD_MEMORY_REQ"));
                        cfm_id = HFP_DIAL_MEMORY_CFM;
                    break;
                    
                    case HFP_INTERNAL_AT_BVRA_REQ:
                        PRINT(("HFP_INTERNAL_AT_BVRA_REQ\n"));
                        cfm_id = HFP_VOICE_RECOGNITION_ENABLE_CFM;
                    break;
                    
                    case HFP_INTERNAL_AT_NREC_REQ:
                        PRINT(("HFP_INTERNAL_AT_NREC_REQ\n"));
                        /* Internal request failed, ignore */
                    break;
                    
                    case HFP_INTERNAL_AT_CLCC_REQ:
                        PRINT(("HFP_INTERNAL_AT_CLCC_REQ\n"));
#ifndef HFP_MIN_CFM
                        cfm_id = HFP_CURRENT_CALLS_CFM;
#endif
                    break;
                            
                    case HFP_INTERNAL_AT_CHLD_REQ:
                        PRINT(("HFP_INTERNAL_AT_CHLD_REQ\n"));
                        hfpHandleChldAtAck(link, ((HFP_INTERNAL_AT_CHLD_REQ_T*)message)->action, hfp_fail);
                    break;
                    
                    case HFP_INTERNAL_AT_BTRH_REQ:
                        PRINT(("HFP_INTERNAL_AT_BTRH_REQ\n"));
#ifndef HFP_MIN_CFM
                        hfpHandleBtrhAtAck(link, ((HFP_INTERNAL_AT_BTRH_REQ_T*)message)->action, hfp_fail);
#endif
                    break;
                    
                    case HFP_INTERNAL_AT_BIA_REQ:
                        PRINT(("HFP_INTERNAL_AT_BIA_REQ\n"));
                        /* Internal request failed, ignore */
                    break;
                    
                    case HFP_INTERNAL_AT_CMEE_REQ:
                        PRINT(("HFP_INTERNAL_AT_CMEE_REQ\n"));
                        /* Internal request failed, ignore */
                    break;
                    
                    case HFP_INTERNAL_AT_CNUM_REQ:
                        PRINT(("HFP_INTERNAL_AT_CNUM_REQ\n"));
#ifndef HFP_MIN_CFM
                        cfm_id = HFP_SUBSCRIBER_NUMBERS_CFM;
#endif
                    break;
                    
                    case HFP_INTERNAL_AT_BINP_REQ:
                        PRINT(("HFP_INTERNAL_AT_BINP_REQ\n"));
#ifndef HFP_MIN_CFM
                        cfm_id = HFP_VOICE_TAG_NUMBER_CFM;
#endif
                    break;
                    
                    case HFP_INTERNAL_AT_VTS_REQ:
                        PRINT(("HFP_INTERNAL_AT_VTS_REQ\n"));
#ifndef HFP_MIN_CFM
                        cfm_id = HFP_DTMF_CFM;
#endif
                    break;
                    
                    case HFP_INTERNAL_AT_COPS_REQ:
                        PRINT(("HFP_INTERNAL_AT_COPS_REQ\n"));
#ifndef HFP_MIN_CFM
                        cfm_id = HFP_NETWORK_OPERATOR_CFM;
#endif
                    break;
                    
                    case HFP_INTERNAL_AT_CCWA_REQ:
                        PRINT(("HFP_INTERNAL_AT_CCWA_REQ\n"));
#ifndef HFP_MIN_CFM
                        cfm_id = HFP_CALL_WAITING_ENABLE_CFM;
#endif
                    break;
                    
                    case HFP_INTERNAL_AT_CMD_REQ:
                        PRINT(("HFP_INTERNAL_AT_CMD_REQ\n"));
#ifndef HFP_MIN_CFM
                        cfm_id = HFP_AT_CMD_CFM;
#endif
                    break;
                    
                    case HFP_INTERNAL_CSR_SUPPORTED_FEATURES_REQ:
                        PRINT(("HFP_INTERNAL_CSR_SUPPORTED_FEATURES_REQ\n"));
                        hfpCsrFeaturesHandleCsrSfAtAck(link, hfp_fail);
                    break;
                    
                    case HFP_INTERNAL_CSR_BATTERY_LEVEL_REQ:
                        PRINT(("HFP_INTERNAL_CSR_BATTERY_LEVEL_REQ\n"));
                        /* No notification for app so ignore this */
                    break;
                    
                    case HFP_INTERNAL_CSR_POWER_SOURCE_REQ:
                        PRINT(("HFP_INTERNAL_CSR_POWER_SOURCE_REQ\n"));
                        /* No notification for app so ignore this */
                    break;
                    
                    case HFP_INTERNAL_CSR_GET_SMS_REQ:
                        PRINT(("HFP_INTERNAL_CSR_GET_SMS_REQ\n"));
                        hfpCsrFeaturesHandleGetSmsAtAck(link, hfp_fail);
                    break;
                    
                    case HFP_INTERNAL_WAIT_AT_TIMEOUT_LINK_0_IND:
                    case HFP_INTERNAL_WAIT_AT_TIMEOUT_LINK_1_IND:
                        PRINT(("HFP_INTERNAL_WAIT_AT_TIMEOUT_IND\n"));
                        /* Timeout on a link we don't recognise */
                        goto hfp_prim_error;
                    break;
                    
                    case HFP_INTERNAL_SLC_DISCONNECT_REQ:
                        PRINT(("HFP_INTERNAL_SLC_DISCONNECT_REQ\n"));
                        /* Disconnect request on invalid link/link with no SLC */
                        hfpSendSlcDisconnectIndToApp(link, hfp_disconnect_no_slc);
                    break;
                    
                    case HFP_INTERNAL_AUDIO_CONNECT_REQ:
                        PRINT(("HFP_INTERNAL_AUDIO_CONNECT_REQ\n"));
                        sendAudioConnectCfmFailToApp(link, hfp_audio_connect_error);
                    break;
                    
                    case HFP_INTERNAL_AUDIO_CONNECT_RES:
                        PRINT(("HFP_INTERNAL_AUDIO_CONNECT_RES\n"));
                        sendAudioConnectCfmFailToApp(link, hfp_audio_connect_error);
                    break;
                    
                    case HFP_INTERNAL_AUDIO_DISCONNECT_REQ:
                        PRINT(("HFP_INTERNAL_AUDIO_DISCONNECT_REQ\n"));
                        sendAudioDisconnectIndToApp(link, hfp_audio_disconnect_error);
                    break;
                    
                    case HFP_INTERNAL_AUDIO_TRANSFER_REQ:
                        PRINT(("HFP_INTERNAL_AUDIO_TRANSFER_REQ\n"));
                        /* What fail message we send depends on the direction requested */
                        switch(((HFP_INTERNAL_AUDIO_TRANSFER_REQ_T*)message)->direction)
                        {
                            case hfp_audio_to_hfp:
                                sendAudioConnectCfmFailToApp(link, hfp_audio_connect_error);
                                break;

                            case hfp_audio_to_ag:
                                sendAudioDisconnectIndToApp(link, hfp_audio_disconnect_error);
                            break;

                            case hfp_audio_transfer:
                                if (link && link->audio_sink)
                                    sendAudioDisconnectIndToApp(link, hfp_audio_disconnect_error);
                                else
                                    sendAudioConnectCfmFailToApp(link, hfp_audio_connect_error);
                            break;
                        }
                    break;
                    
                    case HFP_INTERNAL_HS_INCOMING_TIMEOUT_LINK_0_IND:
                    case HFP_INTERNAL_HS_INCOMING_TIMEOUT_LINK_1_IND:
                        PRINT(("HFP_INTERNAL_HS_INCOMING_TIMEOUT_IND\n"));
                        /* SLC has closed before the incoming timeout fired */
                        goto hfp_prim_error;
                    break;
                    
                    case HFP_INTERNAL_AT_CKPD_REQ:
                        PRINT(("HFP_INTERNAL_AT_CKPD_REQ\n"));
#ifndef HFP_MIN_CFM
                        cfm_id = HFP_HS_BUTTON_PRESS_CFM;
#endif
                    break;
                    
                    default:
                        /* Panic in debug and ignore in release lib variants */  
                        goto hfp_prim_error;
                    break;
                }
                
                /* Send _CFM message to app if necessary */
                if(cfm_id) hfpSendCommonCfmMessageToApp(cfm_id, link, hfp_fail);
            }
        }
        else if(id >= CL_MESSAGE_BASE && id < CL_MESSAGE_TOP)
        {
            switch(id)
            {
                case CL_RFCOMM_REGISTER_CFM:
                    PRINT(("CL_RFCOMM_REGISTER_CFM\n"));
                    goto cl_prim_error;
                break;

                case CL_RFCOMM_CONNECT_IND:
                    PRINT(("CL_RFCOMM_CONNECT_IND\n"));
                    /* Handle the connect cfm */
                    hfpHandleRfcommConnectInd((CL_RFCOMM_CONNECT_IND_T *) message);
                break;
                
                case CL_RFCOMM_CLIENT_CONNECT_CFM:
                    PRINT(("CL_RFCOMM_CLIENT_CONNECT_CFM\n"));
                    hfpHandleRfcommClientConnectCfm((CL_RFCOMM_CLIENT_CONNECT_CFM_T *) message);
                break;
                
                case CL_RFCOMM_SERVER_CONNECT_CFM:
                    PRINT(("CL_RFCOMM_SERVER_CONNECT_CFM\n"));
                    hfpHandleRfcommServerConnectCfm((CL_RFCOMM_SERVER_CONNECT_CFM_T *) message);
                break;
                
                case CL_RFCOMM_DISCONNECT_IND:
                    PRINT(("CL_RFCOMM_DISCONNECT_IND\n"));
                    hfpHandleRfcommDisconnectInd((CL_RFCOMM_DISCONNECT_IND_T *) message);
                break;
                
                case CL_RFCOMM_DISCONNECT_CFM:
                    PRINT(("CL_RFCOMM_DISCONNECT_CFM\n"));
                    hfpHandleRfcommDisconnectCfm((CL_RFCOMM_DISCONNECT_CFM_T *) message);
                break;

                case CL_SDP_REGISTER_CFM:
                    PRINT(("CL_SDP_REGISTER_CFM\n"));
                    hfpHandleSdpRegisterCfm((CL_SDP_REGISTER_CFM_T *) message);
                break;

                case CL_SDP_UNREGISTER_CFM:
                    PRINT(("CL_SDP_UNREGISTER_CFM\n"));
                    handleSdpUnregisterCfm((CL_SDP_UNREGISTER_CFM_T *) message);
                break;

                case CL_SDP_SERVICE_SEARCH_ATTRIBUTE_CFM:
                    PRINT(("CL_SDP_SERVICE_SEARCH_ATTRIBUTE_CFM\n"));
                    /* Currently we only look for attributes during SLC establishment and connection */
                    hfpHandleServiceSearchAttributeCfm((CL_SDP_SERVICE_SEARCH_ATTRIBUTE_CFM_T *) message);
                break;

                case CL_DM_SYNC_CONNECT_IND:
                    PRINT(("CL_DM_SYNC_CONNECT_IND\n"));
                    hfpHandleSyncConnectInd((CL_DM_SYNC_CONNECT_IND_T*)message);
                break;

                case CL_DM_SYNC_CONNECT_CFM:
                    PRINT(("CL_DM_SYNC_CONNECT_CFM\n"));
                    hfpHandleSyncConnectCfm((CL_DM_SYNC_CONNECT_CFM_T*)message);
                break;
                
                case CL_DM_SYNC_DISCONNECT_IND:
                    PRINT(("CL_DM_SYNC_DISCONNECT_IND\n"));
                    hfpHandleSyncDisconnectInd((CL_DM_SYNC_DISCONNECT_IND_T*)message);
                break;

                case CL_RFCOMM_PORTNEG_IND:
                {
                    PRINT(("CL_RFCOMM_PORTNEG_IND\n"));
                    hfpHandleRfcommPortnegInd((CL_RFCOMM_PORTNEG_IND_T*)message);
                }
                break;
                
                case CL_RFCOMM_PORTNEG_CFM:
                case CL_RFCOMM_CONTROL_IND:
                case CL_RFCOMM_CONTROL_CFM:
                case CL_RFCOMM_LINE_STATUS_IND:
                case CL_DM_ROLE_CFM:
                case CL_DM_SYNC_REGISTER_CFM:
                case CL_SM_ENCRYPTION_CHANGE_IND:
                case CL_SM_ENCRYPTION_KEY_REFRESH_IND:
                    /* Silently ignore these */
                break;
                
                default:
                    /* Panic in debug and ignore in release lib variants */  
                    goto cl_prim_error;
                break;
            }
        }
        else
        {
            switch(id)
            {
                case MESSAGE_MORE_DATA:
                {
                    PRINT(("MESSAGE_MORE_DATA"));
                    /* We have received more data into the RFCOMM buffer */
                    hfpHandleReceivedData(((MessageMoreData *) message)->source);
                    PRINT(("\n"));
                }
                break;
                
                case MESSAGE_MORE_SPACE:
                case MESSAGE_SOURCE_EMPTY:
                case MESSAGE_STREAM_DISCONNECT:
                    /* Silently ignore these */
                    break;
                
                default:
                    /* Panic in debug and ignore in release lib variants */    
                    goto sys_prim_error;
                break;
            }
        }
    }
    return;
    
    sys_prim_error:
    handleUnexpected(hfpUnexpectedMessage, id);
    return;
    
    cl_prim_error:
    handleUnexpected(hfpUnexpectedClPrim, id);
    return;

    hfp_prim_error:
    handleUnexpected(hfpUnexpectedHfpPrim, id);
    return;

}
/****************************************************************************
NAME    
    hfpHandleBtrhStatusReq

DESCRIPTION
    Request response hold status from the AG.

RETURNS
    void
*/
void hfpHandleBtrhStatusReq(hfp_link_data* link)
{
    /* Send the AT cmd over the air */
    char btrh[] = "AT+BTRH?\r";
    hfpSendAtCmd(link, strlen(btrh), btrh, hfpBtrhStatusCmdPending);
}
Example #24
0
/****************************************************************************
NAME    
    hfpHandleCindTestRequest

DESCRIPTION
    Send AT+CIND=? to the AG.

RETURNS
    void
*/
static void hfpHandleCindTestRequest(hfp_link_data* link)
{
    /* Send the AT cmd over the air */
    char cind_test[] = "AT+CIND=?\r";
    hfpSendAtCmd(link, stringLen(cind_test), cind_test, hfpCindTestCmdPending);
}