/**************************************************************************** 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; }
/**************************************************************************** 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); } }
/**************************************************************************** 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; }
/**************************************************************************** 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); }
/**************************************************************************** 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; } }
/**************************************************************************** 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); } }