/**************************************************************************** NAME linkPolicyPhonebookAccessComplete DESCRIPTION set the link policy requirements back after phonebook access, based on current device audio state RETURNS void */ void linkPolicyPhonebookAccessComplete(Sink sink) { typed_bdaddr taddr; uint16 DeviceId; uint16 StreamId; uint8 i; bool a2dpSetting = FALSE; /* If device is in the stream a2dp state, use a2dp link policy */ for_all_a2dp(i) { DeviceId = theSink.a2dp_link_data->device_id[i]; StreamId = theSink.a2dp_link_data->stream_id[i]; if( SinkGetBdAddr(sink, &taddr) && BdaddrIsSame(&theSink.a2dp_link_data->bd_addr[i], &taddr.addr) ) { a2dpSetting = TRUE; if(A2dpMediaGetState(DeviceId, StreamId)== a2dp_stream_streaming) linkPolicyUseA2dpSettings(DeviceId, StreamId, A2dpMediaGetSink(DeviceId, StreamId)); else linkPolicyUseHfpSettings(hfp_primary_link, sink); } } /* Otherwise, use hfp link policy */ if(!a2dpSetting) { linkPolicyUseHfpSettings(hfp_primary_link, sink); } }
void A2dpOpen(A2DP *a2dp, uint16 size_local_seids, uint8 *local_seids) { bdaddr addr; #ifdef A2DP_DEBUG_LIB if (!a2dp) A2DP_DEBUG(("A2dpOpen NULL instance\n")); #endif if (!local_seids || !size_local_seids) { /* If the user failed to supply connect params go no further. */ a2dpSendOpenCfm(a2dp, a2dp->clientTask, a2dp_invalid_parameters); return; } if ((a2dp->signal_conn.connection_state != avdtp_connection_connected) || !SinkGetBdAddr(a2dp->signal_conn.sink, &addr)) { /* There must be a signalling channel open first. */ a2dpSendOpenCfm(a2dp, a2dp->clientTask, a2dp_no_signalling_connection); return; } a2dpFreeSeidListMemory(a2dp); a2dp->signal_conn.connect_then_open_media = FALSE; initiateOpen(a2dp, a2dp->clientTask, &addr, size_local_seids, local_seids); }
/**************************************************************************** NAME connectionHandleReadRemoteSupportedFeaturesRequest DESCRIPTION Request to read the supported features of a remote device. RETURNS void */ void connectionHandleReadRemoteSupportedFeaturesRequest(connectionReadInfoState *state, const CL_INTERNAL_DM_READ_REMOTE_SUPP_FEAT_REQ_T *req) { /* Check the resource lock */ if (!state->stateInfoLock) { bdaddr addr; /* Check we got a valid addr */ if (!SinkGetBdAddr(req->sink, &addr)) { /* Send an error to the app as it didn't pass in a valid sink */ sendRemoteSupportedFeaturesCfm(req->theAppTask, hci_error_no_connection, 0, req->sink); } else { /* Response not outstanding so issue request */ MAKE_PRIM_C(DM_HCI_READ_REMOTE_FEATURES); connectionConvertBdaddr_t(&prim->bd_addr, &addr); VmSendDmPrim(prim); /* Set the lock */ state->stateInfoLock = req->theAppTask; state->sink = req->sink; } } else { /* Lock set so queue up the request */ MAKE_CL_MESSAGE(CL_INTERNAL_DM_READ_REMOTE_SUPP_FEAT_REQ); COPY_CL_MESSAGE(req, message); MessageSendConditionallyOnTask(connectionGetCmTask(), CL_INTERNAL_DM_READ_REMOTE_SUPP_FEAT_REQ, message, &state->stateInfoLock); } }
/**************************************************************************** NAME handleClRoleCfm DESCRIPTION Handles the role switch result. */ static void handleClRoleCfm(const CL_DM_ROLE_CFM_T *cfm) { bdaddr addr; devInstanceTaskData *inst = NULL; if (SinkGetBdAddr(cfm->sink, &addr)) inst = devInstanceFindFromBddr(&addr, FALSE); if (inst != NULL) { handleClRole(inst, cfm->role, cfm->status, TRUE); } }
void AvrcpGetProfileExtensions(AVRCP *avrcp) { bdaddr my_addr; if (SinkGetBdAddr(avrcp->sink, &my_addr)) { MessageSendConditionally(&avrcp->task, AVRCP_INTERNAL_GET_EXTENSIONS, 0, &avrcp->sdp_search_mode); } else { avrcpSendGetExtensionsCfm(avrcp, avrcp_device_not_connected, 0); } }
void AvrcpGetSupportedFeatures(AVRCP *avrcp) { bdaddr my_addr; if (SinkGetBdAddr(avrcp->sink, &my_addr)) { MessageSendConditionally(&avrcp->task, AVRCP_INTERNAL_GET_FEATURES, 0, &avrcp->sdp_search_mode); } else { avrcpSendGetSupportedFeaturesCfm(avrcp, avrcp_device_not_connected, 0); } }
/**************************************************************************** NAME slcHandleLinkLossInd DESCRIPTION Indication of change in link loss status. RETURNS void */ void slcHandleLinkLossInd( const HFP_SLC_LINK_LOSS_IND_T *ind ) { typed_bdaddr ag_addr; Sink sink; /* Are we recovering or have we recovered? */ if(ind->status == hfp_link_loss_recovery) { /* Send an event to notify the user */ MessageCancelAll(&theSink.task , EventSysLinkLoss ); MessageSend(&theSink.task , EventSysLinkLoss , 0); /* Go connectable if feature enabled */ if(theSink.features.GoConnectableDuringLinkLoss) sinkEnableConnectable(); } else if(ind->status == hfp_link_loss_none) { sink_attributes attributes; /* Get Sink and bdaddr for the link */ HfpLinkGetSlcSink(ind->priority, &sink); SinkGetBdAddr(sink, &ag_addr); /* Carry out link setup */ slcConnectionSetup(ind->priority, sink, &ag_addr.addr); /* Link loss recovered - disable connectable */ if(theSink.features.GoConnectableDuringLinkLoss) { #ifdef ENABLE_SUBWOOFER if(SwatGetSignallingSink(theSink.rundata->subwoofer.dev_id)) { sinkDisableConnectable(); } #else sinkDisableConnectable(); #endif } /* Reconnect A2DP if appropriate */ if( theSink.features.EnableA2dpStreaming && deviceManagerGetAttributes(&attributes, (const bdaddr *)&ag_addr.addr) && (attributes.profiles & sink_a2dp) ) { SLC_DEBUG(("SLC: Reconnecting A2DP\n")) ; /* attempt reconnection to device supporting A2DP */ A2dpSignallingConnectRequest((bdaddr *)&ag_addr.addr); } } }
/**************************************************************************** NAME connectionHandleWriteFlushTimeoutRequest DESCRIPTION Set the flush timeout for a particular ACL. RETURNS void */ void connectionHandleWriteFlushTimeoutRequest(const CL_INTERNAL_DM_WRITE_FLUSH_TIMEOUT_REQ_T *req) { bdaddr addr; /* Convert the sink to the address of the underlying ACL and only issue this if we have an ACL */ if (SinkGetBdAddr(req->sink, &addr)) { /* Send the request to BlueStack */ MAKE_PRIM_C(DM_HCI_WRITE_AUTO_FLUSH_TIMEOUT); connectionConvertBdaddr_t(&prim->bd_addr, &addr); prim->timeout = req->flush_timeout; VmSendDmPrim(prim); } }
void ConnectionSmEncryptionKeyRefreshSink(Sink sink) { #ifdef CONNECTION_DEBUG_LIB if(!sink) { CL_DEBUG(("Null sink passed in\n")); } #endif { bdaddr addr; if(SinkGetBdAddr(sink, &addr)) { MAKE_CL_MESSAGE(CL_INTERNAL_SM_ENCRYPTION_KEY_REFRESH_REQ); message->bd_addr = addr; MessageSend(connectionGetCmTask(), CL_INTERNAL_SM_ENCRYPTION_KEY_REFRESH_REQ, message); } } }
static void handleA2DPOpenInd(Sink sink, uint8 seid) { bdaddr bdaddr_ind; SendEvent(EVT_A2DP_OPEN_IND,0); if (SinkGetBdAddr(sink, &bdaddr_ind)) { uint8 lAttributes[ATTRIBUTE_SIZE]; avrcpConnectReq(bdaddr_ind, FALSE); /* Retrieve attributes for this device */ if (ConnectionSmGetAttributeNow(PSKEY_ATTRIBUTE_BASE, &bdaddr_ind, ATTRIBUTE_SIZE, lAttributes)) { bool write_params = FALSE; if (lAttributes[attribute_seid] != seid) { lAttributes[attribute_seid] = seid; write_params = TRUE; } if (lAttributes[attribute_a2dp_volume] != theHeadset.gAvVolumeLevel) { lAttributes[attribute_a2dp_volume] = theHeadset.gAvVolumeLevel; write_params = TRUE; } if (write_params) { /* Write params to PS */ ConnectionSmPutAttribute(PSKEY_ATTRIBUTE_BASE, &bdaddr_ind, ATTRIBUTE_SIZE, lAttributes); A2DP_MSG_DEBUG(("A2DP: Store A2DP attributes [%d][%d][%d][%d][%d][%d]\n",lAttributes[0], lAttributes[1],lAttributes[2],lAttributes[3],lAttributes[4],lAttributes[5])) ; } } theHeadset.seid = seid; theHeadset.last_used_seid = seid; A2DP_MSG_DEBUG((" Selected SEID = %d\n", seid)); stateManagerEnterA2dpConnectedState(); PROFILE_MEMORY(("A2DPOpen")) }
/**************************************************************************** NAME hfpGetAgProfileVersion DESCRIPTION Requests HFP profile version supported by the AG. RETURNS void */ void hfpGetAgProfileVersion(HFP *hfp) { bdaddr my_addr; if (SinkGetBdAddr(hfp->sink, &my_addr)) { /* 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. */ hfp->sdp_search_mode = hfp_sdp_search_profile_version; ConnectionSdpServiceSearchAttributeRequest(&hfp->task, &my_addr, 0x32, sizeof(HfpServiceRequest), (uint8 *) HfpServiceRequest, sizeof(profileDescriptorRequest), profileDescriptorRequest); } else { /* Something has gone wrong - panic */ HFP_DEBUG(("SinkGetBdAddr failed\n")); } }
static void handlePbapConnectCfm(PBAPC_CONNECT_CFM_T *pMsg) { PBAP_DEBUG(("PBAPC_CONNECT_CFM, Status : %d, packet size:[%d]\n", pMsg->status, pMsg->packetSize)); if(pMsg->status == pbapc_success) { /* If the Pbap of primary HFP device has been connected, save its device_id as the active link */ bdaddr ag_addr; Sink sink; if( HfpLinkGetSlcSink(hfp_primary_link, &sink) && SinkGetBdAddr(sink, &ag_addr) ) { if(BdaddrIsSame(&ag_addr, &(pMsg->bdAddr))) { theHeadset.pbap_active_link = pMsg->device_id; PBAP_DEBUG(("PBAPC_CONNECT_CFM, Set the active Pbap link as [%d]\n", theHeadset.pbap_active_link)); #ifdef BHC612 PBAP_DEBUG(("[BT Addr: nap %04x uap %02x lap %08lx]\n",ag_addr.nap,ag_addr.uap,ag_addr.lap)); #endif } } /* if we are making Pbapc dialing now */ if(theHeadset.pbap_dial_state == pbapc_dialling) { PBAP_DEBUG(("PBAPC_CONNECT_CFM, Pbap dialling, set the phonebook\n")); /* Set required phonebook */ PbapcSetPhonebook(pMsg->device_id, pbap_local, theHeadset.pbap_active_pb); } } else { /* pbapc profile connection failure */ if(theHeadset.pbap_dial_state == pbapc_dialling) { MessageSend ( &theHeadset.task , EventPbapDialFail , 0 ) ; theHeadset.pbap_dial_state = pbapc_no_dial; } } }
/**************************************************************************** NAME connectionHandleReadRemoteVersionRequest DESCRIPTION Request to read the version information of a remote device. RETURNS void */ void connectionHandleReadRemoteVersionRequest(connectionReadInfoState *state, const CL_INTERNAL_DM_READ_REMOTE_VERSION_REQ_T *req) { /* Check the resource lock */ if (!state->stateInfoLock) { bdaddr addr; /* Check we got a valid addr */ if (!SinkGetBdAddr(req->sink, &addr)) { /* Create and send the message */ MAKE_CL_MESSAGE(CL_DM_REMOTE_VERSION_CFM); message->status = hci_error_no_connection; message->lmpVersion = 0; message->manufacturerName = 0; message->lmpSubVersion = 0; MessageSend(req->theAppTask, CL_DM_REMOTE_VERSION_CFM, message); } else { /* Response not outstanding so issue request */ MAKE_PRIM_C(DM_HCI_READ_REMOTE_VERSION); connectionConvertBdaddr_t(&prim->bd_addr, &addr); VmSendDmPrim(prim); /* Set the lock */ state->stateInfoLock = req->theAppTask; } } else { /* Lock set so queue up the request */ MAKE_CL_MESSAGE(CL_INTERNAL_DM_READ_REMOTE_VERSION_REQ); COPY_CL_MESSAGE(req, message); MessageSendConditionallyOnTask(connectionGetCmTask(), CL_INTERNAL_DM_READ_REMOTE_VERSION_REQ, message, &state->stateInfoLock); } }
/**************************************************************************** NAME connectionHandleWriteFlushTimeoutRequest DESCRIPTION Set the flush timeout for a particular ACL. RETURNS void */ void connectionHandleWriteFlushTimeoutRequest(const CL_INTERNAL_DM_WRITE_FLUSH_TIMEOUT_REQ_T *req) { typed_bdaddr taddr; /* Convert the sink to the address of the underlying ACL and only issue this if we have an ACL */ if (SinkGetBdAddr(req->sink, &taddr)) { if (taddr.type == TYPED_BDADDR_PUBLIC) { /* Send the request to BlueStack */ MAKE_PRIM_C(DM_HCI_WRITE_AUTO_FLUSH_TIMEOUT_REQ); BdaddrConvertVmToBluestack(&prim->bd_addr, &taddr.addr); prim->timeout = req->flush_timeout; VmSendDmPrim(prim); } else { CL_DEBUG(("SinkGetBdAddr returned non-public type\n")); } } }
/* Dial the first entry in the specified phonebook */ static void pbapDial(uint8 phonebook) { /* attempt to dial the first entry in the AG missed call history */ if(theHeadset.pbap_ready) { if(theHeadset.pbap_active_link != pbapc_invalid_link) { /* the Pbap profile of the primary HFP device has been connected */ /* set the phonebook and dial */ PBAP_DEBUG(("Pbap dial, set the phonebook first\n")); PbapcSetPhonebook(theHeadset.pbap_active_link, pbap_local, phonebook); } else { /* Otherwise, try to connect Pbap profile of the primary HFP device before dialling */ bdaddr ag_addr; Sink sink; if( HfpLinkGetSlcSink(hfp_primary_link, &sink) && SinkGetBdAddr(sink, &ag_addr) ) { PBAP_DEBUG(("Pbap dial, connect the Pbap profile first\n")); pbapConnect(ag_addr); } } theHeadset.pbap_active_pb = phonebook; } else { PBAP_DEBUG(("PBAPC profile was not initialised\n")); MessageSend ( &theHeadset.task , EventPbapDialFail , 0 ) ; theHeadset.pbap_dial_state = pbapc_no_dial; } }
/* Accept/reject an incoming audio connect request */ static void audioConnectResponse(AGHFP *aghfp, bool response, sync_pkt_type packet_type, const aghfp_audio_params *audio_params) { tp_bdaddr tpaddr; sync_config_params config_params; AGHFP_DEBUG(("audioConnectResponse\n")); /* If connection request is being rejected, don't worry about validating params being returned */ if ( !response ) { AGHFP_DEBUG(("if !response\n")); /* To send the response we need the bd addr of the underlying connection. */ if(SinkGetBdAddr(aghfp->rfcomm_sink, &tpaddr)) { AGHFP_DEBUG(("SinkGetBdAddr\n")); ConnectionSyncConnectResponse(&aghfp->task, &tpaddr.taddr.addr, FALSE, 0); } /* If we can't get the addr from the sink then quietly don't respond. If the underlying ACL has gone down there's not much we can do. */ } else { AGHFP_DEBUG(("setting audio params\n")); if((aghfp->use_wbs) && !(aghfp->hf_supported_features & aghfp_hf_codec_negotiation)) { AGHFP_DEBUG(("using default CVSD Sco parameters \n")); config_params.tx_bandwidth = 8000; config_params.rx_bandwidth = 8000; config_params.max_latency = 16; config_params.voice_settings = 0; config_params.retx_effort = sync_retx_power_usage; config_params.packet_type = 0x2BF; } else { config_params.tx_bandwidth = audio_params->bandwidth; config_params.rx_bandwidth = audio_params->bandwidth; config_params.max_latency = audio_params->max_latency; config_params.voice_settings = audio_params->voice_settings; config_params.retx_effort = audio_params->retx_effort; config_params.packet_type = packet_type; } /* To send the response we need the bd addr of the underlying connection. If we can't get the addr from the sink then quietly don't respond. If the underlying ACL has gone down there's not much we can do. */ if(SinkGetBdAddr(aghfp->rfcomm_sink, &tpaddr)) { AGHFP_DEBUG(("ConnectionSyncConnectResponse\n")); ConnectionSyncConnectResponse(&aghfp->task, &tpaddr.taddr.addr, TRUE, &config_params); } } }