VirtualBox

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

Last change on this file since 42470 was 40310, checked in by vboxsync, 13 years ago

Devices/VMMDev and Additions: use a single definition for the value range of the Additions pointer position reporting.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 10.4 KB
Line 
1/** @file
2 * VirtualBox X11 Guest Additions, mouse driver for X.Org server 1.5
3 */
4
5/*
6 * Copyright (C) 2006-2007 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 * --------------------------------------------------------------------
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 (krh@redhat.com)
43 * Adam Jackson (ajax@redhat.com)
44 */
45
46#include <VBox/VMMDev.h>
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 read(pInfo->fd, &c, 1);
73 /* The first test here is a workaround for an apparent bug in Xorg Server 1.5 */
74 if (
75#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 2
76 miPointerCurrentScreen() != NULL
77#else
78 miPointerGetScreen(pInfo->dev) != NULL
79#endif
80 && RT_SUCCESS(VbglR3GetMouseStatus(&fFeatures, &cx, &cy))
81 && (fFeatures & VMMDEV_MOUSE_HOST_WANTS_ABSOLUTE))
82 {
83#if ABI_XINPUT_VERSION == SET_ABI_VERSION(2, 0)
84 /* Bug in the 1.4 X server series - conversion_proc was no longer
85 * called, but the server didn't yet do the conversion itself. */
86 cx = (cx * screenInfo.screens[0]->width) / 65535;
87 cy = (cy * screenInfo.screens[0]->height) / 65535;
88#endif
89 /* send absolute movement */
90 xf86PostMotionEvent(pInfo->dev, 1, 0, 2, cx, cy);
91 }
92}
93
94static void
95VBoxPtrCtrlProc(DeviceIntPtr device, PtrCtrl *ctrl)
96{
97 /* Nothing to do, dix handles all settings */
98}
99
100static int
101VBoxInit(DeviceIntPtr device)
102{
103 CARD8 map[2] = { 0, 1 };
104 Atom axis_labels[2] = { 0, 0 };
105 Atom button_labels[2] = { 0, 0 };
106 if (!InitPointerDeviceStruct((DevicePtr)device, map, 2,
107#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
108 button_labels,
109#endif
110#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 2
111 miPointerGetMotionEvents, VBoxPtrCtrlProc,
112 miPointerGetMotionBufferSize()
113#elif GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 3
114 GetMotionHistory, VBoxPtrCtrlProc,
115 GetMotionHistorySize(), 2 /* Number of axes */
116
117#elif GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 3
118 VBoxPtrCtrlProc, GetMotionHistorySize(),
119 2 /* Number of axes */
120#else
121# error Unsupported version of X.Org
122#endif
123#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
124 , axis_labels
125#endif
126 ))
127 return !Success;
128
129 /* Tell the server about the range of axis values we report */
130#if ABI_XINPUT_VERSION <= SET_ABI_VERSION(2, 0)
131 xf86InitValuatorAxisStruct(device, 0, 0, -1, 1, 0, 1);
132 xf86InitValuatorAxisStruct(device, 1, 0, -1, 1, 0, 1);
133#else
134 xf86InitValuatorAxisStruct(device, 0,
135# if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
136 axis_labels[0],
137# endif
138 VMMDEV_MOUSE_RANGE_MIN /* min X */, VMMDEV_MOUSE_RANGE_MAX /* max X */,
139 10000, 0, 10000
140# if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
141 , Absolute
142# endif
143 );
144
145 xf86InitValuatorAxisStruct(device, 1,
146# if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
147 axis_labels[1],
148# endif
149 VMMDEV_MOUSE_RANGE_MIN /* min Y */, VMMDEV_MOUSE_RANGE_MAX /* max Y */,
150 10000, 0, 10000
151# if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
152 , Absolute
153# endif
154 );
155#endif
156 xf86InitValuatorDefaults(device, 0);
157 xf86InitValuatorDefaults(device, 1);
158 xf86MotionHistoryAllocate(device->public.devicePrivate);
159
160 return Success;
161}
162
163static int
164VBoxProc(DeviceIntPtr device, int what)
165{
166 InputInfoPtr pInfo;
167 int rc, xrc;
168 uint32_t fFeatures = 0;
169
170 pInfo = device->public.devicePrivate;
171
172 switch (what)
173 {
174 case DEVICE_INIT:
175 xrc = VBoxInit(device);
176 if (xrc != Success) {
177 VbglR3Term();
178 return xrc;
179 }
180 break;
181
182 case DEVICE_ON:
183 xf86Msg(X_INFO, "%s: On.\n", pInfo->name);
184 if (device->public.on)
185 break;
186 /* Tell the host that we want absolute co-ordinates */
187 rc = VbglR3GetMouseStatus(&fFeatures, NULL, NULL);
188 if (RT_SUCCESS(rc))
189 rc = VbglR3SetMouseStatus( fFeatures
190 | VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE
191 | VMMDEV_MOUSE_NEW_PROTOCOL);
192 if (!RT_SUCCESS(rc)) {
193 xf86Msg(X_ERROR, "%s: Failed to switch guest mouse into absolute mode\n",
194 pInfo->name);
195 return !Success;
196 }
197
198 xf86AddEnabledDevice(pInfo);
199 device->public.on = TRUE;
200 break;
201
202 case DEVICE_OFF:
203 xf86Msg(X_INFO, "%s: Off.\n", pInfo->name);
204 rc = VbglR3GetMouseStatus(&fFeatures, NULL, NULL);
205 if (RT_SUCCESS(rc))
206 rc = VbglR3SetMouseStatus( fFeatures
207 & ~VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE
208 & ~VMMDEV_MOUSE_NEW_PROTOCOL);
209 xf86RemoveEnabledDevice(pInfo);
210 device->public.on = FALSE;
211 break;
212
213 case DEVICE_CLOSE:
214 VbglR3Term();
215 xf86Msg(X_INFO, "%s: Close\n", pInfo->name);
216 break;
217
218 default:
219 return BadValue;
220 }
221
222 return Success;
223}
224
225static int
226VBoxProbe(InputInfoPtr pInfo)
227{
228 int rc = VbglR3Init();
229 if (!RT_SUCCESS(rc)) {
230 xf86Msg(X_ERROR, "%s: Failed to open the VirtualBox device (error %d)\n",
231 pInfo->name, rc);
232 return BadMatch;
233 }
234
235 return Success;
236}
237
238static Bool
239VBoxConvert(InputInfoPtr pInfo, int first, int num, int v0, int v1, int v2,
240 int v3, int v4, int v5, int *x, int *y)
241{
242 if (first == 0) {
243 *x = xf86ScaleAxis(v0, 0, screenInfo.screens[0]->width, 0, 65536);
244 *y = xf86ScaleAxis(v1, 0, screenInfo.screens[0]->height, 0, 65536);
245 return TRUE;
246 } else
247 return FALSE;
248}
249
250static int
251VBoxPreInitInfo(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
252{
253 const char *device;
254 int rc;
255
256 /* Initialise the InputInfoRec. */
257 pInfo->device_control = VBoxProc;
258 pInfo->read_input = VBoxReadInput;
259 /* Unlike evdev, we set this unconditionally, as we don't handle keyboards. */
260 pInfo->type_name = XI_MOUSE;
261 pInfo->flags |= XI86_ALWAYS_CORE;
262
263 device = xf86SetStrOption(pInfo->options, "Device",
264 "/dev/vboxguest");
265
266 xf86Msg(X_CONFIG, "%s: Device: \"%s\"\n", pInfo->name, device);
267 do {
268 pInfo->fd = open(device, O_RDWR, 0);
269 }
270 while (pInfo->fd < 0 && errno == EINTR);
271
272 if (pInfo->fd < 0) {
273 xf86Msg(X_ERROR, "Unable to open VirtualBox device \"%s\".\n", device);
274 return BadMatch;
275 }
276
277 rc = VBoxProbe(pInfo);
278 if (rc != Success)
279 return rc;
280
281 return Success;
282}
283
284#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12
285static InputInfoPtr
286VBoxPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
287{
288 InputInfoPtr pInfo;
289 const char *device;
290
291 if (!(pInfo = xf86AllocateInput(drv, 0)))
292 return NULL;
293
294 /* Initialise the InputInfoRec. */
295 pInfo->name = dev->identifier;
296 pInfo->conf_idev = dev;
297 pInfo->conversion_proc = VBoxConvert;
298 pInfo->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS;
299
300 xf86CollectInputOptions(pInfo, NULL, NULL);
301 xf86ProcessCommonOptions(pInfo, pInfo->options);
302
303 if (VBoxPreInitInfo(drv, pInfo, flags) != Success) {
304 xf86DeleteInput(pInfo, 0);
305 return NULL;
306 }
307
308 pInfo->flags |= XI86_CONFIGURED;
309 return pInfo;
310}
311#endif
312
313_X_EXPORT InputDriverRec VBOXMOUSE = {
314 1,
315 "vboxmouse",
316 NULL,
317#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12
318 VBoxPreInit,
319#else
320 VBoxPreInitInfo,
321#endif
322 NULL,
323 NULL,
324 0
325};
326
327static pointer
328VBoxPlug(pointer module,
329 pointer options,
330 int *errmaj,
331 int *errmin)
332{
333 xf86AddInputDriver(&VBOXMOUSE, module, 0);
334 xf86Msg(X_CONFIG, "Load address of symbol \"VBOXMOUSE\" is %p\n",
335 (void *)&VBOXMOUSE);
336 return module;
337}
338
339static XF86ModuleVersionInfo VBoxVersionRec =
340{
341 "vboxmouse",
342 VBOX_VENDOR,
343 MODINFOSTRING1,
344 MODINFOSTRING2,
345 0, /* Missing from SDK: XORG_VERSION_CURRENT, */
346 1, 0, 0,
347 ABI_CLASS_XINPUT,
348 ABI_XINPUT_VERSION,
349 MOD_CLASS_XINPUT,
350 {0, 0, 0, 0}
351};
352
353_X_EXPORT XF86ModuleData vboxmouseModuleData =
354{
355 &VBoxVersionRec,
356 VBoxPlug,
357 NULL
358};
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