VirtualBox

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

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

Automated rebranding to Oracle copyright/license strings via filemuncher

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