VirtualBox

source: vbox/trunk/src/VBox/Main/KeyboardImpl.cpp@ 3516

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

InnoTek -> innotek: all the headers and comments.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.8 KB
Line 
1/** @file
2 *
3 * VirtualBox COM class implementation
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.virtualbox.org. 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#include "KeyboardImpl.h"
23#include "ConsoleImpl.h"
24
25#include "Logging.h"
26
27#include <VBox/pdm.h>
28#include <VBox/cfgm.h>
29#include <VBox/err.h>
30#include <iprt/asm.h>
31
32// defines
33////////////////////////////////////////////////////////////////////////////////
34
35// globals
36////////////////////////////////////////////////////////////////////////////////
37
38/**
39 * Keyboard driver instance data.
40 */
41typedef struct DRVMAINKEYBOARD
42{
43 /** Pointer to the keyboard object. */
44 Keyboard *pKeyboard;
45 /** Pointer to the driver instance structure. */
46 PPDMDRVINS pDrvIns;
47 /** Pointer to the keyboard port interface of the driver/device above us. */
48 PPDMIKEYBOARDPORT pUpPort;
49 /** Our mouse connector interface. */
50 PDMIKEYBOARDCONNECTOR Connector;
51} DRVMAINKEYBOARD, *PDRVMAINKEYBOARD;
52
53/** Converts PDMIVMMDEVCONNECTOR pointer to a DRVMAINVMMDEV pointer. */
54#define PPDMIKEYBOARDCONNECTOR_2_MAINKEYBOARD(pInterface) ( (PDRVMAINKEYBOARD) ((uintptr_t)pInterface - RT_OFFSETOF(DRVMAINKEYBOARD, Connector)) )
55
56
57// constructor / destructor
58////////////////////////////////////////////////////////////////////////////////
59
60HRESULT Keyboard::FinalConstruct()
61{
62 mParent = NULL;
63 mpDrv = NULL;
64 mpVMMDev = NULL;
65 mfVMMDevInited = false;
66 return S_OK;
67}
68
69void Keyboard::FinalRelease()
70{
71 if (isReady())
72 uninit();
73}
74
75// public methods
76////////////////////////////////////////////////////////////////////////////////
77
78/**
79 * Initializes the keyboard object.
80 *
81 * @returns COM result indicator
82 * @param parent handle of our parent object
83 */
84HRESULT Keyboard::init (Console *parent)
85{
86 LogFlow(("Keyboard::init(): isReady=%d\n", isReady()));
87
88 ComAssertRet (parent, E_INVALIDARG);
89
90 AutoLock alock (this);
91 ComAssertRet (!isReady(), E_UNEXPECTED);
92
93 mParent = parent;
94
95 setReady (true);
96 return S_OK;
97}
98
99/**
100 * Uninitializes the instance and sets the ready flag to FALSE.
101 * Called either from FinalRelease() or by the parent when it gets destroyed.
102 */
103void Keyboard::uninit()
104{
105 LogFlow(("Keyboard::uninit(): isReady=%d\n", isReady()));
106
107 AutoLock alock (this);
108 AssertReturn (isReady(), (void) 0);
109
110 if (mpDrv)
111 mpDrv->pKeyboard = NULL;
112 mpDrv = NULL;
113 mpVMMDev = NULL;
114 mfVMMDevInited = true;
115
116 setReady (false);
117}
118
119/**
120 * Sends a scancode to the keyboard.
121 *
122 * @returns COM status code
123 * @param scancode The scancode to send
124 */
125STDMETHODIMP Keyboard::PutScancode(LONG scancode)
126{
127 AutoLock alock (this);
128 CHECK_READY();
129
130 CHECK_CONSOLE_DRV (mpDrv);
131
132 int rcVBox = mpDrv->pUpPort->pfnPutEvent(mpDrv->pUpPort, (uint8_t)scancode);
133
134 if (VBOX_FAILURE (rcVBox))
135 return setError (E_FAIL,
136 tr ("Could not send scan code 0x%08X to the virtual keyboard (%Vrc)"),
137 scancode, rcVBox);
138
139 return S_OK;
140}
141
142/**
143 * Sends a list of scancodes to the keyboard.
144 *
145 * @returns COM status code
146 * @param scancodes Pointer to the first scancode
147 * @param count Number of scancodes
148 * @param codesStored Address of variable to store the number
149 * of scancodes that were sent to the keyboard.
150 This value can be NULL.
151 */
152STDMETHODIMP Keyboard::PutScancodes(LONG *scancodes,
153 ULONG count,
154 ULONG *codesStored)
155{
156 if (!scancodes)
157 return E_INVALIDARG;
158
159 AutoLock alock (this);
160 CHECK_READY();
161
162 CHECK_CONSOLE_DRV (mpDrv);
163
164 LONG *currentScancode = scancodes;
165 int rcVBox = VINF_SUCCESS;
166
167 for (uint32_t i = 0; (i < count) && VBOX_SUCCESS(rcVBox); i++, currentScancode++)
168 {
169 rcVBox = mpDrv->pUpPort->pfnPutEvent(mpDrv->pUpPort, *(uint8_t*)currentScancode);
170 }
171
172 if (VBOX_FAILURE (rcVBox))
173 return setError (E_FAIL,
174 tr ("Could not send all scan codes to the virtual keyboard (%Vrc)"), rcVBox);
175
176 /// @todo is it actually possible that not all scancodes can be transmitted?
177 if (codesStored)
178 *codesStored = count;
179
180 return S_OK;
181}
182
183/**
184 * Sends Control-Alt-Delete to the keyboard. This could be done otherwise
185 * but it's so common that we'll be nice and supply a convenience API.
186 *
187 * @returns COM status code
188 *
189 */
190STDMETHODIMP Keyboard::PutCAD()
191{
192 static LONG cadSequence[] = {
193 0x1d, // Ctrl down
194 0x38, // Alt down
195 0x53, // Del down
196 0xd3, // Del up
197 0xb8, // Alt up
198 0x9d // Ctrl up
199 };
200
201 return PutScancodes (cadSequence, ELEMENTS (cadSequence), NULL);
202}
203
204//
205// private methods
206//
207
208/**
209 * Queries an interface to the driver.
210 *
211 * @returns Pointer to interface.
212 * @returns NULL if the interface was not supported by the driver.
213 * @param pInterface Pointer to this interface structure.
214 * @param enmInterface The requested interface identification.
215 */
216DECLCALLBACK(void *) Keyboard::drvQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
217{
218 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
219 PDRVMAINKEYBOARD pDrv = PDMINS2DATA(pDrvIns, PDRVMAINKEYBOARD);
220 switch (enmInterface)
221 {
222 case PDMINTERFACE_BASE:
223 return &pDrvIns->IBase;
224 case PDMINTERFACE_KEYBOARD_CONNECTOR:
225 return &pDrv->Connector;
226 default:
227 return NULL;
228 }
229}
230
231
232/**
233 * Destruct a keyboard driver instance.
234 *
235 * @returns VBox status.
236 * @param pDrvIns The driver instance data.
237 */
238DECLCALLBACK(void) Keyboard::drvDestruct(PPDMDRVINS pDrvIns)
239{
240 PDRVMAINKEYBOARD pData = PDMINS2DATA(pDrvIns, PDRVMAINKEYBOARD);
241 LogFlow(("Keyboard::drvDestruct: iInstance=%d\n", pDrvIns->iInstance));
242 if (pData->pKeyboard)
243 {
244 AutoLock kbdLock (pData->pKeyboard);
245 pData->pKeyboard->mpDrv = NULL;
246 pData->pKeyboard->mpVMMDev = NULL;
247 }
248}
249
250DECLCALLBACK(void) keyboardLedStatusChange(PPDMIKEYBOARDCONNECTOR pInterface, PDMKEYBLEDS enmLeds)
251{
252 PDRVMAINKEYBOARD pDrv = PPDMIKEYBOARDCONNECTOR_2_MAINKEYBOARD(pInterface);
253 pDrv->pKeyboard->getParent()->onKeyboardLedsChange(!!(enmLeds & PDMKEYBLEDS_NUMLOCK),
254 !!(enmLeds & PDMKEYBLEDS_CAPSLOCK),
255 !!(enmLeds & PDMKEYBLEDS_SCROLLLOCK));
256}
257
258/**
259 * Construct a keyboard driver instance.
260 *
261 * @returns VBox status.
262 * @param pDrvIns The driver instance data.
263 * If the registration structure is needed, pDrvIns->pDrvReg points to it.
264 * @param pCfgHandle Configuration node handle for the driver. Use this to obtain the configuration
265 * of the driver instance. It's also found in pDrvIns->pCfgHandle, but like
266 * iInstance it's expected to be used a bit in this function.
267 */
268DECLCALLBACK(int) Keyboard::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle)
269{
270 PDRVMAINKEYBOARD pData = PDMINS2DATA(pDrvIns, PDRVMAINKEYBOARD);
271 LogFlow(("Keyboard::drvConstruct: iInstance=%d\n", pDrvIns->iInstance));
272
273 /*
274 * Validate configuration.
275 */
276 if (!CFGMR3AreValuesValid(pCfgHandle, "Object\0"))
277 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
278 PPDMIBASE pBaseIgnore;
279 int rc = pDrvIns->pDrvHlp->pfnAttach(pDrvIns, &pBaseIgnore);
280 if (rc != VERR_PDM_NO_ATTACHED_DRIVER)
281 {
282 AssertMsgFailed(("Configuration error: Not possible to attach anything to this driver!\n"));
283 return VERR_PDM_DRVINS_NO_ATTACH;
284 }
285
286 /*
287 * IBase.
288 */
289 pDrvIns->IBase.pfnQueryInterface = Keyboard::drvQueryInterface;
290
291 pData->Connector.pfnLedStatusChange = keyboardLedStatusChange;
292
293 /*
294 * Get the IKeyboardPort interface of the above driver/device.
295 */
296 pData->pUpPort = (PPDMIKEYBOARDPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_KEYBOARD_PORT);
297 if (!pData->pUpPort)
298 {
299 AssertMsgFailed(("Configuration error: No keyboard port interface above!\n"));
300 return VERR_PDM_MISSING_INTERFACE_ABOVE;
301 }
302
303 /*
304 * Get the Keyboard object pointer and update the mpDrv member.
305 */
306 void *pv;
307 rc = CFGMR3QueryPtr(pCfgHandle, "Object", &pv);
308 if (VBOX_FAILURE(rc))
309 {
310 AssertMsgFailed(("Configuration error: No/bad \"Object\" value! rc=%Vrc\n", rc));
311 return rc;
312 }
313 pData->pKeyboard = (Keyboard *)pv; /** @todo Check this cast! */
314 pData->pKeyboard->mpDrv = pData;
315
316 return VINF_SUCCESS;
317}
318
319
320/**
321 * Keyboard driver registration record.
322 */
323const PDMDRVREG Keyboard::DrvReg =
324{
325 /* u32Version */
326 PDM_DRVREG_VERSION,
327 /* szDriverName */
328 "MainKeyboard",
329 /* pszDescription */
330 "Main keyboard driver (Main as in the API).",
331 /* fFlags */
332 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
333 /* fClass. */
334 PDM_DRVREG_CLASS_KEYBOARD,
335 /* cMaxInstances */
336 ~0,
337 /* cbInstance */
338 sizeof(DRVMAINKEYBOARD),
339 /* pfnConstruct */
340 Keyboard::drvConstruct,
341 /* pfnDestruct */
342 Keyboard::drvDestruct,
343 /* pfnIOCtl */
344 NULL,
345 /* pfnPowerOn */
346 NULL,
347 /* pfnReset */
348 NULL,
349 /* pfnSuspend */
350 NULL,
351 /* pfnResume */
352 NULL,
353 /* pfnDetach */
354 NULL
355};
Note: See TracBrowser for help on using the repository browser.

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