VirtualBox

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

Last change on this file since 15661 was 14772, checked in by vboxsync, 16 years ago

Added vim modelines to aid following coding guidelines, like no tabs,
similar to what is already in the xidl file.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.3 KB
Line 
1/* $Id: KeyboardImpl.cpp 14772 2008-11-28 12:41:22Z 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 "Logging.h"
28
29#include <VBox/com/array.h>
30#include <VBox/pdmdrv.h>
31#include <iprt/asm.h>
32
33// defines
34////////////////////////////////////////////////////////////////////////////////
35
36// globals
37////////////////////////////////////////////////////////////////////////////////
38
39/**
40 * Keyboard driver instance data.
41 */
42typedef struct DRVMAINKEYBOARD
43{
44 /** Pointer to the keyboard object. */
45 Keyboard *pKeyboard;
46 /** Pointer to the driver instance structure. */
47 PPDMDRVINS pDrvIns;
48 /** Pointer to the keyboard port interface of the driver/device above us. */
49 PPDMIKEYBOARDPORT pUpPort;
50 /** Our mouse connector interface. */
51 PDMIKEYBOARDCONNECTOR Connector;
52} DRVMAINKEYBOARD, *PDRVMAINKEYBOARD;
53
54/** Converts PDMIVMMDEVCONNECTOR pointer to a DRVMAINVMMDEV pointer. */
55#define PPDMIKEYBOARDCONNECTOR_2_MAINKEYBOARD(pInterface) ( (PDRVMAINKEYBOARD) ((uintptr_t)pInterface - RT_OFFSETOF(DRVMAINKEYBOARD, Connector)) )
56
57
58// constructor / destructor
59////////////////////////////////////////////////////////////////////////////////
60
61DEFINE_EMPTY_CTOR_DTOR (Keyboard)
62
63HRESULT Keyboard::FinalConstruct()
64{
65 mpDrv = NULL;
66 mpVMMDev = NULL;
67 mfVMMDevInited = false;
68 return S_OK;
69}
70
71void Keyboard::FinalRelease()
72{
73 uninit();
74}
75
76// public methods
77////////////////////////////////////////////////////////////////////////////////
78
79/**
80 * Initializes the keyboard object.
81 *
82 * @returns COM result indicator
83 * @param parent handle of our parent object
84 */
85HRESULT Keyboard::init (Console *aParent)
86{
87 LogFlowThisFunc (("aParent=%p\n", aParent));
88
89 ComAssertRet (aParent, E_INVALIDARG);
90
91 /* Enclose the state transition NotReady->InInit->Ready */
92 AutoInitSpan autoInitSpan (this);
93 AssertReturn (autoInitSpan.isOk(), E_FAIL);
94
95 unconst (mParent) = aParent;
96
97 /* Confirm a successful initialization */
98 autoInitSpan.setSucceeded();
99
100 return S_OK;
101}
102
103/**
104 * Uninitializes the instance and sets the ready flag to FALSE.
105 * Called either from FinalRelease() or by the parent when it gets destroyed.
106 */
107void Keyboard::uninit()
108{
109 LogFlowThisFunc (("\n"));
110
111 /* Enclose the state transition Ready->InUninit->NotReady */
112 AutoUninitSpan autoUninitSpan (this);
113 if (autoUninitSpan.uninitDone())
114 return;
115
116 if (mpDrv)
117 mpDrv->pKeyboard = NULL;
118
119 mpDrv = NULL;
120 mpVMMDev = NULL;
121 mfVMMDevInited = true;
122
123 unconst (mParent).setNull();
124}
125
126/**
127 * Sends a scancode to the keyboard.
128 *
129 * @returns COM status code
130 * @param scancode The scancode to send
131 */
132STDMETHODIMP Keyboard::PutScancode (LONG scancode)
133{
134 HRESULT rc = S_OK;
135
136 AutoCaller autoCaller (this);
137 CheckComRCReturnRC (autoCaller.rc());
138
139 AutoWriteLock alock (this);
140
141 CHECK_CONSOLE_DRV (mpDrv);
142
143 int vrc = mpDrv->pUpPort->pfnPutEvent (mpDrv->pUpPort, (uint8_t)scancode);
144
145 if (RT_FAILURE (vrc))
146 rc = setError (E_FAIL, 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 CheckComRCReturnRC (autoCaller.rc());
172
173 AutoWriteLock alock (this);
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 (E_FAIL, tr ("Could not send all scan codes to the virtual keyboard (%Rrc)"),
185 vrc);
186
187 /// @todo is it actually possible that not all scancodes can be transmitted?
188 if (codesStored)
189 *codesStored = (uint32_t)keys.size();
190
191 return rc;
192}
193
194/**
195 * Sends Control-Alt-Delete to the keyboard. This could be done otherwise
196 * but it's so common that we'll be nice and supply a convenience API.
197 *
198 * @returns COM status code
199 *
200 */
201STDMETHODIMP Keyboard::PutCAD()
202{
203 static com::SafeArray<LONG> cadSequence (6);
204
205 cadSequence [0] = 0x1d; // Ctrl down
206 cadSequence [1] = 0x38; // Alt down
207 cadSequence [2] = 0x53; // Del down
208 cadSequence [3] = 0xd3; // Del up
209 cadSequence [4] = 0xb8; // Alt up
210 cadSequence [5] = 0x9d; // Ctrl up
211
212 return PutScancodes (ComSafeArrayAsInParam (cadSequence), NULL);
213}
214
215//
216// private methods
217//
218
219/**
220 * Queries an interface to the driver.
221 *
222 * @returns Pointer to interface.
223 * @returns NULL if the interface was not supported by the driver.
224 * @param pInterface Pointer to this interface structure.
225 * @param enmInterface The requested interface identification.
226 */
227DECLCALLBACK(void *) Keyboard::drvQueryInterface (PPDMIBASE pInterface, PDMINTERFACE enmInterface)
228{
229 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV (pInterface);
230 PDRVMAINKEYBOARD pDrv = PDMINS_2_DATA (pDrvIns, PDRVMAINKEYBOARD);
231 switch (enmInterface)
232 {
233 case PDMINTERFACE_BASE:
234 return &pDrvIns->IBase;
235 case PDMINTERFACE_KEYBOARD_CONNECTOR:
236 return &pDrv->Connector;
237 default:
238 return NULL;
239 }
240}
241
242
243/**
244 * Destruct a keyboard driver instance.
245 *
246 * @returns VBox status.
247 * @param pDrvIns The driver instance data.
248 */
249DECLCALLBACK(void) Keyboard::drvDestruct (PPDMDRVINS pDrvIns)
250{
251 PDRVMAINKEYBOARD pData = PDMINS_2_DATA(pDrvIns, PDRVMAINKEYBOARD);
252 LogFlow(("Keyboard::drvDestruct: iInstance=%d\n", pDrvIns->iInstance));
253 if (pData->pKeyboard)
254 {
255 AutoWriteLock kbdLock (pData->pKeyboard);
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 * @returns VBox status.
273 * @param pDrvIns The driver instance data.
274 * If the registration structure is needed, pDrvIns->pDrvReg points to it.
275 * @param pCfgHandle Configuration node handle for the driver. Use this to obtain the configuration
276 * of the driver instance. It's also found in pDrvIns->pCfgHandle, but like
277 * iInstance it's expected to be used a bit in this function.
278 */
279DECLCALLBACK(int) Keyboard::drvConstruct (PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle)
280{
281 PDRVMAINKEYBOARD pData = PDMINS_2_DATA (pDrvIns, PDRVMAINKEYBOARD);
282 LogFlow(("Keyboard::drvConstruct: iInstance=%d\n", pDrvIns->iInstance));
283
284 /*
285 * Validate configuration.
286 */
287 if (!CFGMR3AreValuesValid (pCfgHandle, "Object\0"))
288 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
289 PPDMIBASE pBaseIgnore;
290 int rc = pDrvIns->pDrvHlp->pfnAttach (pDrvIns, &pBaseIgnore);
291 if (rc != VERR_PDM_NO_ATTACHED_DRIVER)
292 {
293 AssertMsgFailed (("Configuration error: Not possible to attach anything to this driver!\n"));
294 return VERR_PDM_DRVINS_NO_ATTACH;
295 }
296
297 /*
298 * IBase.
299 */
300 pDrvIns->IBase.pfnQueryInterface = Keyboard::drvQueryInterface;
301
302 pData->Connector.pfnLedStatusChange = keyboardLedStatusChange;
303
304 /*
305 * Get the IKeyboardPort interface of the above driver/device.
306 */
307 pData->pUpPort = (PPDMIKEYBOARDPORT)pDrvIns->pUpBase->pfnQueryInterface (pDrvIns->pUpBase, PDMINTERFACE_KEYBOARD_PORT);
308 if (!pData->pUpPort)
309 {
310 AssertMsgFailed (("Configuration error: No keyboard port interface above!\n"));
311 return VERR_PDM_MISSING_INTERFACE_ABOVE;
312 }
313
314 /*
315 * Get the Keyboard object pointer and update the mpDrv member.
316 */
317 void *pv;
318 rc = CFGMR3QueryPtr (pCfgHandle, "Object", &pv);
319 if (RT_FAILURE (rc))
320 {
321 AssertMsgFailed (("Configuration error: No/bad \"Object\" value! rc=%Rrc\n", rc));
322 return rc;
323 }
324 pData->pKeyboard = (Keyboard *)pv; /** @todo Check this cast! */
325 pData->pKeyboard->mpDrv = pData;
326
327 return VINF_SUCCESS;
328}
329
330
331/**
332 * Keyboard driver registration record.
333 */
334const PDMDRVREG Keyboard::DrvReg =
335{
336 /* u32Version */
337 PDM_DRVREG_VERSION,
338 /* szDriverName */
339 "MainKeyboard",
340 /* pszDescription */
341 "Main keyboard driver (Main as in the API).",
342 /* fFlags */
343 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
344 /* fClass. */
345 PDM_DRVREG_CLASS_KEYBOARD,
346 /* cMaxInstances */
347 ~0,
348 /* cbInstance */
349 sizeof(DRVMAINKEYBOARD),
350 /* pfnConstruct */
351 Keyboard::drvConstruct,
352 /* pfnDestruct */
353 Keyboard::drvDestruct,
354 /* pfnIOCtl */
355 NULL,
356 /* pfnPowerOn */
357 NULL,
358 /* pfnReset */
359 NULL,
360 /* pfnSuspend */
361 NULL,
362 /* pfnResume */
363 NULL,
364 /* pfnDetach */
365 NULL
366};
367/* 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