VirtualBox

source: vbox/trunk/src/VBox/Additions/haiku/VBoxMouse/VBoxMouse.cpp

Last change on this file was 106061, checked in by vboxsync, 3 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.5 KB
Line 
1/* $Id: VBoxMouse.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * VBoxMouse; input_server add-on - Haiku Guest Additions, implementation.
4 */
5
6/*
7 * Copyright (C) 2012-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28/*
29 * This code is based on:
30 *
31 * VirtualBox Guest Additions for Haiku.
32 * Copyright (c) 2011 Mike Smith <[email protected]>
33 * François Revol <[email protected]>
34 *
35 * Permission is hereby granted, free of charge, to any person
36 * obtaining a copy of this software and associated documentation
37 * files (the "Software"), to deal in the Software without
38 * restriction, including without limitation the rights to use,
39 * copy, modify, merge, publish, distribute, sublicense, and/or sell
40 * copies of the Software, and to permit persons to whom the
41 * Software is furnished to do so, subject to the following
42 * conditions:
43 *
44 * The above copyright notice and this permission notice shall be
45 * included in all copies or substantial portions of the Software.
46 *
47 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
48 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
49 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
50 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
51 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
52 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
53 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
54 * OTHER DEALINGS IN THE SOFTWARE.
55 */
56
57#include <errno.h>
58#include <stdio.h>
59#include <stdlib.h>
60#include <sys/time.h>
61#include <Clipboard.h>
62#include <Debug.h>
63#include <Message.h>
64#include <String.h>
65
66#include "VBoxMouse.h"
67#include <VBox/VBoxGuest.h> /** @todo use the VbglR3 interface! */
68#include <VBox/VBoxGuestLib.h>
69#include <VBoxGuestInternal.h>
70#include <VBox/VMMDev.h>
71#include <VBox/log.h>
72#include <iprt/errcore.h>
73
74/* Export as global symbol with C linkage, RTDECL is necessary. */
75RTDECL(BInputServerDevice *)
76instantiate_input_device()
77{
78 return new VBoxMouse();
79}
80
81
82static inline int vboxMouseAcquire()
83{
84 uint32_t fFeatures = 0;
85 int rc = VbglR3GetMouseStatus(&fFeatures, NULL, NULL);
86 if (RT_SUCCESS(rc))
87 {
88 rc = VbglR3SetMouseStatus(fFeatures | VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE | VMMDEV_MOUSE_NEW_PROTOCOL);
89 if (RT_FAILURE(rc))
90 LogRel(("VbglR3SetMouseStatus failed. rc=%d\n", rc));
91 }
92 else
93 LogRel(("VbglR3GetMouseStatus failed. rc=%d\n", rc));
94 return rc;
95}
96
97
98static inline int vboxMouseRelease()
99{
100 uint32_t fFeatures = 0;
101 int rc = VbglR3GetMouseStatus(&fFeatures, NULL, NULL);
102 if (RT_SUCCESS(rc))
103 {
104 rc = VbglR3SetMouseStatus(fFeatures & ~VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE & ~VMMDEV_MOUSE_NEW_PROTOCOL);
105 if (RT_FAILURE(rc))
106 LogRel(("VbglR3SetMouseStatus failed. rc=%d\n", rc));
107 }
108 else
109 LogRel(("VbglR3GetMouseStatus failed. rc=%d\n", rc));
110 return rc;
111}
112
113
114VBoxMouse::VBoxMouse()
115 : BInputServerDevice(),
116 fDriverFD(-1),
117 fServiceThreadID(-1),
118 fExiting(false)
119{
120}
121
122
123VBoxMouse::~VBoxMouse()
124{
125}
126
127
128status_t VBoxMouse::InitCheck()
129{
130 int rc = VbglR3Init();
131 if (!RT_SUCCESS(rc))
132 return ENXIO;
133
134 input_device_ref device = { (char *)"VBoxMouse", B_POINTING_DEVICE, (void *)this };
135 input_device_ref *deviceList[2] = { &device, NULL };
136 RegisterDevices(deviceList);
137
138 return B_OK;
139}
140
141
142status_t VBoxMouse::SystemShuttingDown()
143{
144 VbglR3Term();
145
146 return B_OK;
147}
148
149
150status_t VBoxMouse::Start(const char *device, void *cookie)
151{
152#if 0
153 status_t err;
154 int rc;
155 uint32_t fFeatures = 0;
156 Log(("VBoxMouse::%s()\n", __FUNCTION__));
157
158 rc = VbglR3GetMouseStatus(&fFeatures, NULL, NULL);
159 if (RT_SUCCESS(rc))
160 rc = VbglR3SetMouseStatus(fFeatures
161 | VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE
162 | VMMDEV_MOUSE_NEW_PROTOCOL);
163 if (!RT_SUCCESS(rc))
164 {
165 LogRel(("VBoxMouse: Error switching guest mouse into absolute mode: %d\n", rc));
166 return B_DEVICE_NOT_FOUND;
167 }
168
169 err = fServiceThreadID = spawn_thread(_ServiceThreadNub,
170 "VBoxMouse", B_NORMAL_PRIORITY, this);
171 if (err >= B_OK)
172 {
173 resume_thread(fServiceThreadID);
174 return B_OK;
175 }
176 else
177 LogRel(("VBoxMouse: Error starting service thread: 0x%08lx\n",
178 err));
179
180 // release the mouse
181 rc = VbglR3GetMouseStatus(&fFeatures, NULL, NULL);
182 if (RT_SUCCESS(rc))
183 rc = VbglR3SetMouseStatus(fFeatures
184 & ~VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE
185 & ~VMMDEV_MOUSE_NEW_PROTOCOL);
186
187 return B_ERROR;
188#endif
189
190 status_t err = B_OK;
191 int rc;
192 uint32_t fFeatures = 0;
193 LogFlowFunc(("device=%s cookie=%p\n", device, cookie));
194
195 rc = vboxMouseAcquire();
196 if (RT_SUCCESS(rc))
197 {
198 err = fServiceThreadID = spawn_thread(_ServiceThreadNub, "VBoxMouse", B_NORMAL_PRIORITY, this);
199 if (err >= B_OK)
200 {
201 resume_thread(fServiceThreadID);
202 return B_OK;
203 }
204 else
205 LogRel(("VBoxMouse::Start Error starting service thread: 0x%08lx\n", err));
206
207 vboxMouseRelease();
208 err = B_ERROR;
209 }
210 else
211 {
212 LogRel(("VBoxMouse::Start vboxMouseAcquire failed. rc=%d\n", rc));
213 err = B_DEVICE_NOT_FOUND;
214 }
215
216 return err;
217}
218
219
220status_t VBoxMouse::Stop(const char *device, void *cookie)
221{
222 status_t status;
223 int rc;
224 uint32_t fFeatures = 0;
225 Log(("VBoxMouse::%s()\n", __FUNCTION__));
226
227 fExiting = true;
228
229 vboxMouseRelease();
230
231 close(fDriverFD);
232 fDriverFD = -1;
233 //XXX WTF ?
234 suspend_thread(fServiceThreadID);
235 resume_thread(fServiceThreadID);
236 wait_for_thread(fServiceThreadID, &status);
237 fServiceThreadID = -1;
238 fExiting = false;
239 return B_OK;
240}
241
242
243status_t VBoxMouse::Control(const char *device, void *cookie, uint32 code, BMessage *message)
244{
245 switch (code)
246 {
247 case B_MOUSE_SPEED_CHANGED:
248 case B_CLICK_SPEED_CHANGED:
249 case B_MOUSE_ACCELERATION_CHANGED:
250 default:
251 return BInputServerDevice::Control(device, cookie, code, message);
252 }
253 return B_OK;
254}
255
256
257status_t VBoxMouse::_ServiceThreadNub(void *_this)
258{
259 VBoxMouse *service = (VBoxMouse *)_this;
260 return service->_ServiceThread();
261}
262
263
264status_t VBoxMouse::_ServiceThread()
265{
266 Log(("VBoxMouse::%s()\n", __FUNCTION__));
267
268 fDriverFD = open(VBOXGUEST_DEVICE_NAME, O_RDWR);
269 if (fDriverFD < 0)
270 return ENXIO;
271
272 /* The thread waits for incoming messages from the host. */
273 while (!fExiting)
274 {
275 uint32_t cx, cy, fFeatures;
276 int rc;
277
278 fd_set readSet, writeSet, errorSet;
279 FD_ZERO(&readSet);
280 FD_ZERO(&writeSet);
281 FD_ZERO(&errorSet);
282 FD_SET(fDriverFD, &readSet);
283 if (fDriverFD < 0)
284 break;
285 rc = select(fDriverFD + 1, &readSet, &writeSet, &errorSet, NULL);
286 if (rc < 0)
287 {
288 if (errno == EINTR || errno == EAGAIN)
289 continue;
290 break;
291 }
292
293 rc = VbglR3GetMouseStatus(&fFeatures, &cx, &cy);
294 if ( RT_SUCCESS(rc)
295 && (fFeatures & VMMDEV_MOUSE_HOST_WANTS_ABSOLUTE))
296 {
297 float x = cx * 1.0 / 65535;
298 float y = cy * 1.0 / 65535;
299
300 _debugPrintf("VBoxMouse: at %d,%d %f,%f\n", cx, cy, x, y);
301
302 /* Send absolute movement */
303 bigtime_t now = system_time();
304 BMessage *event = new BMessage(B_MOUSE_MOVED);
305 event->AddInt64("when", now);
306 event->AddFloat("x", x);
307 event->AddFloat("y", y);
308 event->AddFloat("be:tablet_x", x);
309 event->AddFloat("be:tablet_y", y);
310 //event->PrintToStream();
311 EnqueueMessage(event);
312
313 //LogRelFlow(("processed host event rc = %d\n", rc));
314 }
315 }
316 return 0;
317}
318
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