/**************************************************************************** NAME HfpResponseHoldActionRequest DESCRIPTION Requests that the AG performs a given response and hold action. MESSAGE RETURNED HFP_RESPONSE_HOLD_ACTION_CFM RETURNS void */ void HfpResponseHoldActionRequest(hfp_link_priority priority, hfp_btrh_action action) { MAKE_HFP_MESSAGE(HFP_INTERNAL_AT_BTRH_REQ); message->link = hfpGetLinkFromPriority(priority); message->action = action; MessageSend(&theHfp->task, HFP_INTERNAL_AT_BTRH_REQ, message); }
void HfpCsrModifyIndicators(HFP *hfp, uint16 size_indicators, const hfp_csr_mod_indicator *indicators) { if (hfp->use_csr2csr) { hfp_csr_mod_indicator *ind; ind = (hfp_csr_mod_indicator*)malloc(sizeof(hfp_csr_mod_indicator)*size_indicators); if (ind) { MAKE_HFP_MESSAGE(HFP_INTERNAL_CSR_MOD_INDS_REQ); message->size_indicators = size_indicators; message->indicators = ind; memmove(ind, indicators, sizeof(hfp_csr_mod_indicator)*size_indicators); MessageSend(&hfp->task, HFP_INTERNAL_CSR_MOD_INDS_REQ, message); } else { hfpSendCsrModifyIndicatorsCfm(hfp, hfp_csr_mod_ind_no_mem); } } else { hfpSendCsrModifyIndicatorsCfm(hfp, hfp_csr_not_inited); } }
/**************************************************************************** NAME hfpSendSlcConnectCfmToApp DESCRIPTION Send a HFP_SLC_CONNECT_CFM message to the app telling it the outcome of the connect attempt. RETURNS void */ void hfpSendSlcConnectCfmToApp(hfp_link_data* link, const bdaddr* bd_addr, hfp_connect_status status) { if(link && (link->ag_link_loss_state != hfp_link_loss_none)) { if (status == hfp_connect_success) hfpSlcConnectTidy(link); /* We're trying to recover from link loss... keep going */ hfpHandleRfcommLinkLossComplete(link, status); } else { MAKE_HFP_MESSAGE(HFP_SLC_CONNECT_CFM); message->status = status; message->sink = hfpGetLinkSink(link); message->priority = hfpGetLinkPriority(link); message->profile = hfpLinkGetProfile(link); /* Try and get bdaddr from the link data */ if(!hfpGetLinkBdaddr(link, &message->bd_addr) && bd_addr) message->bd_addr = *bd_addr; /* If the connect succeeded need to tidy up a few things */ if(link) { if (status == hfp_connect_success) hfpSlcConnectTidy(link); else if (status != hfp_connect_failed_busy) hfpLinkReset(link, TRUE); } MessageSend(theHfp->clientTask, HFP_SLC_CONNECT_CFM, message); } }
void hfpSendCsrModifyIndicatorsCfm(HFP *hfp, hfp_lib_status status) { MAKE_HFP_MESSAGE(HFP_CSR_MODIFY_INDICATORS_CFM); message->hfp = hfp; message->status = status; MessageSend(hfp->clientTask, HFP_CSR_MODIFY_INDICATORS_CFM, message); }
/**************************************************************************** NAME HfpCallAnswerRequest DESCRIPTION This function is used to answer an incoming call. The AT command to answer the call will be sent out on the SLC corresponding to the priority passed into the function from the application. The message returned indicates whether the command was recognised by the AG or not. MESSAGE RETURNED HFP_CALL_ANSWER_CFM RETURNS void */ void HfpCallAnswerRequest(hfp_link_priority priority, bool accept) { MAKE_HFP_MESSAGE(HFP_INTERNAL_AT_ANSWER_REQ); message->link = hfpGetLinkFromPriority(priority); message->accept = accept; MessageSend(&theHfp->task, HFP_INTERNAL_AT_ANSWER_REQ, message); }
/**************************************************************************** NAME hfpHandleRing DESCRIPTION Received a RING indication. AT INDICATION RING RETURNS void */ void hfpHandleRing(Task link_ptr) { /* Get the link we got ring indication on */ hfp_link_data* link = (hfp_link_data*)link_ptr; if(link) { /* Update call state if required */ hfpHandleCallRingIndication(link); if(link->ag_call_state == hfp_call_state_incoming) { MAKE_HFP_MESSAGE(HFP_RING_IND); message->in_band = FALSE; /* This is an in band ring if... */ if((hfpLinkIsHfp(link) && agFeatureEnabled(link, AG_IN_BAND_RING))) { /* ...AG is HFP and supports in band ring */ message->in_band = TRUE; } else if(hfpLinkIsHsp(link) && link->audio_state == hfp_audio_connected) { /* ...AG is HSP and SCO is open */ message->in_band = TRUE; } /* Send a message to the application */ message->priority = hfpGetLinkPriority(link); MessageSend(theHfp->clientTask, HFP_RING_IND, message); } } }
/**************************************************************************** NAME hfpHandleBtrhAtAck DESCRIPTION Request to AG to perform a response and hold action has been acknowledged (completed) by the AG. RETURNS void */ void hfpHandleBtrhAtAck(hfp_link_data* link, hfp_btrh_action action, hfp_lib_status status) { MAKE_HFP_MESSAGE(HFP_RESPONSE_HOLD_ACTION_CFM); message->priority = hfpGetLinkPriority(link); message->action = action; message->status = status; MessageSend(theHfp->clientTask, HFP_RESPONSE_HOLD_ACTION_CFM, message); }
/**************************************************************************** NAME sendSpeakerVolumeIndToApp DESCRIPTION We're in the right state to inform the app that the volume gain has been changed from the AG. RETURNS void */ static void sendSpeakerVolumeIndToApp(hfp_link_data* link, uint16 gain) { /* This is generated in response to receiving a volume indication from the AG */ MAKE_HFP_MESSAGE(HFP_VOLUME_SYNC_SPEAKER_GAIN_IND); message->priority = hfpGetLinkPriority(link); message->volume_gain = gain; MessageSend(theHfp->clientTask, HFP_VOLUME_SYNC_SPEAKER_GAIN_IND, message); }
void HfpCallHoldActionRequest(hfp_link_priority priority, hfp_chld_action action, uint16 index) { MAKE_HFP_MESSAGE(HFP_INTERNAL_AT_CHLD_REQ); message->link = hfpGetLinkFromPriority(priority); message->action = action; message->index = index; MessageSend(&theHfp->task, HFP_INTERNAL_AT_CHLD_REQ, message); }
static void sendIndicatorBattChgToApp(hfp_link_data* link, uint16 batt_chg) { /* Send a message to the app */ MAKE_HFP_MESSAGE(HFP_BATTCHG_IND); message->priority = hfpGetLinkPriority(link); message->battchg = batt_chg; MessageSend(theHfp->clientTask, HFP_BATTCHG_IND, message); }
static void sendIndicatorServiceToApp(hfp_link_data* link, uint16 service) { /* Send a message to the app */ MAKE_HFP_MESSAGE(HFP_SERVICE_IND); message->priority = hfpGetLinkPriority(link); message->service = service; MessageSend(theHfp->clientTask, HFP_SERVICE_IND, message); }
/**************************************************************************** NAME sendMicVolumeIndToApp DESCRIPTION Pass on the received microphone gain indication to the app. RETURNS void */ static void sendMicVolumeIndToApp(hfp_link_data* link, uint16 mic_gain) { /* This is generated in response to receiving a mic indication from the AG */ MAKE_HFP_MESSAGE(HFP_VOLUME_SYNC_MICROPHONE_GAIN_IND); message->priority = hfpGetLinkPriority(link); message->mic_gain = mic_gain; MessageSend(theHfp->clientTask, HFP_VOLUME_SYNC_MICROPHONE_GAIN_IND, message); }
static void sendIndicatorRoamToApp(hfp_link_data* link, uint16 roam) { /* Send a message to the app */ MAKE_HFP_MESSAGE(HFP_ROAM_IND); message->priority = hfpGetLinkPriority(link); message->roam = roam; MessageSend(theHfp->clientTask, HFP_ROAM_IND, message); }
static void sendIndicatorSignalToApp(hfp_link_data* link, uint16 signal) { /* Send a message to the app */ MAKE_HFP_MESSAGE(HFP_SIGNAL_IND); message->priority = hfpGetLinkPriority(link); message->signal = signal; MessageSend(theHfp->clientTask, HFP_SIGNAL_IND, message); }
/* Handle +CSR=0 sent from AG */ void hfpHandleResponseCSRModAgIndicatorsDisable(Task task) { HFP *hfp = (HFP*)task; if (hfp->use_csr2csr) { MAKE_HFP_MESSAGE(HFP_CSR_AG_INDICATORS_DISABLE_IND); message->hfp = hfp; MessageSend(hfp->clientTask, HFP_CSR_AG_INDICATORS_DISABLE_IND, message); } }
/**************************************************************************** NAME hfpHandleRfcommConnectInd DESCRIPTION Notification of an incoming rfcomm connection, pass this up to the app to decide whather to accept this or not. RETURNS void */ void hfpHandleRfcommConnectInd(HFP *hfp, const CL_RFCOMM_CONNECT_IND_T *ind) { /* Ask the app whather to accept this connection or not */ MAKE_HFP_MESSAGE(HFP_SLC_CONNECT_IND); message->addr = ind->bd_addr; message->hfp = hfp; MessageSend(hfp->clientTask, HFP_SLC_CONNECT_IND, message); /* Update the local state to indicate we're in the middle of connecting. */ hfpSetState(hfp, hfpSlcConnecting); }
static void sendUnhandledIndicatorToApp(hfp_link_data* link, uint16 index, uint16 value) { /* We have received an indicator not defined by the HFP spec. Pass it up to the application as it might want to make use of these extra indicators that some AGs send out. */ MAKE_HFP_MESSAGE(HFP_EXTRA_INDICATOR_UPDATE_IND); message->priority = hfpGetLinkPriority(link); message->index = index; message->value = value; MessageSend(theHfp->clientTask, HFP_EXTRA_INDICATOR_UPDATE_IND, message); }
/* Send the indicator list to the app so it can parse it for any non-HFP indicators it is interested in */ static void hfpSendUnhandledIndicatorListToApp(hfp_link_data* link, uint16 register_index, uint16 cind_index, uint16 min_range, uint16 max_range) { MAKE_HFP_MESSAGE(HFP_EXTRA_INDICATOR_INDEX_IND); message->priority = hfpGetLinkPriority(link); message->indicator_register_index = register_index; message->indicator_index = cind_index; message->min_range = min_range; message->max_range = max_range; MessageSend(theHfp->clientTask, HFP_EXTRA_INDICATOR_INDEX_IND, message); /* Store the extra indicator index internally */ hfpStoreUnhandledIndicator(link, cind_index); }
/**************************************************************************** NAME HfpVoiceRecognitionEnable DESCRIPTION Enable / disable voice recognition function at the AG. An SLC for the supplied profile instance (hfp) must already be established before calling this function. The enable flag determines whether a request will be made to the AG to enabe or disable its voice recognition function. The message returned indicates whether the command was recognised by the AG or not. The AG may autonomously notify the HFP device of a change in the state of its voice recognition function. This notification will be passed on to the application using a HFP_VOICE_RECOGNITION_IND message. MESSAGE RETURNED HFP_VOICE_RECOGNITION_ENABLE_CFM RETURNS void */ void HfpVoiceRecognitionEnable(HFP *hfp, bool enable) { #ifdef HFP_DEBUG_LIB if (!hfp) HFP_DEBUG(("Null hfp task ptr passed in.\n")); #endif { /* Send an internal message to kick off SLC creation */ MAKE_HFP_MESSAGE(HFP_INTERNAL_AT_BVRA_REQ); message->enable = enable; MessageSend(&hfp->task, HFP_INTERNAL_AT_BVRA_REQ, message); } }
static void hfpSendCsrSupportedFeaturesCfm(HFP *hfp, hfp_lib_status status, bool callerName, bool rawText, bool smsInd, bool battLevel, bool pwrSource , uint16 codecs) { /* Send an internal message */ MAKE_HFP_MESSAGE(HFP_CSR_SUPPORTED_FEATURES_CFM); message->hfp = hfp; message->status = status; message->callerName = callerName; message->rawText = rawText; message->smsInd = smsInd; message->battLevel = battLevel; message->pwrSource = pwrSource; message->codecs = codecs ; MessageSend(hfp->clientTask, HFP_CSR_SUPPORTED_FEATURES_CFM, message); }
void hfpHandleFeatureNegotiation ( Task task , const struct hfpHandleFeatureNegotiation *feat ) { HFP *hfp = (HFP*)task; PRINT(("CSFN received\n" )); if ( hfp->use_csr2csr) { MAKE_HFP_MESSAGE(HFP_CSR_FEATURE_NEGOTIATION_IND); message->hfp = hfp; message->indicator = feat->ind; message->value = feat->val ; MessageSend(hfp->clientTask, HFP_CSR_FEATURE_NEGOTIATION_IND, message); } }
void HfpCsrPowerSource(HFP *hfp, hfp_csr_power_status_report pwr_status) { #ifdef HFP_DEBUG_LIB if (!hfp) { HFP_DEBUG(("Null hfp task ptr passed in.\n")); } #endif if (hfp->use_csr2csr) { /* Send an internal message */ MAKE_HFP_MESSAGE(HFP_INTERNAL_CSR_POWER_SOURCE_REQ); message->pwr_status = pwr_status; MessageSend(&hfp->task, HFP_INTERNAL_CSR_POWER_SOURCE_REQ, message); } }
/**************************************************************************** NAME hfpHandleRfcommDisconnectInd DESCRIPTION Indication that the RFCOMM connection has been disconnected. RETURNS void */ void hfpHandleRfcommDisconnectInd(HFP *hfp, const CL_RFCOMM_DISCONNECT_IND_T *ind) { if (hfp->state == hfpSlcConnecting) { /* Rfcomm connection has been shutdown during the SLC connection process */ /* Cancel the AT response timeout message because we'll have no more AT cmds being sent */ (void) MessageCancelAll(&hfp->task, HFP_INTERNAL_WAIT_AT_TIMEOUT_IND); /* Report a failed connect attempt to app */ hfpSendSlcConnectCfmToApp(hfp_connect_slc_failed, hfp); } else { /* Convert the rfc disconnect status into its hfp counterpart and inform library */ MAKE_HFP_MESSAGE(HFP_INTERNAL_SLC_DISCONNECT_IND); message->status = convertRfcommDisconnectStatus(ind->status); MessageSend(&hfp->task, HFP_INTERNAL_SLC_DISCONNECT_IND, message); } }
void HfpCsrPowerLevel(HFP *hfp, uint16 pwr_level) { #ifdef HFP_DEBUG_LIB if (!hfp) { HFP_DEBUG(("Null hfp task ptr passed in.\n")); } #endif if (hfp->use_csr2csr) { /* Send an internal message */ MAKE_HFP_MESSAGE(HFP_INTERNAL_CSR_POWER_LEVEL_REQ); message->pwr_level = pwr_level; MessageSend(&hfp->task, HFP_INTERNAL_CSR_POWER_LEVEL_REQ, message); } }
/**************************************************************************** NAME hfpSendSlcDisconnectIndToApp DESCRIPTION Send a HFP_SLC_DISCONNECT_IND message to the app notifying it that the SLC has been disconnected. RETURNS void */ void hfpSendSlcDisconnectIndToApp(hfp_link_data* link, hfp_disconnect_status status) { MAKE_HFP_MESSAGE(HFP_SLC_DISCONNECT_IND); message->status = status; message->priority = hfpGetLinkPriority(link); (void)hfpGetLinkBdaddr(link, &message->bd_addr); /* Tidy up if valid link was disconnected */ if(status != hfp_disconnect_no_slc) { /* Reset the connection related state */ hfpLinkReset(link, TRUE); /* Cancel the AT response timeout message because we'll have no more AT cmds being sent */ (void) MessageCancelAll(&theHfp->task, hfpGetLinkTimeoutMessage(link, HFP_INTERNAL_WAIT_AT_TIMEOUT_LINK_0_IND)); } MessageSend(theHfp->clientTask, HFP_SLC_DISCONNECT_IND, message); }
void hfpHandleReponseCSRSupportedFeatures(Task task, const struct hfpHandleReponseCSRSupportedFeatures *features) { HFP *hfp = (HFP*)task; if (!hfp->use_csr2csr) { /* CSR 2 CSR Extensions not initialised. Ignore */ return; } else { /* Send internal message */ MAKE_HFP_MESSAGE(HFP_INTERNAL_CSR_SUPPORTED_FEATURES_ACK); message->callerName = (features->callerName=='0'?FALSE:TRUE); message->rawText = (features->rawText=='0'?FALSE:TRUE); message->smsInd = (features->smsInd=='0'?FALSE:TRUE); message->battLevel = (features->battLevel=='0'?FALSE:TRUE); message->pwrSource = (features->pwrSource=='0'?FALSE:TRUE); MessageSend(task, HFP_INTERNAL_CSR_SUPPORTED_FEATURES_ACK, message); } }
void HfpCsrGetSms(HFP *hfp, uint16 index) { #ifdef HFP_DEBUG_LIB if (!hfp) { HFP_DEBUG(("Null hfp task ptr passed in.\n")); } #endif if (hfp->use_csr2csr) { /* Send an internal message */ MAKE_HFP_MESSAGE(HFP_INTERNAL_CSR_GET_SMS_REQ); message->index = index; MessageSend(&hfp->task, HFP_INTERNAL_CSR_GET_SMS_REQ, message); } else { hfpSendCsrSmsCfm(hfp, hfp_csr_not_inited, 0, NULL); } }
/**************************************************************************** NAME hfpHandleChldAtAck DESCRIPTION This function handles the receipt of an OK or ERROR response to a multiparty call handling request. The status argument is used to inform the application whether the AT command was recognised by the AG or not. RETURNS void */ void hfpHandleChldAtAck(hfp_link_data* link, hfp_chld_action action, hfp_lib_status status) { /* Handle special cases for CHLD Acks */ if(action == hfp_chld_add_held_to_multiparty) { /* Enter multiparty state if AG doesn't support CLCC */ if(status == hfp_success) hfpHandleCallMultiparty(link); } else if(action == hfp_chld_release_active_accept_other) { hfp_at_cmd pending_cmd = hfpCmdPending; /* Try sending AT+CHUP if AT+CHLD=1 failed and we are in TWC state (regardless of TWC support) */ if(status == hfp_fail && hfpCheckCallActionState(link, action, 0, &pending_cmd)) { /* If we already tried sending AT+CHUP give up */ if(!link->at_chup_retried) { /* Otherwise attempt sending AT+CHUP */ link->at_chup_retried = hfpHandleTerminateCall(link, pending_cmd); /* If we sent AT+CHUP don't send confirmation yet */ if(link->at_chup_retried) return; } } /* Clear the chup retry flag */ link->at_chup_retried = FALSE; } #ifndef HFP_MIN_CFM { MAKE_HFP_MESSAGE(HFP_CALL_HOLD_ACTION_CFM); message->priority = hfpGetLinkPriority(link); message->action = action; message->status = status; MessageSend(theHfp->clientTask, HFP_CALL_HOLD_ACTION_CFM, message); } #endif }
/**************************************************************************** NAME HfpDialMemoryLocation DESCRIPTION This function issues a request to the AG to dial from the the supplied memory_location (the HFP specification defines the command but it is AG implementation dependent how this is implemented). The request is issued on the SLC associated with the hfp profile instance passed in by the application. The length argument specifies the length in bytes of the memory_location to be sent. The memory_location is the location the AG must dial from. The message returned indicates whether the command was recognised by the AG or not. MESSAGE RETURNED HFP_DIAL_MEMORY_CFM RETURNS void */ void HfpDialMemoryLocation(HFP *hfp, uint16 length, const uint8 *memory_location) { #ifdef HFP_DEBUG_LIB if (!hfp) HFP_DEBUG(("Null hfp task ptr passed in.\n")); if (!length) HFP_DEBUG(("Zero length passed in.\n")); if (!memory_location) HFP_DEBUG(("Null memory location ptr passed in.\n")); #endif /* Send an internal message */ { MAKE_HFP_MESSAGE(HFP_INTERNAL_AT_ATD_MEMORY_REQ); message->length = length; message->memory = (uint8 *) PanicUnlessMalloc(length); memmove(message->memory, memory_location, length); MessageSend(&hfp->task, HFP_INTERNAL_AT_ATD_MEMORY_REQ, message); } }
/**************************************************************************** NAME hfpHandleDisconnectRequest DESCRIPTION We're in the right state and have received a disconnect request, handle it here. RETURNS void */ void hfpHandleDisconnectRequest(hfp_link_data* link) { if (link->audio_sink) { MAKE_HFP_MESSAGE(HFP_INTERNAL_SLC_DISCONNECT_REQ); message->link = link; /* If we have a SCO/eSCO active need to tear that down first */ hfpHandleAudioDisconnectReq(link); /* Queue up the SLC disconnect message */ MessageSendConditionally(&theHfp->task, HFP_INTERNAL_SLC_DISCONNECT_REQ, message, (uint16 *) &link->audio_sink); /*lint !e740 */ } else { /* If recovering from link loss or timed out we need to be sure to force disconnect */ if (link->ag_link_loss_state == hfp_link_loss_recovery || link->ag_link_loss_state == hfp_link_loss_timeout) { /* Link was recovering from link loss, stop the procedure */ MessageId message_id = hfpGetLinkTimeoutMessage(link, HFP_RFCOMM_LINK_LOSS_TIMEOUT_LINK_0_IND); MessageCancelFirst(&theHfp->task, message_id); hfpHandleRfcommLinkLossAbort(link, TRUE); } /* Either no link loss or we aborted link loss recovery. Now bring down the link. */ else { /* Can only get here from searching/outgoing/incoming/connected/complete */ if(link->ag_slc_state == hfp_slc_searching) { /* Notify application of connection failure (link will be reset so SDP results ignored) */ hfpSendSlcConnectCfmToApp(link, NULL, hfp_connect_sdp_fail); } else { /* Request the connection lib aborts/disconnects the RFCOMM connection */ ConnectionRfcommDisconnectRequest(&theHfp->task, hfpGetLinkSink(link)); } } } }