VirtualBox

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

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

Main: coding style

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