VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxBFE/KeyboardImpl.cpp@ 2397

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

Don't crash if a key is pressed before everything is initialized. (just ignore the key)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.3 KB
Line 
1/** @file
2 *
3 * VBox frontends: Basic Frontend (BFE):
4 * Implementation of Keyboard class and related things
5 */
6
7/*
8 * Copyright (C) 2006 InnoTek Systemberatung GmbH
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License as published by the Free Software Foundation,
14 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
15 * distribution. VirtualBox OSE is distributed in the hope that it will
16 * be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * If you received this file as part of a commercial VirtualBox
19 * distribution, then only the terms of your commercial VirtualBox
20 * license agreement apply instead of the previous paragraph.
21 */
22
23#ifdef VBOXBFE_WITHOUT_COM
24# include "COMDefs.h"
25#else
26# include <VBox/com/defs.h>
27#endif
28#include <VBox/pdm.h>
29#include <VBox/cfgm.h>
30#include <VBox/err.h>
31#include <iprt/assert.h>
32#include <VBox/log.h>
33#include <iprt/asm.h>
34#include "KeyboardImpl.h"
35
36// defines
37////////////////////////////////////////////////////////////////////////////////
38
39// globals
40////////////////////////////////////////////////////////////////////////////////
41
42/**
43 * Keyboard driver instance data.
44 */
45typedef struct DRVMAINKEYBOARD
46{
47 /** Pointer to the keyboard object. */
48 Keyboard *pKeyboard;
49 /** Pointer to the driver instance structure. */
50 PPDMDRVINS pDrvIns;
51 /** Pointer to the keyboard port interface of the driver/device above us. */
52 PPDMIKEYBOARDPORT pUpPort;
53 /** Our mouse connector interface. */
54 PDMIKEYBOARDCONNECTOR Connector;
55} DRVMAINKEYBOARD, *PDRVMAINKEYBOARD;
56
57// constructor / destructor
58////////////////////////////////////////////////////////////////////////////////
59
60Keyboard::Keyboard()
61{
62 mpDrv = NULL;
63 mpVMMDev = NULL;
64 mfVMMDevInited = false;
65}
66
67Keyboard::~Keyboard()
68{
69 if (mpDrv)
70 mpDrv->pKeyboard = NULL;
71 mpDrv = NULL;
72 mpVMMDev = NULL;
73 mfVMMDevInited = true;
74}
75
76// public methods
77////////////////////////////////////////////////////////////////////////////////
78
79/**
80 * Sends a scancode to the keyboard.
81 *
82 * @returns COM status code
83 * @param scancode The scancode to send
84 */
85STDMETHODIMP Keyboard::PutScancode(LONG scancode)
86{
87 if (!mpDrv)
88 return S_OK;
89
90 int rcVBox = mpDrv->pUpPort->pfnPutEvent(mpDrv->pUpPort, (uint8_t)scancode);
91 if (VBOX_FAILURE (rcVBox))
92 return E_FAIL;
93
94 return S_OK;
95}
96
97/**
98 * Sends a list of scancodes to the keyboard.
99 *
100 * @returns COM status code
101 * @param scancodes Pointer to the first scancode
102 * @param count Number of scancodes
103 * @param codesStored Address of variable to store the number
104 * of scancodes that were sent to the keyboard.
105 This value can be NULL.
106 */
107STDMETHODIMP Keyboard::PutScancodes(LONG *scancodes,
108 ULONG count,
109 ULONG *codesStored)
110{
111 if (!scancodes)
112 return E_INVALIDARG;
113 if (!mpDrv)
114 return S_OK;
115
116 LONG *currentScancode = scancodes;
117 int rcVBox = VINF_SUCCESS;
118
119 for (uint32_t i = 0; (i < count) && VBOX_SUCCESS(rcVBox); i++, currentScancode++)
120 {
121 rcVBox = mpDrv->pUpPort->pfnPutEvent(mpDrv->pUpPort, *(uint8_t*)currentScancode);
122 }
123
124 if (VBOX_FAILURE (rcVBox))
125 return E_FAIL;
126
127 /// @todo is it actually possible that not all scancodes can be transmitted?
128 if (codesStored)
129 *codesStored = count;
130
131 return S_OK;
132}
133
134/**
135 * Sends Control-Alt-Delete to the keyboard. This could be done otherwise
136 * but it's so common that we'll be nice and supply a convenience API.
137 *
138 * @returns COM status code
139 *
140 */
141STDMETHODIMP Keyboard::PutCAD()
142{
143 static LONG cadSequence[] = {
144 0x1d, // Ctrl down
145 0x38, // Alt down
146 0x53, // Del down
147 0xd3, // Del up
148 0xb8, // Alt up
149 0x9d // Ctrl up
150 };
151
152 return PutScancodes (cadSequence, ELEMENTS (cadSequence), NULL);
153}
154
155//
156// private methods
157//
158
159/**
160 * Queries an interface to the driver.
161 *
162 * @returns Pointer to interface.
163 * @returns NULL if the interface was not supported by the driver.
164 * @param pInterface Pointer to this interface structure.
165 * @param enmInterface The requested interface identification.
166 */
167DECLCALLBACK(void *) Keyboard::drvQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
168{
169 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
170 PDRVMAINKEYBOARD pDrv = PDMINS2DATA(pDrvIns, PDRVMAINKEYBOARD);
171 switch (enmInterface)
172 {
173 case PDMINTERFACE_BASE:
174 return &pDrvIns->IBase;
175 case PDMINTERFACE_KEYBOARD_CONNECTOR:
176 return &pDrv->Connector;
177 default:
178 return NULL;
179 }
180}
181
182
183/**
184 * Destruct a keyboard driver instance.
185 *
186 * @returns VBox status.
187 * @param pDrvIns The driver instance data.
188 */
189DECLCALLBACK(void) Keyboard::drvDestruct(PPDMDRVINS pDrvIns)
190{
191 PDRVMAINKEYBOARD pData = PDMINS2DATA(pDrvIns, PDRVMAINKEYBOARD);
192 LogFlow(("Keyboard::drvDestruct: iInstance=%d\n", pDrvIns->iInstance));
193 if (pData->pKeyboard)
194 {
195 pData->pKeyboard->mpDrv = NULL;
196 pData->pKeyboard->mpVMMDev = NULL;
197 }
198}
199
200
201/** @copydoc PDMIKEYBOARDCONNECTOR::pfnLedStatusChange */
202DECLCALLBACK(void) keyboardLedStatusChange(PPDMIKEYBOARDCONNECTOR pInterface, PDMKEYBLEDS enmLeds)
203{
204 /** @todo Implement me. */
205}
206
207
208/**
209 * Construct a keyboard driver instance.
210 *
211 * @returns VBox status.
212 * @param pDrvIns The driver instance data.
213 * If the registration structure is needed, pDrvIns->pDrvReg points to it.
214 * @param pCfgHandle Configuration node handle for the driver. Use this to obtain the configuration
215 * of the driver instance. It's also found in pDrvIns->pCfgHandle, but like
216 * iInstance it's expected to be used a bit in this function.
217 */
218DECLCALLBACK(int) Keyboard::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle)
219{
220 PDRVMAINKEYBOARD pData = PDMINS2DATA(pDrvIns, PDRVMAINKEYBOARD);
221 LogFlow(("Keyboard::drvConstruct: iInstance=%d\n", pDrvIns->iInstance));
222
223 /*
224 * Validate configuration.
225 */
226 if (!CFGMR3AreValuesValid(pCfgHandle, "Object\0"))
227 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
228 PPDMIBASE pBaseIgnore;
229 int rc = pDrvIns->pDrvHlp->pfnAttach(pDrvIns, &pBaseIgnore);
230 if (rc != VERR_PDM_NO_ATTACHED_DRIVER)
231 {
232 AssertMsgFailed(("Configuration error: Not possible to attach anything to this driver!\n"));
233 return VERR_PDM_DRVINS_NO_ATTACH;
234 }
235
236 /*
237 * IBase.
238 */
239 pDrvIns->IBase.pfnQueryInterface = Keyboard::drvQueryInterface;
240
241 pData->Connector.pfnLedStatusChange = keyboardLedStatusChange;
242
243 /*
244 * Get the IKeyboardPort interface of the above driver/device.
245 */
246 pData->pUpPort = (PPDMIKEYBOARDPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_KEYBOARD_PORT);
247 if (!pData->pUpPort)
248 {
249 AssertMsgFailed(("Configuration error: No keyboard port interface above!\n"));
250 return VERR_PDM_MISSING_INTERFACE_ABOVE;
251 }
252
253 /*
254 * Get the Keyboard object pointer and update the mpDrv member.
255 */
256 void *pv;
257 rc = CFGMR3QueryPtr(pCfgHandle, "Object", &pv);
258 if (VBOX_FAILURE(rc))
259 {
260 AssertMsgFailed(("Configuration error: No/bad \"Object\" value! rc=%Vrc\n", rc));
261 return rc;
262 }
263 pData->pKeyboard = (Keyboard *)pv; /** @todo Check this cast! */
264 pData->pKeyboard->mpDrv = pData;
265
266 return VINF_SUCCESS;
267}
268
269
270/**
271 * Keyboard driver registration record.
272 */
273const PDMDRVREG Keyboard::DrvReg =
274{
275 /* u32Version */
276 PDM_DRVREG_VERSION,
277 /* szDriverName */
278 "MainKeyboard",
279 /* pszDescription */
280 "Main keyboard driver (Main as in the API).",
281 /* fFlags */
282 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
283 /* fClass. */
284 PDM_DRVREG_CLASS_KEYBOARD,
285 /* cMaxInstances */
286 ~0,
287 /* cbInstance */
288 sizeof(DRVMAINKEYBOARD),
289 /* pfnConstruct */
290 Keyboard::drvConstruct,
291 /* pfnDestruct */
292 Keyboard::drvDestruct,
293 /* pfnIOCtl */
294 NULL,
295 /* pfnPowerOn */
296 NULL,
297 /* pfnReset */
298 NULL,
299 /* pfnSuspend */
300 NULL,
301 /* pfnResume */
302 NULL,
303 /* pfnDetach */
304 NULL
305};
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