/***************************************************************************
 *
 *  Oxford Semiconductor Proprietary and Confidential Information
 *
 *  Copyright:      Oxford Semiconductor Ltd, 2006
 *
 *  Description:    Debug and tracing related function defintions and macros.
 *
 ***************************************************************************/

#ifndef INC_DbgTrace_h
#define INC_DbgTrace_h

#include "OsTypes.h"
#include "Trace.h"


/**
 *  Trace/Debug levels.
 */
typedef enum
{
    OS_LEVEL_NONE        = TRACE_LEVEL_NONE,
    OS_LEVEL_CRITICAL    = TRACE_LEVEL_CRITICAL,
    OS_LEVEL_FATAL       = TRACE_LEVEL_FATAL,
    OS_LEVEL_ERROR       = TRACE_LEVEL_ERROR,
    OS_LEVEL_WARNING     = TRACE_LEVEL_WARNING,
    OS_LEVEL_INFORMATION = TRACE_LEVEL_INFORMATION,
    OS_LEVEL_VERBOSE     = TRACE_LEVEL_VERBOSE

} TraceDebugLevel;

/**
 *  Trace flags.
 */
#define OS_TRACE_FLAG_INIT              TRACE_FLAG_INIT
#define OS_TRACE_FLAG_UNINIT            TRACE_FLAG_UNINIT
#define OS_TRACE_FLAG_PNP               TRACE_FLAG_PNP
#define OS_TRACE_FLAG_POWER             TRACE_FLAG_POWER
#define OS_TRACE_FLAG_WMI               TRACE_FLAG_WMI
#define OS_TRACE_FLAG_CREATE_CLOSE      TRACE_FLAG_CREATE_CLOSE
#define OS_TRACE_FLAG_IOCTLS            TRACE_FLAG_IOCTLS
#define OS_TRACE_FLAG_WRITE             TRACE_FLAG_WRITE
#define OS_TRACE_FLAG_READ              TRACE_FLAG_READ
#define OS_TRACE_FLAG_DPC               TRACE_FLAG_DPC
#define OS_TRACE_FLAG_INTERRUPT         TRACE_FLAG_INTERRUPT
#define OS_TRACE_FLAG_LOCKS             TRACE_FLAG_LOCKS
#define OS_TRACE_FLAG_QUEUEING          TRACE_FLAG_QUEUEING
#define OS_TRACE_FLAG_HW_ACCESS         TRACE_FLAG_HW_ACCESS
#define OS_TRACE_FLAG_ASSERT            TRACE_FLAG_ASSERT
#define OS_TRACE_FLAG_PATH_TRACE        TRACE_FLAG_PATH_TRACE
#define OS_TRACE_FLAG_FUNC_TRACE        TRACE_FLAG_FUNC_TRACE

/**
 *  Debug flags.
 */
#define OS_DEBUG_FLAG_INIT              0x00000001
#define OS_DEBUG_FLAG_UNINIT            0x00000002
#define OS_DEBUG_FLAG_PNP               0x00000004
#define OS_DEBUG_FLAG_POWER             0x00000008
#define OS_DEBUG_FLAG_WMI               0x00000010
#define OS_DEBUG_FLAG_CREATE_CLOSE      0x00000020
#define OS_DEBUG_FLAG_IOCTLS            0x00000040
#define OS_DEBUG_FLAG_WRITE             0x00000080
#define OS_DEBUG_FLAG_READ              0x00000100
#define OS_DEBUG_FLAG_DPC               0x00000200
#define OS_DEBUG_FLAG_INTERRUPT         0x00000400
#define OS_DEBUG_FLAG_LOCKS             0x00000800
#define OS_DEBUG_FLAG_QUEUEING          0x00001000
#define OS_DEBUG_FLAG_HW_ACCESS         0x00002000
#define OS_DEBUG_FLAG_ASSERT            0x00004000
#define OS_DEBUG_FLAG_PATH_TRACE        0x00008000
#define OS_DEBUG_FLAG_FUNC_TRACE        0x00010000



/**
 *  Initialise the debug module.
 *  This function can be called only after a successful
 *  call to WdfDriverCreate().
 */
#if DBG
void
OsDebugInit(
    void
    );
#else
inline void
OsDebugInit(
    void
    )
{
    ;
}
#endif


/**
 *  Output a debug message.
 * @param Specifies the severity of the message being output.
 * @param Specifies the component calling this routine.
 * @param Specifies a pointer to the format string to print (printf style).
 * @param Specifies arguments for the format string.
 */
#if DBG
void
OsDebugOutput(
    TraceDebugLevel debugLevel,
    unsigned long   debugFlags,
    const char *    pMsgFormat,
    ...);
#else
inline void
OsDebugOutput(
    TraceDebugLevel debugLevel,
    unsigned long   debugFlags,
    const char *    pMsgFormat,
    ...)
{
    ;
}
#endif


/**
 *  Output a debug message.
 * @param Specifies the severity of the message being output.
 * @param Specifies the component calling this routine.
 * @param A boolean specifying whether to trace or not.
 * @param Specifies a pointer to the format string to print (printf style).
 * @param Specifies arguments for the format string.
 */
#if DBG
void
OsDebugOutputCond(
    TraceDebugLevel debugLevel,
    unsigned long   debugFlags,
    BOOLEAN         bCondition,
    const char *    pMsgFormat,
    ...);
#else
inline void
OsDebugOutputCond(
    TraceDebugLevel debugLevel,
    unsigned long   debugFlags,
    BOOLEAN         bCondition,
    const char *    pMsgFormat,
    ...)
{
    ;
}
#endif


#if !defined(EVENT_TRACING)

/**
 *  Trace a message.
 * @param Specifies the severity of the trace message.
 * @param Specifies the component being traced.
 * @param Specifies a pointer to the format string to trace (printf style).
 * @param Specifies arguments for the format string.
 */
#define OsTrace                         OsDebugOutput

/**
 *  Conditionally trace a message.
 * @param Specifies the severity of the trace message.
 * @param Specifies the component being traced.
 * @param A boolean specifying whether to trace or not.
 * @param Specifies a pointer to the format string to trace (printf style).
 * @param Specifies arguments for the format string.
 */
#define OsTraceCond                     OsDebugOutputCond


/**
 *  Asserts and path tracing macros.
 *  Note that the assert macros do not use OsDebugOutputCond(),
 *  but OsDebugOutput(), for performance reasons.
 */
#define PATH_NOT_YET_TESTED()           OsDebugOutput(OS_LEVEL_WARNING,             \
                                                      OS_DEBUG_FLAG_PATH_TRACE,     \
                                                      "PNT %s/%u\n",                \
                                                      __FILE__,                     \
                                                      __LINE__)
#define PRECONDITION(c)                                                             \
    do                                                                              \
    {                                                                               \
        BOOLEAN bOk = !!(c);                                                        \
        if (!bOk)                                                                   \
        {                                                                           \
            OsDebugOutput(OS_LEVEL_CRITICAL,                                        \
                          OS_DEBUG_FLAG_ASSERT,                                     \
                          "ERROR PRECONDITION %s/%u\n",                             \
                          __FILE__,                                                 \
                          __LINE__);                                                \
        }                                                                           \
    } while(FALSE)

#define POSTCONDITION(c)                                                            \
    do                                                                              \
    {                                                                               \
        BOOLEAN bOk = !!(c);                                                        \
        if (!bOk)                                                                   \
        {                                                                           \
            OsDebugOutput(OS_LEVEL_CRITICAL,                                        \
                          OS_DEBUG_FLAG_ASSERT,                                     \
                          "ERROR POSTCONDITION %s/%u\n",                            \
                          __FILE__,                                                 \
                          __LINE__);                                                \
        }                                                                           \
    } while(FALSE)

#define EXPECT(c)                                                                   \
    do                                                                              \
    {                                                                               \
        BOOLEAN bOk = !!(c);                                                        \
        if (!bOk)                                                                   \
        {                                                                           \
            OsDebugOutput(OS_LEVEL_CRITICAL,                                        \
                          OS_DEBUG_FLAG_ASSERT,                                     \
                          "ERROR EXPECT %s/%u\n",                                   \
                          __FILE__,                                                 \
                          __LINE__);                                                \
        }                                                                           \
    } while(FALSE)

#endif


#endif // INC_DbgTrace_h

