/*******************************************************************************
* Project:      Amped'RF Bluetooth
* File name:    GKI_trace.c
* Description:  DMA abstraction layer
*
* Copyright (c) 2013 Amped'RF Inc., AR Technology  All rights reserved.
*******************************************************************************/
#include "Common.h"
#include "btu_logtext.h"
#include "hcidefs.h"
#include "vendor.h"



#ifdef GKI_TRACE_HCI
#define PRINT(fmt)                          sprintf(msg, fmt);   GKI_putstring(msg)
#define PRINT1(fmt, a1)                     sprintf(msg, fmt, a1);  GKI_putstring(msg)
#define PRINT2(fmt, a1, a2)                 sprintf(msg, fmt, a1, a2);  GKI_putstring(msg)
#define PRINT3(fmt, a1, a2, a3)             sprintf(msg, fmt, a1, a2, a3);    GKI_putstring(msg)
#define PRINT4(fmt, a1, a2, a3, a4)         sprintf(msg, fmt, a1, a2, a3, a4);  GKI_putstring(msg)
#define PRINT5(fmt, a1, a2, a3, a4, a5)     sprintf(msg, fmt, a1, a2, a3, a4, a5);  GKI_putstring(msg)
#else
#define PRINT(fmt)
#define PRINT1(fmt, a1)
#define PRINT2(fmt, a1, a2)
#define PRINT3(fmt, a1, a2, a3)
#define PRINT4(fmt, a1, a2, a3, a4)
#define PRINT5(fmt, a1, a2, a3, a4, a5)
#endif


#define FILTER_WRITE_FILE_BLOCK
//#define FILTER_READ_REVISION
//#define FILTER_ALL


#ifdef GKI_TRACE_HCI
static u16 filter_opcodes[]={
#ifdef FILTER_WRITE_FILE_BLOCK
    HCI_CMD_ERICSSON_WRITE_FILE_BLOCK,
#endif
#ifdef FILTER_READ_REVISION
    HCI_CMD_ERICSSON_READ_REVISION_INFORMATION,
#endif
    0
};
u16 filter_opcode_num = (sizeof(filter_opcodes)/sizeof(u16)) - 1;
#endif


#ifdef GKI_TRACE_HCI
static bool FilterPackets(tHciUartPacket  * pPkt)
{
#ifdef FILTER_ALL
    return true;
#else
    switch (pPkt->PktTypeCode)
    {
    case HCI_UART_CMD:
        for (int i=0; i<filter_opcode_num; i++) {
            if (pPkt->PktType.Cmd.Opcode == filter_opcodes[i])
                return true;
        }
        break;

    case HCI_UART_EVT:
        for (int i=0; i<filter_opcode_num; i++) {
            if ((pPkt->PktType.Event.Code == HCI_COMMAND_COMPLETE_EVT)
                && (pPkt->PktType.Event.EvtType.Command_Complete.Opcode == filter_opcodes[i]))
                return true;
            if ((pPkt->PktType.Event.Code == HCI_COMMAND_STATUS_EVT)
                && (pPkt->PktType.Event.EvtType.Command_Status.Opcode == filter_opcodes[i]))
                return true;
        }
        break;
    }
    return false;
#endif
}
#endif


#ifdef GKI_TRACE_HCI
void GKI_show_hci_packet(tHciUartPacket *pPkt, u16 len)
{
    tHciCommand *pCmd;
    uint16 count;
    uint8 status;
    uint16 handle;
    uint16 reason;
    char *p;
    char msg[200];

    GKI_putstring("HCI  ");

    switch (pPkt->PktTypeCode)
    {
    case HCI_UART_CMD:
        pCmd = &pPkt->PktType.Cmd;
        PRINT3("%02d Cmd   %04X %s",
                0, //Footprint[i].v.hci.Num_HCI_Command_Packets,
                pCmd->Opcode,
                GetCommandName(pCmd->Opcode));
        if (pCmd->Length==1) {
            PRINT1(" (%02X)", pCmd->Data[0]);
        }

        //----------------------------------
        switch (pCmd->Opcode)
        {
        case HCI_CMD_ERICSSON_WRITE_FILE_BLOCK:
            PRINT1(" - Seq=%02X", pCmd->Data[0]);
            break;

        case HCI_PIN_CODE_REQUEST_REPLY:
            PRINT( " - ");
            count = pCmd->Data[6];
            p = (char *)&pCmd->Data[7];
            while (count--) {
                PRINT1("%c", *p++);
            }
            break;
        }
        //----------------------------------
        break;

    case HCI_UART_EVT:
        status = pPkt->PktType.Event.EvtType.Command_Complete.Params[0];
        if (pPkt->PktType.Event.Code == HCI_COMMAND_COMPLETE_EVT) {
            status = pPkt->PktType.Event.EvtType.Command_Complete.Params[0];
            switch (pPkt->PktType.Event.EvtType.Command_Complete.Opcode)
            {
            case HCI_CMD_ERICSSON_WRITE_FILE_BLOCK:
                PRINT5("%02d Evt%02X %04X %s - %s",
                    0, //Footprint[i].v.hci.Num_HCI_Command_Packets,
                    pPkt->PktType.Event.Code,
                    pPkt->PktType.Event.EvtType.Command_Complete.Opcode,
                    GetCommandName(pPkt->PktType.Event.EvtType.Command_Complete.Opcode),
                    GetHciStatusText(status));
                break;

            default:
                PRINT5("%02d Evt%02X %04X %s - %s",
                    0, //Footprint[i].v.hci.Num_HCI_Command_Packets,
                    pPkt->PktType.Event.Code,
                    pPkt->PktType.Event.EvtType.Command_Complete.Opcode,
                    GetCommandName(pPkt->PktType.Event.EvtType.Command_Complete.Opcode),
                    GetHciStatusText(status));
                break;
            }
        }
        else if (pPkt->PktType.Event.Code == HCI_COMMAND_STATUS_EVT) {
            status = pPkt->PktType.Event.EvtType.Command_Status.Status;
            PRINT5("%02d Evt%02X %04X %s - %s",
                    0, //Footprint[i].v.hci.Num_HCI_Command_Packets,
                    pPkt->PktType.Event.Code,
                    pPkt->PktType.Event.EvtType.Command_Status.Opcode,
                    GetCommandName(pPkt->PktType.Event.EvtType.Command_Status.Opcode),
                    GetHciStatusText(status));
        }
        else {
            status = pPkt->PktType.Event.EvtType.Params[0];
            PRINT2("   Evt%02X %s",
                    pPkt->PktType.Event.Code,
                    GetEventName(pPkt->PktType.Event.Code));
            switch (pPkt->PktType.Event.Code)
            {
            case HCI_INQUIRY_RESULT_EVT:
            case HCI_FLUSH_OCCURED_EVT:
            case HCI_NUM_COMPL_DATA_PKTS_EVT:
            case HCI_LINK_KEY_REQUEST_EVT:
            case HCI_PIN_CODE_REQUEST_EVT:
            case HCI_MAX_SLOTS_CHANGED_EVT:
            case HCI_LINK_KEY_NOTIFICATION_EVT:
                break;

            case HCI_AUTHENTICATION_COMP_EVT:
            case HCI_RMT_NAME_REQUEST_COMP_EVT:
            case HCI_ENCRYPTION_CHANGE_EVT:
            case HCI_SIMPLE_PAIRING_COMPLETE_EVT:
                PRINT1(" - %s", GetHciStatusText(status));
                break;

            case HCI_DISCONNECTION_COMP_EVT:
                handle = *(uint16 *)&pPkt->PktType.Event.EvtType.Params[1];
                reason = pPkt->PktType.Event.EvtType.Params[3];
                PRINT1(" - %s", GetHciStatusText(status));
                PRINT2(", %04x, %s", handle, GetHciStatusText(reason));
                break;

            default:
                break;
            }
        }
        break;

    case HCI_UART_ACL:
        /*
        //sprintf(buf, "   ACL %c ", dir==FOOTPRINT_RX ? '>':'<');
        PRINT1("   ACL %s ", dir==FOOTPRINT_RX ? "Rx":"Tx");
        buf += strlen(buf);
        FootprintAclString(buf, pPkt);*/
        break;

    case HCI_UART_SCO:
        PRINT("   Sco");
        break;

    default:
        PRINT("   ***");
    }

    PRINT("\r\n");
}
#endif



void GKI_HCI_Rx(void *pData, u16 Length)
{
#ifdef GKI_TRACE_HCI
    if (Length==99) {
        tHciUartPacket *pPkt = pData;
        if (FilterPackets(pPkt))
            return;
        GKI_putstring(" <== ");
        GKI_show_hci_packet(pData, Length);
    }
#endif
}


void GKI_HCI_Tx(void *pData, u16 Length)
{
#ifdef GKI_TRACE_HCI
    if (Length==99) {
        tHciUartPacket *pPkt = pData;
        if (FilterPackets(pPkt))
            return;
        //char msg[8];
        GKI_putstring(" ==> ");
        GKI_show_hci_packet(pData, Length);
        if (pPkt->PktTypeCode == HCI_UART_CMD) {
            char msg[8];
            Length = pPkt->PktType.Cmd.Length;
            if (Length>0 && Length<8) {
                GKI_putstring("                   ");
                for (u8 *p=pPkt->PktType.Cmd.Data; Length--; ) {
                    PRINT1(" %02x", *p++);
                }
                GKI_putstring("\r\n");
            }
        }
    }
#endif
}



//--------------------------------------------------------------
//