/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*     DMC APE centric event handler class declaration.
*
*/


#ifndef DMC_EVENT_HANDLER_APE_CENT_H
#define DMC_EVENT_HANDLER_APE_CENT_H

#ifndef DMC_INTERNAL_INCLUDE
#error Illegal usage of dmc_event_handler_ape_cent.h, It is only for DMC internal use !
#endif // DMC_INTERNAL_INCLUDE

//  INCLUDES
#include <e32def.h>                            // Data types, TUint8 etc.
#include <boot_reason_api/boot_reason_api.h>   // TBootReason and TStartupMode handling

//  CONSTANTS

/**
* INPUT EVENTS:
*   This constanst defines event types / inputs to this event handler.
*
*
*   Kernel events (KERNEL_*) can be one of the following:
*      - ISI messages
*      - Power Handler(Power Up / Power Down)
*      - Isa Access Channel lost and open notification
*
*   User events (USER_*) are:
*      - Commands through DMC user interface.
*/
// An ISI-message. Can be a PN_MODEM_MCE or PN_DMC owned messages.
#define KERNEL_EVENT_ISI                      0x00
// Power Handler Power Down
#define KERNEL_EVENT_PWR_HANDLER              0x01
// IAD Modem connection lost
#define KERNEL_EVENT_MODEM_CONNECTION_NOT_OK  0x02
// Get the type of the event to be sent to kernel side client
#define KERNEL_GET_EVENT_TYPE                 0x03
// Used through DMC kernel IF
#define KERNEL_IF_GET_STARTUP_MODE            0x04
// Get hidden reset status, used through DMC kernel IF
#define KERNEL_IF_GET_HIDDEN_RESET_STATUS     0x05
// Generate reset requested from kernel side
#define KERNEL_IF_GENERATE_RESET              0x06
// Power off the device
#define KERNEL_IF_POWER_OFF                   0x07
// Used for detecting the event type
#define KERNEL_LAST_KERNEL_EVENT              KERNEL_IF_POWER_OFF
// Get target startup mode
#define USER_GET_TARGET_STARTUP_MODE          0x08
// Generate reset requested from user side
#define USER_GENERATE_RESET                   0x09
// Power off the device
#define USER_POWER_OFF                        0x0A
// Get hidden reset status
#define USER_GET_HIDDEN_RESET_STATUS          0x0B
// Get the type of the event to be sent to user side client
#define USER_GET_EVENT_TYPE                   0x0C
#define LAST_EVENT                            (USER_GET_EVENT_TYPE + 1)
#define NO_EVENTS_DEFINED                     0x00


/**
* OUTPUT EVENTS:
*   This constanst defines type of user side client events
*   generated by this event handler.
*
*   Event types are needed in case of Modem or PC SW
*   orginated controlled or uncontrolled power off / reset.
*/
// Modem or PC SW orginated power off.
#define DMC_CLIENT_POWER_OFF_EVENT           0x01
// Modem or PC SW orginated resest.
#define DMC_CLIENT_RESET_EVENT               0x02
// No event requested
#define DMC_CLIENT_NO_EVENT                  0x00


/**
* CLIENT TYPE:
*    A type of the client that request services.
*/
#define DMC_USER_BIT                          0x01
#define DMC_KERNEL_BIT                        0x02

//  MACROS
//  DATA TYPES
//  EXTERNAL DATA STRUCTURES
//  FUNCTION PROTOTYPES
//  FORWARD DECLARATIONS
class DDmcExtension;
class DMutex;
class TDfc;

NONSHARABLE_CLASS(DmcEvHandApeCent)
    {
    public: // Event handler new public functions

        /**
        * Init the event handler
        *
        * @param   *aDmcExt     A pointer to the DMC kernel extension.
        * @return  None
        */
        static void Init(DDmcExtension* const aDmcExt);

        /**
        * Subscribe events.
        *
        * @param   aTypeBitMask             DMC_USER_BIT or/and DMC_KERNEL_BIT
        * @param   *aReceiveEventDfcPtr     A pointer to TDfc queue.
        * @return  None
        */
        static void SubscribeEvents(const TUint8 aTypeBitMask, TDfc* const aReceiveEventDfcPtr);

        /**
        * Unsubscribe events.
        *
        * @param   *aUserEventDfcPtr     A pointer to DMC logical device TDfc queue.
        * @return  None
        */
        static void UnsubscribeEvents(TDfc* const aUserEventDfcPtr);

        /**
        * A function that handles all incoming events.
        * This is the entry point for all events.
        *
        * @param   aEventType       Type of the message. A table "EVENTS" in the
        *                           dmc_event_handler_ape_cent.cpp-file defines allowed values.
        * @param   *aKernMsgPtr     A pointer to a incoming kernel message.
        * @param   *aUsrMsgPtr      A pointer to a incoming user message.
        * @return  KErrNone or one of the system wide error
        */
        static TInt HandleEvent(const TUint8  aType,
                                TUint8* const aKernMsgPtr,
                                TUint* const  aUsrMsgPtr);

    private:  // Event handler new private functions

        /**
        * Locks a section of code for an execution more
        * than one thread concurrently.
        *
        * Use Unlock to free this lock.
        *
        * @param   None
        * @return  None
        */
        inline static void Lock();

        /**
        * Frees the Lock.
        *
        * @param   None
        * @return  None
        */
        inline static void Unlock();

        /**
        * This function process an ANY-state.
        * There are events, which always must be handled regardless of
        * an ongoing transaction. These type of events are handled in the state ANY.
        *
        * @param   aEventType       Type of the message. A table "EVENTS" in the
        *                           dmc_event_handler_ape_cent.cpp-file defines allowed values.
        * @param   *aKernMsgPtr     A pointer to a incoming kernel message.
        * @param   *aUsrMsgPtr      A pointer to a incoming user message.
        * @return  KErrNone or one of the system wide error
        */
        static TInt StateAny(const TUint8  aEventType,
                             TUint8* const aKernMsgPtr,
                             TUint* const  aUsrMsgPtr);

        /**
        * This function process an IDLE-state.
        * IDLE-state is the only state in which a new transaction is started.
        *
        * @param   aEventType       Type of the message. A table "EVENTS" in the
        *                           dmc_event_handler_ape_cent.cpp-file defines allowed values.
        * @param   *aKernMsgPtr     A pointer to a incoming kernel message.
        * @param   *aUsrMsgPtr      A pointer to a incoming user message.
        * @return  KErrNone or one of the system wide error
        */
        static TInt StateIdle(const TUint8  aEventType,
                              const TUint8* const aKernMsgPtr,
                              TUint* const  aUsrMsgPtr);

        /**
        * This function processes an APE_PWR_OFF-state (PC or SSM Adaptation).
        *
        * @param   aEventType       Type of the message. A table "EVENTS" in the
        *                           dmc_event_handler_ape_cent.cpp-file defines allowed values.
        * @param   *aKernMsgPtr     A pointer to a incoming kernel message.
        * @param   *aUsrMsgPtr      A pointer to a incoming user message.
        * @return  KErrNone or one of the system wide error
        */
        static TInt StateApePwrOff(const TUint8  aEventType,
                                   const TUint8* const aKernMsgPtr,
                                   TUint* const  aUsrMsgPtr);

        /**
        * This function process an APE_RESET-state (APE orginated reset).
        *
        * @param   aEventType       Type of the message. A table "EVENTS" in the
        *                           dmc_event_handler_ape_cent.cpp-file defines allowed values.
        * @param   *aKernMsgPtr     A pointer to a incoming kernel message.
        * @param   *aUsrMsgPtr      A pointer to a incoming user message.
        * @return  KErrNone or one of the system wide error
        */
        static TInt StateApeReset(const TUint8  aEventType,
                                  const TUint8* const aKernMsgPtr,
                                  TUint* const  aUsrMsgPtr);

        /**
        * This function process a MODEM_PWR_OFF-state.
        *
        * @param   aEventType       Type of the message. A table "EVENTS" in the
        *                           dmc_event_handler_ape_cent.cpp-file defines allowed values.
        * @param   *aKernMsgPtr     A pointer to a incoming kernel message.
        * @param   *aUsrMsgPtr      A pointer to a incoming user message.
        * @return  KErrNone or one of the system wide error
        */
        static TInt StateModemPwrOff(const TUint8  aEventType,
                                     const TUint8* const aKernMsgPtr,
                                     TUint* const  aUsrMsgPtr);

        /**
        * This function process a MODEM_CONTROLLED_RESET-state.
        *
        * @param   aEventType       Type of the message. A table "EVENTS" in the
        *                           dmc_event_handler_ape_cent.cpp-file defines allowed values.
        * @param   *aKernMsgPtr     A pointer to a incoming kernel message.
        * @param   *aUsrMsgPtr      A pointer to a incoming user message.
        * @return  KErrNone or one of the system wide error
        */
        static TInt StateModemControlledReset(const TUint8  aEventType,
                                              const TUint8* const aKernMsgPtr,
                                              TUint* const  aUsrMsgPtr);

        /**
        * This function process a MODEM_UNCONTROLLED_RESET-state.
        *
        * @param   aEventType       Type of the message. A table "EVENTS" in the
        *                           dmc_event_handler_ape_cent.cpp-file defines allowed values.
        * @param   *aKernMsgPtr     A pointer to a incoming kernel message.
        * @param   *aUsrMsgPtr      A pointer to a incoming user message.
        * @return  KErrNone or one of the system wide error
        */
        static TInt StateModemUncontrolledReset(const TUint8  aEventType,
                                                const TUint8* const aKernMsgPtr,
                                                TUint* const  aUsrMsgPtr);


        /**
        * A function to handle a MCE_MODEM_STATE_QUERY_RESP
        *
        * @param   *msgPtr     A pointer to a response.
        * @return  None
        */
        static void HandleMceModemStateQueryResp(const TUint8* const aMsgPtr);


        /**
        * This function Generates an event for user and kernel side clients.
        * The event is generated only if events are subscribed.
        *
        * @param   aToWhomBitMask   Defines whom to generate an event.
        *                           DMC_USER_BIT or/and DMC_KERNEL_BIT
        * @return  None
        */
        static void GenerateEvent(const TUint8 aToWhomBitMask);


        /**
        * Handles a state transition of the DMC Event Handler.
        * This function also checks if the a required state transition is allowed.
        *
        * @param   aNextState    Next state to be transferred.
        *                        A table "STATES" on top of this file defines
        *                        allowed values.
        * @return  None
        */
        static void SetNextState(const TUint8 aNextState);

        /**
        * This function checks if the incomming event is part of the any state.
        * Requests that are part of the any state are processed regardless
        * about the ongoing transaction. Requests are processed as long
        * as possible.
        *
        * @param   aEventType       Type of the message. A table "EVENTS" in the
        *                           dmc_event_handler_ape_cent.cpp-file.
        * @param   aKernMsgPtr      Pointer to Kernel event
        * @return  1: Bit set to indicate that a requested event is part of the any state.
        *          0: Bit not set to indicate that a requested event is not part of the any state.
        */
        static TUint8 IsAnyStateEvent(const TUint8 aEventType, const TUint8* const aKernMsgPtr);

    private: // data types

        /**
        * A pointer to DMC extension.
        * DMC extension owns this pointer.
        *
        */
        static DDmcExtension* iDmcExtPtr;

        /**
        * A pointer to mutex.
        * This class owns this pointer.
        *
        */
        static DMutex* iMutexPtr;

        /**
        * A pointer to DMC user Dfc-queue.
        * This class does not own this pointer.
        *
        */
        static TDfc* iUserEventDfcPtr;

        /**
        * A pointer to DMC kernel Dfc-queue.
        * This class does not own this pointer.
        *
        */
        static TDfc* iKernelEventDfcPtr;

        /**
        * Event for signaling upstairs to start power off
        *
        */
        static TRawEvent iSwitchOffEvent;

        /**
        * Event for signaling upstairs to start reset
        *
        */
        static TRawEvent iResetEvent;


        /**
        * A target start-up mode.
        * Values in the boot_reason_api.h-file.
        */
        static TBootReason::TStartupMode iTargetStartupMode;

        /**
        * A  hidden reset status.
        * Values in the boot_reason_api.h-file.
        *
        * ETrue if the reset is hidden, otherwise EFalse.
        */
        static TBool iHiddenStatus;

        /**
        * This bitmap a defines requests that are part
        * of the any state.
        */
        static const TUint32 iAnyStateMap;

        /**
        * This variable is needed to detect whether the Power Handler
        * PowerDown() has been called.
        *
        * DMC needs this information to know if the Power Handler
        * PowerDownDone must be called in case the modem connection
        * is lost and there is an ongoing transaction.
        *
        * If there is no ongoing transaction, the modem connection
        * lost is handled as a "MODEM_UNCONTROLLED_RESET".
        *
        * Only one transaction is allowed, thus if there is already
        * ongoing transaction, the modem connection is handled as
        * below.
        *
        * ModemConnection lost AND "transaction ongoing":
        *     IF "Power Handler PowerDown called"
        *         -> Acknowlege to Power Handler by
        *            PowerDownDone()
        *     ELSE
        *        -> Standby and wait until Power Handler
        *           PowerDown() is called and then
        *           acknowledge back immediately by
        *           calling PowerDownDone().
        *
        * Allowed values: TRUE / FALSE
        */
        static TUint8 iPowerDownCalled;

        /**
        * Modem action bit map.
        *
        * This bit map defines actions that have
        * been happend in the Modem state transition
        * and a modem connection.
        *
        * Action information is needed to find a correct
        * slot to acknowledge the Power Handler PowerDownDone.
        */
        static TUint8 iModemActionBitMap;

        /**
        * A current modem state.
        *
        * Values from mceisi.h-file.
        */
        static TUint8 iModemCurrentState;

        /**
        * Event type.
        *
        * Defines the type of the event to be sent
        * user side client. The event type is used in case
        * PC SW or Modem orginated power off or reset or
        * in case of uncontrolled Modem reset..
        *
        * Values from OUTPUT EVENTS: defined beginning of this file.
        */
        static TUint8 iEventType;

        /**
        * Current state
        * Allowed values defined in dmc_event_handler_ape_cent.cpp-file.
        *
        */
        static TUint8 iCurrentState;

        /**
        * This table defines allowed state transitions.
        */
        static const TUint8 iStateTransitionMap[];

    };

#endif // DMC_EVENT_HANDLER_APE_CENT_H

// End of File
