1352N/A# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
1352N/A
1352N/A--- a/src/sun_mouse.c Mon Jul 30 16:37:55 2012
1352N/A+++ b/src/sun_mouse.c Mon Mar 18 17:34:23 2013
1352N/A@@ -1,6 +1,5 @@
1352N/A /*
1352N/A- * Copyright (c) 2004-2005, 2008-2010, Oracle and/or its affiliates.
1352N/A- * All rights reserved.
1352N/A+ * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
1352N/A *
1352N/A * Permission is hereby granted, free of charge, to any person obtaining a
1352N/A * copy of this software and associated documentation files (the "Software"),
1352N/A@@ -69,6 +68,8 @@
1352N/A # include <sys/vuid_wheel.h>
1352N/A #endif
1352N/A
1352N/A+#include <libdevinfo.h>
1352N/A+
1352N/A /* Support for scaling absolute coordinates to screen size in
1352N/A * Solaris 10 updates and beyond */
1352N/A #if !defined(HAVE_ABSOLUTE_MOUSE_SCALING)
1352N/A@@ -104,6 +105,9 @@
1352N/A Ms_screen_resolution absres;
1352N/A #endif
1352N/A OsTimerPtr remove_timer; /* Callback for removal on ENODEV */
1352N/A+ int relToAbs;
1352N/A+ int absX;
1352N/A+ int absY;
1352N/A } VuidMseRec, *VuidMsePtr;
1352N/A
1352N/A static VuidMsePtr vuidMouseList = NULL;
1352N/A@@ -117,6 +121,9 @@
1352N/A static void vuidMouseSendScreenSize(ScreenPtr pScreen, VuidMsePtr pVuidMse);
1352N/A static void vuidMouseAdjustFrame(ADJUST_FRAME_ARGS_DECL);
1352N/A
1352N/A+static int CheckRelToAbs(InputInfoPtr pInfo);
1352N/A+static int CheckRelToAbsWalker(di_node_t node, void *arg);
1352N/A+
1352N/A static int vuidMouseGeneration = 0;
1352N/A
1352N/A #if HAS_DEVPRIVATEKEYREC
1352N/A@@ -219,6 +226,11 @@
1352N/A
1352N/A pVuidMse->buffer = (unsigned char *)&pVuidMse->event;
1352N/A pVuidMse->strmod = xf86SetStrOption(pInfo->options, "StreamsModule", NULL);
1352N/A+ pVuidMse->relToAbs = xf86SetIntOption(pInfo->options, "RelToAbs", -1);
1352N/A+ if (pVuidMse->relToAbs == -1)
1352N/A+ pVuidMse->relToAbs = CheckRelToAbs(pInfo);
1352N/A+ pVuidMse->absX = 0;
1352N/A+ pVuidMse->absY = 0;
1352N/A
1352N/A /* Setup the local procs. */
1352N/A pVuidMse->wrapped_device_control = pInfo->device_control;
1352N/A@@ -240,6 +252,120 @@
1352N/A return TRUE;
1352N/A }
1352N/A
1352N/A+/*
1352N/A+ * It seems that the mouse that is presented by the Emulex ILOM
1352N/A+ * device (USB 0x430, 0xa101 and USB 0x430, 0xa102) sends relative
1352N/A+ * mouse movements. But relative mouse movements are subject to
1352N/A+ * acceleration. This causes the position indicated on the ILOM
1352N/A+ * window to not match what the Xorg server actually has. This
1352N/A+ * makes the mouse in this environment rather unusable. So, for the
1352N/A+ * Emulex ILOM device, we will change all relative mouse movements
1352N/A+ * into absolute mouse movements, making it appear more like a
1352N/A+ * tablet. This will not be subject to acceleration, and this
1352N/A+ * should keep the ILOM window and Xorg server with the same values
1352N/A+ * for the coordinates of the mouse.
1352N/A+ */
1352N/A+
1352N/A+typedef struct reltoabs_match {
1352N/A+ int matched;
1352N/A+ char const *matchname;
1352N/A+ } reltoabs_match_t;
1352N/A+
1352N/A+/* Sun Microsystems, keyboard / mouse */
1352N/A+#define RELTOABS_MATCH1 "usbif430,a101.config1.1"
1352N/A+/* Sun Microsystems, keyboard / mouse / storage */
1352N/A+#define RELTOABS_MATCH2 "usbif430,a102.config1.1"
1352N/A+
1352N/A+static int
1352N/A+CheckRelToAbsWalker(di_node_t node, void *arg)
1352N/A+{
1352N/A+ di_minor_t minor;
1352N/A+ char *path;
1352N/A+ int numvalues;
1352N/A+ int valueon;
1352N/A+ char const *stringptr;
1352N/A+ int status;
1352N/A+ reltoabs_match_t *const matchptr = (reltoabs_match_t *)arg;
1352N/A+ char *stringvalues;
1352N/A+
1352N/A+ for (minor = di_minor_next(node, DI_MINOR_NIL);
1352N/A+ minor != DI_MINOR_NIL;
1352N/A+ minor = di_minor_next(node, minor)) {
1352N/A+ path = di_devfs_minor_path(minor);
1352N/A+ status = path != NULL && strcmp(path, matchptr -> matchname) == 0;
1352N/A+ di_devfs_path_free(path);
1352N/A+ if (status)
1352N/A+ break;
1352N/A+ }
1352N/A+
1352N/A+ if (minor == DI_MINOR_NIL)
1352N/A+ return (DI_WALK_CONTINUE);
1352N/A+
1352N/A+ numvalues = di_prop_lookup_strings(DDI_DEV_T_ANY, node,
1352N/A+ "compatible", &stringvalues);
1352N/A+ if (numvalues <= 0)
1352N/A+ return (DI_WALK_CONTINUE);
1352N/A+
1352N/A+ for (valueon = 0, stringptr = stringvalues; valueon < numvalues;
1352N/A+ valueon++, stringptr += strlen(stringptr) + 1) {
1352N/A+ if (strcmp(stringptr, RELTOABS_MATCH1) == 0) {
1352N/A+ matchptr -> matched = 1;
1352N/A+ return (DI_WALK_TERMINATE);
1352N/A+ }
1352N/A+ if (strcmp(stringptr, RELTOABS_MATCH2) == 0) {
1352N/A+ matchptr -> matched = 2;
1352N/A+ return (DI_WALK_TERMINATE);
1352N/A+ }
1352N/A+ }
1352N/A+ return (DI_WALK_CONTINUE);
1352N/A+}
1352N/A+
1352N/A+static int
1352N/A+CheckRelToAbs(InputInfoPtr pInfo)
1352N/A+{
1352N/A+ char const *device;
1352N/A+ char const *matchname;
1352N/A+ ssize_t readstatus;
1352N/A+ di_node_t node;
1352N/A+ struct stat statbuf;
1352N/A+ char linkname[512];
1352N/A+ reltoabs_match_t reltoabs_match;
1352N/A+
1352N/A+ device = xf86CheckStrOption(pInfo->options, "Device", NULL);
1352N/A+ if (device == NULL)
1352N/A+ return (0);
1352N/A+
1352N/A+ matchname = device;
1352N/A+
1352N/A+ if (lstat(device, &statbuf) == 0 &&
1352N/A+ (statbuf.st_mode & S_IFMT) == S_IFLNK) {
1352N/A+ readstatus = readlink(device, linkname, sizeof(linkname));
1352N/A+ if (readstatus > 0 && readstatus < sizeof(linkname)) {
1352N/A+ linkname[readstatus] = 0;
1352N/A+ matchname = linkname;
1352N/A+ if (strncmp(matchname, "../..", sizeof("../..") - 1) == 0)
1352N/A+ matchname += sizeof("../..") - 1;
1352N/A+ }
1352N/A+ }
1352N/A+
1352N/A+ if (strncmp(matchname, "/devices", sizeof("/devices") - 1) == 0)
1352N/A+ matchname += sizeof("/devices") - 1;
1352N/A+
1352N/A+ reltoabs_match.matched = 0;
1352N/A+ reltoabs_match.matchname = matchname;
1352N/A+
1352N/A+ node = di_init("/", DINFOCPYALL);
1352N/A+ if (node == DI_NODE_NIL)
1352N/A+ return (0);
1352N/A+
1352N/A+ di_walk_node(node, DI_WALK_CLDFIRST, (void *)&reltoabs_match,
1352N/A+ CheckRelToAbsWalker);
1352N/A+
1352N/A+ di_fini(node);
1352N/A+
1352N/A+ return (reltoabs_match.matched != 0);
1352N/A+}
1352N/A+
1352N/A static void
1352N/A vuidFlushAbsEvents(InputInfoPtr pInfo, int absX, int absY,
1352N/A Bool *absXset, Bool *absYset)
1352N/A@@ -275,21 +401,29 @@
1352N/A static void
1352N/A vuidReadInput(InputInfoPtr pInfo)
1352N/A {
1352N/A- MouseDevPtr pMse;
1352N/A- VuidMsePtr pVuidMse;
1352N/A- int buttons;
1352N/A+ MouseDevPtr pMse = pInfo->private;
1352N/A+ VuidMsePtr pVuidMse = getVuidMsePriv(pInfo);
1352N/A+ int buttons = pMse->lastButtons;
1352N/A int dx = 0, dy = 0, dz = 0, dw = 0;
1352N/A- unsigned int n;
1352N/A- unsigned char *pBuf;
1352N/A+ unsigned int n = 0;
1352N/A+ unsigned char *pBuf = pVuidMse->buffer;
1352N/A int absX = 0, absY = 0;
1352N/A+ int hdisplay = 0, vdisplay = 0;
1352N/A Bool absXset = FALSE, absYset = FALSE;
1352N/A+ int relToAbs = pVuidMse->relToAbs;
1352N/A
1352N/A- pMse = pInfo->private;
1352N/A- pVuidMse = getVuidMsePriv(pInfo);
1352N/A- buttons = pMse->lastButtons;
1352N/A- pBuf = pVuidMse->buffer;
1352N/A- n = 0;
1352N/A+ if (relToAbs) {
1352N/A+ ScreenPtr pScreen = miPointerGetScreen(pInfo->dev);
1352N/A+ ScrnInfoPtr pScr = XF86SCRNINFO(pScreen);
1352N/A
1352N/A+ if (pScr->currentMode) {
1352N/A+ hdisplay = pScr->currentMode->HDisplay;
1352N/A+ vdisplay = pScr->currentMode->VDisplay;
1352N/A+ }
1352N/A+ absX = pVuidMse->absX;
1352N/A+ absY = pVuidMse->absY;
1352N/A+ }
1352N/A+
1352N/A do {
1352N/A n = read(pInfo->fd, pBuf, sizeof(Firm_event));
1352N/A
1352N/A@@ -348,10 +482,34 @@
1352N/A int delta = pVuidMse->event.value;
1352N/A switch(pVuidMse->event.id) {
1352N/A case LOC_X_DELTA:
1352N/A- dx += delta;
1352N/A+ if (!relToAbs)
1352N/A+ dx += delta;
1352N/A+ else {
1352N/A+ if (absXset)
1352N/A+ vuidFlushAbsEvents(pInfo, absX, absY, &absXset, &absYset);
1352N/A+ absX += delta;
1352N/A+ if (absX < 0)
1352N/A+ absX = 0;
1352N/A+ else if (absX >= hdisplay && hdisplay > 0)
1352N/A+ absX = hdisplay - 1;
1352N/A+ pVuidMse->absX = absX;
1352N/A+ absXset = TRUE;
1352N/A+ }
1352N/A break;
1352N/A case LOC_Y_DELTA:
1352N/A- dy -= delta;
1352N/A+ if (!relToAbs)
1352N/A+ dy -= delta;
1352N/A+ else {
1352N/A+ if (absYset)
1352N/A+ vuidFlushAbsEvents(pInfo, absX, absY, &absXset, &absYset);
1352N/A+ absY -= delta;
1352N/A+ if (absY < 0)
1352N/A+ absY = 0;
1352N/A+ else if (absY >= vdisplay && vdisplay > 0)
1352N/A+ absY = vdisplay - 1;
1352N/A+ pVuidMse->absY = absY;
1352N/A+ absYset = TRUE;
1352N/A+ }
1352N/A break;
1352N/A case LOC_X_ABSOLUTE:
1352N/A if (absXset) {