VirtualBox

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

Last change on this file since 6734 was 5999, checked in by vboxsync, 17 years ago

The Giant CDDL Dual-License Header Change.

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