/*
 * Copyright (c) 2017, The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials provided
 *       with the distribution.
 *     * Neither the name of The Linux Foundation nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "IoctlDev.h"
#include "wlct_procfs.h"
#include "public.h"
#include "LoggerSupport.h"
#include <iostream>
#include <fstream>

#include <algorithm>

#define PROC_MODULES_PATH "/proc/modules"
#define DRIVER_KEYWORD "wil6210"

void CIoctlDev::FormatCDevFName(void)
{
    int sres = snprintf(cdevFileName, sizeof(cdevFileName),
                        "/tmp/%s", WLCT_CDEV_NAME);

    WLCT_ASSERT((size_t)sres < sizeof(cdevFileName));
    (void)sres;
}

CIoctlDev::CIoctlDev(const TCHAR *tchDeviceName)
    : IIoctlDev(tchDeviceName)
{
    if( strstr(szInterfaceName, "wEP") != NULL || strstr(szInterfaceName, "wep") != NULL ){
	cdevFile = new CWlctCDevSocket();
    }  else{
        cdevFile = new CWlctCDevFile();
    }
    // Name in format WLCT_PCI_LDEVNAME_FMT/WLCT_PCI_RDEVNAME_FMT
    FormatCDevFName();
}

CIoctlDev::~CIoctlDev()
{
    delete cdevFile;
    Close();
}

bool CIoctlDev::IsOpened(void)
{
    return cdevFile->IsOpened();
}

wlct_os_err_t CIoctlDev::DebugFS(char *FileName, void *dataBuf, DWORD dataBufLen, DWORD DebugFSFlags)
{
    return cdevFile->DebugFS(FileName, dataBuf, dataBufLen, DebugFSFlags);
}

bool WilDriverExistForEP(TCHAR *szInterfaceName)
{

    if( strstr(szInterfaceName, "wEP") != NULL || strstr(szInterfaceName, "wep") != NULL ){
        ifstream ifs(PROC_MODULES_PATH);
        string DriverKey = DRIVER_KEYWORD;
        string line;
        while(getline(ifs, line)) {
            if (line.find(DriverKey, 0) != string::npos) {
                LOG_MESSAGE_INFO(_T("Found WIGIG interface [wEP0!MARLON]"));
                return true;
            }
        }
    }
    return false;
}
wlct_os_err_t CIoctlDev::Open()
{
    wlct_os_err_t res = WLCT_OS_ERROR_GEN_FAILURE;

    WLCT_ASSERT(!IsOpened());

    bOldIoctls = TRUE;

    if (WilDriverExistForEP(szInterfaceName))
    {
        // Bug fix
        char tempInterfaceName[INTERFACE_NAME_LENGTH];
        snprintf(tempInterfaceName, INTERFACE_NAME_LENGTH, "%s", szInterfaceName);

        LOG_MESSAGE_DEBUG("Tokenizing: %s\n", tempInterfaceName);

        res = cdevFile->Open(cdevFileName, tempInterfaceName);
        if (res == WLCT_OS_ERROR_SUCCESS)
        {
            LOG_MESSAGE_DEBUG("Cdev file '%s' opened (uid=%u)",
                              cdevFileName, uID);
        }
        else
        {
            LOG_MESSAGE_ERROR("Cdev file '%s' (uid=%u) opening failed (%d)",
                              cdevFileName, uID, res);
        }
    }
    else
    {
        LOG_MESSAGE_ERROR("Cannot get UID by PciDevName (%s)",
                          szInterfaceName);
        res = WLCT_OS_ERROR_NO_SUCH_ENTRY;
    }

    return res;
}

void CIoctlDev::Close()
{
    if (IsOpened())
    {
        cdevFile->Close();
    }
}

wlct_os_err_t CIoctlDev::Ioctl(uint32_t Id,
                               const void *inBuf, uint32_t inBufSize,
                               void *outBuf, uint32_t outBufSize)
{
    wlct_os_err_t     res = WLCT_OS_ERROR_GEN_FAILURE;
    wlct_ioctl_hdr_t *ioctlHdr = NULL;
    uint32_t          ioctlBufSize = 0;

    WLCT_ASSERT(IsOpened());

    if (!inBuf || !inBufSize)
    {
        inBuf     = NULL;
        inBufSize = 0;
    }

    if (!outBuf || !outBufSize)
    {
        outBuf     = NULL;
        outBufSize = 0;
    }

    ioctlBufSize = sizeof(wlct_ioctl_hdr_t) + inBufSize + outBufSize;

    ioctlHdr = (wlct_ioctl_hdr_t *)malloc(ioctlBufSize);
    if (ioctlHdr)
    {
        uint32_t offset     = 0;
        uint32_t ioctlFlags = 0;

        memset(ioctlHdr, 0, ioctlBufSize);

        ioctlHdr->deviceUID    = uID;
        ioctlHdr->commandID    = Id;
        ioctlHdr->dataSize     = inBufSize + outBufSize;
        if (inBufSize)
        {
            ioctlHdr->inBufOffset  = offset;
            ioctlHdr->inBufSize    = inBufSize;
            ioctlFlags            |= WLCT_IOCTL_FLAG_SET;

            memcpy(wlct_ioctl_data_in(ioctlHdr), inBuf, inBufSize);

            offset += inBufSize;
        }

        if (outBufSize)
        {
            ioctlHdr->outBufOffset  = offset;
            ioctlHdr->outBufSize    = outBufSize;
            ioctlFlags             |= WLCT_IOCTL_FLAG_GET;

            offset += outBufSize;
        }

        res = cdevFile->Ioctl(ioctlHdr, ioctlBufSize, ioctlFlags);

        if (res != WLCT_OS_ERROR_SUCCESS)
        {
            LOG_MESSAGE_ERROR("IOCTL failed with error %u (id=%u)",
                              res, Id);
        }
        else if (outBufSize)
        {
            memcpy(outBuf, wlct_ioctl_data_out(ioctlHdr), outBufSize);
        }

        free(ioctlHdr);
    }
    else
    {
        LOG_MESSAGE_ERROR("Cannot allocate IOCTL buffer of %u bytes (id=%u)",
                          ioctlBufSize, Id);

        res = WLCT_OS_ERROR_NOT_ENOUGH_MEMORY;
    }


    return res;
}
