DrvHostParallel.cpp revision ad48e47654d22f79b025dc4b21cb162cb123801a
/* $Id$ */
/** @file
* VirtualBox Host Parallel Port Driver.
*
* Contributed by: Alexander Eichner
*/
/*
* Copyright (C) 2006-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#define LOG_GROUP LOG_GROUP_DRV_HOST_PARALLEL
#include <iprt/semaphore.h>
#ifdef RT_OS_LINUX
# include <fcntl.h>
# include <unistd.h>
# include <errno.h>
#endif
#include "VBoxDD.h"
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
/**
* Host parallel port driver instance data.
* @implements PDMIHOSTPARALLELCONNECTOR
*/
typedef struct DRVHOSTPARALLEL
{
/** Pointer to the driver instance structure. */
/** Our host device interface. */
/** Device Path */
char *pszDevicePath;
/** Device Handle */
/** Thread waiting for interrupts. */
/** Wakeup pipe read end. */
/** Wakeup pipe write end. */
/** Current mode the parallel port is in. */
/** Converts a pointer to DRVHOSTPARALLEL::IHostDeviceConnector to a PDRHOSTPARALLEL. */
#define PDMIHOSTPARALLELCONNECTOR_2_DRVHOSTPARALLEL(pInterface) ( (PDRVHOSTPARALLEL)((uintptr_t)pInterface - RT_OFFSETOF(DRVHOSTPARALLEL, IHostParallelConnector)) )
/**
* Changes the current mode of the host parallel port.
*
* @returns VBox status code.
* @param pThis The host parallel port instance data.
* @param enmMode The mode to change the port to.
*/
{
int iMode = 0;
int rc = VINF_SUCCESS;
int rcLnx;
{
switch (enmMode)
{
break;
break;
break;
default:
return VERR_NOT_SUPPORTED;
}
if (RT_UNLIKELY(rcLnx < 0))
else
}
return rc;
}
/* -=-=-=-=- IBase -=-=-=-=- */
/**
* @interface_method_impl{PDMIBASE,pfnQueryInterface}
*/
{
return NULL;
}
/* -=-=-=-=- IHostDeviceConnector -=-=-=-=- */
/** @copydoc PDMICHARCONNECTOR::pfnWrite */
static DECLCALLBACK(int) drvHostParallelWrite(PPDMIHOSTPARALLELCONNECTOR pInterface, const void *pvBuf, size_t cbWrite, PDMPARALLELPORTMODE enmMode)
{
int rc = VINF_SUCCESS;
int rcLnx = 0;
if (RT_FAILURE(rc))
return rc;
if (enmMode == PDM_PARALLEL_PORT_MODE_SPP)
{
/* Set the data lines directly. */
}
else
{
/* Use write interface. */
}
if (RT_UNLIKELY(rcLnx < 0))
return rc;
}
static DECLCALLBACK(int) drvHostParallelRead(PPDMIHOSTPARALLELCONNECTOR pInterface, void *pvBuf, size_t cbRead, PDMPARALLELPORTMODE enmMode)
{
int rc = VINF_SUCCESS;
int rcLnx = 0;
if (RT_FAILURE(rc))
return rc;
if (enmMode == PDM_PARALLEL_PORT_MODE_SPP)
{
/* Set the data lines directly. */
}
else
{
/* Use write interface. */
}
if (RT_UNLIKELY(rcLnx < 0))
return rc;
}
static DECLCALLBACK(int) drvHostParallelSetPortDirection(PPDMIHOSTPARALLELCONNECTOR pInterface, bool fForward)
{
int rc = VINF_SUCCESS;
int rcLnx = 0;
int iMode = 0;
if (!fForward)
iMode = 1;
if (RT_UNLIKELY(rcLnx < 0))
return rc;
}
static DECLCALLBACK(int) drvHostParallelWriteControl(PPDMIHOSTPARALLELCONNECTOR pInterface, uint8_t fReg)
{
int rc = VINF_SUCCESS;
int rcLnx = 0;
if (RT_UNLIKELY(rcLnx < 0))
return rc;
}
static DECLCALLBACK(int) drvHostParallelReadControl(PPDMIHOSTPARALLELCONNECTOR pInterface, uint8_t *pfReg)
{
int rc = VINF_SUCCESS;
int rcLnx = 0;
if (RT_UNLIKELY(rcLnx < 0))
else
{
}
return rc;
}
static DECLCALLBACK(int) drvHostParallelReadStatus(PPDMIHOSTPARALLELCONNECTOR pInterface, uint8_t *pfReg)
{
int rc = VINF_SUCCESS;
int rcLnx = 0;
if (RT_UNLIKELY(rcLnx < 0))
else
{
}
return rc;
}
{
/*
* We can wait for interrupts using poll on linux hosts.
*/
{
int rc;
if (rc < 0)
{
return RTErrConvertFromErrno(errno);
}
break;
{
break;
/* notification to terminate -- drain the pipe */
char ch;
continue;
}
/* Interrupt occurred. */
}
return VINF_SUCCESS;
}
/**
* Unblock the monitor thread so it can respond to a state change.
*
* @returns a VBox status code.
* @param pDrvIns The driver instance.
* @param pThread The send thread.
*/
{
}
/**
* Destruct a host parallel driver instance.
*
* Most VM resources are freed by the VM. This callback is provided so that
* any non-VM resources can be freed correctly.
*
* @param pDrvIns The driver instance data.
*/
{
int rc;
if (pThis->pszDevicePath)
{
}
}
/**
* Construct a host parallel driver instance.
*
* @copydoc FNPDMDRVCONSTRUCT
*/
static DECLCALLBACK(int) drvHostParallelConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
{
/*
* Init basic data members and interfaces.
*
* Must be done before returning any failure because we've got a destructor.
*/
/* IBase. */
/* IHostParallelConnector. */
/*
* Validate the config.
*/
N_("Unknown host parallel configuration option, only supports DevicePath"));
/*
* Query configuration.
*/
/* Device */
if (RT_FAILURE(rc))
{
return rc;
}
/*
* Open the device
*/
rc = RTFileOpen(&pThis->hFileDevice, pThis->pszDevicePath, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
if (RT_FAILURE(rc))
/*
* Try to get exclusive access to parallel port
*/
if (rc < 0)
N_("Parallel#%d could not get exclusive access for parallel port '%s'"
"Be sure that no other process or driver accesses this port"),
/*
* Claim the parallel port
*/
if (rc < 0)
N_("Parallel#%d could not claim parallel port '%s'"
"Be sure that no other process or driver accesses this port"),
/*
*/
if (!pThis->pDrvHostParallelPort)
return PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_MISSING_INTERFACE_ABOVE, RT_SRC_POS, N_("Parallel#%d has no parallel port interface above"),
/*
* Create wakeup pipe.
*/
/*
* Start in SPP mode.
*/
if (RT_FAILURE(rc))
return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("HostParallel#%d cannot change mode of parallel mode to SPP"), pDrvIns->iInstance);
/*
* Start waiting for interrupts.
*/
rc = PDMDrvHlpThreadCreate(pDrvIns, &pThis->pMonitorThread, pThis, drvHostParallelMonitorThread, drvHostParallelWakeupMonitorThread, 0,
RTTHREADTYPE_IO, "ParMon");
if (RT_FAILURE(rc))
return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("HostParallel#%d cannot create monitor thread"), pDrvIns->iInstance);
return VINF_SUCCESS;
}
/**
* Char driver registration record.
*/
const PDMDRVREG g_DrvHostParallel =
{
/* u32Version */
/* szName */
"HostParallel",
/* szRCMod */
"",
/* szR0Mod */
"",
/* pszDescription */
"Parallel host driver.",
/* fFlags */
/* fClass. */
/* cMaxInstances */
~0U,
/* cbInstance */
sizeof(DRVHOSTPARALLEL),
/* pfnConstruct */
/* pfnDestruct */
/* pfnRelocate */
NULL,
/* pfnIOCtl */
NULL,
/* pfnPowerOn */
NULL,
/* pfnReset */
NULL,
/* pfnSuspend */
NULL,
/* pfnResume */
NULL,
/* pfnAttach */
NULL,
/* pfnDetach */
NULL,
/* pfnPowerOff */
NULL,
/* pfnSoftReset */
NULL,
/* u32EndVersion */
};