root/src/add-ons/kernel/drivers/ports/pc_serial/Tracing.cpp
/*
 * Copyright (c) 2007-2008 by Michael Lotz
 * Heavily based on the original usb_serial driver which is:
 *
 * Copyright (c) 2003 by Siarzhuk Zharski <imker@gmx.li>
 * Distributed under the terms of the MIT License.
 */
#include "Tracing.h"
#include "Driver.h"

#include <stdio.h> //sprintf
#include <unistd.h> //posix file i/o - create, write, close
#include <Drivers.h>
#include <directories.h>
#include <driver_settings.h>


#if DEBUG
bool gLogEnabled = true;
#else
bool gLogEnabled = false;
#endif

bool gLogToFile = false;
bool gLogAppend = false;
bool gLogFunctionCalls = false;
bool gLogFunctionReturns = false;
bool gLogFunctionResults = false;

static const char *sLogFilePath = kSystemLogDirectory "/" DRIVER_NAME ".log";
static sem_id sLogLock;


void
load_settings()
{
        void *settingsHandle;
        settingsHandle = load_driver_settings(DRIVER_NAME);

#if !DEBUG
        gLogEnabled = get_driver_boolean_parameter(settingsHandle,
                "debug_output", gLogEnabled, true);
#endif

        gLogToFile = get_driver_boolean_parameter(settingsHandle,
                "debug_output_in_file", gLogToFile, true);
        gLogAppend = !get_driver_boolean_parameter(settingsHandle,
                "debug_output_file_rewrite", !gLogAppend, true);
        gLogFunctionCalls = get_driver_boolean_parameter(settingsHandle,
                "debug_trace_func_calls", gLogFunctionCalls, false);
        gLogFunctionReturns = get_driver_boolean_parameter(settingsHandle,
                "debug_trace_func_returns", gLogFunctionReturns, false);
        gLogFunctionResults = get_driver_boolean_parameter(settingsHandle,
                "debug_trace_func_results", gLogFunctionResults, false);

        unload_driver_settings(settingsHandle);
}


void
create_log_file()
{
        if(!gLogToFile)
                return;

        int flags = O_WRONLY | O_CREAT | (!gLogAppend ? O_TRUNC : 0);
        close(open(sLogFilePath, flags, 0666));
        sLogLock = create_sem(1, DRIVER_NAME"-logging");
}


void
pc_serial_trace(bool force, const char *format, ...)
{
        if (!gLogEnabled && !force)
                return;

        static char buffer[1024];
        char *bufferPointer = buffer;
        if (!gLogToFile) {
                const char *prefix = "\033[32m" DRIVER_NAME ":\033[0m ";
                strcpy(bufferPointer, prefix);
                bufferPointer += strlen(prefix);
        }

        va_list argumentList;
        va_start(argumentList, format);
        vsprintf(bufferPointer, format, argumentList);
        va_end(argumentList);

        if (gLogToFile) {
                acquire_sem(sLogLock);
                int fd = open(sLogFilePath, O_WRONLY | O_APPEND);
                write(fd, buffer, strlen(buffer));
                close(fd);
                release_sem(sLogLock);
        } else
                dprintf("%s", buffer);
}


void
trace_termios(struct termios *tios)
{
        TRACE("struct termios:\n"
                "\tc_iflag:  0x%08x\n"
                "\tc_oflag:  0x%08x\n"
                "\tc_cflag:  0x%08x\n"
                "\tc_lflag:  0x%08x\n"
                "\tc_line:   0x%08x\n"
//              "\tc_ixxxxx: 0x%08x\n"
//              "\tc_oxxxxx: 0x%08x\n"
                "\tc_cc[0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x]\n",
                tios->c_iflag, tios->c_oflag, tios->c_cflag, tios->c_lflag, 
                tios->c_line, 
//              tios->c_ixxxxx, tios->c_oxxxxx, 
                tios->c_cc[0], tios->c_cc[1], tios->c_cc[2], tios->c_cc[3], 
                tios->c_cc[4], tios->c_cc[5], tios->c_cc[6], tios->c_cc[7], 
                tios->c_cc[8], tios->c_cc[9], tios->c_cc[10]);
}