static bool id_match(const conn_instance* p, conn_type type, conn_id id)
{
    bool match = FALSE;

    if(p != NULL)
    {
        if(p->type == type)
        {
            switch(type)
            {
            case conn_rfcomm:
                /* Searching for an RFCOMM connection instance is complicated as only limited
                   data is available during the early phases of connection establishment.  It's
                   not until the completion of parameter negotiation that the mux id and server 
                   channel have been assigned */
                if(id.rfcomm_id.server_channel == INVALID_SERVER_CHANNEL)
                {
                    /* Invalid Server Channel, match on Bluetooth Device Address and Multiplexer id */
                    if(BdaddrIsSame(&p->id.rfcomm_id.bd_addr, &id.rfcomm_id.bd_addr) || (p->id.rfcomm_id.mux_id == id.rfcomm_id.mux_id))
                    {
                        match = TRUE;
                    }
                    if(BdaddrIsZero(&id.rfcomm_id.bd_addr) && (p->id.rfcomm_id.mux_id == id.rfcomm_id.mux_id))
                    {
                        if(p->id.rfcomm_id.server_channel == 0xff)
                            match = TRUE;
                    }
                }
                else if(id.rfcomm_id.mux_id == INVALID_MUX_ID)
                {
                    /* Invalid Multiplexer ID, match on Bluetooth Address and Server Channel */
                    if (BdaddrIsSame(&p->id.rfcomm_id.bd_addr, &id.rfcomm_id.bd_addr) && (p->id.rfcomm_id.server_channel == id.rfcomm_id.server_channel))
                        match = TRUE;
                }
                else
                {
                    /* Match on Multiplexer ID and Server Channel */
                    if((p->id.rfcomm_id.mux_id == id.rfcomm_id.mux_id && p->id.rfcomm_id.server_channel == id.rfcomm_id.server_channel))
                    {
                        match = TRUE;
                    }
                }
                break;

            case conn_l2cap:
                if(p->id.l2cap_id.cid == id.l2cap_id.cid && id.l2cap_id.cid != L2CA_CID_INVALID)
                    match = TRUE;
				else if ((p->id.l2cap_id.psm == id.l2cap_id.psm) && (id.l2cap_id.psm != L2CA_PSM_INVALID) &&
					(id.l2cap_id.cid != L2CA_CID_INVALID) &&(p->id.l2cap_id.cid == L2CA_CID_INVALID))
					match = FALSE;
                else if (p->id.l2cap_id.psm == id.l2cap_id.psm && id.l2cap_id.psm != L2CA_PSM_INVALID && 
                    p->id.l2cap_id.cid == L2CA_CID_INVALID)
                    match = TRUE;
                break;
            }
        }
    }

    return match;
}
Example #2
0
/*************************************************************************
NAME    
    gattFindConnAddr
    
DESCRIPTION
    Find GATT connection entry in task_cid_map by the address. This only done 
    for SDP searches and so the transport will always be BREDR and the address
    type PUBLIC.

RETURNS
    
*/
cid_map_t *gattFindConnAddr(const bdaddr *addr)
{
    cid_map_t *found = NULL;
    cid_map_t *conn;
    tp_bdaddr tpaddr;
    uint16 i;

    /* go through active connections */
    for (i = 0; i < MAX_ATT_CONNECTIONS; i++)
    {
        conn = &theGatt->u.cid_map[i];
        
        /* fake instance for SDP search */
        if ((conn->data.scenario == gatt_ms_discover_all_bredr_services ||
             conn->data.scenario == gatt_ms_discover_bredr_service) &&
            BdaddrIsSame(
                addr,
                &conn->data.req.discover_all_bredr_services.addr))
        {
            return conn;
        }
        
        /* get address from cid */
        else if (VmGetBdAddrtFromCid(conn->cid, &tpaddr) &&
                 tpaddr.transport == TRANSPORT_BREDR_ACL &&
                 tpaddr.taddr.type == TBDADDR_PUBLIC &&
                 BdaddrIsSame(addr, &tpaddr.taddr.addr))
        {
            found = conn;
        }
    }

    return found;
}
Example #3
0
/****************************************************************************
NAME    
    sinkCheckAvrcpStateMatch
    
DESCRIPTION
    helper function to check an avrcp play status for a given a2dp link priority
    
RETURNS
    true is the avrcp play state matches that passed in
    false if state does not match or no matching avrcp link is found for a2dp profile index
*/
bool sinkCheckAvrcpStateMatch(a2dp_link_priority priority, avrcp_play_status play_status)
{
    if((BdaddrIsSame(&theSink.a2dp_link_data->bd_addr[priority], &theSink.avrcp_link_data->bd_addr[a2dp_primary])&&(theSink.avrcp_link_data->play_status[a2dp_primary] == play_status))||
       (BdaddrIsSame(&theSink.a2dp_link_data->bd_addr[priority], &theSink.avrcp_link_data->bd_addr[a2dp_secondary])&&(theSink.avrcp_link_data->play_status[a2dp_secondary] == play_status)))
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}
Example #4
0
/****************************************************************************
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); 
    }
}
/****************************************************************************
NAME	
	sendSearchRequest

DESCRIPTION
	Decide whather a search request primitive can be sent to BlueStack or not

RETURNS
	sdp_search_req - see typedef above
*/
static sdp_search_req sendSearchRequest(Task theAppTask, const connectionSdpState *state, const bdaddr *bd_addr)
{
	/* Check the first lock */
	if (state->sdpLock)
	{
		/* SDP search session open or non search primitive sent to BlueStack */
		if (BdaddrIsZero(&state->sdpServerAddr))
		{
			/* 
				SDP search session not open but another prim is currently 
				being handled (sdpLock set) so we can't start the search yet
			*/
			return sdp_lock_set;
		}
		else
		{
			/* Addr set - SDP search session open */
			if (state->sdpSearchLock)
			{
				/* Search currently active so can't start another one */
				return sdp_search_lock_set;
			}
			else
			{
				/* SDP session open but no active search */
				if (BdaddrIsSame(&state->sdpServerAddr, bd_addr))
				{
					/* 
						SDP search session open to the device we want to search 
						so we can just start our search
					*/
					return sdp_start_search;
				}
				else
				{
					/* 
						SDP search session open to a different device so we can't
						do our search until this session is closed.
					*/
					return sdp_session_open_other_dev;
				}
			}
		}
	}
	else
	{
		/* Check if we currently have a search active, block internal requests if sdpLock not set */
		if (state->sdpSearchLock || theAppTask == connectionGetCmTask())
		{
			/* Search currently active */
			return sdp_search_lock_set;
		}
		else
		{
			/* No search currently active */
			return sdp_start_search;
		}
	}
}
Example #6
0
/****************************************************************************
NAME    
    sinkPartyModeCheckForOtherPausedSource
    
DESCRIPTION
    function to look for a device other than the one passed in that is in an paused
    state
    
RETURNS
    link priority if an avrcp paused device is found
*/
a2dp_link_priority sinkPartyModeCheckForOtherPausedSource(a2dp_link_priority link)
{
    
    /* determine if the other device is connected and has avrcp connected*/
    if(BdaddrIsSame(&theSink.a2dp_link_data->bd_addr[OTHER_DEVICE(link)], &theSink.avrcp_link_data->bd_addr[a2dp_primary]))
    {
        /* device is connected, check its current avrcp state, if paused then return index of device */
        if(theSink.avrcp_link_data->play_status[a2dp_primary] == avrcp_play_status_paused)
            return OTHER_DEVICE(link);
    }
    /* determine if the other device is connected and has avrcp connected*/
    else if(BdaddrIsSame(&theSink.a2dp_link_data->bd_addr[OTHER_DEVICE(link)], &theSink.avrcp_link_data->bd_addr[a2dp_secondary]))
    {
        /* device is connected, check its current avrcp state, if paused then return index of device */        
        if(theSink.avrcp_link_data->play_status[a2dp_secondary] == avrcp_play_status_paused)
            return OTHER_DEVICE(link);
    }
    /* no paused other devices found */
    return a2dp_invalid;
}    
/****************************************************************************
NAME 
	hidFindFromBddr
DESCRIPTION
	Searches for a HID instance with matching address.
RETURNS
	HID - Pointer to HID instance, or NULL if no match.
*/
HID *hidFindFromBddr(HID_LIB *hid_lib, const bdaddr *addr)
{
    HID *hid = hid_lib->list;
    while (hid)
    {
        if (BdaddrIsSame(&hid->remote_addr, addr))
            break;
        hid = hid->next;        
    }
    
    return hid;
}
Example #8
0
/****************************************************************************
NAME    
    deviceManagerIsSameDevice
    
DESCRIPTION
    Determines if the supplied HF and AV devices are actually one and the same

RETURNS
    TRUE if the devices are the same, FALSE otherwise
*/
bool deviceManagerIsSameDevice(a2dp_link_priority a2dp_link, hfp_link_priority hfp_link)
{
    typed_bdaddr tbdaddr1, tbdaddr2;
    
    if (theSink.a2dp_link_data && theSink.a2dp_link_data->connected[a2dp_link])
    {   /* A2dp link data present and device marked as connected */
        if (HfpLinkGetBdaddr(hfp_link, &tbdaddr1.addr) && A2dpDeviceGetBdaddr(theSink.a2dp_link_data->device_id[a2dp_link], &tbdaddr2.addr))
        {   /* Successfully obtained bdaddrs */
            return BdaddrIsSame(&tbdaddr1.addr, &tbdaddr2.addr);
        }
    }

    return FALSE;
}
Example #9
0
/****************************************************************************
NAME	
	mapcGetLinkFromBdAddr
    
DESCRIPTION
    Searches through any MAP connections looking for a match of bdaddr, if found
    returns the link associated with that bdaddr
    
PARAMS
    @pAddr
    
RETURNS
	mapc_link_priority
*/
static mapc_link_priority mapcGetLinkFromBdAddr(const bdaddr *pAddr)
{
    mapc_link_priority device_id = 0;
    
    /* search all possible map connections */
    for(device_id = 0; device_id < MAX_MAPC_CONNECTIONS; device_id ++)
    {
        mapcState *state = &(theSink.rundata->mapc_data.state[device_id]);
        /* if bdaddr matches that passed then return the appropriate link id */
        if(BdaddrIsSame(&state->bdAddr, pAddr))
            return(device_id);
    }
    /* no map connections matching the passed in bdaddr */
    return(mapc_invalid_link);
}
/****************************************************************************

DESCRIPTION
	This function searches for the specified peer device in the Trusted Device 
	List (TDL). The value returned as position defines the record number of the
	device in TDL.

	 --------------------------------------
	|R1 | R2 | R3 | R4 | R5 | R6 | R7 | R8 |
	 --------------------------------------

	If the value returned is zero then the device does not exist in
	the TDL
*/
static uint16 find_trusted_device(const bdaddr* p_peer_addr)
{
	uint16						rec;
    TrustedDeviceRecordType     record;

	/* Loop through list of trusted devices */
	for(rec = 0; rec < NO_DEVICES_TO_MANAGE; rec++)
	{
		if(PsRetrieve(TRUSTED_DEVICE_LIST_BASE + rec, &record, sizeof(TrustedDeviceRecordType)))
		{
			/* If this device is already a trusted device? */
			if(BdaddrIsSame(&record.bd_addr, p_peer_addr))
				return (rec + 1);
		}
	}
	/* Device is not in the trusted device list */
	return 0;
}
Task connectionGetPsmBdaddrMatch(uint16 psm_local, bdaddr addr, uint16 *instances)
{
	conn_instance*   curr = conn_list_head;
	Task appTask = NULL;
	
	*instances = 0;

    while(curr != NULL)
    {
        if((curr->type == conn_l2cap) && BdaddrIsSame(&curr->addr, &addr) && (curr->id.l2cap_id.psm == psm_local))
        {
            *instances = *instances + 1;
			appTask = curr->appTask;
        }
        curr = curr->next;
    }

    return appTask;
}
Example #12
0
/****************************************************************************
NAME    
    deviceManagerProfilesConnected
    
DESCRIPTION
    Compare bdaddr against those of the current connected devices

RETURNS
    conn_mask indicating which profiles the device is connected to
*/
conn_mask deviceManagerProfilesConnected(const bdaddr * bd_addr)
{
    bdaddr dev_addr;
    conn_mask mask, result = 0;
    
    /* Go through all profiles */
    for(mask = conn_hfp_pri; mask <= conn_a2dp_sec; mask <<=1)
    {
        /* Get bluetooth address for profile if connected */
        if(deviceManagerGetProfileAddr(mask, &dev_addr))
        {
            /* If address matches device passed in... */
            if(BdaddrIsSame(bd_addr, &dev_addr))
                result |= mask;
        }
    }
    DEV_DEBUG(("DEV: profiles connected bdaddr %x %x %x Conn Mask %X\n", (uint16)bd_addr->nap,(uint16)bd_addr->uap,(uint16)bd_addr->lap,result));
    return result;
}
Task connectionCompletedConnectionsGetPsmBdaddrMatch(uint16 psm_local, bdaddr addr, uint16 *instances)
{
	multiple_channels_instance*   curr = multiple_channels_list_head;
	Task appTask = NULL;
	uint16 i = 0;

	*instances = 0;

    for (i = 0; i < multiple_channels_entries; i++)
    {
        if(BdaddrIsSame(&curr->addr, &addr) && (curr->psm == psm_local))
        {
            *instances = *instances + 1;
			appTask = curr->appTask;
        }
        curr++;
    }

    return appTask;
}
Example #14
0
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
    scanStoreInquireResult

DESCRIPTION
    Stores the data returned in an inquiry result message.
    
*/
void scanStoreInquireResult (const CL_DM_INQUIRE_RESULT_T *prim)
{
    /* Default EIR values */
    mvdEirData    result;
    
    DEBUG_SCAN(("Found device: 0x%X 0x%X 0x%lX\n", (uint16)prim->bd_addr.nap, (uint16)prim->bd_addr.uap, (uint32)prim->bd_addr.lap));
    
    result = parseEirData(prim->size_eir_data, prim->eir_data);
            
    result.profiles &= the_app->supported_profiles;
    
    /* If device doesn't support anything we can use forget it */
    if ((result.profiles == ProfileNone) && (result.profiles_complete))
    {        
        DEBUG_SCAN(("Device Unsupported\n"));
        return;
    }
    
    /* Subtract RSSI from Inquiry Tx Power, assume min possible RSSI if unknown */
    result.path_loss -= (prim->rssi == CL_RSSI_UNKNOWN) ? -127 : prim->rssi;
    
    DEBUG_SCAN(("path loss: %i\n",result.path_loss));
    
    if ( (s_inquiry_scan_data != NULL) && (s_inquiry_scan_data->write_idx < INQUIRY_SCAN_BUFFER_SIZE) )
    {
        uint8 j,k;    
        
        /* Start by checking if we have already found this device */
        for ( k = 0 ; k < s_inquiry_scan_data->write_idx ; k++ )
        {
            /* Found duplicate */
            if (BdaddrIsSame(&prim->bd_addr, &s_inquiry_scan_data->buffer[k]))
            {
                DEBUG_SCAN(("Device already found\n"));
                
                /* If we got a lower path loss this time */
                if (result.path_loss < s_inquiry_scan_data->eir_data[k].path_loss)
                {
                    /* Remove the old record and put this one in */
                    DEBUG_SCAN((" - updating\n"));
                    s_inquiry_scan_data->write_idx--;
                    for ( j=k ; j < s_inquiry_scan_data->write_idx ; j++)
                    {
                        memcpy(&s_inquiry_scan_data->buffer[j],&s_inquiry_scan_data->buffer[j+1], sizeof(bdaddr));
                        s_inquiry_scan_data->eir_data[j] = s_inquiry_scan_data->eir_data[j+1];
                    }
                    break;
                }
                else
                {
                    /* No point updating */
                    DEBUG_SCAN((" - returning\n"));
                    return;
                }
            }
        }
        
        /* Move up the found devices list */
        for ( k = k ; k > 0 ; k-- )
        {
            /* If next dev up has lower path loss we have found our place */
            if (s_inquiry_scan_data->eir_data[k-1].path_loss <= result.path_loss)
                break;
        }
        
        DEBUG_SCAN(("Adding device at %d of %d\n",k,s_inquiry_scan_data->write_idx));
        
        
        /* Shuffle down other entries if required */
        for ( j = s_inquiry_scan_data->write_idx ; j > k ; j-- )
        {
            memcpy(&s_inquiry_scan_data->buffer[j],&s_inquiry_scan_data->buffer[j-1], sizeof(bdaddr));
            s_inquiry_scan_data->eir_data[j] = s_inquiry_scan_data->eir_data[j-1];
        }
        
        /* Add device at k and increment write index */
        memcpy(&s_inquiry_scan_data->buffer[k], &prim->bd_addr, sizeof(bdaddr));
        s_inquiry_scan_data->eir_data[k] = result;
        s_inquiry_scan_data->write_idx++;
    }
}
bool BdaddrTypedIsSame(const typed_bdaddr *first, const typed_bdaddr *second)
{
    return  first->type == second->type && 
            BdaddrIsSame(&first->addr, &second->addr);
}
Example #17
0
/****************************************************************************
NAME    
    inquiry_store_result - Store the device returned in the CL_DM_INQUIRE_RESULT message
*/
static void inquiry_store_result(const CL_DM_INQUIRE_RESULT_T *prim)
{      
    INQUIRY_EIR_DATA_T result;
    
    INQUIRY_DEBUG(("INQUIRY: Found device:"));
    DEBUG_BDADDR(prim->bd_addr);
    
    result = inquiry_parse_eir_data(prim->size_eir_data, prim->eir_data);
             
    /* If device doesn't support anything we can use forget it */
    if ((result.profiles == PROFILE_NONE) && (result.profiles_complete))
    {        
        INQUIRY_DEBUG(("INQUIRY: Device Unsupported\n"));
        return;
    }
    
    /* Subtract RSSI from Inquiry Tx Power, assume min possible RSSI if unknown */
    result.path_loss -= (prim->rssi == CL_RSSI_UNKNOWN) ? -127 : prim->rssi;
    
    INQUIRY_DEBUG(("INQUIRY: path loss: %i\n", result.path_loss));
    
    if ((theSource->inquiry_data != NULL) && (theSource->inquiry_data->write_idx < INQUIRY_SCAN_BUFFER_SIZE))
    {
        uint8 j, k;    
        
        /* Start by checking if we have already found this device */
        for (k = 0; k < theSource->inquiry_data->write_idx; k++)
        {
            /* Found duplicate */
            if (BdaddrIsSame(&prim->bd_addr, &theSource->inquiry_data->buffer[k] ))
            {
                INQUIRY_DEBUG(("INQUIRY: Device already found\n"));
                
                /* If we got a lower path loss this time */
                if (result.path_loss < theSource->inquiry_data->eir_data[k].path_loss)
                {
                    /* Remove the old record and put this one in */
                    INQUIRY_DEBUG(("INQUIRY: - updating\n"));
                    theSource->inquiry_data->write_idx--;
                    for (j = k; j < theSource->inquiry_data->write_idx; j++)
                    {
                        theSource->inquiry_data->buffer[j] = theSource->inquiry_data->buffer[j+1];
                        theSource->inquiry_data->eir_data[j] = theSource->inquiry_data->eir_data[j+1];
                    }
                    break;
                }
                else
                {
                    /* No point updating */
                    INQUIRY_DEBUG(("INQUIRY: - returning\n"));
                    return;
                }
            }
        }
        
        /* Move up the found devices list */
        for (k = k; k > 0; k--)
        {
            /* If next dev up has lower path loss we have found our place */
            if (theSource->inquiry_data->eir_data[k-1].path_loss <= result.path_loss)
                break;
        }
        
        INQUIRY_DEBUG(("INQUIRY: Adding device at %d of %d\n", k, theSource->inquiry_data->write_idx));        
        INQUIRY_DEBUG(("    path_loss:%d  profiles:%d  profiles_complete:%d\n", result.path_loss, result.profiles, result.profiles_complete));
        DEBUG_BDADDR(prim->bd_addr);
        
        
        /* Shuffle down other entries if required */
        for (j = theSource->inquiry_data->write_idx; j > k; j--)
        {
            theSource->inquiry_data->buffer[j] = theSource->inquiry_data->buffer[j-1];
            theSource->inquiry_data->eir_data[j] = theSource->inquiry_data->eir_data[j-1];
        }
        
        /* Add device at k and increment write index */
        theSource->inquiry_data->buffer[k] = prim->bd_addr;
        theSource->inquiry_data->eir_data[k] = result;
        theSource->inquiry_data->write_idx++;
    }
}
Example #18
0
/****************************************************************************
NAME    
    sinkHandleSlcConnectCfm
    
DESCRIPTION
    Confirmation that the SLC has been established (or not).

RETURNS
    void
*/
bool sinkHandleSlcConnectCfm( const HFP_SLC_CONNECT_CFM_T *cfm )
{
    sink_attributes attributes;
    bool lResult = FALSE;
    
#ifdef ENABLE_PEER    
    inquiry_result_t* connecting_device = inquiryGetConnectingDevice();
#endif
    
    deviceManagerGetDefaultAttributes(&attributes, FALSE);
    (void)deviceManagerGetAttributes(&attributes, &cfm->bd_addr);
    
    /* cancel any link loss reminders */        
    MessageCancelAll(&theSink.task , EventSysLinkLoss );

    /* Check the status of the SLC attempt */
    if (cfm->status == hfp_connect_success)
    {
        SLC_DEBUG(("SLC: ConnCfm - Success\n")) ;
        lResult = TRUE ;

        /* update the profile volume level */
        theSink.profile_data[PROFILE_INDEX(cfm->priority)].audio.gSMVolumeLevel = attributes.hfp.volume;     
        /* Handle new connection setup */
        slcConnectionComplete(cfm->priority, cfm->sink, (bdaddr *)&cfm->bd_addr);
        /* Handle common setup for new SLC/link loss */
        slcConnectionSetup(cfm->priority, cfm->sink, (bdaddr *)&cfm->bd_addr);
        /* Record the position of the device in the PDL - prevents reconnection later */
        theSink.profile_data[PROFILE_INDEX(cfm->priority)].status.list_id = deviceManagerSetPriority((bdaddr *)&cfm->bd_addr);
        
#ifdef ENABLE_PEER
        /* If RSSI pairing, check inquiry results for A2DP support */
        if (theSink.inquiry.action == rssi_pairing)
        {
            if ((connecting_device != NULL) && BdaddrIsSame(&connecting_device->bd_addr, &cfm->bd_addr) && (connecting_device->remote_profiles & profile_a2dp))
            {
                attributes.profiles |= sink_a2dp;
            }
        }
#endif
        
        /* Make sure we store this device */
        attributes.profiles |= sink_hfp;
        deviceManagerStoreAttributes(&attributes, &cfm->bd_addr);
                
        /* if rssi pairing check to see if need to cancel rssi pairing or not */           
        if(theSink.inquiry.action == rssi_pairing)
        {   
            /* if rssi pairing has completed and the device being connected currently doesn't support A2DP, then stop it progressing further */            
            if(!((theSink.features.PairIfPDLLessThan) && ( ConnectionTrustedDeviceListSize() < theSink.features.PairIfPDLLessThan )))
            {
#ifdef ENABLE_PEER                
                if(!((connecting_device != NULL) && BdaddrIsSame(&connecting_device->bd_addr, &cfm->bd_addr) && (connecting_device->remote_profiles & profile_a2dp)))
#endif
                {
                    inquiryStop();
                }
            }
        }

        /* Disable A2dp link loss management if connected on remote device */
        if( theSink.a2dp_link_data && (theSink.a2dp_link_data->connected[a2dp_primary]) && BdaddrIsSame(&cfm->bd_addr, &theSink.a2dp_link_data->bd_addr[a2dp_primary]) )
        {
            A2dpDeviceManageLinkloss(theSink.a2dp_link_data->device_id[a2dp_primary], FALSE);
        }
        else if( theSink.a2dp_link_data && (theSink.a2dp_link_data->connected[a2dp_secondary]) && BdaddrIsSame(&cfm->bd_addr, &theSink.a2dp_link_data->bd_addr[a2dp_secondary]) )
        {
            A2dpDeviceManageLinkloss(theSink.a2dp_link_data->device_id[a2dp_secondary], FALSE);
        }

        /* Auto answer call if ringing - only answer the incoming call if its 
           on the connecting AG */
        if ( (theSink.features.AutoAnswerOnConnect) && (HfpLinkPriorityFromCallState(hfp_call_state_incoming) == cfm->priority) && (stateManagerGetState() < deviceActiveCallSCO) )
        {
            MessageSend (&theSink.task , EventUsrAnswer , 0 ) ;
            SLC_DEBUG(("SLC: AutoAnswer triggered\n")) ;
        }
    }
    else
    {
        SLC_DEBUG(("SLC: ConnCfm - Fail\n")) ;
        
        /* a connection timeout will arrive here, need to report fail for multipoint
           connections also such that a link loss retry will be performed */
        if(!stateManagerIsConnected() || theSink.MultipointEnable)
        {
            /* Update local state to reflect this */
            slcConnectFail();
        }
    }
 
    /* if using multipoint and both devices are connected disable connectable */
    if((theSink.MultipointEnable) && (deviceManagerNumConnectedDevs() == MAX_MULTIPOINT_CONNECTIONS))
    {
        SLC_DEBUG(("SLC: disable Conn \n" ));
        MessageCancelAll(&theSink.task, EventSysConnectableTimeout);

#ifdef ENABLE_SUBWOOFER     
        if(SwatGetSignallingSink(theSink.rundata->subwoofer.dev_id))
        {
           sinkDisableConnectable();            
        }        
#else
        sinkDisableConnectable();            
#endif        
    }
    
    SLC_DEBUG(("SLC: Connect A2DP? En=%d att=%d\n",theSink.features.EnableA2dpStreaming,attributes.profiles)) ;
    
    /* if the AG supports A2DP profile attempt to connect to it if auto reconnect is enabled */
    if ((theSink.features.EnableA2dpStreaming) && 
         ((!cfm->priority)||(cfm->status == hfp_connect_success) || (cfm->status == hfp_connect_sdp_fail) || (cfm->status == hfp_connect_rejected)) &&
         ((slcDetermineConnectAction() & AR_Rssi)||(attributes.profiles & sink_a2dp)) &&                         
         ((slcDetermineConnectAction() & AR_Rssi)||(stateManagerGetState()!=deviceConnDiscoverable)))                          
    {
        SLC_DEBUG(("SLC: Connecting A2DP Remote %x\n",gSlcData.gSlcConnectRemote)) ;
        /* attempt connection to device supporting A2DP */
        theSink.a2dp_link_data->remote_connection = gSlcData.gSlcConnectRemote;
        A2dpSignallingConnectRequest((bdaddr *)&cfm->bd_addr);
        MessageCancelFirst(&theSink.task, EventSysContinueSlcConnectRequest);
        /* if rssi pairing check to see if need to cancel rssi pairing or not */           
        if(theSink.inquiry.action == rssi_pairing)
        {
            /* if rssi pairing has completed then stop it progressing further */            
            if(!((theSink.features.PairIfPDLLessThan)&&( ConnectionTrustedDeviceListSize() < theSink.features.PairIfPDLLessThan )))
            {
#ifdef ENABLE_PEER                
                if(!((connecting_device != NULL) && BdaddrIsSame(&connecting_device->bd_addr, &cfm->bd_addr) && (connecting_device->remote_profiles & profile_a2dp)))
#endif                   
                {
                    inquiryStop();
                }
            }
        }
    }
    else
    {
        /* reset connection via remote ag instead of device flag */
        gSlcData.gSlcConnectRemote = FALSE;
    }

#ifdef ENABLE_MAPC
    mapcMasConnectRequest((bdaddr *)&cfm->bd_addr);    
#endif
    
    return lResult ;
}
Example #19
0
/****************************************************************************
NAME    
    sinkPartyModeTrackChangeIndication
    
DESCRIPTION
    Called when AVRCP has detected a track change indication
    
RETURNS
    none
*/
void sinkPartyModeTrackChangeIndication(uint16 index)
{        
    /* check to see if this is an indication from the currently active device */
    if ((theSink.PartyModeEnabled)&&(theSink.features.PartyMode)&&(index == sinkAvrcpGetActiveConnection()))
    {
        PTY_DEBUG(("PTY: track change active dev\n"));
        
        if(!theSink.features.avrcp_enabled ||
           !theSink.features.EnableAvrcpAudioSwitching)
        {
            PTY_DEBUG(("PTY: ignore AVRCP in party mode\n"));
            return;
        }
        /*  check whether to changing the audio routing */
        else
        {
            /* get current audio status */
            audio_source_status * lAudioStatus = audioGetStatus(theSink.routed_audio);        
       
            /* ensure device is still streaming/playing */ 
            
            /* determine which device track change came from */
            if(BdaddrIsSame(&theSink.a2dp_link_data->bd_addr[a2dp_primary], &theSink.avrcp_link_data->bd_addr[index]))
            {
                /* track change on primary a2dp device, check it is still streaming and audio is routed */
                if(((theSink.avrcp_link_data->play_status[index] == avrcp_play_status_playing)||(theSink.avrcp_link_data->play_status[index] == avrcp_play_status_stopped)||(theSink.avrcp_link_data->play_status[index] == avrcp_play_status_paused))&&
                    (lAudioStatus->a2dpSinkPri == lAudioStatus->audio_routed)&&(lAudioStatus->a2dpStatePri == a2dp_stream_streaming))
                {
                    /* track change on a2dp primary is valid, check if a2dp secondary is paused */
                    if((lAudioStatus->a2dpStateSec == a2dp_stream_streaming)||(lAudioStatus->a2dpStateSec == a2dp_stream_open))
                    {
                        /* check avrcp play status is paused */        
                        if((theSink.rundata->partymode_pause.audio_source_secondary_paused)&&(theSink.avrcp_link_data->play_status[(index^1)] == avrcp_play_status_paused))
                        {
                            PTY_DEBUG(("PTY: track change route sec dis pri\n"));

                            /* disconnect primary device */                            
                            sinkPartyModeDisconnectAndResume(a2dp_primary, lAudioStatus);
                            /* reset paused flag */
                            theSink.rundata->partymode_pause.audio_source_secondary_paused = FALSE;
                        }
                    }
                }                     
            }
            else if(BdaddrIsSame(&theSink.a2dp_link_data->bd_addr[a2dp_secondary], &theSink.avrcp_link_data->bd_addr[index]))
            {
                /* track change on primary a2dp device, check it is still streaming and audio is routed */
                if(((theSink.avrcp_link_data->play_status[index] == avrcp_play_status_playing)||(theSink.avrcp_link_data->play_status[index] == avrcp_play_status_stopped)||(theSink.avrcp_link_data->play_status[index] == avrcp_play_status_paused))&&
                    (lAudioStatus->a2dpSinkSec == lAudioStatus->audio_routed)&&(lAudioStatus->a2dpStateSec == a2dp_stream_streaming))
                {
                    /* track change on a2dp primary is valid, check if a2dp secondary is paused */
                    if((lAudioStatus->a2dpStatePri == a2dp_stream_streaming)||(lAudioStatus->a2dpStatePri == a2dp_stream_open))
                    {
                        /* check avrcp play status is paused */        
                        if((theSink.rundata->partymode_pause.audio_source_primary_paused)&&(theSink.avrcp_link_data->play_status[(index^1)] == avrcp_play_status_paused))
                        {
                            PTY_DEBUG(("PTY: track change route pri dis sec\n"));
                            /* disconnect secondary device */                            
                            sinkPartyModeDisconnectAndResume(a2dp_secondary, lAudioStatus);
                            /* reset paused flag */
                            theSink.rundata->partymode_pause.audio_source_primary_paused = FALSE;
                        }
                    }
                }                     
                
            }
            /* free malloc'd status memory slot */
            freePanic(lAudioStatus);
        }
    }
    /* indication from device that isn't currently streaming audio, ignore */
    else
    {
        PTY_DEBUG(("PTY: track change ignored PTY[%d] index[%d] ActiveIdx[%d]\n",(theSink.PartyModeEnabled && theSink.features.PartyMode),index,sinkAvrcpGetActiveConnection()));
    }
}
Example #20
0
/****************************************************************************
NAME    
    sinkHandleSlcDisconnectInd
    
DESCRIPTION
    Indication that the SLC has been released.

RETURNS
    void
*/
void sinkHandleSlcDisconnectInd( const HFP_SLC_DISCONNECT_IND_T *ind )
{	    
    conn_mask mask = deviceManagerProfilesConnected(&ind->bd_addr);

    SLC_DEBUG(("SLC: slc DiscInd for index %d, status = %d\n",ind->priority, ind->status)) ;     
        
    if(ind->status == hfp_disconnect_success || ind->status == hfp_disconnect_link_loss || ind->status == hfp_disconnect_abnormally)
    {
        /* store volume info */
        deviceManagerUpdateAttributes(&ind->bd_addr, sink_hfp, ind->priority, 0); 

        /* Sends the indication to the device manager to send an event out if a device has disconnected*/
        deviceManagerDeviceDisconnectedInd(&ind->bd_addr);
	
        /*if the device is off then this is disconnect as part of the power off cycle - dont re-enable connectable*/	
    	if ( stateManagerGetState() != deviceLimbo)
        {
            /* Enable A2dp link loss management if connected on remote device */
            if( theSink.a2dp_link_data && (theSink.a2dp_link_data->connected[a2dp_primary]) && BdaddrIsSame(&ind->bd_addr, &theSink.a2dp_link_data->bd_addr[a2dp_primary]) )
            {
                A2dpDeviceManageLinkloss(theSink.a2dp_link_data->device_id[a2dp_primary], TRUE);
            }
            else if( theSink.a2dp_link_data && (theSink.a2dp_link_data->connected[a2dp_secondary]) && BdaddrIsSame(&ind->bd_addr, &theSink.a2dp_link_data->bd_addr[a2dp_secondary]) )
            {
                A2dpDeviceManageLinkloss(theSink.a2dp_link_data->device_id[a2dp_secondary], TRUE);
            }

            /* Kick role checking now a device has disconnected */
            linkPolicyCheckRoles();

            /* at least one device disconnected, re-enable connectable for another 60 seconds */
            sinkEnableMultipointConnectable();
        }
    
        /*a disconnect in active call state is a call transfer*/
        if ( (stateManagerGetState() == deviceActiveCallSCO) || 
             (stateManagerGetState() == deviceActiveCallNoSCO) )
        {
		    gSlcData.gCallTransferInProgress = TRUE ;           
        }
        else
        {
		    gSlcData.gCallTransferInProgress = FALSE ;	
        }
    
        /* if not a link loss reset the last outgoing AG as AG1 will no longer exist now */        
        theSink.last_outgoing_ag = hfp_primary_link;

        /* reset the list id of the device just dropped */              
        theSink.profile_data[PROFILE_INDEX(ind->priority)].status.list_id = INVALID_LIST_ID;

        /* if device has now disconnected all profiles, mark as disconnected */
        if((ind->status != hfp_disconnect_link_loss)&&(!(mask & conn_hfp)))
            theSink.profile_data[PROFILE_INDEX(ind->priority)].status.connected = FALSE;
        
        /* If primary disconnected */
        if(ind->priority == hfp_primary_link)
        {
            /* ...and we have a secondary link it will be promoted to primary */
            if(theSink.profile_data[PROFILE_INDEX(hfp_secondary_link)].status.list_id != INVALID_LIST_ID)
            {
                /* Block copy secondary data to primary location */
                theSink.profile_data[PROFILE_INDEX(hfp_primary_link)] = theSink.profile_data[PROFILE_INDEX(hfp_secondary_link)];
                /* Secondary link no longer exists, set it to invalid */
                theSink.profile_data[PROFILE_INDEX(hfp_secondary_link)].status.list_id = INVALID_LIST_ID;
            }
        }
        /* send event slc disconnected only if the status of the indication is success or link loss indication */
        MessageSend(&theSink.task , ((ind->status == hfp_disconnect_link_loss) ? EventSysReconnectFailed : EventSysSLCDisconnected) , 0) ;
    }
    

    /*if the device is off then this is disconnect as part of the power off cycle, otherwise check
      whether device needs to be made connectable */	
	if ( stateManagerGetState() != deviceLimbo)
    {
	    /* if the device state still shows connected and there are no profiles currently
           connected then update the device state to reflect the change of connections */
	    if ((stateManagerIsConnected()) && (!deviceManagerNumConnectedDevs()))
	    {
	        stateManagerEnterConnectableState( FALSE ) ;
	    }
    }
    
}
Example #21
0
/****************************************************************************
NAME
    deviceManagerSetPriority
    
DESCRIPTION
    Set a device's priority in the PDL

RETURNS
    new pdl listId of passed in src addr
*/
uint8 deviceManagerSetPriority(const bdaddr* dev_addr)
{
    conn_mask mask = deviceManagerProfilesConnected(dev_addr);
    uint8 ListId = 0;
    
    DEV_DEBUG(("DEV: Update PDL/MRU\n")) ;

    
    /* more than 1 connected device ? */
    if(deviceManagerNumConnectedDevs() > 1)
    {
        typed_bdaddr  typed_ag_addr;
        bdaddr ag_addr;
        sink_attributes attributes;      
 

        DEV_DEBUG(("DEV: Update MRU - two devices connected\n")) ;
        
        /* is this a connection of a2dp or hfp to the already connected primary device ? */            
        deviceManagerGetIndexedAttributes(0, &attributes, &typed_ag_addr);
        /* extract bluetooth address from packed structure */
        ag_addr = typed_ag_addr.addr;
        /* check if this is the primary device? */
        if(BdaddrIsSame(&ag_addr,dev_addr))
        {
            DEV_DEBUG(("DEV: Update MRU - two devices two profiles connected - primary device\n")) ;
            ListId = 0;
        }
        else
        {
            DEV_DEBUG(("DEV: Update MRU - two devices two profiles connected - secondary device\n")) ;
            /* Move the second device to top of the PDL */
            ConnectionSmUpdateMruDevice(dev_addr);      
            /* get bdaddr of the device that was previously the primary device but is
               now the secondary device */
            deviceManagerGetIndexedAttributes(1, &attributes, &typed_ag_addr);
            /* extract bluetooth address from packed structure */
            ag_addr = typed_ag_addr.addr;
            /* then move the what is now 'secondary device' back to the top of the PDL */                
            ConnectionSmUpdateMruDevice(&ag_addr);              
            /* this is the secondary device */
            ListId = 1;
            /* send connected event if not already done so */
            if(mask && !((mask & conn_hfp)&&(mask & conn_a2dp)))
            {
               MessageSend (&theSink.task , EventSecondaryDeviceConnected , NULL );        
            }
        }        
    }
    /* only 1 device so must be primary */
    else
    {
        /* Move device to top of the PDL */
        DEV_DEBUG(("DEV: Update MRU - primary device\n")) ;
        ConnectionSmUpdateMruDevice(dev_addr);    
        /* if this is the first profile for the device to be connected then send
           the primary device connected event */
        if(mask && !((mask & conn_hfp)&&(mask & conn_a2dp)))
        {
           MessageSend (&theSink.task , EventPrimaryDeviceConnected , NULL );        
        }
    }
   
    /* return current pdl list position of this device which is 0, top of list */        
    DEV_DEBUG(("DEV: Update MRU - ListId = %x\n",ListId)) ;
    return ListId;
}