/**************************************************************************** DESCRIPTION function to detect edge changes of buttons / multiple buttons. */ static void ButtonsEdgeDetect ( const uint32 pInput , ButtonsTaskData * pButtonsTask ) { uint32 lNewInput = (uint32) (pInput & (pButtonsTask->gPerformInputEdgeCheck) ) ; uint32 lOldInput = (uint32) (pButtonsTask->gBOldInputState & pButtonsTask->gPerformInputEdgeCheck); uint32 lInput = ButtonsWhichButtonChanged( lOldInput , lNewInput ) ; B_DEBUG(("But Edge Det: Old Edge[%lx] New Edge[%lx] Button[%lx] Low2High[%lx}\n", lOldInput , lNewInput ,lInput ,(lNewInput & lInput) )) ; /*if a button has changed*/ if ( lInput ) { /*determine which edge has been received and process accordingly*/ if ( lNewInput & lInput ) { ButtonsButtonDetected ( pButtonsTask , lInput , B_LOW_TO_HIGH ) ; /* check whether device needs to be made connectable as a result of a button press on a multipoint device */ if(theSink.features.GoConnectableButtonPress) sinkEnableMultipointConnectable(); } else { ButtonsButtonDetected ( pButtonsTask , lInput , B_HIGH_TO_LOW ) ; } } }
/**************************************************************************** DESCRIPTION function to detect level changes of buttons / multiple buttons, both PIO and capsense */ static void ButtonsLevelDetect ( const uint32 pInput , ButtonsTaskData * pButtonsTask ) { uint32 lNewInput = (uint32) (pInput & (pButtonsTask->gPerformInputLevelCheck)) ; uint32 lOldInput = (uint32) (pButtonsTask->gBOldInputState & pButtonsTask->gPerformInputLevelCheck); B_DEBUG(("But Lev Det|:NewInput[%lx] OldInput[%lx]\n", lNewInput, pButtonsTask->gBOldInputState )) ; if ( ButtonsWasButtonPressed(lOldInput, lNewInput ) ) { /* check whether device needs to be made connectable as a result of a button press on a multipoint device */ if(theSink.features.GoConnectableButtonPress) sinkEnableMultipointConnectable(); /*cancel all previously timed messages*/ MessageCancelAll ( &pButtonsTask->task , B_INTERNAL_TIMER ) ; MessageCancelAll ( &pButtonsTask->task , B_REPEAT_TIMER ) ; /* send new timed messages*/ MessageSendLater ( &pButtonsTask->task , B_INTERNAL_TIMER , 0 , pButtonsTask->button_config->long_press_time ) ; MessageSendLater ( &pButtonsTask->task , B_REPEAT_TIMER , 0 , pButtonsTask->button_config->repeat_time ) ; /*having restrted the timers, reset the time*/ pButtonsTask->gBTime = B_SHORT ; if (stateManagerGetState() == deviceTestMode) { checkDUTKeyPress(lNewInput); } } /*button was released or was masked out, check to make sure there is an input bit change as vreg enable can generate an addition MSG without any input's changing state */ else if(lOldInput!= lNewInput ) { /*it was only a released if there was a button actually pressed last time around - buttons we have masked out still end up here but no state changes are made */ if ( lOldInput != 0 ) { /*if we have had a double press in the required time and the button pressed was the same as this one*/ if ( (pButtonsTask->gBTapCount ) && (lOldInput == pButtonsTask->gBMultipleState ) ) { /* button has been released, increment multiple press counter */ pButtonsTask->gBTapCount++; B_DEBUG(("TapCount: [%lx][%lx][%x]\n", lOldInput , pButtonsTask->gBMultipleState , pButtonsTask->gBTapCount )) ; /* if the multiple press count is 2, set the time as a double, this will be used if no further presses are detected before the multiple press timeout occurs */ if(pButtonsTask->gBTapCount == DOUBLE_PRESS) pButtonsTask->gBTime = B_DOUBLE ; /* if the multiple press count is 3, process immediately as a triple press and cancel the multiple press timer */ else if(pButtonsTask->gBTapCount == TRIPLE_PRESS) { pButtonsTask->gBTime = B_TRIPLE ; /* indicate a triple press has been detected */ ButtonsButtonDetected ( pButtonsTask , lOldInput , B_TRIPLE ); /* reset current state and multiple press counter */ pButtonsTask->gBMultipleState = 0x0000 ; pButtonsTask->gBTapCount = 0; MessageCancelAll ( &pButtonsTask->task , B_MULTIPLE_TIMER ) ; } } /*only send a message if it was a short one - long / v long /double handled elsewhere*/ if ( (pButtonsTask->gBTime == B_SHORT ) ) { ButtonsButtonDetected ( pButtonsTask , lOldInput , B_SHORT ); /*store the double state*/ pButtonsTask->gBMultipleState = lOldInput ; pButtonsTask->gBTapCount++; /*start the double timer - only applicable to a short press*/ MessageSendLater ( &pButtonsTask->task , B_MULTIPLE_TIMER , 0 ,pButtonsTask->button_config->double_press_time ) ; } else if ( (pButtonsTask->gBTime == B_LONG) ) { ButtonsButtonDetected ( pButtonsTask , lOldInput , B_LONG_RELEASE ); } else if ( (pButtonsTask->gBTime == B_VERY_LONG) ) { ButtonsButtonDetected ( pButtonsTask , lOldInput , B_VERY_LONG_RELEASE ); } else if ( (pButtonsTask->gBTime == B_VERY_VERY_LONG) ) { ButtonsButtonDetected ( pButtonsTask , lOldInput , B_VERY_VERY_LONG_RELEASE ); } if (pButtonsTask->gBTime != B_INVALID) { MessageCancelAll ( &pButtonsTask->task , B_INTERNAL_TIMER) ; MessageCancelAll ( &pButtonsTask->task , B_REPEAT_TIMER ) ; } /*removing this allows all releases to generate combination presses is this right?*/ if ( !lNewInput ) { pButtonsTask->gBTime = B_INVALID ; } } } }
/**************************************************************************** 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 ) ; } } }