Пример #1
0
/****************************************************************************

DESCRIPTION
 	function to detect edge changes of buttons / multiple buttons. 

*/ 
static void ButtonsEdgeDetect ( const uint32 pState , ButtonsTaskData * pButtonsTask ) 
{
    uint32 lNewState = 0x0000 ;
    
    uint32 lButton = 0x0000 ;
    
    /*what has changed */
    lNewState = (uint32) ( pState & (pButtonsTask->gPerformEdgeCheck) ) ;
    
    lButton = ButtonsWhichButtonChanged( pButtonsTask->gBOldEdgeState , lNewState ) ;
    
    
    B_DEBUG(("But Edge Det: [%lx][%lx][%lx]\n", pButtonsTask->gBOldEdgeState , lNewState , pButtonsTask->gButtonLevelMask  )) ;
    B_DEBUG(("But Edge Det: [%lx][%lx][%lx]\n", lNewState , lButton , (lNewState & lButton) )) ;
    
        /*if a button has changed*/
    if ( lButton )
    {
            /*determine which edge has been received and process accordingly*/
        if ( lNewState & lButton )
        {  
            ButtonsButtonDetected ( pButtonsTask , lButton , B_LOW_TO_HIGH )   ;
        }
        else
        {
            ButtonsButtonDetected ( pButtonsTask , lButton , B_HIGH_TO_LOW  )   ;
        }
    }
        /*remember the last state*/
    pButtonsTask->gBOldEdgeState = lNewState;
}
Пример #2
0
/****************************************************************************

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  )   ;
        }
    }
}
Пример #3
0
/****************************************************************************
DESCRIPTION
 	function to detect level changes of buttons / multiple buttons. 
*/ 
static void ButtonsLevelDetect ( const uint32 pState , ButtonsTaskData * pButtonsTask ) 
{
    uint32 lNewState = 0;

    	/*we have an indication from the PIO subsytem that a PIO has changed value*/
    lNewState = (uint32) (pState & (pButtonsTask->gPerformLevelCheck) ) ;
    
    B_DEBUG(("But Lev Det|:[%lx][%lx]\n", pState , (pButtonsTask->gButtonLevelMask) )) ;
    B_DEBUG(("But Lev Det|:[%lx][%lx]\n", pButtonsTask->gBOldState , lNewState )) ;
    
    if ( ButtonsWasButtonPressed( pButtonsTask->gBOldState , lNewState )  )
    {
        /*cancel all previously timed messages*/   
        MessageCancelAll ( &pButtonsTask->task , B_INTERNAL_TIMER ) ;
        MessageCancelAll ( &pButtonsTask->task , B_REPEAT_TIMER ) ;
        MessageCancelAll ( &pButtonsTask->task , B_DOUBLE_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 ;      
    }
    /*button was released or was masked out, check to make sure there is a pio bit change as vreg enable
      can generate an addition MSG without any pio's changing state */
    else if(pButtonsTask->gBOldState != lNewState )              
    {         /*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 ( pButtonsTask->gBOldState != 0 )
        {
                 /*if we have had a double press in the required time 
                 and the button pressed was the same as this one*/
             if (  (pButtonsTask->gBDoubleTap ) && (pButtonsTask->gBOldState == pButtonsTask->gBDoubleState ) )
             {
                 pButtonsTask->gBTime = B_DOUBLE ;
                    /*reset the double state*/
                 pButtonsTask->gBDoubleState = 0x0000 ;
                 pButtonsTask->gBDoubleTap = FALSE ;
                 ButtonsButtonDetected ( pButtonsTask , pButtonsTask->gBOldState , B_DOUBLE  ); 
             }                    

             
                /*only send a message if it was a short one - long / v long /double handled elsewhere*/
             if ( (pButtonsTask->gBTime == B_SHORT ) )
             {
                 ButtonsButtonDetected ( pButtonsTask , pButtonsTask->gBOldState , B_SHORT  ); 
                 
                 /*store the double state*/
                 pButtonsTask->gBDoubleState = pButtonsTask->gBOldState ;
                 pButtonsTask->gBDoubleTap = TRUE ;
        
                    /*start the double timer - only applicable to a short press*/
                 MessageSendLater ( &pButtonsTask->task , B_DOUBLE_TIMER , 0 ,pButtonsTask->button_config->double_press_time ) ;
             }  
             else if ( (pButtonsTask->gBTime == B_LONG) )
             {
                 ButtonsButtonDetected ( pButtonsTask , pButtonsTask->gBOldState , B_LONG_RELEASE  );                  
             }
             else if ( (pButtonsTask->gBTime == B_VERY_LONG) )
             {
                 ButtonsButtonDetected ( pButtonsTask , pButtonsTask->gBOldState , B_VERY_LONG_RELEASE  ); 
             }
             else if ( (pButtonsTask->gBTime == B_VERY_VERY_LONG) )
             {
                 ButtonsButtonDetected ( pButtonsTask , pButtonsTask->gBOldState , 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 ( !lNewState )
             {
                 pButtonsTask->gBTime = B_INVALID ;      
             } 
         }     
    }
    pButtonsTask->gBOldState = lNewState ;
}
Пример #4
0
static void ButtonsMessageHandler ( Task pTask, MessageId pId, Message pMessage ) 
{   
    ButtonsTaskData * lBTask = (ButtonsTaskData*)pTask ;

    B_DEBUG(("B:Message\n")) ;
    switch ( pId )
    {
	    case MESSAGE_PIO_CHANGED : 
        {
            const MessagePioChanged * lMessage = ( const MessagePioChanged * ) (pMessage ) ;
            uint32 lNewPioState = (uint32)( lMessage->state | CHARGER_VREG_VALUE | CHARGER_CONNECT_VALUE) ;
            
            B_DEBUG(("B:BMH - PIO_CHANGE: %x %x\n",lMessage->state16to31, lMessage->state)) ;
            
        
            /* when a pio is configured for an edge detect only there is significant performance gain to be had
               by only doing an edge detect call and not a level detect. To do this use a previously set edge
               detect mask and check this against the current pio being reported. Also need to check if a previously
               set PIO has now been removed and check for the edge transition once again. */
            if((lBTask->gPerformEdgeCheck & lNewPioState) ||
               (lBTask->gPerformEdgeCheck & lBTask->gOldPioState))
            {
                /* check for a valid edge transition against current pio states masked with edge configured pios
                   and perform appropriate action */                
                ButtonsEdgeDetect  ( (uint32)( lNewPioState & lBTask->gPerformEdgeCheck), lBTask ) ;
            }          
            
            /* only do a level detect call which is vm/messaging intensive when a pio has been configured as 
               short or long or very long or very very long, i.e. not rising or falling */
            if((lBTask->gPerformLevelCheck & lNewPioState ) ||
               (lBTask->gPerformLevelCheck & lBTask->gOldPioState))
            {
                /* perform a level detection, this call uses a number of messages and is quite slow to process */
                ButtonsLevelDetect ( ((uint32)lNewPioState & lBTask->gPerformLevelCheck) , lBTask) ;            
            }         
            
            /* store current set pio state in order to be able to detect the transition of a PIO configured as edge 
               detect only */
            lBTask->gOldPioState = lNewPioState ;
        
        }
    	break ;
        
        case MESSAGE_CHARGER_CHANGED:
	    {
		    const MessageChargerChanged *m = (const MessageChargerChanged *) (pMessage ) ;			
         
            /* when a charger or vreg change event is detectecd perform both an edge and level detection
               passing in only those approriately masked pios for edge or level configured buttons */
            ButtonsLevelDetect ( (((uint32)m->vreg_en_high << VREG_PIN) | ((uint32)m->charger_connected << CHG_PIN) | PIOGET()) & lBTask->gPerformLevelCheck , lBTask) ;           
            ButtonsEdgeDetect  ( (((uint32)m->vreg_en_high << VREG_PIN) | ((uint32)m->charger_connected << CHG_PIN) | PIOGET()) & lBTask->gPerformEdgeCheck , lBTask ) ;           
	    }
        break;
   
    	case B_DOUBLE_TIMER:
		{
				/*if we have reached here, then a double timer has been received*/
         	B_DEBUG(("B:Double[%lx][%x]\n", lBTask->gBDoubleState , B_SHORT_SINGLE)) ;
    
         	lBTask->gBDoubleTap = FALSE ;
        		/*indicate that a short button was pressed and it did not become a double press */
        	ButtonsButtonDetected ( lBTask, lBTask->gBDoubleState , B_SHORT_SINGLE ); 
		} 
        break ;
    	case B_INTERNAL_TIMER:
		{
			/*if we have reached here, then the buttons have been held longer than one of the timed messages*/
	        B_DEBUG(("B:Timer\n")) ;
            
            /* an internal timer has triggered which was initiated from the level detect function call */
        	if ( lBTask->gBTime == B_VERY_LONG )
        	{
                /* update timer state flag */
                lBTask->gBTime = B_VERY_VERY_LONG ;                
        	}
			/* a long press timer event has triggered */
            else if ( lBTask->gBTime == B_LONG )
        	{
                /* don't send very very long timer message until needed, i.e. very_long timer expired */
                MessageSendLater ( &lBTask->task , B_INTERNAL_TIMER , 0 ,  (lBTask->button_config->very_very_long_press_time - lBTask->button_config->very_long_press_time ) ) ;                   
                /* update tiemr state flag */
            	lBTask->gBTime = B_VERY_LONG ;
               	/*notify the app that the timer has expired*/
            	MessageSend( &theHeadset.task , EventVLongTimer , 0 ) ;    
        	}
			/* the first timer event triggered from the level detect call */
            else
        	{
                /* only send very long message when long timer expired to save messaging.                 */
                MessageSendLater ( &lBTask->task , B_INTERNAL_TIMER , 0 , (lBTask->button_config->very_long_press_time - lBTask->button_config->long_press_time)) ;
               	/*notify the app that the timer has expired*/
            	MessageSend( &theHeadset.task , EventLongTimer , 0 ) ;    
           		lBTask->gBTime = B_LONG ;
        	}    
            	/*indicate that we have received a message */
        	ButtonsButtonDetected ( lBTask, lBTask->gBOldState , lBTask->gBTime ); 
		}         
        break ;
    	case B_REPEAT_TIMER:
		{
			/*if we have reached here, the repeat time has been reached so send a new message*/
        	B_DEBUG(("B:Repeat[%lx][%x]\n", lBTask->gBOldState , B_REPEAT  )) ;
        
        	/*send another repeat message*/
        	MessageSendLater ( &lBTask->task , B_REPEAT_TIMER , 0 ,  lBTask->button_config->repeat_time ) ; 

        	ButtonsButtonDetected ( lBTask, lBTask->gBOldState , B_REPEAT ); 
		}
        break;
    	default :
           B_DEBUG(("B:?[%x]\n",pId)) ; 
        break ;
    }
}
Пример #5
0
/****************************************************************************
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 ;      
             } 
         }     
    }
}
Пример #6
0
static void ButtonsMessageHandler ( Task pTask, MessageId pId, Message pMessage ) 
{   
    ButtonsTaskData * lBTask = (ButtonsTaskData*)pTask ;

    B_DEBUG(("B:Message\n")) ;
    switch ( pId )
    {
#ifdef ENABLE_CAPSENSE
        
        /* delay handling of messages until capsense hardware has settled down */
        case B_MESSAGE_CAPSENSE_ENABLE :
        {
            /* connect the cap sense task to this task */    
            MessageCapsenseTask(&lBTask->task);
        }
        break;

        /* indication of a change of one of the capacitive touch sensors */
        case MESSAGE_CAPSENSE_CHANGED : 
        {
            uint8 i;
            const MessageCapsenseChanged * lMessage = ( const MessageCapsenseChanged * ) (pMessage ) ;
            uint16 CurrentCapState = lBTask->gOldCapState;
                      
            B_DEBUG(("B:Cap - Events = %x pad = %x dir = %x\n",lMessage->num_events,lMessage->event[0].pad,lMessage->event[0].direction)) ;

            /* the cap sense changed message may contain more than one button press, check for other
               presses or releases */
            for(i=0;i<lMessage->num_events;i++)
            {
                /* update the state of any sensor changes, direction is inverted, 0 = down, 1 = up  */
                if(lMessage->event[i].direction == CAPSENSE_EVENT_POS)
                    CurrentCapState |= (1<<(lMessage->event[i].pad));
                /* due to the fact that the fw will not report multiple press need to maintain
                    which touch sensors are up and which are down and set/reset appropriately */
                else
                    CurrentCapState &= ~(1<<(lMessage->event[i].pad));                
                        
                /* as the touch sensors as less effective when releasing, increase sesitivity 
                   when button indicates pressed to accurately detect the release event */
                if(lMessage->event[i].direction == CAPSENSE_EVENT_POS)
                {
                   if(!CapsenseConfigurePad(lMessage->event[i].pad, CAPSENSE_SET_TRIGGER_LEVEL, BM_CAP_SENSOR_HIGH_SENSITIVITY))
                       B_DEBUG(("B:Cap - invalid threshold %d\n",BM_CAP_SENSOR_LOW_SENSITIVITY));

                   /* button gone down, it is possible to record the time in mS at which the 
                      button went down, this can be used to accurately determine how long the 
                      button was held down for */                   
                   B_DEBUG(("B:Cap - Down Time %x = %ld mS\n",i,(uint32)lMessage->event[i].time_ms)) ;
                }
                /* return to original sensitivity when releasing button */                
                else
                {
                   if(!CapsenseConfigurePad(lMessage->event[i].pad, CAPSENSE_SET_TRIGGER_LEVEL, BM_CAP_SENSOR_LOW_SENSITIVITY))
                       B_DEBUG(("B:Cap - invalid threshold %d\n",BM_CAP_SENSOR_LOW_SENSITIVITY));
                       
                   /* button gone up, the time in mS can be used to get accurate duration information */
                   B_DEBUG(("B:Cap - Up Time %x = %ld mS\n",i,(uint32)lMessage->event[i].time_ms)) ;
                }
            }      
            
            B_DEBUG(("B:Cap - state = %x\n",CurrentCapState)) ;

            /* check whether the sensor status change requires an event to be generated */
            ButtonsCheckDetection(CurrentCapState, lBTask->gOldPIOState);
            
            /* update the last state value */
            lBTask->gOldCapState = CurrentCapState;
        }
        break;
#endif  
        
        case MESSAGE_PIO_CHANGED : 
        {
            const MessagePioChanged * lMessage = ( const MessagePioChanged * ) (pMessage ) ;
            /* get current pio state, eor with pio invert mask  */
            uint32 lNewPioState = (uint32)(theSink.conf1->PIOIO.pio_invert ^ (( lMessage->state | CHARGER_VREG_VALUE | CHARGER_CONNECT_VALUE) | (((uint32)lMessage->state16to31)<<16)));
            
            B_DEBUG(("B:BMH - PIO_CHANGE: %x %x\n",lMessage->state16to31, lMessage->state)) ;
            
#ifdef ENABLE_CAPSENSE
 
            /* check whether the pio status change requires an event to be generated */
            ButtonsCheckDetection(lBTask->gOldCapState, lNewPioState);
#else
            /* check whether the pio status change requires an event to be generated */
            ButtonsCheckDetection(0, lNewPioState);
#endif
        }
        break ;
        
        case MESSAGE_CHARGER_CHANGED:
        {
            const MessageChargerChanged *m = (const MessageChargerChanged *) (pMessage ) ;          
         
            B_DEBUG(("B:BMH - CHG_CHANGE: %lx\n",(((uint32)m->vreg_en_high << VREG_PIN) | ((uint32)m->charger_connected << CHG_PIN) | (PIOGET()^theSink.conf1->PIOIO.pio_invert)))) ;

            /* when a charger or vreg change event is detectecd perform both an edge and level detection
               passing in only those approriately masked pios for edge or level configured buttons */
                        /* check whether the pio status change requires an event to be generated */
#ifdef ENABLE_CAPSENSE
            ButtonsCheckDetection(lBTask->gOldCapState, (((uint32)m->vreg_en_high << VREG_PIN) | ((uint32)m->charger_connected << CHG_PIN) | (PIOGET()^theSink.conf1->PIOIO.pio_invert)));
#else
            ButtonsCheckDetection(0, (((uint32)m->vreg_en_high << VREG_PIN) | ((uint32)m->charger_connected << CHG_PIN) | (PIOGET()^theSink.conf1->PIOIO.pio_invert)));
#endif            
        }
        break;
   
        case B_MULTIPLE_TIMER:
        {
                /*if we have reached here, then a double timer has been received*/
            B_DEBUG(("B:Double[%lx][%x]\n", lBTask->gBMultipleState , B_SHORT_SINGLE)) ;
    
            /* when the multiple press timer has expired, check to see if a double press was
               made and if so indicate it */
            if(lBTask->gBTapCount == DOUBLE_PRESS)
                ButtonsButtonDetected ( lBTask , (lBTask->gBMultipleState & lBTask->gPerformInputLevelCheck) , B_DOUBLE  );                 
            /* no double press and no triple press, therefore indicate as a short single press */            
            else            
                ButtonsButtonDetected ( lBTask, (lBTask->gBMultipleState & lBTask->gPerformInputLevelCheck), B_SHORT_SINGLE );                        
            
            /* reset the multiple button press count */
            lBTask->gBTapCount = 0 ;            
            lBTask->gBMultipleState = 0x0000;
        } 
        break ;
        
        case B_INTERNAL_TIMER:
        {
            /*if we have reached here, then the buttons have been held longer than one of the timed messages*/
            B_DEBUG(("B:Timer\n")) ;

            /* since a long/vlong or vvlong has been triggered, cancel any pending double press checks */
            lBTask->gBMultipleState = 0x0000 ;
            lBTask->gBTapCount = 0 ;
            MessageCancelAll ( &lBTask->task , B_MULTIPLE_TIMER ) ;           

            /* an internal timer has triggered which was initiated from the level detect function call */
            if ( lBTask->gBTime == B_VERY_LONG )
            {
                /* update timer state flag */
                lBTask->gBTime = B_VERY_VERY_LONG ;                
            }
            /* a long press timer event has triggered */
            else if ( lBTask->gBTime == B_LONG )
            {
                /* don't send very very long timer message until needed, i.e. very_long timer expired */
                MessageSendLater ( &lBTask->task , B_INTERNAL_TIMER , 0 ,  (lBTask->button_config->very_very_long_press_time - lBTask->button_config->very_long_press_time ) ) ;                   
                /* update tiemr state flag */
                lBTask->gBTime = B_VERY_LONG ;
                /*notify the app that the timer has expired*/
                MessageSend( &theSink.task , EventSysVLongTimer , 0 ) ;    
            }
            /* the first timer event triggered from the level detect call */
            else
            {
                /* only send very long message when long timer expired to save messaging.                 */
                MessageSendLater ( &lBTask->task , B_INTERNAL_TIMER , 0 , (lBTask->button_config->very_long_press_time - lBTask->button_config->long_press_time)) ;
                /*notify the app that the timer has expired*/
                MessageSend( &theSink.task , EventSysLongTimer , 0 ) ;    
                lBTask->gBTime = B_LONG ;
            }    
            /*indicate that we have received a message */
            ButtonsButtonDetected ( lBTask, (lBTask->gBOldInputState & lBTask->gPerformInputLevelCheck) , lBTask->gBTime ); 
        }         
        break ;
        
        case B_REPEAT_TIMER:
        {
            /*if we have reached here, the repeat time has been reached so send a new message*/
            B_DEBUG(("B:Repeat[%lx][%x]\n", lBTask->gBOldInputState , B_REPEAT  )) ;
            
            /*send another repeat message*/
            MessageSendLater ( &lBTask->task , B_REPEAT_TIMER , 0 ,  lBTask->button_config->repeat_time ) ; 

            ButtonsButtonDetected ( lBTask, (lBTask->gBOldInputState & lBTask->gPerformInputLevelCheck) , B_REPEAT ); 
        }
        break;
        default :
           B_DEBUG(("B:?[%x]\n",pId)) ; 
        break ;
    }
}