예제 #1
0
/****************************************************************************
 Outcome of the RFCOMM connect request or response.
*/
static void aghfpHandleRfcommConnectCfm(AGHFP *aghfp, rfcomm_connect_status status)
{
    /* Check the status of the rfcomm connect cfm */
    if (status == rfcomm_connect_success)
    {
        /* RFCOMM connection is up! Check which profile is supported by this task */
        if (supportedProfileIsHsp(aghfp->supported_profile))
        {
            /* HSP supported - SLC is up so tell the app */
   			aghfpSendSlcConnectCfmToApp(aghfp_connect_success, aghfp);
        }
        else if (supportedProfileIsHfp(aghfp->supported_profile))
        {
            /* HFP supported - RFCOMM is up, so just wait for HF to send us some AT commends */
        }
        else
        {
            /* This should never happen */
            AGHFP_DEBUG_PANIC(("Unhandled profile type 0x%x\n", aghfp->supported_profile));
        }

  		/* Check for data in the buffer */
  		aghfpHandleReceivedData(aghfp, StreamSourceFromSink(aghfp->rfcomm_sink));
    }
    else
    {
        /* RFCOMM connect failed - Tell the app. */
        aghfpSendSlcConnectCfmToApp(convertRfcommConnectStatus(status), aghfp);
    }
	
	aghfp->rfcomm_lock = FALSE;
}
예제 #2
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);
	}
}
예제 #3
0
/****************************************************************************
NAME	
	hfpHandleRfcommConnectCfm

DESCRIPTION
	Outcome of the RFCOMM connect request or response.

RETURNS
	void
*/
void hfpHandleRfcommConnectCfm(HFP *hfp, const CL_RFCOMM_CONNECT_CFM_T *cfm)
{
    /* Check the status of the rfcomm connect cfm */
    if (cfm->status == rfcomm_connect_success)
    {
		/* Store the sink */
		hfp->sink = cfm->sink;

        /* RFCOMM connection is up! Check which profile is supported by this task */
        if (supportedProfileIsHsp(hfp->hfpSupportedProfile))
        {
	        hfp->agSupportedProfile = hfp_headset_profile;
	        
            /* HSP supported - SLC is up so tell the app */
            hfpSendSlcConnectCfmToApp(hfp_connect_success, hfp);
        }
        else if (supportedProfileIsHfp(hfp->hfpSupportedProfile))
        {
            /* Initiate SLC establishment */
			MessageSend(&hfp->task, HFP_INTERNAL_AT_BRSF_REQ, 0);
        }
        else
        {
            /* This should never happen */
            HFP_DEBUG(("Unhandled profile type 0x%x\n", hfp->hfpSupportedProfile));
        }

		/* Check for data in the buffer */
		hfpHandleReceivedData(hfp, StreamSourceFromSink(cfm->sink));
    }
    else
    {
        /* RFCOMM connect failed - Tell the app. */
        hfpSendSlcConnectCfmToApp(convertRfcommConnectStatus(cfm->status), hfp);
    }
	
	/* Free the rfcomm lock */
	hfp->rfcomm_lock = FALSE;
}
예제 #4
0
/****************************************************************************
 Initiate a service search to get the rfcomm server channel of the
 required service on the remote device. We need this before we can
 initiate a service level connection.
*/
void aghfpGetProfileServerChannel(AGHFP *aghfp, const bdaddr *addr)
{
	uint16 sp_len;
	uint8 *sp_ptr;

	sp_len = 0;
	sp_ptr = 0;

	/* Check which profile we support so we can device which search to use */
	if (supportedProfileIsHsp(aghfp->supported_profile))
	{
		/* This task supports the HSP */
		sp_ptr = (uint8 *) HspServiceRequest;
		sp_len = sizeof(HspServiceRequest);
	}
	else if (supportedProfileIsHfp(aghfp->supported_profile))
	{
		/* This task supports the HFP */
		sp_ptr = (uint8 *)HfpServiceRequest;
		sp_len = sizeof(HfpServiceRequest);
	}
	else
	{
		/* This should never happen */
		Panic();
	}

	/*  Issue the search request to the connection lib. The max number of attribute bytes
	is set to an arbitrary number, however the aim is to set it to a value so that
	if the remote end returns this many bytes we still have a block big enough to
	copy the data into.
	*/
	ConnectionSdpServiceSearchAttributeRequest(
		&aghfp->task, addr, 0x32,
        sp_len, sp_ptr,
        sizeof(protocolAttributeRequest),
        protocolAttributeRequest);
}
예제 #5
0
/****************************************************************************
NAME    
    hfpRegisterServiceRecord

DESCRIPTION
    Register the service record corresponding to the specified service

RETURNS
    void
*/
void hfpRegisterServiceRecord(hfp_service_data* service)
{
    /* Ignore this silently if service is already registered */
    if(service->sdp_record_handle == 0 && !hfpGetVisibleServiceFromProfile(service->profile))
    {
        if(!theHfp->busy_channel)
        {
            const uint8* service_record      = NULL;
            uint16       size_service_record = 0;
            
            theHfp->busy_channel  = service->rfc_server_channel;
            
            /* Create a copy of the service record that we can modify */
            if (supportedProfileIsHsp(service->profile))
            {
                size_service_record = sizeof(hsp_service_record);
                
                /* If RFC channel matches use a constant record */
                if(service->rfc_server_channel == HSP_DEFAULT_CHANNEL)
                    service_record = hsp_service_record;
                else if(service->rfc_server_channel == HSP_DEFAULT_CHANNEL_2)
                    service_record = hsp_service_record_2;
                else
                    service_record = hfpSdpHspRecordCreate(service->rfc_server_channel);
            }
            else if (supportedProfileIsHfp(service->profile))
            {
                uint16 features = BRSF_BITMAP_TO_SDP_BITMAP(theHfp->hf_supported_features);
                uint16 version = supportedProfileIsHfp106(service->profile) ? HFP_1_6_VERSION_NUMBER : HFP_1_5_VERSION_NUMBER;
                
                size_service_record = sizeof(hfp_service_record);
                
                /* If features, version and RFC channel match use a constant record */
                if(features == HFP_DEFAULT_FEATURES && version == HFP_DEFAULT_VERSION)
                {
                    if(service->rfc_server_channel == HFP_DEFAULT_CHANNEL)
                        service_record = hfp_service_record;
                    else if(service->rfc_server_channel == HFP_DEFAULT_CHANNEL_2)
                        service_record = hfp_service_record_2;
                }
                
                /* Something didn't match, use a dynamic record */
                if(!service_record)
                    service_record = hfpSdpRecordCreate(service->rfc_server_channel, version, features);
            }
            else
            {
                /* If this is going to fail it will be during init, send init fail */
                hfpInitSdpRegisterComplete(hfp_fail);
                return;
            }
            
            /* Send the service record to the connection lib to be registered with BlueStack */
            ConnectionRegisterServiceRecord(&theHfp->task, size_service_record, service_record);
        }
        else
        {
            /* Queue registering this service */
            MAKE_HFP_MESSAGE(HFP_INTERNAL_SDP_REGISTER_REQ);
            message->service = service;
            MessageSendConditionally(&theHfp->task, HFP_INTERNAL_SDP_REGISTER_REQ, message, (uint16*)&theHfp->busy_channel);
        }
    }
    else if(!theHfp->initialised && service == HFP_SERVICE_TOP)
    {
        /* Make sure we complete init if we're not registering the top service */
        theHfp->busy_channel = service->rfc_server_channel;
        hfpInitSdpRegisterComplete(hfp_success);
    }
}
static void handleAghfpMessages(Task task, MessageId id, Message message)
{
	AGHFP *aghfp = (AGHFP *) task;
	aghfp_state profileState = aghfp->state;

	switch(id)
	{
		/*************************************************************************/
		/* Init messages                                                         */
		/*************************************************************************/



		case AGHFP_INTERNAL_INIT_REQ:
			PRINT(("AGHFP_INTERNAL_INIT_REQ\n"));

			switch(profileState)
			{
				case aghfp_initialising:
					aghfpHandleInternalInitReq(aghfp);
					break;
				default:
					handleUnexpected(aghfpUnexpectedAghfpPrim, profileState, id);
					break;
			}
			break;

		case AGHFP_INTERNAL_INIT_CFM:
			PRINT(("AGHFP_INTERNAL_INIT_CFM\n"));

			switch(profileState)
			{
				case aghfp_initialising:
					aghfpHandleInternalInitCfm(aghfp, (AGHFP_INTERNAL_INIT_CFM_T *) message);
					break;
				default:
					handleUnexpected(aghfpUnexpectedAghfpPrim, profileState, id);
					break;
			}
			break;

		/*************************************************************************/
		/* SDP Messages                                                          */
		/*************************************************************************/

		case AGHFP_INTERNAL_SDP_REGISTER_CFM:
			PRINT(("AGHFP_INTERNAL_SDP_REGISTER_CFM\n"));

			switch(profileState)
			{
				case aghfp_initialising:
					aghfpHandleSdpInternalRegisterInit(aghfp, (AGHFP_INTERNAL_SDP_REGISTER_CFM_T *) message);
					break;
				case aghfp_ready:
					aghfpHandleSdpInternalRegisterCfm((AGHFP_INTERNAL_SDP_REGISTER_CFM_T *) message);
					break;
				default:
					handleUnexpected(aghfpUnexpectedAghfpPrim, profileState, id);
					break;
			}
			break;

		/*************************************************************************/
		/* SLC Messages                                                          */
		/*************************************************************************/

		case AGHFP_INTERNAL_SLC_CONNECT_REQ:
			PRINT(("AGHFP_INTERNAL_SLC_CONNECT_REQ\n"));

			switch(profileState)
			{
				case aghfp_ready:
					aghfpHandleSlcConnectRequest(aghfp, (AGHFP_INTERNAL_SLC_CONNECT_REQ_T *) message);
					break;

				case aghfp_slc_connecting:
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
					/*  If this profile instance is already connecting/connected then
					reject the SLC connect request and inform the app. */
					aghfpSendSlcConnectCfmToApp(aghfp_connect_failed_busy, aghfp);
					break;

				default:
					handleUnexpected(aghfpUnexpectedAghfpPrim, profileState, id);
					break;
			}
			break;

		case AGHFP_INTERNAL_SLC_CONNECT_RES:
			PRINT(("AGHFP_INTERNAL_SLC_CONNECT_RES\n"));

			switch(profileState)
			{
				case aghfp_slc_connecting:
					aghfpHandleSlcConnectResponse(aghfp, (AGHFP_INTERNAL_SLC_CONNECT_RES_T *) message);
					break;

				case aghfp_ready:
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
					/*  If the app is sending us an SLC connect response when we're not
					connecting then send it an error message since we currently don't
					have an SLC being established. */
					aghfpSendSlcConnectCfmToApp(aghfp_connect_failed_busy, aghfp);
					break;

				default:
					handleUnexpected(aghfpUnexpectedAghfpPrim, profileState, id);
					break;
			}
			break;

		case AGHFP_INTERNAL_RFCOMM_CONNECT_REQ:
			PRINT(("AGHFP_INTERNAL_RFCOMM_CONNECT_REQ\n"));

			switch(profileState)
			{
				case aghfp_slc_connecting:
					aghfpHandleRfcommConnectRequest(aghfp, (AGHFP_INTERNAL_RFCOMM_CONNECT_REQ_T *) message);
					break;
				default:
					/* Something wrong, this message is sent internally from the AGHFP */
					handleUnexpected(aghfpUnexpectedAghfpPrim, profileState, id);
					break;
			}
			break;

		case AGHFP_INTERNAL_SLC_DISCONNECT_REQ:
			PRINT(("AGHFP_INTERNAL_SLC_DISCONNECT_REQ"));

			switch(profileState)
			{
				case aghfp_slc_connecting:
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
                case aghfp_active_call:				
					aghfpHandleSlcDisconnect(aghfp);
					break;
				case aghfp_ready:
					/* Send disconnect message with error - nothing to disconnect */
					aghfpHandleDisconnectRequestFail(aghfp);
					break;
                case aghfp_initialising:
				default:
					handleUnexpected(aghfpUnexpectedAghfpPrim, profileState, id);
					break;
			}
			break;


		/*************************************************************************/
		/* AT Messages                                                           */
		/*************************************************************************/

		case AGHFP_INTERNAL_AT_CKPD_CMD:
			PRINT(("AGHFP_INTERNAL_AT_CKPD_CMD\n"));

			switch(profileState)
			{
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
				case aghfp_active_call:
					aghfpHandleKeypadCommand(aghfp, ((AGHFP_INTERNAL_AT_CKPD_CMD_T*)message)->keycode);
					break;
				default:
					aghfpSendError(aghfp);
					break;
			}
			break;
			
		case AGHFP_INTERNAL_AT_BRSF_REQ:
			PRINT(("AGHFP_INTERNAL_AT_BRSF_REQ\n"));

			switch(profileState)
			{
				case aghfp_slc_connecting:
				{
					uint16 hf_supported_features = ((AGHFP_INTERNAL_AT_BRSF_REQ_T *)message)->hf_supported_features;

					/* Only allowed if we are an HFP device */
					if (!supportedProfileIsHfp(aghfp->supported_profile)) Panic();

					aghfpHandleBrsfRequest(aghfp, hf_supported_features);
					break;
				}
				default:
					aghfpSendError(aghfp);
					break;
			}
			break;

		case AGHFP_INTERNAL_AT_CIND_SUPPORTED_REQ:
			PRINT(("AGHFP_INTERNAL_AT_CIND_SUPPORTED_REQ\n"));

			switch(profileState)
			{
				case aghfp_slc_connecting:
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
				case aghfp_active_call:
					/* Only allowed if we are an HFP device */
					if (!supportedProfileIsHfp(aghfp->supported_profile)) Panic();
					aghfpHandleCindSupportedRequest(aghfp);
					break;
				default:
					aghfpSendError(aghfp);
					break;
			}
			break;

		case AGHFP_INTERNAL_AT_CIND_STATUS_REQ:
			PRINT(("AGHFP_INTERNAL_AT_CIND_STATUS_REQ\n"));

			switch(profileState)
			{
				case aghfp_slc_connecting:
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
				case aghfp_active_call:
					/* Only allowed if we are an HFP device */
					if (!supportedProfileIsHfp(aghfp->supported_profile)) Panic();
					aghfpHandleCindStatusRequest(aghfp);
					break;
				default:
					aghfpSendError(aghfp);
					break;
			}
			break;

		case AGHFP_INTERNAL_AT_CMER_REQ:
			PRINT(("AGHFP_INTERNAL_AT_CMER_REQ\n"));

			switch(profileState)
			{
				case aghfp_slc_connecting:
				{
					AGHFP_INTERNAL_AT_CMER_REQ_T *data = (AGHFP_INTERNAL_AT_CMER_REQ_T *)message;

					/* Only allowed if we are an HFP device */
					if (!supportedProfileIsHfp(aghfp->supported_profile)) Panic();

					aghfpHandleCmerRequest(aghfp, data->mode, data->ind);
					break;
				}
				default:
					aghfpSendError(aghfp);
					break;
			}
			break;

		case AGHFP_INTERNAL_CALL_HOLD_SUPPORT_REQ: /* HF sent AT+CHLD=? query */
			PRINT(("AGHFP_INTERNAL_CALL_HOLD_SUPPORT_REQ\n"));

			switch(profileState)
			{
				case aghfp_slc_connecting:
					/* Only allowed if we are an HFP device */
					if (!supportedProfileIsHfp(aghfp->supported_profile)) Panic();
					aghfpHandleCallHoldSupportRequest(aghfp);
					break;
				default:
					aghfpSendError(aghfp);
					break;
			}
			break;

		case AGHFP_INTERNAL_CALL_HOLD_REQ: /* HF sent AT+CHLD=<action>[<idx>] instruction */
		{
    		AGHFP_INTERNAL_CALL_HOLD_REQ_T *msg = (AGHFP_INTERNAL_CALL_HOLD_REQ_T *)message;
			PRINT(("AGHFP_INTERNAL_CALL_HOLD_REQ\n"));

			switch(profileState)
			{
				case aghfp_active_call:
					aghfpHandleCallHoldReq(aghfp, msg->action, msg->index);
					break;
				default:
					aghfpSendError(aghfp);
					break;
			}

			break;
		}

		case AGHFP_INTERNAL_ANSWER_REQ: /* HF wants to answer the call */
			PRINT(("AGHFP_INTERNAL_ANSWER_REQ\n"));

			switch(profileState)
			{
				case aghfp_incoming_call_establish:
#if 0	/* Always pass notification to app and let it call AghfpCallAnswer() */						
					if ( aghfpCallManagerActive(aghfp) )
					{
						aghfpSendOk(aghfp);
						aghfpManageCall(aghfp, CallEventAnswer, CallFlagOpenAudio);
					}
					else
#endif
					{
						aghfpHandleAnswer(aghfp);
					}
					break;
				default:
					aghfpSendError(aghfp);
					break;
			}
			break;

		case AGHFP_INTERNAL_CALLER_ID_SETUP_REQ: /* HF wants to enable/disable caller ID notification */
			PRINT(("AGHFP_INTERNAL_CALLER_ID_REQ\n"));

			switch(profileState)
			{
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
				case aghfp_active_call:
					aghfpHandleCallerIdSetupReq(aghfp, ((AGHFP_INTERNAL_CALLER_ID_SETUP_REQ_T*)message)->state);
					break;
				default:
					aghfpSendError(aghfp);
					break;
			}
			break;

		case AGHFP_INTERNAL_CALL_WAITING_SETUP_REQ: /* HF wants to enable/disable call waiting notification */
			PRINT(("AGHFP_INTERNAL_CALL_WAITING_REQ\n"));

			switch(profileState)
			{
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
				case aghfp_active_call:
					aghfpHandleCallWaitingSetupReq(aghfp, ((AGHFP_INTERNAL_CALL_WAITING_SETUP_REQ_T*)message)->state);
					break;
				default:
					aghfpSendError(aghfp);
					break;
			}
			break;

		case AGHFP_INTERNAL_CALL_HANG_UP_REQ: /* HF wants to reject incoming call */
			PRINT(("AGHFP_INTERNAL_CALL_HANG_UP_REQ\n"));

			switch(profileState)
			{
				case aghfp_incoming_call_establish:
                case aghfp_outgoing_call_establish:
				case aghfp_active_call:
#if 0	/* Always pass notification up to app and let it call AghfpCallTerminate() */
					if ( aghfpCallManagerActive(aghfp) )
					{
						aghfpSendOk(aghfp);
						aghfpManageCall(aghfp, CallEventTerminate, CallFlagCloseAudio);
					}
					else
#endif
					{
						aghfpHandleCallHangUpReq(aghfp);
					}
					break;
				default:
					aghfpSendError(aghfp);
					break;
			}
			break;

		case AGHFP_INTERNAL_DIAL_REQ: /* HF wants to dial a number */
			PRINT (("AGHFP_INTERNAL_DIAL_REQ\n"));

			switch(profileState)
			{
				case aghfp_slc_connected:
				case aghfp_active_call:
				{
					AGHFP_INTERNAL_DIAL_REQ_T *data = (AGHFP_INTERNAL_DIAL_REQ_T*)message;
					aghfpHandleDialReq(aghfp, data->number, data->size_number);
					break;
				}
				default:
					aghfpSendError(aghfp);
					break;
			}
			break;

		case AGHFP_INTERNAL_MEMORY_DIAL_REQ: /* HF wants to dial a number from the AG's phonebook */
			PRINT (("AGHFP_INTERNAL_MEMORY_DIAL_REQ\n"));

			switch(profileState)
			{
				case aghfp_slc_connected:
				{
					AGHFP_INTERNAL_MEMORY_DIAL_REQ_T *data = (AGHFP_INTERNAL_MEMORY_DIAL_REQ_T*)message;
					aghfpHandleMemoryDialReq(aghfp, data->number, data->size_number);
					break;
				}
				default:
					aghfpSendError(aghfp);
					break;
			}
			break;

		case AGHFP_INTERNAL_LAST_NUMBER_REDIAL_REQ: /* HF wants to redial last number dialed by AG */
			PRINT (("AGHFP_INTERNAL_LAST_NUMBER_REDIAL_REQ\n"));

			switch(profileState)
			{
				case aghfp_slc_connected:
					aghfpHandleLastNumberRedialReq(aghfp);
					break;
				default:
					aghfpSendError(aghfp);
					break;
			}
			break;

		case AGHFP_INTERNAL_NREC_SETUP_REQ:
			PRINT (("AGHFP_INTERNAL_NREC_SETUP_REQ\n"));

			switch(profileState)
			{
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
				case aghfp_active_call:
					aghfpHandleNrecSetupReq(aghfp, ((AGHFP_INTERNAL_NREC_SETUP_REQ_T*)message)->state);
					break;
				default:
					aghfpSendError(aghfp);
					break;
			}
			break;

		case AGHFP_INTERNAL_VOICE_RECOGNITION_SETUP_REQ:
			PRINT (("AGHFP_INTERNAL_VOICE_RECOGNITION_SETUP_REQ\n"));

			switch(profileState)
			{
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
				case aghfp_active_call:
					aghfpHandleVoiceRecognitionSetupReq(aghfp, ((AGHFP_INTERNAL_VOICE_RECOGNITION_SETUP_REQ_T*)message)->state);
					break;
				default:
					aghfpSendError(aghfp);
					break;
			}
			break;


		case AGHFP_INTERNAL_PHONE_NUMBER_REQ:
			PRINT (("AGHFP_INTERNAL_PHONE_NUMBER_REQ\n"));

			switch(profileState)
			{
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
				case aghfp_active_call:
					aghfpHandlePhoneNumberForVoiceTagReq(aghfp);
					break;
				default:
					aghfpSendError(aghfp);
					break;
			}
			break;


		case AGHFP_INTERNAL_TRANSMIT_DTMF_CODE:
		{
			AGHFP_INTERNAL_TRANSMIT_DTMF_CODE_T *data = (AGHFP_INTERNAL_TRANSMIT_DTMF_CODE_T*)message;
			PRINT (("AGHFP_INTERNAL_TRANSMIT_DTMF_CODE\n"));

			switch(profileState)
			{
				case aghfp_active_call:
					aghfpHandleTransmitDtmfCode(aghfp, data->code);
					break;
				default:
					aghfpSendError(aghfp);
					break;
			}
			break;
		}

        case AGHFP_INTERNAL_RESPONSE_HOLD_STATUS_REQUEST_REQ:    /* AT+BTRH?         */
            PRINT (("AGHFP_INTERNAL_RESPONSE_HOLD_STATUS_REQUEST_REQ\n"));
        	switch(profileState)
        	{
            	case aghfp_slc_connected:
            	case aghfp_incoming_call_establish:
            	case aghfp_outgoing_call_establish:
            	case aghfp_active_call:
            	    aghfpHandleResponseHoldStatusRequest(aghfp);
            	    break;
        		default:
        			aghfpSendError(aghfp);
        			break;
        	}
            break;

        case AGHFP_INTERNAL_SET_RESPONSE_HOLD_STATUS_REQ:           /* AT+BTRH=c        */
        {
            AGHFP_INTERNAL_SET_RESPONSE_HOLD_STATUS_REQ_T *msg = (AGHFP_INTERNAL_SET_RESPONSE_HOLD_STATUS_REQ_T *)message;
            PRINT (("AGHFP_INTERNAL_SET_RESPONSE_HOLD_STATUS_REQ\n"));
        	switch(profileState)
        	{
            	case aghfp_slc_connected:
            	case aghfp_incoming_call_establish:
            	case aghfp_outgoing_call_establish:
            	case aghfp_active_call:
            	    aghfpHandleSetResponseHoldStatus(aghfp,msg->cmd);
            	    break;
        		default:
        			aghfpSendError(aghfp);
        			break;
        	}
            break;
        }

        case AGHFP_INTERNAL_SUBSCRIBER_NUMBER_REQ:       /* AT+CNUM          */
            PRINT (("AGHFP_INTERNAL_SUBSCRIBER_NUMBER_REQ\n"));
        	switch(profileState)
        	{
            	case aghfp_slc_connected:
            	case aghfp_incoming_call_establish:
            	case aghfp_outgoing_call_establish:
            	case aghfp_active_call:
            	    aghfpHandleSubscriberNumbersRequest(aghfp);
            	    break;
        		default:
        			aghfpSendError(aghfp);
        			break;
        	}
            break;

        case AGHFP_INTERNAL_CURRENT_CALLS_REQ:           /* AT+CLCC          */
            PRINT (("AGHFP_INTERNAL_CURRENT_CALLS_REQ\n"));
        	switch(profileState)
        	{
            	case aghfp_slc_connected:
            	case aghfp_incoming_call_establish:
            	case aghfp_outgoing_call_establish:
            	case aghfp_active_call:
            	    aghfpHandleCurrentCallsRequest(aghfp);
            	    break;
        		default:
        			aghfpSendError(aghfp);
        			break;
        	}
            break;

        case AGHFP_INTERNAL_NETWORK_OPERATOR_FORMAT_REQ: /* AT+COPS=m,f      */
        {
            AGHFP_INTERNAL_NETWORK_OPERATOR_FORMAT_REQ_T *msg = (AGHFP_INTERNAL_NETWORK_OPERATOR_FORMAT_REQ_T *)message;
            PRINT (("AGHFP_INTERNAL_NETWORK_OPERATOR_FORMAT_REQ\n"));
        	switch(profileState)
        	{
            	case aghfp_slc_connected:
            	case aghfp_incoming_call_establish:
            	case aghfp_outgoing_call_establish:
            	case aghfp_active_call:
            	    aghfpHandleNetworkOperatorFormatRequest(aghfp, msg->mode, msg->format);
            	    break;
        		default:
        			aghfpSendError(aghfp);
        			break;
        	}
            break;
        }

        case AGHFP_INTERNAL_NETWORK_OPERATOR_REQ:        /* AT+COPS?         */
            PRINT (("AGHFP_INTERNAL_NETWORK_OPERATOR_REQ\n"));
        	switch(profileState)
        	{
            	case aghfp_slc_connected:
            	case aghfp_incoming_call_establish:
            	case aghfp_outgoing_call_establish:
            	case aghfp_active_call:
            	    aghfpHandleNetworkOperatorRequest(aghfp);
            	    break;
        		default:
        			aghfpSendError(aghfp);
        			break;
        	}
            break;


		/*************************************************************************/
		/* Audio Connection Messages                                             */
		/*************************************************************************/

		case AGHFP_INTERNAL_AUDIO_TRANSFER_REQ:
			/* TODO - really need to handle this message! */
			break;

		case AGHFP_INTERNAL_AUDIO_CONNECT_REQ:
			PRINT(("AGHFP_INTERNAL_AUDIO_CONNECTION_REQ\n"));

			switch(profileState)
			{
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
				case aghfp_active_call:
					aghfpHandleAudioConnectReq(aghfp, (AGHFP_INTERNAL_AUDIO_CONNECT_REQ_T*)message);
					break;
				default:
					/* Panic in debug and ignore in release lib variants */
					handleUnexpected(aghfpUnexpectedAghfpPrim, profileState, id);
					break;
			}
			break;

		case AGHFP_INTERNAL_AUDIO_CONNECT_RES:
			PRINT(("AGHFP_INTERNAL_AUDIO_CONNECT_RES\n"));

			switch(profileState)
			{
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
				case aghfp_active_call:
				{
					aghfpHandleAudioConnectRes(aghfp, (AGHFP_INTERNAL_AUDIO_CONNECT_RES_T*)message);
					break;
				}
				default:
					/* Panic in debug and ignore in release lib variants */
					handleUnexpected(aghfpUnexpectedAghfpPrim, profileState, id);
					break;
			}
			break;

		case AGHFP_INTERNAL_AUDIO_DISCONNECT_REQ:
			PRINT(("AGHFP_INTERNAL_AUDIO_DISCONNECT_REQ\n"));

			switch(profileState)
			{
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
				case aghfp_active_call:
					aghfpHandleAudioDisconnectReq(aghfp);
					break;
				default:
					/* Panic in debug and ignore in release lib variants */
					handleUnexpected(aghfpUnexpectedAghfpPrim, profileState, id);
					break;
			}
			break;

		case AGHFP_INTERNAL_SET_AUDIO_PARAMS_REQ:
			PRINT(("AGHFP_INTERNAL_SET_AUDIO_PARAMS_REQ\n"));
			
			switch(profileState)
			{
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
				case aghfp_active_call:
					aghfpHandleSetAudioParamsReq(aghfp, (AGHFP_INTERNAL_SET_AUDIO_PARAMS_REQ_T*)message);
					break;
				default:
					/* Panic in debug and ignore in release lib variants */
					handleUnexpected(aghfpUnexpectedAghfpPrim, profileState, id);
					break;
			}
			break;
			

		/*************************************************************************/
		/* Indicator Messages                                                    */
		/*************************************************************************/

		case AGHFP_INTERNAL_SEND_SERVICE_INDICATOR:
			PRINT(("AGHFP_INTERNAL_SEND_SERVICE_INDICATOR\n"));

			switch(profileState)
			{
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
					aghfpHandleSendServiceIndicator(aghfp,
					((AGHFP_INTERNAL_SEND_SERVICE_INDICATOR_T*)message)->availability);
					break;
				default:
					aghfpSendCommonCfmMessageToApp(AGHFP_SEND_SERVICE_INDICATOR_CFM, aghfp, aghfp_fail);
					break;
			}
			break;

		case AGHFP_INTERNAL_SEND_CALL_INDICATOR:
		{
			aghfp_call_status status = ((AGHFP_INTERNAL_SEND_CALL_INDICATOR_T*)message)->status;

			PRINT(("AGHFP_INTERNAL_SEND_CALL_INDICATOR\n"));

			if ((profileState == aghfp_incoming_call_establish && status == aghfp_call_active) ||
				(profileState == aghfp_outgoing_call_establish && status == aghfp_call_active) ||
				(profileState == aghfp_active_call             && status == aghfp_call_none))
			{
				aghfpHandleSendCallIndicator(aghfp, status);
			}
			else
			{
				aghfpSendCommonCfmMessageToApp(AGHFP_SEND_CALL_INDICATOR_CFM, aghfp, aghfp_fail);
			}

			break;
		}

		case AGHFP_INTERNAL_SEND_CALL_SETUP_INDICATOR:
		{
			aghfp_call_setup_status status;
			status = ((AGHFP_INTERNAL_SEND_CALL_SETUP_INDICATOR_T*)message)->type;

			PRINT(("AGHFP_INTERNAL_SEND_CALL_SETUP_INDICATOR\n"));

			if ((profileState == aghfp_slc_connected    		&& status == aghfp_call_setup_incoming) ||
				(profileState == aghfp_slc_connected    		&& status == aghfp_call_setup_outgoing) ||
				(profileState == aghfp_incoming_call_establish 	&& status == aghfp_call_setup_none) ||
                (profileState == aghfp_outgoing_call_establish 	&& status == aghfp_call_setup_none) ||
				(profileState == aghfp_outgoing_call_establish  && status == aghfp_call_setup_remote_alert) ||
				(profileState == aghfp_active_call) )
			{
				aghfpHandleSendCallSetupIndicator(aghfp, status);
			}
			else
			{
				aghfpSendCommonCfmMessageToApp(AGHFP_SEND_CALL_SETUP_INDICATOR_CFM, aghfp, aghfp_fail);
			}

			break;
		}

		case AGHFP_INTERNAL_SEND_CALL_HELD_INDICATOR:
			/* TODO - really need to handle this message */
			break;
			
		case AGHFP_INTERNAL_SEND_SIGNAL_INDICATOR:
			/* TODO - really need to handle this message */
			break;
		
		case AGHFP_INTERNAL_SEND_ROAM_INDICATOR:
			/* TODO - really need to handle this message */
			break;
			
		case AGHFP_INTERNAL_SEND_BATT_CHG_INDICATOR:
			/* TODO - really need to handle this message */
			break;

		case AGHFP_INTERNAL_SEND_CALL_WAITING_NOTIFICATION:
		{
			AGHFP_INTERNAL_SEND_CALL_WAITING_NOTIFICATION_T *scwn =	(AGHFP_INTERNAL_SEND_CALL_WAITING_NOTIFICATION_T *)message;
			PRINT(("AGHFP_INTERNAL_SEND_CALL_WAITING_NOTIFICATION\n"));

			switch(profileState)
			{
				case aghfp_active_call:
					aghfpHandleSendCallWaitingNotification(aghfp, scwn->type, scwn->size_number, scwn->number, scwn->size_string, scwn->string);
					break;
				default:
					free(scwn->string);
					aghfpSendCommonCfmMessageToApp(AGHFP_SEND_CALL_WAITING_NOTIFICATION_CFM, aghfp, aghfp_fail);
					break;
			}

			break;
		}

		case AGHFP_INTERNAL_SET_SERVICE_STATE:
		{
			PRINT(("AGHFP_INTERNAL_SET_SERVICE_STATE\n"));

			switch (profileState)
			{
				case aghfp_initialising:
					break;	/* Silently ignore */
				case aghfp_ready:
				case aghfp_slc_connecting:
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
				case aghfp_active_call:
					aghfpHandleSetServiceState(aghfp, ((AGHFP_INTERNAL_SET_SERVICE_STATE_T*)message)->service_state);
					break;
			}

			break;
		}


		/*************************************************************************/
		/* Call Related Messages                                                 */
		/*************************************************************************/

		case AGHFP_INTERNAL_SEND_RING_ALERT:
			PRINT(("AGHFP_INTERNAL_SEND_RING_ALERT\n"));

			switch(profileState)
			{
				case aghfp_incoming_call_establish:
					aghfpHandleSendRingAlert(aghfp);
					break;
				default:
					aghfpSendCommonCfmMessageToApp(AGHFP_SEND_RING_ALERT_CFM, aghfp, aghfp_fail);
					break;
			}
			break;

		case AGHFP_INTERNAL_SEND_CALLER_ID:
		{
			AGHFP_INTERNAL_SEND_CALLER_ID_T *msg = (AGHFP_INTERNAL_SEND_CALLER_ID_T*)message;
			switch(profileState)
			{
				case aghfp_incoming_call_establish:
					aghfpHandleSendCallerId(aghfp, msg->type, msg->size_number, msg->size_string, msg->data);
					break;
				default:
					aghfpSendCommonCfmMessageToApp(AGHFP_SEND_CALLER_ID_CFM, aghfp, aghfp_fail);
					break;
			}
			break;
		}
		case AGHFP_INTERNAL_INBAND_RING_TONE_ENABLE:
			PRINT(("AGHFP_INTERNAL_INBAND_RING_TONE_ENABLE\n"));

			switch(profileState)
			{
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
					aghfpHandleInBandRingToneEnable(aghfp, ((AGHFP_INTERNAL_INBAND_RING_TONE_ENABLE_T*)message)->enable);
					break;
				default:
					aghfpSendCommonCfmMessageToApp(AGHFP_INBAND_RING_ENABLE_CFM, aghfp, aghfp_fail);
					break;
			}
			break;


		/*************************************************************************/
		/* Call Management Messages                                              */
		/*************************************************************************/

		case AGHFP_INTERNAL_CALL_MGR_CREATE_REQ:
			PRINT(("AGHFP_INTERNAL_CALL_MGR_CREATE_REQ\n"));
			
			switch(profileState)
			{
				case aghfp_slc_connected:
					aghfpHandleCallCreate(aghfp, (AGHFP_INTERNAL_CALL_MGR_CREATE_REQ_T *)message);
					break;
				default:
					aghfpSendCallCreateCfmToApp(aghfp, aghfp_call_create_error);
					break;
			}
			break;
			
			
		case AGHFP_INTERNAL_CALL_MGR_CREATE_WITH_AUDIO_REQ:
			PRINT(("AGHFP_INTERNAL_CALL_MGR_CREATE_WITH_AUDIO_REQ\n"));
			
			switch(profileState)
			{
				case aghfp_slc_connected:
					aghfpHandleCallCreateAudio(aghfp, (AGHFP_INTERNAL_CALL_MGR_CREATE_WITH_AUDIO_REQ_T *)message);
					break;
				default:
					aghfpSendCallCreateCfmToApp(aghfp, aghfp_call_create_error);
					break;
			}
			break;
			
			
		case AGHFP_INTERNAL_CALL_MGR_ANSWER_REQ:
			PRINT(("AGHFP_INTERNAL_CALL_MGR_ANSWER_REQ\n"));
			
			switch(profileState)
			{
				case aghfp_incoming_call_establish:
					aghfpHandleCallAnswer(aghfp);
					break;
				default:
					/* Silently ignore message */
					break;
			}
			break;
			
			
		case AGHFP_INTERNAL_CALL_MGR_REMOTE_ANSWERED_REQ:
			PRINT(("AGHFP_INTERNAL_CALL_MGR_REMOTE_ANSWERED_REQ\n"));
			
			switch(profileState)
			{
				case aghfp_outgoing_call_establish:
					aghfpHandleCallRemoteAnswered(aghfp);
					break;
				default:
					/* Silently ignore message */
					break;
			}
			break;
			
			
		case AGHFP_INTERNAL_CALL_MGR_TERMINATE_REQ:
			PRINT(("AGHFP_INTERNAL_CALL_MGR_TERMINATE_REQ\n"));
			
			switch(profileState)
			{
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
				case aghfp_active_call:
					aghfpHandleCallTerminate(aghfp, (AGHFP_INTERNAL_CALL_MGR_TERMINATE_REQ_T *)message);
					break;
				default:
					aghfpSendCommonCfmMessageToApp(AGHFP_CALL_MGR_TERMINATE_IND, aghfp, aghfp_fail);
					break;
			}
			break;
			
			
		case AGHFP_INTERNAL_RING_REPEAT_REQ:
			PRINT(("AGHFP_INTERNAL_RING_REPEAT_REQ\n"));
			
			switch(profileState)
			{
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
					aghfpManageCall(aghfp, CallEventRing, CallFlagsNone);
					break;
				default:
					/* Silently ignore message */
					break;
			}
			break;
			
		
			
		/*************************************************************************/
		/* Misc Other Messages                                                   */
		/*************************************************************************/

		case AGHFP_INTERNAL_SET_CALLER_ID_DETAILS_REQ:
			PRINT(("AGHFP_INTERNAL_SET_CALLER_ID_DETAILS_REQ\n"));
			
			switch(profileState)
			{
				case aghfp_initialising:
				case aghfp_ready:
				case aghfp_slc_connecting:
				case aghfp_slc_connected:
					aghfpHandleSetCallerIdDetails(aghfp, (AGHFP_INTERNAL_SET_CALLER_ID_DETAILS_REQ_T *)message);
					break;
				default:
					aghfpSendCommonCfmMessageToApp(AGHFP_SET_CALLER_ID_DETAILS_CFM, aghfp, aghfp_fail);
					break;
			}
			break;
			
		case AGHFP_INTERNAL_VOICE_RECOGNITION_ENABLE:
			PRINT(("AGHFP_INTERNAL_VOICE_RECOGNITION_ENABLE\n"));

			switch(profileState)
			{
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
				case aghfp_active_call:
					aghfpHandleVoiceRecognitionEnable(aghfp, ((AGHFP_INTERNAL_VOICE_RECOGNITION_ENABLE_T*)message)->enable);
					break;
				default:
					aghfpSendCommonCfmMessageToApp(AGHFP_VOICE_RECOGNITION_ENABLE_CFM, aghfp, aghfp_fail);
			}
			break;

		case AGHFP_INTERNAL_SEND_PHONE_NUMBER_FOR_VOICE_TAG:
		{
			AGHFP_INTERNAL_SEND_PHONE_NUMBER_FOR_VOICE_TAG_T *data;
			data = (AGHFP_INTERNAL_SEND_PHONE_NUMBER_FOR_VOICE_TAG_T *)message;
			PRINT(("AGHFP_INTERNAL_SEND_PHONE_NUMBER_FOR_VOICE_TAG\n"));

			switch(profileState)
			{
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
				case aghfp_active_call:
					aghfpHandleSendPhoneNumberForVoiceTag(aghfp, data->size_number, data->number);
					break;
				default:
					aghfpSendCommonCfmMessageToApp(AGHFP_SEND_PHONE_NUMBER_FOR_VOICE_TAG_CFM, aghfp, aghfp_fail);
			}
			break;
		}

		case AGHFP_INTERNAL_SET_REMOTE_MICROPHONE_GAIN:
			PRINT(("AGHFP_INTERNAL_SET_REMOTE_MICROPHONE_GAIN\n"));

			switch(profileState)
			{
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
				case aghfp_active_call:
					aghfpHandleSetRemoteMicrophoneGain(aghfp, ((AGHFP_INTERNAL_SET_REMOTE_MICROPHONE_GAIN_T*)message)->gain);
					break;
				default:
					aghfpSendCommonCfmMessageToApp(AGHFP_SET_REMOTE_MICROPHONE_GAIN_CFM, aghfp, aghfp_fail);
			}
			break;

		case AGHFP_INTERNAL_SET_REMOTE_SPEAKER_VOLUME:
			PRINT(("AGHFP_INTERNAL_SET_REMOTE_SPEAKER_VOLUME\n"));

			switch(profileState)
			{
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
				case aghfp_active_call:
					aghfpHandleSetRemoteSpeakerVolume(aghfp, ((AGHFP_INTERNAL_SET_REMOTE_SPEAKER_VOLUME_T*)message)->volume);
					break;
				default:
					aghfpSendCommonCfmMessageToApp(AGHFP_SET_REMOTE_SPEAKER_VOLUME_CFM, aghfp, aghfp_fail);
			}
			break;

		case AGHFP_INTERNAL_SYNC_MIC_GAIN:
			PRINT(("AGHFP_INTERNAL_SYNC_MIC_GAIN\n"));

			switch(profileState)
			{
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
				case aghfp_active_call:
					aghfpHandleSyncMicrophoneGain(aghfp, ((AGHFP_INTERNAL_SYNC_MIC_GAIN_T*)message)->gain);
					break;
				default:
					/* We've received a mic gain command from the HF, but we haven't currently
					   got an SLC. That can't really happen. If it does, then just silently ignore. */
					break;
			}
			break;

		case AGHFP_INTERNAL_SYNC_SPEAKER_VOLUME:
			PRINT(("AGHFP_INTERNAL_SYNC_SPEAKER_VOLUME\n"));

			switch(profileState)
			{
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
				case aghfp_active_call:
					aghfpHandleSyncSpeakerVolume(aghfp, ((AGHFP_INTERNAL_SYNC_SPEAKER_VOLUME_T*)message)->volume);
					break;
				default:
					/* We've received a speaker gain command from the HF, but we haven't currently
					   got an SLC. That can't really happen. If it does, then just silently ignore. */
					break;
			}
			break;

        case AGHFP_INTERNAL_SEND_RESPONSE_HOLD_STATE:
			PRINT(("AGHFP_INTERNAL_SEND_RESPONSE_HOLD_STATE\n"));

			switch(profileState)
			{
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
				case aghfp_active_call:
					aghfpHandleSendResponseHoldState(aghfp, ((AGHFP_INTERNAL_SEND_RESPONSE_HOLD_STATE_T*)message)->state);
					break;
				default:
					/* We've received a  command from the HF, but we haven't currently
					   got an SLC. That can't really happen. If it does, then just silently ignore. */
					break;
			}
			break;

        case AGHFP_INTERNAL_CONFIRM_RESPONSE_HOLD_STATE:
			PRINT(("AGHFP_INTERNAL_CONFIRM_RESPONSE_HOLD_STATE\n"));

			switch(profileState)
			{
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
				case aghfp_active_call:
					aghfpHandleConfirmResponseHoldState(aghfp, ((AGHFP_INTERNAL_CONFIRM_RESPONSE_HOLD_STATE_T*)message)->state);
					break;
				default:
					/* We've received a  command from the HF, but we haven't currently
					   got an SLC. That can't really happen. If it does, then just silently ignore. */
					break;
			}
			break;

        case AGHFP_INTERNAL_SEND_SUBSCRIBER_NUMBER:
			PRINT(("AGHFP_INTERNAL_SEND_SUBSCRIBER_NUMBER\n"));

			switch(profileState)
			{
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
				case aghfp_active_call:
					aghfpHandleSendSubscriberNumber(aghfp, (AGHFP_INTERNAL_SEND_SUBSCRIBER_NUMBER_T*)message);
					break;
				default:
					/* We've received a  command from the HF, but we haven't currently
					   got an SLC. That can't really happen. If it does, then just silently ignore. */
					break;
			}
			break;

        case AGHFP_INTERNAL_SEND_SUBSCRIBER_NUMBERS_COMPLETE:
			PRINT(("AGHFP_INTERNAL_SEND_SUBSCRIBER_NUMBERS_COMPLETE\n"));

			switch(profileState)
			{
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
				case aghfp_active_call:
					aghfpHandleSendSubscriberNumbersComplete(aghfp);
					break;
				default:
					/* We've received a  command from the HF, but we haven't currently
					   got an SLC. That can't really happen. If it does, then just silently ignore. */
					break;
			}
			break;

        case AGHFP_INTERNAL_SEND_CURRENT_CALL:
			PRINT(("AGHFP_INTERNAL_SEND_CURRENT_CALL\n"));

			switch(profileState)
			{
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
				case aghfp_active_call:
					aghfpHandleSendCurrentCall(aghfp, (AGHFP_INTERNAL_SEND_CURRENT_CALL_T*)message);
					break;
				default:
					/* We've received a  command from the HF, but we haven't currently
					   got an SLC. That can't really happen. If it does, then just silently ignore. */
					break;
			}
			break;

        case AGHFP_INTERNAL_SEND_CURRENT_CALLS_COMPLETE:
			PRINT(("AGHFP_INTERNAL_SEND_CURRENT_CALLS_COMPLETE\n"));

			switch(profileState)
			{
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
				case aghfp_active_call:
					aghfpHandleSendCurrentCallsComplete(aghfp);
					break;
				default:
					/* We've received a  command from the HF, but we haven't currently
					   got an SLC. That can't really happen. If it does, then just silently ignore. */
					break;
			}
			break;

        case AGHFP_INTERNAL_SEND_NETWORK_OPERATOR:
        {
			AGHFP_INTERNAL_SEND_NETWORK_OPERATOR_T *msg = (AGHFP_INTERNAL_SEND_NETWORK_OPERATOR_T*)message;
			PRINT(("AGHFP_INTERNAL_SEND_NETWORK_OPERATOR\n"));

			switch(profileState)
			{
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
				case aghfp_active_call:
					aghfpHandleSendNetworkOperator(aghfp, msg->mode, msg->size_operator, msg->operator);
					break;
				default:
					/* We've received a  command from the HF, but we haven't currently
					   got an SLC. That can't really happen. If it does, then just silently ignore. */
					break;
			}
			break;
		}

        case AGHFP_INTERNAL_USER_DATA_REQ:
            PRINT(("AGHFP_INTERNAL_USER_DATA_REQ\n"));

			switch(profileState)
			{
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
				case aghfp_active_call:
					aghfpHandleUserDataReq(aghfp, (AGHFP_INTERNAL_USER_DATA_REQ_T *) message);
					break;

                case aghfp_ready:
                case aghfp_slc_connecting:
                    /* Cannot send the data, haven't got a valid SLC established */
                    aghfpHandleUserDataReqFail(aghfp, (AGHFP_INTERNAL_USER_DATA_REQ_T *) message);
                    break;

                case aghfp_initialising:
				default:
					/* We have received a request to send user data and we're in the wrong state */
					break;
			}
            break;

        case AGHFP_INTERNAL_SEND_ERROR_REQ:
            PRINT(("AGHFP_INTERNAL_SEND_ERROR_REQ\n"));

			switch(profileState)
			{
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
				case aghfp_active_call:
                case aghfp_slc_connecting:
					aghfpSendError(aghfp);
					break;

                case aghfp_ready:
                    /* Cannot send error, haven't got a valid RFCOMM established */
                    aghfpSendCommonCfmMessageToApp(AGHFP_SEND_ERROR_CFM, aghfp, aghfp_fail);
                    break;

                case aghfp_initialising:
				default:
					/* We have received this request in the wrong state */
					break;
			}
            break;

        case AGHFP_INTERNAL_SEND_OK_REQ:
            PRINT(("AGHFP_INTERNAL_SEND_OK_REQ\n"));

			switch(profileState)
			{
				case aghfp_slc_connected:
				case aghfp_incoming_call_establish:
				case aghfp_outgoing_call_establish:
				case aghfp_active_call:
                case aghfp_slc_connecting:
					aghfpSendOk(aghfp);
					break;

                case aghfp_ready:
                    /* Cannot send error, haven't got a valid RFCOMM established */
                    aghfpSendCommonCfmMessageToApp(AGHFP_SEND_OK_CFM, aghfp, aghfp_fail);
                    break;

                case aghfp_initialising:
				default:
					/* We have received this request in the wrong state */
					break;
			}
            break;

		/* WB-Speech Messages */
		case AGHFP_INTERNAL_WBS_CODEC_NEGOTIATE_REQ:
			PRINT(("AGHFP_INTERNAL_WBS_CODEC_NEGOTIATE_REQ\n"));
			aghfpHandleWbsCodecNegReq(aghfp, ((AGHFP_INTERNAL_WBS_CODEC_NEGOTIATE_REQ_T*)message)->codec);
			break;
			
		case AGHFP_INTERNAL_WBS_CODEC_CONNECTION_REQ:
			PRINT(("AGHFP_INTERNAL_WBS_CODEC_CONNECTION_REQ\n"));
			aghfpHandleWbsCodecConReq(aghfp);
			break;
				
		case AGHFP_INTERNAL_CODEC_NEGOTIATION_REQ:
			PRINT(("AGHFP_INTERNAL_CODEC_NEGOTIATION_REQ\n"));
			aghfpHandleCodecNegotiationReq(aghfp, (AGHFP_INTERNAL_CODEC_NEGOTIATION_REQ_T*)message);
			break;

		default:
			PRINT(("Unhandled message\n"));
			/* Received an unhandled message */
			handleUnexpected(aghfpUnexpectedMessage, profileState, id);
			break;
    }
}
예제 #7
0
/****************************************************************************
NAME	
	hfpRegisterServiceRecord

DESCRIPTION
	Register the service record corresponding to the specified profile 

RETURNS
	void
*/
void hfpRegisterServiceRecord(HFP *hfp)
{
	uint8 *service_record = 0;
    hfp_profile profile = hfp->hfpSupportedProfile;
    uint8 chan = hfp->local_rfc_server_channel;

	if (!hfp->service_record)
	{
		if (supportedProfileIsHsp(profile))
        {
            hfp->size_service_record = sizeof(hsp_service_record);
			hfp->service_record = (uint8 *) hsp_service_record;
        }
		else if (supportedProfileIsHfp(profile))
        {
            hfp->size_service_record = sizeof(hfp_service_record);
			hfp->service_record = (uint8 *) hfp_service_record;
        }
		else
		{
			/* Unknown profile, send an error */
            sendInternalSdpRegisterCfmMessage(hfp, hfp_fail);
			return;
		}
	}

	/* Create a copy of the service record that we can modify */
	service_record = (uint8 *)PanicUnlessMalloc(hfp->size_service_record);
	memmove(service_record, hfp->service_record, hfp->size_service_record);
	
	if (supportedProfileIsHfp(profile))
	{
		/* Insert the supported features into the service record. */
		if (!insertHfpSupportedFeatures(service_record, service_record + hfp->size_service_record, hfp->hfpSupportedFeatures))
		{
			/* Failed to insert the supported features into the service record */
            sendInternalSdpRegisterCfmMessage(hfp, hfp_fail);

			/* Free the allocated memory */
			free(service_record);
			return;
		}

        /* Insert the profile version number */
        if (!insertHfpProfileVersion(service_record, service_record + hfp->size_service_record, profile))
        {
            /* SDP register failed */
            sendInternalSdpRegisterCfmMessage(hfp, hfp_fail);

			/* Free the allocated memory */
			free(service_record);
			return;
        }
	}
	
	if (!insertRfcommServerChannel(service_record, service_record + hfp->size_service_record, chan))
	{
		/* If we fail to insert the rfcomm channel return an error to the app */		
        sendInternalSdpRegisterCfmMessage(hfp, hfp_fail);
		
		/* Free the allocated memory */
		free(service_record);
	}
	else
	{
		/* Send the service record to the connection lib to be registered with BlueStack */
		ConnectionRegisterServiceRecord(&hfp->task, hfp->size_service_record, service_record);
	}
}