/*===========================================================================

FILE: OEMNativeNotifier.c

SERVICES: Sample nativenotifier class using AEE

DESCRIPTION
  This file contains a class that implements the INativeNotifier interface.
  INativeNotifier interface implements services that allows a user applet to 
  register to be notified when the deviec enters / exits the IDLE screen.
  See ISHELL_RegisterNotify function descriptions for more information on 
  registering events with the shell.
  
PUBLIC CLASSES:  
   N/A

   	   Copyright © 2004-2005 QUALCOMM Incorporated.
	                  All Rights Reserved.
                   QUALCOMM Proprietary/GTDR
===========================================================================*/

/*===============================================================================
                     INCLUDES AND VARIABLE DEFINITIONS
=============================================================================== */

#include "OEMFeatures.h"
#include "AEE_OEMDispatch.h"

#include "AEEModGen.h"
#include "AEEAppGen.h"
#include "AEEShell.h"
#include "AEEDisp.h"
#include "AEEStdLib.h"
#include "AEEBridle.h"
#include "AEENativeNotifier.h"

/*===========================================================================

                      PUBLIC DATA DECLARATIONS

===========================================================================*/

#define  MAX_NATIVENOTIFY      5

/*-------------------------------------------------------------------
            Type Declarations
-------------------------------------------------------------------*/

// NativeNotifier class strucutre.
typedef struct _NativeNotifierClass
{
   DECLARE_VTBL(INotifier)
   AEECLSID     clsID;          // ClassID of nativenotifier class

   uint32       m_nRefs;        // Class reference counter
   IShell    *  m_pIShell;      // pointer to IShell

   uint32       m_dwNotifyMask;
   uint32       m_dwNotifyBit[MAX_NATIVENOTIFY];
   byte         m_byNotifyCountIn;
   byte         m_byNotifyCountOut;

   AEECallback  m_cbNotify;
} NativeNotifierClass;

/*-------------------------------------------------------------------
            Function Prototypes
-------------------------------------------------------------------*/

// NativeNotifier function prototypes
uint32  NativeNotifierClass_AddRef(INotifier* po);
uint32  NativeNotifierClass_Release(INotifier* po);
void    NativeNotifierClass_Notify(void *po, uint32 dwBit);
void    NativeNotifierClass_NotifyCallback(INotifier * po);
void    NativeNotifierClass_SetMask(INotifier* po, const uint32 * dwMask);
int     NativeNotifierClass_New(IShell * pIShell, AEECLSID cls, void **ppobj);

/*-------------------------------------------------------------------
            Global Constant Definitions
-------------------------------------------------------------------*/
 
/*-------------------------------------------------------------------
            Global Data Definitions
-------------------------------------------------------------------*/

NativeNotifierClass *gpNativeNotifier = NULL;
void                *gpNativeNotifierPtr = NULL;

/*-------------------------------------------------------------------
            Static variable Definitions
-------------------------------------------------------------------*/

/*===============================================================================
                     FUNCTION DEFINITIONS
=============================================================================== */

/*===========================================================================

Function:  NativeNotifierClass_AddRef()

Description:
	This function increases the referecne count for the NativeNotifierClass object

Prototype:
	uint32  NativeNotifierClass_AddRef(Notifier* po)

Parameters:
   po: Pointer to NativeNotifier interface whose reference count is to be incremented

Return Value:
	The updated reference count

Comments:  This function is a part of the NativeNotifier class which implements
           a basic notification service.

Side Effects: None

==============================================================================*/
uint32  NativeNotifierClass_AddRef(INotifier* po)
{
   return ++(((NativeNotifierClass *)po)->m_nRefs);
}

/*===========================================================================

Function:  NativeNotifierClass_Release()

Description:
		This function decreases the referecne count for the NativeNotifier object. If
		the reference count reaches zero, it does the required cleanup

Prototype:
	uint32  NativeNotifierClass_Release(Notifier* po)

Parameters:
   po: Pointer to the NativeNotifier interface whose reference count needs to be
       decremented.

Return Value:
   The updated reference count

Comments:  This function is a part of the NativeNotifier class which implements
           a basic notification service.

Side Effects: None

==============================================================================*/
uint32  NativeNotifierClass_Release(INotifier* po)
{
   NativeNotifierClass * pMe = (NativeNotifierClass *)po;

   if (--pMe->m_nRefs != 0)
      return pMe->m_nRefs;

   ISHELL_Release(pMe->m_pIShell);   // Release the Shell

   // delete this NativeNotifierClass object allocated in NotifierClass_New
   FREEOBJ(pMe);   
   
   gpNativeNotifier = NULL;
   gpNativeNotifierPtr = NULL;

   return 0;
}

/*===========================================================================

   This function is called by the native when the Idle / Non Idle
   transition happens. The native need to pass gpNativeNotifierPtr as 
   the first argument to this routine and the second argument the 
   corresponding mask releated to Idle / Non Idle transition

===========================================================================*/
void NativeNotifierClass_Notify(void *po, uint32 dwBit)
{
   NativeNotifierClass * pMe = (NativeNotifierClass *)po;

#ifdef NATIVENOTIFIER_DEBUG
   DBGPRINTF("Native Notify: %u, %u", pMe, dwBit);
#endif

   if (!pMe)
      return;

   BRIDLE_CHECK_WRITEACCESS(BRIDLE_FROM_UNPRIV, pMe, sizeof(NativeNotifierClass));

#ifdef  NOTIFY_MULTIPLE_PENDING_EVENTS
   pMe->m_dwNotifyBit[pMe->m_byNotifyCountIn] = dwBit;
   if (++pMe->m_byNotifyCountIn >= MAX_NATIVENOTIFY) {
      pMe->m_byNotifyCountIn = 0;
   }
#else
   pMe->m_dwNotifyBit[0] = dwBit;
#endif

   AEE_SYS_RESUME(&pMe->m_cbNotify);
}

/*===========================================================================

===========================================================================*/
void NativeNotifierClass_NotifyCallback(INotifier * po)
{
   NativeNotifierClass * pMe = (NativeNotifierClass *)po;
   byte                  byArr;

#ifdef NATIVENOTIFIER_DEBUG
   DBGPRINTF("Notify Callback: %u", pMe);
#endif

   if (!pMe)
      return;

#ifdef  NOTIFY_MULTIPLE_PENDING_EVENTS
   byArr = pMe->m_byNotifyCountOut++;
   if (pMe->m_byNotifyCountOut >= MAX_NATIVENOTIFY) {
      pMe->m_byNotifyCountOut = 0;
   }
#else
   byArr = 0;
#endif

#ifdef NATIVENOTIFIER_DEBUG
   DBGPRINTF("Notify Bit: %u", pMe->m_dwNotifyBit[byArr]);
   DBGPRINTF("Notify Mask: %u", pMe->m_dwNotifyMask);
#endif
   if (pMe->m_dwNotifyBit[byArr] == NOTIFY_MASK_NATIVE_IDLE_EVENT) {
      pMe->m_dwNotifyBit[byArr] = 0;
      if (pMe->m_dwNotifyMask & NOTIFY_MASK_NATIVE_IDLE_EVENT) {
         ISHELL_Notify(pMe->m_pIShell, AEECLSID_NATIVENOTIFIER, NOTIFY_MASK_NATIVE_IDLE_EVENT, NULL);
      }
   }

   if (pMe->m_dwNotifyBit[byArr] == NOTIFY_MASK_NATIVE_NONIDLE_EVENT) {
      pMe->m_dwNotifyBit[byArr] = 0;
      if (pMe->m_dwNotifyMask & NOTIFY_MASK_NATIVE_NONIDLE_EVENT) {
         ISHELL_Notify(pMe->m_pIShell, AEECLSID_NATIVENOTIFIER, NOTIFY_MASK_NATIVE_NONIDLE_EVENT, NULL);
      }
   }
}

/*===========================================================================

Function:  NativeNotifierClass_SetMask()

Description:
   This function gets called by the Shell when an user applet has requested 
   a notification be done when a event of type "dwMask" has occured on the
   notification service.

   In a typical notification service, "dwMask" will be stored
   in an event list. When the corresponding event occurs a notification 
   is sent to the Shell informing of the event occuring on the notification
   service object.

   Instead in this object, a timer is set up to occur in 3 seconds. 
   This timer expiration triggers the NativeNotifierClass_TimerCB()
   function to be called. In the the callback function the Shell is 
   notified that the requested event has occured on the nativenotifier service 
   object. In turn the Shell will send the EVT_NOTIFY event to the user 
   applet which requested the event notify.

Prototype:
	void NativeNotifierClass_SetMask(Notifier* po, const uint32 * dwMask)

Parameters:
   po     [in]: pointer to NativeNotifier interface.
   dwMask [in]: contains a const pointer to the event mask

Return Value: None

Comments:  This function is a part of the NativeNotifier class which implements
           a basic notification service.

Side Effects: None

==============================================================================*/
void NativeNotifierClass_SetMask(INotifier* po, const uint32 * dwMask)
{
   NativeNotifierClass * pMe = (NativeNotifierClass *)po;

   // just check if the nativenotifier is the value sent by the user.
   if (dwMask == NULL)
      return;

#ifdef NATIVENOTIFIER_DEBUG
   DBGPRINTF("Native Notifier Mask: %u", *dwMask);
#endif

   // Store the event that was requested for later use in the callback function.
   pMe->m_dwNotifyMask = GET_NOTIFIER_MASK(*dwMask);
}

/*===========================================================================

Function: NativeNotifierClass_New

Description:
	This function is invoked when the nativenotifier class is being loaded. It creates 
   a new instance of the NativeNotifierClass structure. This function is invoked from 
   within the AEEClsCreateInstance() function.

Prototype:
	boolean NativeNotifierClass_New( AEECLSID clsID,
							        IShell * pIShell, 
							        NativeNotifierClass **ppobj)

Parameters:
	clsID: [in]: Specifies the ClassID of this class
	pIShell: [in]: Contains a valid pointer to the AEE IShell interface
	ppobj: [out]: On return, *ppobj points to a valid NativeNotifierClass structure. This 
       allocation is done by this function

Dependancies: None

Return Value:
  TRUE: If successful
  FALSE: If failed

Comments:  This function is a part of the NativeNotifier class which implements
           a basic notification service.

Side Effects: None

===========================================================================*/
int NativeNotifierClass_New(IShell   *pIShell,
                            AEECLSID  clsID,
                            void    **ppobj)
{
   NativeNotifierClass   *pMe = NULL;
   VTBL(INotifier)       *appFuncs;
   int                    nSize;
		
   *ppobj = NULL;

   //Validate parameters
   if (!pIShell) 
      return EBADPARM;

   if (gpNativeNotifier) {
      ++gpNativeNotifier->m_nRefs;
   } else {
      // Allow the creation of first instance only in user mode
      if (BRIDLE_IS_ENABLED() && !BRIDLE_IS_IN_USR_MODE())
         return EFAILED;

      nSize = sizeof(NativeNotifierClass);
      // Allocate memory for the nativenotifier object and the INativeNotifierVtbl
      if (NULL == (pMe = (NativeNotifierClass*)MALLOC(nSize + sizeof(INotifierVtbl))))
         return ENOMEMORY;

      appFuncs = (INotifierVtbl *)((byte *)pMe + nSize);

      //Initialize the individual entries in the VTBL
      appFuncs->AddRef      = NativeNotifierClass_AddRef; 
      appFuncs->Release     = NativeNotifierClass_Release;
      appFuncs->SetMask     = NativeNotifierClass_SetMask;
   
      INIT_VTBL(pMe, INotifier, *appFuncs);   // Initialize the VTBL

      //Initialize the data members
      pMe->m_nRefs      = 1;
      pMe->m_pIShell    = pIShell;
      pMe->clsID        = clsID;

      ISHELL_AddRef(pIShell);

      // Init the callback...
      CALLBACK_Init(&pMe->m_cbNotify, (PFNNOTIFY)NativeNotifierClass_NotifyCallback,
                    pMe);

      gpNativeNotifier = pMe;
      gpNativeNotifierPtr = (void *)pMe;
   }

   *ppobj = (NativeNotifierClass*)gpNativeNotifier;  

   return SUCCESS;
}

