VirtualBox

source: vbox/trunk/src/VBox/Additions/x11/vboxmouse/vboxmouse.c@ 69496

Last change on this file since 69496 was 69496, checked in by vboxsync, 7 years ago

*: scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 10.6 KB
Line 
1/* $Id: vboxmouse.c 69496 2017-10-28 14:55:58Z vboxsync $ */
2/** @file
3 * VirtualBox X11 Guest Additions, mouse driver for X.Org server 1.5
4 */
5
6/*
7 * Copyright (C) 2006-2017 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 * This code is based on evdev.c from X.Org with the following copyright
18 * and permission notice:
19 *
20 * Copyright © 2004-2008 Red Hat, Inc.
21 *
22 * Permission to use, copy, modify, distribute, and sell this software
23 * and its documentation for any purpose is hereby granted without
24 * fee, provided that the above copyright notice appear in all copies
25 * and that both that copyright notice and this permission notice
26 * appear in supporting documentation, and that the name of Red Hat
27 * not be used in advertising or publicity pertaining to distribution
28 * of the software without specific, written prior permission. Red
29 * Hat makes no representations about the suitability of this software
30 * for any purpose. It is provided "as is" without express or implied
31 * warranty.
32 *
33 * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
34 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
35 * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
36 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
37 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
38 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
39 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
40 *
41 * Authors:
42 * Kristian Høgsberg ([email protected])
43 * Adam Jackson ([email protected])
44 */
45
46#include <VBox/VMMDev.h> /* for VMMDEV_MOUSE_XXX */
47#include <VBox/VBoxGuestLib.h>
48#include <iprt/err.h>
49#include <xf86.h>
50#include <xf86Xinput.h>
51#include <mipointer.h>
52
53#include <xf86Module.h>
54
55#ifdef VBOX_GUESTR3XF86MOD
56# define _X_EXPORT
57#else
58# include <errno.h>
59# include <fcntl.h>
60# include <unistd.h>
61#endif
62
63#include "product-generated.h"
64
65static void
66VBoxReadInput(InputInfoPtr pInfo)
67{
68 uint32_t cx, cy, fFeatures;
69
70 /* Read a byte from the device to acknowledge the event */
71 char c;
72 int res = read(pInfo->fd, &c, 1);
73 NOREF(res);
74 /* The first test here is a workaround for an apparent bug in Xorg Server 1.5 */
75 if (
76#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 2
77 miPointerCurrentScreen() != NULL
78#else
79 miPointerGetScreen(pInfo->dev) != NULL
80#endif
81 && RT_SUCCESS(VbglR3GetMouseStatus(&fFeatures, &cx, &cy))
82 && (fFeatures & VMMDEV_MOUSE_HOST_WANTS_ABSOLUTE))
83 {
84#if ABI_XINPUT_VERSION == SET_ABI_VERSION(2, 0)
85 /* Bug in the 1.4 X server series - conversion_proc was no longer
86 * called, but the server didn't yet do the conversion itself. */
87 cx = (cx * screenInfo.screens[0]->width) / 65535;
88 cy = (cy * screenInfo.screens[0]->height) / 65535;
89#endif
90 /* send absolute movement */
91 xf86PostMotionEvent(pInfo->dev, 1, 0, 2, cx, cy);
92 }
93}
94
95static void
96VBoxPtrCtrlProc(DeviceIntPtr device, PtrCtrl *ctrl)
97{
98 /* Nothing to do, dix handles all settings */
99 RT_NOREF(device, ctrl);
100}
101
102static int
103VBoxInit(DeviceIntPtr device)
104{
105 CARD8 map[2] = { 0, 1 };
106#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
107 Atom axis_labels[2] = { 0, 0 };
108 Atom button_labels[2] = { 0, 0 };
109#endif
110 if (!InitPointerDeviceStruct((DevicePtr)device, map, 2,
111#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
112 button_labels,
113#endif
114#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 2
115 miPointerGetMotionEvents, VBoxPtrCtrlProc,
116 miPointerGetMotionBufferSize()
117#elif GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 3
118 GetMotionHistory, VBoxPtrCtrlProc,
119 GetMotionHistorySize(), 2 /* Number of axes */
120
121#elif GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 3
122 VBoxPtrCtrlProc, GetMotionHistorySize(),
123 2 /* Number of axes */
124#else
125# error Unsupported version of X.Org
126#endif
127#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
128 , axis_labels
129#endif
130 ))
131 return !Success;
132
133 /* Tell the server about the range of axis values we report */
134#if ABI_XINPUT_VERSION <= SET_ABI_VERSION(2, 0)
135 xf86InitValuatorAxisStruct(device, 0, 0, -1, 1, 0, 1);
136 xf86InitValuatorAxisStruct(device, 1, 0, -1, 1, 0, 1);
137#else
138 xf86InitValuatorAxisStruct(device, 0,
139# if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
140 axis_labels[0],
141# endif
142 VMMDEV_MOUSE_RANGE_MIN /* min X */, VMMDEV_MOUSE_RANGE_MAX /* max X */,
143 10000, 0, 10000
144# if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
145 , Absolute
146# endif
147 );
148
149 xf86InitValuatorAxisStruct(device, 1,
150# if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
151 axis_labels[1],
152# endif
153 VMMDEV_MOUSE_RANGE_MIN /* min Y */, VMMDEV_MOUSE_RANGE_MAX /* max Y */,
154 10000, 0, 10000
155# if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
156 , Absolute
157# endif
158 );
159#endif
160 xf86InitValuatorDefaults(device, 0);
161 xf86InitValuatorDefaults(device, 1);
162 xf86MotionHistoryAllocate(device->public.devicePrivate);
163
164 return Success;
165}
166
167static int
168VBoxProc(DeviceIntPtr device, int what)
169{
170 InputInfoPtr pInfo;
171 int rc, xrc;
172 uint32_t fFeatures = 0;
173
174 pInfo = device->public.devicePrivate;
175
176 switch (what)
177 {
178 case DEVICE_INIT:
179 xrc = VBoxInit(device);
180 if (xrc != Success) {
181 VbglR3Term();
182 return xrc;
183 }
184 break;
185
186 case DEVICE_ON:
187 xf86Msg(X_INFO, "%s: On.\n", pInfo->name);
188 if (device->public.on)
189 break;
190 /* Tell the host that we want absolute co-ordinates */
191 rc = VbglR3GetMouseStatus(&fFeatures, NULL, NULL);
192 fFeatures &= VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR;
193 if (RT_SUCCESS(rc))
194 rc = VbglR3SetMouseStatus( fFeatures
195 | VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE
196 | VMMDEV_MOUSE_NEW_PROTOCOL);
197 if (!RT_SUCCESS(rc)) {
198 xf86Msg(X_ERROR, "%s: Failed to switch guest mouse into absolute mode\n",
199 pInfo->name);
200 return !Success;
201 }
202
203 xf86AddEnabledDevice(pInfo);
204 device->public.on = TRUE;
205 break;
206
207 case DEVICE_OFF:
208 xf86Msg(X_INFO, "%s: Off.\n", pInfo->name);
209 rc = VbglR3GetMouseStatus(&fFeatures, NULL, NULL);
210 fFeatures &= VMMDEV_MOUSE_GUEST_NEEDS_HOST_CURSOR;
211 if (RT_SUCCESS(rc))
212 rc = VbglR3SetMouseStatus( fFeatures
213 & ~VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE
214 & ~VMMDEV_MOUSE_NEW_PROTOCOL);
215 xf86RemoveEnabledDevice(pInfo);
216 device->public.on = FALSE;
217 break;
218
219 case DEVICE_CLOSE:
220 VbglR3Term();
221 xf86Msg(X_INFO, "%s: Close\n", pInfo->name);
222 break;
223
224 default:
225 return BadValue;
226 }
227
228 return Success;
229}
230
231static int
232VBoxProbe(InputInfoPtr pInfo)
233{
234 int rc = VbglR3Init();
235 if (!RT_SUCCESS(rc)) {
236 xf86Msg(X_ERROR, "%s: Failed to open the VirtualBox device (error %d)\n",
237 pInfo->name, rc);
238 return BadMatch;
239 }
240
241 return Success;
242}
243
244static Bool
245VBoxConvert(InputInfoPtr pInfo, int first, int num, int v0, int v1, int v2,
246 int v3, int v4, int v5, int *x, int *y)
247{
248 RT_NOREF(pInfo, num, v2, v3, v4, v5);
249
250 if (first == 0) {
251 *x = xf86ScaleAxis(v0, 0, screenInfo.screens[0]->width, 0, 65536);
252 *y = xf86ScaleAxis(v1, 0, screenInfo.screens[0]->height, 0, 65536);
253 return TRUE;
254 }
255 return FALSE;
256}
257
258static int
259VBoxPreInitInfo(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
260{
261 const char *device;
262 int rc;
263 RT_NOREF(drv, flags);
264
265 /* Initialise the InputInfoRec. */
266 pInfo->device_control = VBoxProc;
267 pInfo->read_input = VBoxReadInput;
268 /* Unlike evdev, we set this unconditionally, as we don't handle keyboards. */
269 pInfo->type_name = XI_MOUSE;
270 pInfo->flags |= XI86_ALWAYS_CORE;
271
272 device = xf86SetStrOption(pInfo->options, "Device",
273 "/dev/vboxguest");
274
275 xf86Msg(X_CONFIG, "%s: Device: \"%s\"\n", pInfo->name, device);
276 do {
277 pInfo->fd = open(device, O_RDWR, 0);
278 }
279 while (pInfo->fd < 0 && errno == EINTR);
280
281 if (pInfo->fd < 0) {
282 xf86Msg(X_ERROR, "Unable to open VirtualBox device \"%s\".\n", device);
283 return BadMatch;
284 }
285
286 rc = VBoxProbe(pInfo);
287 if (rc != Success)
288 return rc;
289
290 return Success;
291}
292
293#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12
294static InputInfoPtr
295VBoxPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
296{
297 InputInfoPtr pInfo = xf86AllocateInput(drv, 0);
298 if (!pInfo)
299 return NULL;
300
301 /* Initialise the InputInfoRec. */
302 pInfo->name = dev->identifier;
303 pInfo->conf_idev = dev;
304 pInfo->conversion_proc = VBoxConvert;
305 pInfo->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS;
306
307 xf86CollectInputOptions(pInfo, NULL, NULL);
308 xf86ProcessCommonOptions(pInfo, pInfo->options);
309
310 if (VBoxPreInitInfo(drv, pInfo, flags) != Success) {
311 xf86DeleteInput(pInfo, 0);
312 return NULL;
313 }
314
315 pInfo->flags |= XI86_CONFIGURED;
316 return pInfo;
317}
318#endif
319
320_X_EXPORT InputDriverRec VBOXMOUSE = {
321 1,
322 "vboxmouse",
323 NULL,
324#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12
325 VBoxPreInit,
326#else
327 VBoxPreInitInfo,
328#endif
329 NULL,
330 NULL,
331 0
332};
333
334static pointer
335VBoxPlug(pointer module, pointer options, int *errmaj, int *errmin)
336{
337 RT_NOREF(options, errmaj, errmin);
338 xf86AddInputDriver(&VBOXMOUSE, module, 0);
339 xf86Msg(X_CONFIG, "Load address of symbol \"VBOXMOUSE\" is %p\n",
340 (void *)&VBOXMOUSE);
341 return module;
342}
343
344static XF86ModuleVersionInfo VBoxVersionRec =
345{
346 "vboxmouse",
347 VBOX_VENDOR,
348 MODINFOSTRING1,
349 MODINFOSTRING2,
350 0, /* Missing from SDK: XORG_VERSION_CURRENT, */
351 1, 0, 0,
352 ABI_CLASS_XINPUT,
353 ABI_XINPUT_VERSION,
354 MOD_CLASS_XINPUT,
355 {0, 0, 0, 0}
356};
357
358_X_EXPORT XF86ModuleData vboxmouseModuleData =
359{
360 &VBoxVersionRec,
361 VBoxPlug,
362 NULL
363};
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