VirtualBox

source: vbox/trunk/src/VBox/Devices/Parallel/DrvHostParallel.cpp@ 4014

Last change on this file since 4014 was 4014, checked in by vboxsync, 18 years ago

Use pdmdrv.h and pdmdev.h where appropirate.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 9.8 KB
Line 
1/* $Id: DrvHostParallel.cpp 4014 2007-08-03 00:44:13Z vboxsync $ */
2/** @file
3 * VirtualBox Host Parallel Port Driver.
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * If you received this file as part of a commercial VirtualBox
18 * distribution, then only the terms of your commercial VirtualBox
19 * license agreement apply instead of the previous paragraph.
20 */
21
22/*******************************************************************************
23* Header Files *
24*******************************************************************************/
25#define LOG_GROUP LOG_GROUP_DRV_HOST_PARALLEL
26#include <VBox/pdmdrv.h>
27#include <iprt/asm.h>
28#include <iprt/assert.h>
29#include <iprt/stream.h>
30#include <iprt/semaphore.h>
31
32#ifdef RT_OS_LINUX
33# include <sys/ioctl.h>
34# include <sys/types.h>
35# include <sys/stat.h>
36# include <fcntl.h>
37# include <unistd.h>
38# include <linux/ppdev.h>
39# include <linux/parport.h>
40#endif
41
42#include "Builtins.h"
43#include "ParallelIOCtlCmd.h"
44
45
46/*******************************************************************************
47* Structures and Typedefs *
48*******************************************************************************/
49/**
50 * Host parallel port driver instance data.
51 */
52typedef struct DRVHOSTPARALLEL
53{
54 /** Pointer to the driver instance structure. */
55 PPDMDRVINS pDrvIns;
56 /** Pointer to the char port interface of the driver/device above us. */
57 PPDMIHOSTDEVICEPORT pDrvHostDevicePort;
58 /** Our host device interface. */
59 PDMIHOSTDEVICECONNECTOR IHostDeviceConnector;
60 /** Our host device port interface. */
61 PDMIHOSTDEVICEPORT IHostDevicePort;
62 /** Device Path */
63 char *pszDevicePath;
64 /** Device Handle */
65 RTFILE FileDevice;
66 /** Flag to notify the receive thread it should terminate. */
67 volatile bool fShutdown;
68 /** Receive thread ID. */
69 RTTHREAD ReceiveThread;
70 /** Send thread ID. */
71 RTTHREAD SendThread;
72 /** Send event semephore */
73 RTSEMEVENT SendSem;
74
75} DRVHOSTPARALLEL, *PDRVHOSTPARALLEL;
76
77/** Converts a pointer to DRVHOSTPARALLEL::IHostDeviceConnector to a PDRHOSTPARALLEL. */
78#define PDMIHOSTDEVICECONNECTOR_2_DRVHOSTPARALLEL(pInterface) ( (PDRVHOSTPARALLEL)((uintptr_t)pInterface - RT_OFFSETOF(DRVHOSTPARALLEL, IHostDeviceConnector)) )
79/** Converts a pointer to DRVHOSTPARALLEL::IHostDevicePort to a PDRHOSTPARALLEL. */
80#define PDMIHOSTDEVICEPORT_2_DRVHOSTPARALLEL(pInterface) ( (PDRVHOSTPARALLEL)((uintptr_t)pInterface - RT_OFFSETOF(DRVHOSTPARALLEL, IHostDevicePort)) )
81
82/* -=-=-=-=- IBase -=-=-=-=- */
83
84/**
85 * Queries an interface to the driver.
86 *
87 * @returns Pointer to interface.
88 * @returns NULL if the interface was not supported by the driver.
89 * @param pInterface Pointer to this interface structure.
90 * @param enmInterface The requested interface identification.
91 */
92static DECLCALLBACK(void *) drvHostParallelQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
93{
94 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
95 PDRVHOSTPARALLEL pData = PDMINS2DATA(pDrvIns, PDRVHOSTPARALLEL);
96 switch (enmInterface)
97 {
98 case PDMINTERFACE_BASE:
99 return &pDrvIns->IBase;
100 case PDMINTERFACE_HOST_DEVICE_CONNECTOR:
101 return &pData->IHostDeviceConnector;
102 default:
103 return NULL;
104 }
105}
106
107/* -=-=-=-=- IHostDeviceConnector -=-=-=-=- */
108
109/** @copydoc PDMICHAR::pfnWrite */
110static DECLCALLBACK(int) drvHostParallelWrite(PPDMIHOSTDEVICECONNECTOR pInterface, const void *pvBuf, size_t *cbWrite)
111{
112 PDRVHOSTPARALLEL pData = PDMIHOSTDEVICECONNECTOR_2_DRVHOSTPARALLEL(pInterface);
113 const unsigned char *pBuffer = (const unsigned char *)pvBuf;
114
115 LogFlow(("%s: pvBuf=%#p cbWrite=%d\n", __FUNCTION__, pvBuf, *cbWrite));
116
117 ioctl(pData->FileDevice, PPWDATA, pBuffer);
118
119 RTSemEventSignal(pData->SendSem);
120 return VINF_SUCCESS;
121}
122
123static DECLCALLBACK(int) drvHostParallelRead(PPDMIHOSTDEVICECONNECTOR pInterface, void *pvBuf, size_t *cbRead)
124{
125 PDRVHOSTPARALLEL pData = PDMIHOSTDEVICECONNECTOR_2_DRVHOSTPARALLEL(pInterface);
126 unsigned char *pBuffer = (unsigned char *)pvBuf;
127
128 LogFlow(("%s: pvBuf=%#p cbRead=%d\n", __FUNCTION__, pvBuf, cbRead));
129
130 ioctl(pData->FileDevice, PPRDATA, pBuffer);
131 *cbRead = 1;
132
133 return VINF_SUCCESS;
134}
135
136static DECLCALLBACK(int) drvHostParallelIOCtl(PPDMIHOSTDEVICECONNECTOR pInterface, RTUINT uCommand,
137 void *pvData)
138{
139 PDRVHOSTPARALLEL pData = PDMIHOSTDEVICECONNECTOR_2_DRVHOSTPARALLEL(pInterface);
140 unsigned long ioctlCommand;
141
142 LogFlow(("%s: uCommand=%d pvData=%#p\n", __FUNCTION__, uCommand, pvData));
143
144 switch (uCommand) {
145 case LPT_IOCTL_COMMAND_SET_CONTROL:
146 ioctlCommand = PPWCONTROL;
147 break;
148 case LPT_IOCTL_COMMAND_GET_CONTROL:
149 ioctlCommand = PPRCONTROL;
150 break;
151 }
152
153 ioctl(pData->FileDevice, ioctlCommand, pvData);
154
155 return VINF_SUCCESS;
156}
157
158/**
159 * Construct a host parallel driver instance.
160 *
161 * @returns VBox status.
162 * @param pDrvIns The driver instance data.
163 * If the registration structure is needed,
164 * pDrvIns->pDrvReg points to it.
165 * @param pCfgHandle Configuration node handle for the driver. Use this to
166 * obtain the configuration of the driver instance. It's
167 * also found in pDrvIns->pCfgHandle as it's expected to
168 * be used frequently in this function.
169 */
170static DECLCALLBACK(int) drvHostParallelConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle)
171{
172 PDRVHOSTPARALLEL pData = PDMINS2DATA(pDrvIns, PDRVHOSTPARALLEL);
173 LogFlow(("%s: iInstance=%d\n", __FUNCTION__, pDrvIns->iInstance));
174
175 /*
176 * Init basic data members and interfaces.
177 */
178 pData->ReceiveThread = NIL_RTTHREAD;
179 pData->fShutdown = false;
180 /* IBase. */
181 pDrvIns->IBase.pfnQueryInterface = drvHostParallelQueryInterface;
182 /* IChar. */
183 pData->IHostDeviceConnector.pfnWrite = drvHostParallelWrite;
184 pData->IHostDeviceConnector.pfnIOCtl = drvHostParallelIOCtl;
185 pData->IHostDeviceConnector.pfnRead = drvHostParallelRead;
186
187 /*
188 * Query configuration.
189 */
190 /* Device */
191 int rc = CFGMR3QueryStringAlloc(pCfgHandle, "DevicePath", &pData->pszDevicePath);
192 if (VBOX_FAILURE(rc))
193 {
194 AssertMsgFailed(("Configuration error: query for \"DevicePath\" string returned %Vra.\n", rc));
195 return rc;
196 }
197
198 /*
199 * Open the device
200 */
201 pData->FileDevice = open(pData->pszDevicePath, O_RDWR | O_NONBLOCK);
202 if (pData->FileDevice < 0) {
203
204 }
205
206 /*
207 * Try to get exclusive access to parallel port
208 */
209 if (ioctl(pData->FileDevice, PPEXCL) < 0) {
210 }
211
212 /*
213 * Claim the parallel port
214 */
215 if (ioctl(pData->FileDevice, PPCLAIM) < 0) {
216 }
217
218 /*
219 * Get the IHostDevicePort interface of the above driver/device.
220 */
221 pData->pDrvHostDevicePort = (PPDMIHOSTDEVICEPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_HOST_DEVICE_PORT);
222 if (!pData->pDrvHostDevicePort)
223 return PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_MISSING_INTERFACE_ABOVE, RT_SRC_POS, N_("Parallel#%d has no parallel port interface above"), pDrvIns->iInstance);
224
225 rc = RTSemEventCreate(&pData->SendSem);
226 AssertRC(rc);
227
228 return VINF_SUCCESS;
229}
230
231
232/**
233 * Destruct a host parallel driver instance.
234 *
235 * Most VM resources are freed by the VM. This callback is provided so that
236 * any non-VM resources can be freed correctly.
237 *
238 * @param pDrvIns The driver instance data.
239 */
240static DECLCALLBACK(void) drvHostParallelDestruct(PPDMDRVINS pDrvIns)
241{
242 PDRVHOSTPARALLEL pData = PDMINS2DATA(pDrvIns, PDRVHOSTPARALLEL);
243
244 LogFlow(("%s: iInstance=%d\n", __FUNCTION__, pDrvIns->iInstance));
245
246 pData->fShutdown = true;
247 if (pData->ReceiveThread)
248 {
249 RTThreadWait(pData->ReceiveThread, 1000, NULL);
250 if (pData->ReceiveThread != NIL_RTTHREAD)
251 LogRel(("Parallel%d: receive thread did not terminate\n", pDrvIns->iInstance));
252 }
253
254 RTSemEventSignal(pData->SendSem);
255 RTSemEventDestroy(pData->SendSem);
256 pData->SendSem = NIL_RTSEMEVENT;
257
258 if (pData->SendThread)
259 {
260 RTThreadWait(pData->SendThread, 1000, NULL);
261 if (pData->SendThread != NIL_RTTHREAD)
262 LogRel(("Parallel%d: send thread did not terminate\n", pDrvIns->iInstance));
263 }
264
265 ioctl(pData->FileDevice, PPRELEASE);
266 close(pData->FileDevice);
267}
268
269/**
270 * Char driver registration record.
271 */
272const PDMDRVREG g_DrvHostParallel =
273{
274 /* u32Version */
275 PDM_DRVREG_VERSION,
276 /* szDriverName */
277 "HostParallel",
278 /* pszDescription */
279 "Parallel host driver.",
280 /* fFlags */
281 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
282 /* fClass. */
283 PDM_DRVREG_CLASS_CHAR,
284 /* cMaxInstances */
285 ~0,
286 /* cbInstance */
287 sizeof(DRVHOSTPARALLEL),
288 /* pfnConstruct */
289 drvHostParallelConstruct,
290 /* pfnDestruct */
291 drvHostParallelDestruct,
292 /* pfnIOCtl */
293 NULL,
294 /* pfnPowerOn */
295 NULL,
296 /* pfnReset */
297 NULL,
298 /* pfnSuspend */
299 NULL,
300 /* pfnResume */
301 NULL,
302 /* pfnDetach */
303 NULL,
304 /** pfnPowerOff */
305 NULL
306};
307
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette