VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/Support/darwin/SUPKeyboardService-darwin.cpp@ 48647

Last change on this file since 48647 was 48647, checked in by vboxsync, 11 years ago

Mac OS X host: keyboard LEDs sync: GUI part; code is still disabled.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.6 KB
Line 
1/* $Id: SUPKeyboardService-darwin.cpp 48647 2013-09-24 08:30:29Z vboxsync $ */
2/** @file
3 * VirtualBox Support Driver - VBoxKeyboard IOService.
4 */
5
6/*
7 * Copyright (C) 2013 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 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27#define LOG_GROUP LOG_GROUP_SUP_DRV
28
29#include <IOKit/IOLib.h>
30#include <IOKit/IOService.h>
31#include <IOKit/IOUserClient.h>
32#include <IOKit/hidsystem/IOHIKeyboard.h>
33#include <IOKit/hidsystem/IOHIDUsageTables.h>
34
35#include <iprt/asm.h>
36#include <iprt/semaphore.h>
37#include <iprt/err.h>
38#include <VBox/log.h>
39
40#define superservice IOService
41#define superclient IOUserClient
42
43#define VBOX_KEYBOARD_SERVICE_REQ_TIMEOUT (1000)
44
45/** The number of IOService class instances. */
46static bool volatile g_fInstantiated = 0;
47
48class org_virtualbox_VBoxKeyboard : public IOService
49{
50 OSDeclareDefaultStructors(org_virtualbox_VBoxKeyboard);
51
52 protected:
53
54 RTSEMMUTEX lock;
55
56 public:
57
58 virtual bool start(IOService* provider);
59 virtual void stop(IOService* provider);
60 virtual bool terminate(IOOptionBits fOptions);
61
62 IOReturn syncKeyboardDevicesLeds(void);
63};
64
65OSDefineMetaClassAndStructors(org_virtualbox_VBoxKeyboard, IOService);
66
67class org_virtualbox_VBoxKeyboardClient : public IOUserClient
68{
69 OSDeclareDefaultStructors(org_virtualbox_VBoxKeyboardClient);
70
71 protected:
72
73 org_virtualbox_VBoxKeyboard *pServiceProvider;
74
75 virtual IOReturn externalMethod(uint32_t iCmd, IOExternalMethodArguments *pArgs, IOExternalMethodDispatch *pDispatchFn, OSObject *pTarget, void *pReference);
76
77 public:
78
79 virtual bool start(IOService* provider);
80 virtual IOReturn clientClose(void);
81};
82
83OSDefineMetaClassAndStructors(org_virtualbox_VBoxKeyboardClient, IOUserClient);
84
85bool org_virtualbox_VBoxKeyboard::start(IOService* pProvider)
86{
87 if (!superservice::start(pProvider))
88 return false;
89
90 /* Low level initialization should be performed only once */
91 if (!ASMAtomicCmpXchgBool(&g_fInstantiated, true, false))
92 {
93 superservice::stop(pProvider);
94 return false;
95 }
96
97 if (RTSemMutexCreate((PRTSEMMUTEX)&lock) != 0)
98 {
99 Log2(("Unable to create mutex\n"));
100
101 superservice::stop(pProvider);
102 return false;
103 }
104
105 registerService();
106
107 return true;
108}
109
110void org_virtualbox_VBoxKeyboard::stop(IOService* pProvider)
111{
112 Log2(("Stopping %s.\n", getName()));
113
114 if (RTSemMutexDestroy(lock) != 0)
115 {
116 Log2(("Unable to destroy mutex\n"));
117 }
118
119 superservice::stop(pProvider);
120
121 ASMAtomicWriteBool(&g_fInstantiated, false);
122}
123
124bool org_virtualbox_VBoxKeyboard::terminate(IOOptionBits fOptions)
125{
126 return superservice::terminate(fOptions);
127}
128
129IOReturn org_virtualbox_VBoxKeyboard::syncKeyboardDevicesLeds(void)
130{
131 OSDictionary *pMatchingDictionary;
132
133 Log2(("org_virtualbox_VBoxKeyboardClient::syncKeyboardDevicesLeds\n"));
134
135 pMatchingDictionary = IOService::serviceMatching("IOHIDKeyboard");
136 if (pMatchingDictionary)
137 {
138 OSIterator *pIter;
139 IOHIKeyboard *pKeyboard;
140 int rc;
141
142 rc = RTSemMutexRequest(lock, VBOX_KEYBOARD_SERVICE_REQ_TIMEOUT);
143 if (RT_SUCCESS(rc))
144 {
145 pIter = IOService::getMatchingServices(pMatchingDictionary);
146 if (pIter)
147 {
148 unsigned fLeds;
149 unsigned fNewFlags;
150 unsigned fDeviceFlags;
151
152 while ((pKeyboard = (IOHIKeyboard *)pIter->getNextObject()))
153 {
154 fLeds = pKeyboard->getLEDStatus();
155
156 /* Take care about CAPSLOCK */
157 pKeyboard->setAlphaLock((fLeds & kHIDUsage_LED_CapsLock) ? true : false);
158 fDeviceFlags = pKeyboard->deviceFlags();
159 fNewFlags = ((fLeds & kHIDUsage_LED_CapsLock)) ? fDeviceFlags | NX_ALPHASHIFTMASK : fDeviceFlags & ~NX_ALPHASHIFTMASK;
160 pKeyboard->setDeviceFlags(fNewFlags);
161
162 /* Take care about NUMLOCK */
163 pKeyboard->setNumLock ((fLeds & kHIDUsage_LED_NumLock ) ? true : false);
164 fDeviceFlags = pKeyboard->deviceFlags();
165 fNewFlags = ((fLeds & kHIDUsage_LED_NumLock )) ? fDeviceFlags | NX_NUMERICPADMASK : fDeviceFlags & ~NX_NUMERICPADMASK;
166 pKeyboard->setDeviceFlags(fNewFlags);
167 }
168
169 pIter->release();
170 }
171
172 RTSemMutexRelease(lock);
173 }
174
175 pMatchingDictionary->release();
176 }
177
178 return 0;
179}
180
181bool org_virtualbox_VBoxKeyboardClient::start(IOService *pProvider)
182{
183 pServiceProvider = OSDynamicCast(org_virtualbox_VBoxKeyboard, pProvider);
184 if (pServiceProvider)
185 {
186 superclient::start(pProvider);
187 Log2(("Started: %s\n", getName()));
188 return true;
189 }
190
191 Log2(("Failed to start: %s\n", getName()));
192
193 return false;
194}
195
196IOReturn org_virtualbox_VBoxKeyboardClient::clientClose(void)
197{
198 if (pServiceProvider)
199 {
200 if (pServiceProvider->isOpen(this))
201 pServiceProvider->close(this);
202 else
203 return kIOReturnError;
204 }
205
206 if (superclient::terminate())
207 {
208 Log2(("Terminated successfully\n"));
209 return kIOReturnSuccess;
210 }
211 else
212 {
213 Log2(("Failed to terminate\n"));
214 return kIOReturnError;
215 }
216
217}
218
219IOReturn org_virtualbox_VBoxKeyboardClient::externalMethod(uint32_t iCmd, IOExternalMethodArguments *pArgs,
220 IOExternalMethodDispatch *pDispatchFn, OSObject *pTarget, void *pReference)
221{
222 IOExternalMethodDispatch *pStaticFnList;
223 uint32_t cStaticFnList;
224 IOReturn rc;
225
226 switch (iCmd)
227 {
228 case 0:
229 rc = pServiceProvider->syncKeyboardDevicesLeds();
230 break;
231
232 default:
233 rc = kIOReturnBadArgument;
234 }
235
236 /* Do not call parent class externalMethod()! */
237 return rc;
238}
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