Exemplo n.º 1
0
void connectionHandleRfcommEstablishCfm(const RFC_ESTABLISH_CFM_T* cfm)
{
    /* Get the connection instance data keyed by server channel and mux id */
    conn_instance *conn = getRfcommConnection(NULL, cfm->mux_id, cfm->server_chan);

    if(conn)
    {
        if(cfm->result_code == RFC_SUCCESS)
        {
            /* Move to the modem status phase */
            conn->config.rfcomm.state = modem_status_phase;

            /* 
				Send modem status signal, data cannot be exchanged until both
				sides have exchanged modem status signals 
			*/
            startControlPhase(conn);
        }
        else if (cfm->result_code == DLC_ALREADY_EXISTS)
        {
            /* Send a cfm to the app indicating an error has ocurred*/
            sendRfcommConnectionCfm(conn->config.rfcomm.app_task, rfcomm_connect_channel_already_open, INVALID_SERVER_CHANNEL, 0, 0);

            /* Cancel the connect timeout and clean up the connection state data. */
            (void) MessageCancelFirst(connectionGetCmTask(), CL_INTERNAL_RFCOMM_CONNECT_TIMEOUT_IND);
            (void) deleteRfcommConnection(NULL, cfm->mux_id, cfm->server_chan);
        }
        else if (cfm->result_code == REMOTE_REFUSAL)
        {
            /* Connection establishment failed, clean up */
            endConnection(conn);

			/* Inform the app of the failure */
            sendRfcommConnectionCfm(conn->config.rfcomm.app_task, rfcomm_connect_rejected, INVALID_SERVER_CHANNEL, 0, 0);

			/* Cancel the connect timeout and clean up the connection state data. */
            (void) MessageCancelFirst(connectionGetCmTask(), CL_INTERNAL_RFCOMM_CONNECT_TIMEOUT_IND);
            (void) deleteRfcommConnection(NULL, cfm->mux_id, cfm->server_chan);
        }
        else
        {
			/* Connection establishment failed, clean up */
            endConnection(conn);

			/* Inform the app of the failure */
            sendRfcommConnectionCfm(conn->config.rfcomm.app_task, rfcomm_connect_failed, INVALID_SERVER_CHANNEL, 0, 0);

			/* Cancel the connect timeout and clean up the connection state data. */
            (void) MessageCancelFirst(connectionGetCmTask(), CL_INTERNAL_RFCOMM_CONNECT_TIMEOUT_IND);
            (void) deleteRfcommConnection(NULL, cfm->mux_id, cfm->server_chan);
        }
    }
	/* 
		This could happen if the connect timeout has triggered and cleaned up the connection 
		state entry and then we get an RFC_ESTABLISH_CFM indicating the remote end failed to 
		respond. We should just ignore this cfm. 
	*/
}
Exemplo n.º 2
0
/****************************************************************************
NAME    
    audio_start_active_timer - Starts the audio active timer in USB mode if the USB audio interfaces are inactive

*/
void audio_start_active_timer(void)
{
    MessageCancelFirst(&theSource->app_data.appTask, APP_USB_AUDIO_ACTIVE);
    MessageCancelFirst(&theSource->app_data.appTask, APP_USB_AUDIO_INACTIVE);
    
#ifndef ANALOGUE_INPUT_DEVICE    
    /* Audio active timer only applies to a USB device as an Analogue input device cannot be notified when audio is present */
    if ((theSource->ps_config->ps_timers.usb_audio_active_timer != TIMER_NO_TIMEOUT) &&
        (!theSource->audio_data.audio_usb_active))
    {
        /* send the audio inactive message after the PS configured delay */
        MessageSendLater(&theSource->app_data.appTask, APP_USB_AUDIO_INACTIVE, 0, D_SEC(theSource->ps_config->ps_timers.usb_audio_active_timer));        
    }
#endif    
}
Exemplo n.º 3
0
void connectionHandleRfcommRegisterCfm(connectionRfcommState *rfcommState, const RFC_REGISTER_CFM_T *cfm)
{
	connection_lib_status status = fail;
	
    /* Cancel the message checking we got a register cfm from BlueStack */
	(void) MessageCancelFirst(connectionGetCmTask(), CL_INTERNAL_RFCOMM_REGISTER_TIMEOUT_IND);

    if(rfcommState->registerLock)
    {
        if(cfm->accept)
        {
            map_id id, new_id;

            id.channel = INVALID_SERVER_CHANNEL;
            new_id.channel = cfm->server_chan;

            /* Update the task map with the registered server channel. */
            connectionUpdateTaskMap(conn_rfcomm, id, new_id);

            status = success;
        }
        else
        {
            /* Delete task map entry the rfcomm register failed */
            deleteTaskMap(INVALID_SERVER_CHANNEL);
        }

        /* Send register cfm message to Client application */
        sendRfcommRegisterCfm(rfcommState->registerLock, status, status==success?cfm->server_chan:0x00);
				
        /* Reset lock */
        rfcommState->registerLock = 0;
    }
}
/*******************************************************************************
NAME
    handleWriteBatteryLevelClientConfig

DESCRIPTION
    Handle when a GATT_BATTERY_SERVER_WRITE_CLIENT_CONFIG_IND message is recieved.

PARAMETERS
    ind Pointer to a GATT_BATTERY_SERVER_WRITE_CLIENT_CONFIG_IND message.

RETURNS
    void
*/
static void handleWriteBatteryLevelClientConfig(GATT_BATTERY_SERVER_WRITE_CLIENT_CONFIG_IND_T * ind)
{
    gatt_client_connection_t *conn = gattClientFindByCid(ind->cid);

    /* 
     * Check whether the remote device has enabled or disabled 
     * notifications for the Battery Level characteristic. This value will need
     * to be stored as device attributes so they are persistent.
    */
    GATT_BATTERY_SERVER_INFO(("GATT_BATTERY_SERVER_WRITE_CLIENT_CONFIG_IND bas=[0x%p] cid=[0x%x] value[0x%x]\n", 
        (void *)ind->battery_server, ind->cid, ind->config_value));

    if (conn)
    {
		unsigned short updateNeedsSending = 0;

        if (ind->battery_server == GATT_SERVER.bas_server_local)
        {
            conn->client_config.battery_local = ind->config_value;
            GATT_BATTERY_SERVER_INFO((" battery local client_config[0x%x]\n", conn->client_config.battery_local));
            gattClientStoreConfigAttributes(ind->cid, gatt_attr_service_battery_local);
            
			if( LOCAL_UPDATE_REQD(conn) )
			{
				updateNeedsSending++;
			}
        }
        else if (ind->battery_server == GATT_SERVER.bas_server_remote)
        {
            conn->client_config.battery_remote = ind->config_value;
            GATT_BATTERY_SERVER_INFO((" battery remote client_config[0x%x]\n", conn->client_config.battery_remote));
            gattClientStoreConfigAttributes(ind->cid, gatt_attr_service_battery_remote);
            
			if( REMOTE_UPDATE_REQD(conn) )
			{
				updateNeedsSending++;
			}
        }
        else if (ind->battery_server == GATT_SERVER.bas_server_peer)
        {
            conn->client_config.battery_peer = ind->config_value;
            GATT_BATTERY_SERVER_INFO((" battery peer client_config[0x%x]\n", conn->client_config.battery_peer));
            gattClientStoreConfigAttributes(ind->cid, gatt_attr_service_battery_peer);
            
			if( PEER_UPDATE_REQD(conn) )
			{
				updateNeedsSending++;
			}
        }

		if( updateNeedsSending > 0 )
		{
			MessageCancelFirst( sinkGetBleTask(), BLE_INTERNAL_MESSAGE_BATTERY_READ_TIMER );
			MessageSend( sinkGetBleTask(), BLE_INTERNAL_MESSAGE_BATTERY_READ_TIMER, 0 );
		}
    }
}
Exemplo n.º 5
0
/****************************************************************************
NAME	
    connectionSendInitCfm

DESCRIPTION
    This function is called from the main Connection Library task handler to 
    indicate to the Client application the result of the request to initialise
    the Connection Library
*/
void connectionSendInitCfm(Task task, connection_lib_status status, cl_dm_bt_version version)
{    
    MAKE_CL_MESSAGE(CL_INIT_CFM);
    message->status = status;
    message->version = version;
    MessageSend(task, CL_INIT_CFM, message);

    /* Cancel initialisation timeout */
    if(status == success)
        (void) MessageCancelFirst(connectionGetCmTask(), CL_INTERNAL_INIT_TIMEOUT_IND);
}
Exemplo n.º 6
0
/* We end up here after reboot */
bool HandleCommitHostContinue(MessageId id, Message message)
{
    switch(id)
    {
    case UPGRADE_HOST_IN_PROGRESS_RES:
        {
            UPGRADE_HOST_IN_PROGRESS_RES_T *msg = (UPGRADE_HOST_IN_PROGRESS_RES_T *)message;

            MessageCancelFirst(UpgradeGetUpgradeTask(), UPGRADE_INTERNAL_RECONNECTION_TIMEOUT);

            if(msg->action == 0)
            {
                MoveToState(UPGRADE_STATE_COMMIT_VERIFICATION);
            }
            else
            {
                MoveToState(UPGRADE_STATE_SYNC);
            }
        }
        break;

    case UPGRADE_INTERNAL_RECONNECTION_TIMEOUT:
        {
            bool dfu = UpgradePartitionDataIsDfuUpdate();
            uint16 err = LoaderErrorCheck();

            if(dfu && !err)
            {
                /* Carry on */
                CommitConfirmYes();
            }
            else
            {
                /* Revert */
                UpgradeRevertUpgrades();
                UpgradeCtxGetPSKeys()->upgrade_in_progress_key = UPGRADE_RESUME_POINT_ERROR;
                UpgradeSavePSKeys();
                PRINT(("P&R: UPGRADE_RESUME_POINT_ERROR saved\n"));
                SetState(UPGRADE_STATE_SYNC);
                BootSetMode(BootGetMode());
            }
        }
        break;

    default:
        return FALSE;
    }

    return TRUE;
}
Exemplo n.º 7
0
/****************************************************************************
NAME    
    slcAttemptConnection
    
DESCRIPTION
    attemp connection to next item in pdl

RETURNS
    void
*/
void slcAttemptConnection(void)
{
    typed_bdaddr  ag_addr;
    sink_attributes attributes;      

    /* attempt to obtain the device attributes for the current ListID required */
    if(deviceManagerGetIndexedAttributes(gSlcData.gListID, &attributes, &ag_addr))
    {
        /* device exists, determine whether the device supports HFP/HSP, A2DP or both and connect
           as appropriate */
        SLC_DEBUG(("SLC: slcAttConn, listId = %d, attrib = %x\n",gSlcData.gListID,attributes.profiles)) ;

        /* ensure the device supports the required profiles before attempting to connect otherwise
           try to find another device */
        if((attributes.profiles & (sink_hfp | sink_a2dp | sink_avrcp))&&(IsSameBTAdrSALT(&ag_addr.addr)==FALSE))
        {
            /* attempt to connect to device */
            slcConnectDevice(&ag_addr.addr, attributes.profiles);
        }
        /* device does not support required profiles, try to find another device that does */
        else
        {
            /* attempts to find another paired device in the PDL */
            MessageCancelFirst(&theSink.task, EventSysContinueSlcConnectRequest);
            MessageSend(&theSink.task, EventSysContinueSlcConnectRequest, 0);
        }
    }
    else
    {
        /* attempts to find another paired device in the PDL */
        MessageCancelFirst(&theSink.task, EventSysContinueSlcConnectRequest);
        MessageSend(&theSink.task, EventSysContinueSlcConnectRequest, 0);
    }
    
    SLC_DEBUG(("SLC: slcAttConnm\n")) ;
                   
}
Exemplo n.º 8
0
/****************************************************************************
NAME    
    slcConnectionSetup
    
DESCRIPTION
    Perform link setup for a given SLC

RETURNS
    void
*/
static void slcConnectionSetup(hfp_link_priority priority, Sink sink, bdaddr* bd_addr)
{
    uint16 priorityIdx = PROFILE_INDEX(priority);
    
    /* Set timeout to 5 seconds */
    ConnectionSetLinkSupervisionTimeout(sink, SINK_LINK_SUPERVISION_TIMEOUT);
    
    /* Send our link policy settings */
	linkPolicyUseHfpSettings(priority, sink);
    
    /* Send a delayed message to request a role indication and make necessary changes as appropriate */
    MessageCancelFirst(&theSink.task , EventSysCheckRole);    
    MessageSendConditionally (&theSink.task , EventSysCheckRole , NULL , &theSink.rundata->connection_in_progress );
    
#ifdef ENABLE_PBAP 
    /* Connect the PBAP link of this device */
    pbapConnect(priority);
#endif
    
    /* Sync volume level and mute settings with AG */
    VolumeSendAndSetHeadsetVolume(theSink.profile_data[priorityIdx].audio.gSMVolumeLevel ,FALSE , priority) ;
    
    /* Enable +CLIP from AG if using Audio Prompt numbers/names or display, always request if using display */
#if !defined(ENABLE_DISPLAY)
    if(theSink.features.VoicePromptNumbers)
#endif
        HfpCallerIdEnableRequest(priority, TRUE);

    /* HS uses call waiting indications when AG SCO is not routed */
    HfpCallWaitingEnableRequest(priority, TRUE);
    
    /* Attempt to pull the audio across if not already present, delay by 5 seconds
       to prevent a race condition occuring with certain phones */
    MessageSendLater ( &theSink.task , EventSysCheckForAudioTransfer , 0 , 5000 ) ;

    /* Send different event if first connection since power on - allows different LED pattern */
    if((theSink.features.UseDiffConnectedEventAtPowerOn)&&(theSink.powerup_no_connection))
        MessageSend (&theSink.task , EventSysSLCConnectedAfterPowerOn , NULL );
    else
        MessageSend (&theSink.task , EventSysSLCConnected , NULL );    

    /* Reset the flag - first connection indicated */
    theSink.powerup_no_connection = FALSE;
}
Exemplo n.º 9
0
void connectionHandleRfcommControlInd(const RFC_CONTROL_IND_T *ind)
{
    /* Get the connection instance data keyed by server channel and mux id */
    conn_instance *conn = getRfcommConnection(NULL, ind->mux_id, ind->server_chan);
	
    if(conn)
    {
		/* Get the connection sink */
		Sink sink = StreamRfcommSink(ind->mux_id, ind->server_chan);

        /* Cancel the connection timeout */
	    (void) MessageCancelFirst(connectionGetCmTask(), CL_INTERNAL_RFCOMM_CONNECT_TIMEOUT_IND);		

        /* Connection establishment complete, let the client application know */     
        sendRfcommConnectionCfm(conn->config.rfcomm.app_task, rfcomm_connect_success, ind->server_chan, conn->config.rfcomm.maxMtu, sink);

		/* Associate the task with its sink */
		(void) MessageSinkTask(sink, conn->config.rfcomm.app_task);
		
        /* No longer require connection instance data */
        (void) deleteRfcommConnection(NULL, ind->mux_id, ind->server_chan);
    }
    else
    {
        /* 
            This indicates that the connection is already established and
            as we throw away connection state on successful connection 
            establishment, we wouldn't expect to find a connection instance 
        */
        Task task;
        Sink sink = StreamRfcommSink(ind->mux_id, ind->server_chan);
        task = MessageSinkGetTask(sink);

        /* Send modem status indication */
        if(task)
            sendRfcommControlInd(task, sink, ind->control_pars.break_signal, ind->control_pars.modem_signal);
    }
}
Exemplo n.º 10
0
/****************************************************************************
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));
            }
        }
    }
}
Exemplo n.º 11
0
/****************************************************************************
NAME 
    handleUsbMessage
    
DESCRIPTION
    Handle firmware USB messages
    
RETURNS
    void
*/ 
void handleUsbMessage(Task task, MessageId id, Message message) 
{
    USB_DEBUG(("USB: "));
    switch (id)
    {
        case MESSAGE_USB_ATTACHED:
        {
            USB_DEBUG(("MESSAGE_USB_ATTACHED\n"));
            usbUpdateChargeCurrent();
            audioHandleRouting(audio_source_none);
            usbSetLowPowerMode(theSink.usb.config.attach_timeout);
            if(theSink.usb.dead_battery)
                MessageSendLater(&theSink.task, EventUsbDeadBatteryTimeout, 0, D_MIN(45));
            break;
        }
        case MESSAGE_USB_DETACHED:
        {
            USB_DEBUG(("MESSAGE_USB_DETACHED\n"));
            theSink.usb.enumerated = FALSE;
            theSink.usb.suspended  = FALSE;
            theSink.usb.deconfigured = FALSE;
            usbUpdateChargeCurrent();
            audioHandleRouting(audio_source_none);
            MessageCancelAll(&theSink.task, EventUsbLowPowerMode);
            MessageCancelAll(&theSink.task, EventUsbDeadBatteryTimeout);
            break;
        }
        case MESSAGE_USB_ENUMERATED:
        {
            USB_DEBUG(("MESSAGE_USB_ENUMERATED\n"));
            if(!theSink.usb.enumerated)
            {
                theSink.usb.enumerated = TRUE;
                usbUpdateChargeCurrent();
                MessageCancelAll(&theSink.task, EventUsbLowPowerMode);
                MessageCancelAll(&theSink.task, EventUsbDeadBatteryTimeout);
            }
            break;
        }
        case MESSAGE_USB_SUSPENDED:
        {
            MessageUsbSuspended* ind = (MessageUsbSuspended*)message;
            USB_DEBUG(("MESSAGE_USB_SUSPENDED - %s\n", (ind->has_suspended ? "Suspend" : "Resume")));
            if(ind->has_suspended != theSink.usb.suspended)
            {
                theSink.usb.suspended = ind->has_suspended;
                usbUpdateChargeCurrent();
            }
            break;
        }
        case MESSAGE_USB_DECONFIGURED:
        {
            USB_DEBUG(("MESSAGE_USB_DECONFIGURED\n"));
            if(theSink.usb.enumerated)
            {
                theSink.usb.enumerated = FALSE;
                theSink.usb.deconfigured  = TRUE;
                usbUpdateChargeCurrent();
                usbSetLowPowerMode(theSink.usb.config.deconfigured_timeout);
            }
            break;
        }
        case MESSAGE_USB_ALT_INTERFACE:
        {
            uint16 interface_id;
            MessageUsbAltInterface* ind = (MessageUsbAltInterface*)message;

            USB_DEBUG(("MESSAGE_USB_ALT_INTERFACE %d %d\n", ind->interface, ind->altsetting));
            UsbDeviceClassGetValue(USB_DEVICE_CLASS_GET_MIC_INTERFACE_ID, &interface_id);
            if(interface_id == ind->interface)
            {
                theSink.usb.mic_active = (ind->altsetting ? TRUE : FALSE);
                USB_DEBUG(("USB: Mic ID %d active %d\n", interface_id, theSink.usb.mic_active));
            }
            UsbDeviceClassGetValue(USB_DEVICE_CLASS_GET_SPEAKER_INTERFACE_ID, &interface_id);
            if(interface_id == ind->interface)
            {
                theSink.usb.spkr_active = (ind->altsetting ? TRUE : FALSE);
                USB_DEBUG(("USB: Speaker ID %d active %d\n", interface_id, theSink.usb.spkr_active));
            }
#ifdef ENABLE_USB_AUDIO            
            /* check for changes in required audio routing */
            USB_DEBUG(("USB: MESSAGE_USB_ALT_INTERFACE checkAudioRouting\n"));
            MessageCancelFirst(&theSink.task, EventCheckAudioRouting);            
            MessageSendLater(&theSink.task, EventCheckAudioRouting, 0, USB_AUDIO_DISCONNECT_DELAY);            
#endif            
            break;
        }
        case USB_DEVICE_CLASS_MSG_AUDIO_LEVELS_IND:
        {
            USB_DEBUG(("USB_DEVICE_CLASS_MSG_AUDIO_LEVELS_IND\n"));
            usbAudioSetVolume();
            break;
        }
        default:
        {
            USB_DEBUG(("Unhandled USB message 0x%x\n", id));
            break;
        }
    }
}
/****************************************************************************
NAME
    sysHandleSystemMessage

DESCRIPTION
    Handle messages received from firmware/DSP.

*/
void sysHandleSystemMessage(MessageId id, Message message)
{
    switch(id)
    {
    case MESSAGE_FROM_KALIMBA:
    {
        switch (*((uint16*)message))
        {
        case KALIMBA_AUDIO_USB_OUT_STATUS:
        {
            DEBUG_KALIMBA(("KALIMBA_AUDIO_USB_OUT_STATUS:%u\n",*(((uint16*)message)+1)));
            if ( *(((uint16*)message)+1) )
            {
                if ( !MessageCancelFirst(&the_app->task, APP_AUDIO_STREAMING_INACTIVE) )
                {
                    MessageSend(&the_app->task, APP_AUDIO_STREAMING_ACTIVE, NULL);
                }
            }
            else
            {
                MessageSendLater(&the_app->task, APP_AUDIO_STREAMING_INACTIVE, NULL, DSP_MSG_FILTER_DELAY);
            }
            break;
        }
        case KALIMBA_AUDIO_USB_IN_STATUS:
        {
            DEBUG_KALIMBA(("KALIMBA_AUDIO_USB_IN_STATUS:%u\n",*(((uint16*)message)+1)));
#if !defined USE_HID_TELEPHONY
            /* only do VOIP calls if HFP connected */
            if (aghfpSlcGetConnectedHF() != NULL)
            {
                if ( *(((uint16*)message)+1) )
                {
                    if ( !MessageCancelFirst(&the_app->task, APP_VOIP_CALL_INACTIVE) )
                    {
                        MessageSendLater(&the_app->task, APP_VOIP_CALL_ACTIVE, NULL, VISTA_MSG_FILTER_DELAY);
                    }
                }
                else
                {
                    if ( !MessageCancelFirst(&the_app->task, APP_VOIP_CALL_ACTIVE) )
                    {
                        MessageSendLater(&the_app->task, APP_VOIP_CALL_INACTIVE, NULL, DSP_MSG_FILTER_DELAY);
                    }
                }
            }
#endif
            break;
        }
        default:
        {
            break;
        }
        }
        break;
    }
    case MESSAGE_MORE_DATA:
    {
        DEBUG(("MESSAGE_MORE_DATA\n"));
        /* If this is on the USB source handle it as such */
        usbHidHandleInterfaceEvent(((MessageMoreData *)message)->source);
        break;
    }
    default:
    {
        DEBUG(("Unhandled System message 0x%X\n", (uint16)id));
        break;
    }
    }
}
Exemplo n.º 13
0
/****************************************************************************
    This function handler is called in response to an RFC_START_CFM message
    being sent by Bluestack.  This message is sent to indicate the status of 
    the requested RFCOMM MUX session.
*/
void connectionHandleRfcommStartCfm(connectionRfcommState* rfcommState, const RFC_START_CFM_T* cfm)
{
	conn_instance*  conn;
	bdaddr	addr;
	connectionConvertBdaddr(&addr, &cfm->bd_addr);
	
    /* 
        It's possible to have multiple MUX sessions being setup to different 
        devices, therefore first get the connection instance that this 
        message refers.  At this point in the connection state machine, the
        only parameter that uniquely identifies this connection instance is
        the target Bluetooth Device Address 
    */
    conn = getRfcommConnection(&addr, INVALID_MUX_ID, INVALID_SERVER_CHANNEL);

    if(conn)
    {
        /* Determine the current status */
        switch(cfm->result_code)
        {
            case RFC_CONNECTION_PENDING:
			{
                /* 
                    Wait for second RFC_START_CFM, if we never get this message
                    then the RFCOMM connection timeout will expire to cancel the
                    connection request 
                */                
                conn->id.rfcomm_id.mux_id = cfm->mux_id;
                break;
			}

            case MUX_ALREADY_OPEN:
            case RFC_SUCCESS:
                {
                    /* 
                        A MUX session has successfully been established or was already
                        open, move to the parameter negotiation phase 
                    */
                    conn->config.rfcomm.state = parneg_phase;
                    
                    /* Add the mux_id */
                    conn->id.rfcomm_id.mux_id = cfm->mux_id;
                    
                    /* Initiate parameter negotiation */
                    startParnegPhase(conn);
                    
                    /* Unlock */
                    rfcommState->lock = 0;
                }
                break;

            default:
			{
                /* This indicates that Mux session establishment has failed */
                sendRfcommConnectionCfm(conn->config.rfcomm.app_task, rfcomm_connect_failed, INVALID_SERVER_CHANNEL, 0, 0);
            
                /* CAncel the watchdog timer and delete connection data */
                (void) MessageCancelFirst(connectionGetCmTask(), CL_INTERNAL_RFCOMM_CONNECT_TIMEOUT_IND);
                (void) deleteRfcommConnection(&addr, INVALID_MUX_ID, INVALID_SERVER_CHANNEL);
	            
                /* Unlock */
                rfcommState->lock = 0;
                break;
			}
        }
    }
    else
    {
        /* 
            This indicates that a previous attempt to open a Mux has failed resulting 
            in a timeout.  We need to tear down this mux 
        */
        closeMuxSession(cfm->mux_id);
    }
}
Exemplo n.º 14
0
void connectionHandleRfcommReleaseInd(const RFC_EX_RELEASE_IND_T *ind)
{
    /* Get the connection instance data keyed by server channel and mux id */
    conn_instance *conn = getRfcommConnection(NULL, ind->mux_id, ind->server_chan);

    if(conn)
    {
        /* 
            If the client application task id is valid then notify them of
            the connection status.  If the task is not valid then we never
            informed the client application task that an incoming connection
            was active therefore they do not need to know that the attempt
            has been terminated for some reason 
        */
        if(conn->config.rfcomm.app_task)
        {
            /* Cancel the connection timeout */
	        (void) MessageCancelFirst(connectionGetCmTask(), CL_INTERNAL_RFCOMM_CONNECT_TIMEOUT_IND);

            if (conn->config.rfcomm.state != disconnected)
            {
                /* Connection establishment not completed, connection failed */
                if (ind->reason_code == REMOTE_REFUSAL)
                    sendRfcommConnectionCfm(conn->config.rfcomm.app_task, rfcomm_connect_rejected, ind->server_chan, 0, 0);
                else
                    sendRfcommConnectionCfm(conn->config.rfcomm.app_task, rfcomm_connect_failed, ind->server_chan, 0, 0);

                if(ind->num_server_chans == 1)
                {
                    /* Close down mux if we opened it */
                    if((ind->reason_code == RFC_SUCCESS)||(ind->reason_code == REMOTE_REFUSAL))
                        closeMuxSession(ind->mux_id);
                }       
            }

            /* No longer require connection instance data */
            (void) deleteRfcommConnection(NULL, ind->mux_id, ind->server_chan);
        }
    }
    else
    {
        /* 
            This indicates that the connection was fully established and
            as we throw away connection state on successful connection 
            establishment, we wouldn't expect to find a connection instance 

            Check if this is the last DLC on this mux, RFC_EX_RELEASE_IND tells us 
            how many DLC's are still open
        */
        Sink sink;

        if(ind->num_server_chans == 1)
        {
            /* Close down mux if we opened it */
            if(ind->reason_code == RFC_SUCCESS)
            {
                closeMuxSession(ind->mux_id);
            }
        }

        /* 
            Send notification to the client application that the connection has
            been disconnected 
        */
        sink = StreamRfcommSink(ind->mux_id, ind->server_chan);        
        sendRfcommDisconnectInd(MessageSinkGetTask(sink), ind->reason_code, sink);
    }
}
Exemplo n.º 15
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 ;
}