VirtualBox

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

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

build fix

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