blob: 44733152353150e3a22794cc37397041f284163f [file] [log] [blame]
/*
* 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;
}