VirtualBox

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

Last change on this file since 25860 was 25860, checked in by vboxsync, 15 years ago

Main: cleanup: get rid of VirtualBoxBaseProto, move AutoCaller*/*Span* classes out of VirtualBoxBaseProto class scope and into separate header; move CombinedProgress into separate header (it's only used by Console any more)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.1 KB
Line 
1/* $Id: KeyboardImpl.cpp 25860 2010-01-15 13:27:26Z vboxsync $ */
2
3/** @file
4 *
5 * VirtualBox COM class implementation
6 */
7
8/*
9 * Copyright (C) 2006-2008 Sun Microsystems, Inc.
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
20 * Clara, CA 95054 USA or visit http://www.sun.com if you need
21 * additional information or have any questions.
22 */
23
24#include "KeyboardImpl.h"
25#include "ConsoleImpl.h"
26
27#include "AutoCaller.h"
28#include "Logging.h"
29
30#include <VBox/com/array.h>
31#include <VBox/pdmdrv.h>
32#include <iprt/asm.h>
33
34// defines
35////////////////////////////////////////////////////////////////////////////////
36
37// globals
38////////////////////////////////////////////////////////////////////////////////
39
40/**
41 * Keyboard driver instance data.
42 */
43typedef struct DRVMAINKEYBOARD
44{
45 /** Pointer to the keyboard object. */
46 Keyboard *pKeyboard;
47 /** Pointer to the driver instance structure. */
48 PPDMDRVINS pDrvIns;
49 /** Pointer to the keyboard port interface of the driver/device above us. */
50 PPDMIKEYBOARDPORT pUpPort;
51 /** Our mouse connector interface. */
52 PDMIKEYBOARDCONNECTOR Connector;
53} DRVMAINKEYBOARD, *PDRVMAINKEYBOARD;
54
55/** Converts PDMIVMMDEVCONNECTOR pointer to a DRVMAINVMMDEV pointer. */
56#define PPDMIKEYBOARDCONNECTOR_2_MAINKEYBOARD(pInterface) ( (PDRVMAINKEYBOARD) ((uintptr_t)pInterface - RT_OFFSETOF(DRVMAINKEYBOARD, Connector)) )
57
58
59// constructor / destructor
60////////////////////////////////////////////////////////////////////////////////
61
62DEFINE_EMPTY_CTOR_DTOR (Keyboard)
63
64HRESULT Keyboard::FinalConstruct()
65{
66 mpDrv = NULL;
67 mpVMMDev = NULL;
68 mfVMMDevInited = false;
69 return S_OK;
70}
71
72void Keyboard::FinalRelease()
73{
74 uninit();
75}
76
77// public methods
78////////////////////////////////////////////////////////////////////////////////
79
80/**
81 * Initializes the keyboard object.
82 *
83 * @returns COM result indicator
84 * @param parent handle of our parent object
85 */
86HRESULT Keyboard::init (Console *aParent)
87{
88 LogFlowThisFunc(("aParent=%p\n", aParent));
89
90 ComAssertRet (aParent, E_INVALIDARG);
91
92 /* Enclose the state transition NotReady->InInit->Ready */
93 AutoInitSpan autoInitSpan(this);
94 AssertReturn(autoInitSpan.isOk(), E_FAIL);
95
96 unconst(mParent) = aParent;
97
98 /* Confirm a successful initialization */
99 autoInitSpan.setSucceeded();
100
101 return S_OK;
102}
103
104/**
105 * Uninitializes the instance and sets the ready flag to FALSE.
106 * Called either from FinalRelease() or by the parent when it gets destroyed.
107 */
108void Keyboard::uninit()
109{
110 LogFlowThisFunc(("\n"));
111
112 /* Enclose the state transition Ready->InUninit->NotReady */
113 AutoUninitSpan autoUninitSpan(this);
114 if (autoUninitSpan.uninitDone())
115 return;
116
117 if (mpDrv)
118 mpDrv->pKeyboard = NULL;
119
120 mpDrv = NULL;
121 mpVMMDev = NULL;
122 mfVMMDevInited = true;
123
124 unconst(mParent).setNull();
125}
126
127/**
128 * Sends a scancode to the keyboard.
129 *
130 * @returns COM status code
131 * @param scancode The scancode to send
132 */
133STDMETHODIMP Keyboard::PutScancode (LONG scancode)
134{
135 HRESULT rc = S_OK;
136
137 AutoCaller autoCaller(this);
138 if (FAILED(autoCaller.rc())) return autoCaller.rc();
139
140 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
141
142 CHECK_CONSOLE_DRV (mpDrv);
143
144 int vrc = mpDrv->pUpPort->pfnPutEvent (mpDrv->pUpPort, (uint8_t)scancode);
145
146 if (RT_FAILURE(vrc))
147 rc = setError (VBOX_E_IPRT_ERROR,
148 tr ("Could not send scan code 0x%08X to the virtual keyboard (%Rrc)"),
149 scancode, vrc);
150
151 return rc;
152}
153
154/**
155 * Sends a list of scancodes to the keyboard.
156 *
157 * @returns COM status code
158 * @param scancodes Pointer to the first scancode
159 * @param count Number of scancodes
160 * @param codesStored Address of variable to store the number
161 * of scancodes that were sent to the keyboard.
162 This value can be NULL.
163 */
164STDMETHODIMP Keyboard::PutScancodes (ComSafeArrayIn (LONG, scancodes),
165 ULONG *codesStored)
166{
167 HRESULT rc = S_OK;
168
169 if (ComSafeArrayInIsNull (scancodes))
170 return E_INVALIDARG;
171
172 AutoCaller autoCaller(this);
173 if (FAILED(autoCaller.rc())) return autoCaller.rc();
174
175 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
176
177 CHECK_CONSOLE_DRV (mpDrv);
178
179 com::SafeArray<LONG> keys (ComSafeArrayInArg (scancodes));
180 int vrc = VINF_SUCCESS;
181
182 for (uint32_t i = 0; (i < keys.size()) && RT_SUCCESS(vrc); i++)
183 vrc = mpDrv->pUpPort->pfnPutEvent (mpDrv->pUpPort, (uint8_t)keys [i]);
184
185 if (RT_FAILURE(vrc))
186 return setError (VBOX_E_IPRT_ERROR,
187 tr ("Could not send all scan codes to the virtual keyboard (%Rrc)"),
188 vrc);
189
190 /// @todo is it actually possible that not all scancodes can be transmitted?
191 if (codesStored)
192 *codesStored = (uint32_t)keys.size();
193
194 return rc;
195}
196
197/**
198 * Sends Control-Alt-Delete to the keyboard. This could be done otherwise
199 * but it's so common that we'll be nice and supply a convenience API.
200 *
201 * @returns COM status code
202 *
203 */
204STDMETHODIMP Keyboard::PutCAD()
205{
206 static com::SafeArray<LONG> cadSequence (6);
207
208 cadSequence [0] = 0x1d; // Ctrl down
209 cadSequence [1] = 0x38; // Alt down
210 cadSequence [2] = 0x53; // Del down
211 cadSequence [3] = 0xd3; // Del up
212 cadSequence [4] = 0xb8; // Alt up
213 cadSequence [5] = 0x9d; // Ctrl up
214
215 return PutScancodes (ComSafeArrayAsInParam (cadSequence), NULL);
216}
217
218//
219// private methods
220//
221
222/**
223 * Queries an interface to the driver.
224 *
225 * @returns Pointer to interface.
226 * @returns NULL if the interface was not supported by the driver.
227 * @param pInterface Pointer to this interface structure.
228 * @param enmInterface The requested interface identification.
229 */
230DECLCALLBACK(void *) Keyboard::drvQueryInterface (PPDMIBASE pInterface, PDMINTERFACE enmInterface)
231{
232 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV (pInterface);
233 PDRVMAINKEYBOARD pDrv = PDMINS_2_DATA (pDrvIns, PDRVMAINKEYBOARD);
234 switch (enmInterface)
235 {
236 case PDMINTERFACE_BASE:
237 return &pDrvIns->IBase;
238 case PDMINTERFACE_KEYBOARD_CONNECTOR:
239 return &pDrv->Connector;
240 default:
241 return NULL;
242 }
243}
244
245
246/**
247 * Destruct a keyboard driver instance.
248 *
249 * @returns VBox status.
250 * @param pDrvIns The driver instance data.
251 */
252DECLCALLBACK(void) Keyboard::drvDestruct (PPDMDRVINS pDrvIns)
253{
254 PDRVMAINKEYBOARD pData = PDMINS_2_DATA(pDrvIns, PDRVMAINKEYBOARD);
255 LogFlow(("Keyboard::drvDestruct: iInstance=%d\n", pDrvIns->iInstance));
256 if (pData->pKeyboard)
257 {
258 AutoWriteLock kbdLock(pData->pKeyboard COMMA_LOCKVAL_SRC_POS);
259 pData->pKeyboard->mpDrv = NULL;
260 pData->pKeyboard->mpVMMDev = NULL;
261 }
262}
263
264DECLCALLBACK(void) keyboardLedStatusChange (PPDMIKEYBOARDCONNECTOR pInterface, PDMKEYBLEDS enmLeds)
265{
266 PDRVMAINKEYBOARD pDrv = PPDMIKEYBOARDCONNECTOR_2_MAINKEYBOARD (pInterface);
267 pDrv->pKeyboard->getParent()->onKeyboardLedsChange (!!(enmLeds & PDMKEYBLEDS_NUMLOCK),
268 !!(enmLeds & PDMKEYBLEDS_CAPSLOCK),
269 !!(enmLeds & PDMKEYBLEDS_SCROLLLOCK));
270}
271
272/**
273 * Construct a keyboard driver instance.
274 *
275 * @copydoc FNPDMDRVCONSTRUCT
276 */
277DECLCALLBACK(int) Keyboard::drvConstruct (PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle, uint32_t fFlags)
278{
279 PDRVMAINKEYBOARD pData = PDMINS_2_DATA (pDrvIns, PDRVMAINKEYBOARD);
280 LogFlow(("Keyboard::drvConstruct: iInstance=%d\n", pDrvIns->iInstance));
281
282 /*
283 * Validate configuration.
284 */
285 if (!CFGMR3AreValuesValid (pCfgHandle, "Object\0"))
286 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
287 AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
288 ("Configuration error: Not possible to attach anything to this driver!\n"),
289 VERR_PDM_DRVINS_NO_ATTACH);
290
291 /*
292 * IBase.
293 */
294 pDrvIns->IBase.pfnQueryInterface = Keyboard::drvQueryInterface;
295
296 pData->Connector.pfnLedStatusChange = keyboardLedStatusChange;
297
298 /*
299 * Get the IKeyboardPort interface of the above driver/device.
300 */
301 pData->pUpPort = (PPDMIKEYBOARDPORT)pDrvIns->pUpBase->pfnQueryInterface (pDrvIns->pUpBase, PDMINTERFACE_KEYBOARD_PORT);
302 if (!pData->pUpPort)
303 {
304 AssertMsgFailed (("Configuration error: No keyboard port interface above!\n"));
305 return VERR_PDM_MISSING_INTERFACE_ABOVE;
306 }
307
308 /*
309 * Get the Keyboard object pointer and update the mpDrv member.
310 */
311 void *pv;
312 int rc = CFGMR3QueryPtr (pCfgHandle, "Object", &pv);
313 if (RT_FAILURE(rc))
314 {
315 AssertMsgFailed (("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
316 return rc;
317 }
318 pData->pKeyboard = (Keyboard *)pv; /** @todo Check this cast! */
319 pData->pKeyboard->mpDrv = pData;
320
321 return VINF_SUCCESS;
322}
323
324
325/**
326 * Keyboard driver registration record.
327 */
328const PDMDRVREG Keyboard::DrvReg =
329{
330 /* u32Version */
331 PDM_DRVREG_VERSION,
332 /* szDriverName */
333 "MainKeyboard",
334 /* pszDescription */
335 "Main keyboard driver (Main as in the API).",
336 /* fFlags */
337 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
338 /* fClass. */
339 PDM_DRVREG_CLASS_KEYBOARD,
340 /* cMaxInstances */
341 ~0,
342 /* cbInstance */
343 sizeof(DRVMAINKEYBOARD),
344 /* pfnConstruct */
345 Keyboard::drvConstruct,
346 /* pfnDestruct */
347 Keyboard::drvDestruct,
348 /* pfnIOCtl */
349 NULL,
350 /* pfnPowerOn */
351 NULL,
352 /* pfnReset */
353 NULL,
354 /* pfnSuspend */
355 NULL,
356 /* pfnResume */
357 NULL,
358 /* pfnAttach */
359 NULL,
360 /* pfnDetach */
361 NULL,
362 /* pfnPowerOff */
363 NULL,
364 /* pfnSoftReset */
365 NULL,
366 /* u32EndVersion */
367 PDM_DRVREG_VERSION
368};
369/* vi: set tabstop=4 shiftwidth=4 expandtab: */
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