aboutsummaryrefslogtreecommitdiff
path: root/xorg-server
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2011-01-08 19:40:59 +0000
committermarha <marha@users.sourceforge.net>2011-01-08 19:40:59 +0000
commit432768f75da13ee5343957df6ce5cd316a62929f (patch)
treeb02a3961540984c3d2caf783a6f0854b9b00f92a /xorg-server
parent43b6c9073b8aad1170536ae5c6a5a019617659f1 (diff)
downloadvcxsrv-432768f75da13ee5343957df6ce5cd316a62929f.tar.gz
vcxsrv-432768f75da13ee5343957df6ce5cd316a62929f.tar.bz2
vcxsrv-432768f75da13ee5343957df6ce5cd316a62929f.zip
xserver mesa libX11 xkbcomp pixman git update 8/1/2011
Diffstat (limited to 'xorg-server')
-rw-r--r--xorg-server/Xext/geext.c2
-rw-r--r--xorg-server/Xext/security.c2
-rw-r--r--xorg-server/Xext/sync.c5820
-rw-r--r--xorg-server/Xi/xigrabdev.c322
-rw-r--r--xorg-server/Xi/xipassivegrab.c2
-rw-r--r--xorg-server/Xi/xiselectev.c15
-rw-r--r--xorg-server/composite/compalloc.c38
-rw-r--r--xorg-server/composite/compinit.c62
-rw-r--r--xorg-server/composite/compint.h5
-rw-r--r--xorg-server/composite/compwindow.c34
-rw-r--r--xorg-server/config/udev.c19
-rw-r--r--xorg-server/dix/events.c15
-rw-r--r--xorg-server/dix/property.c3
-rw-r--r--xorg-server/dix/window.c4
-rw-r--r--xorg-server/doc/xml/Xserver-spec.xml7
-rw-r--r--xorg-server/exa/exa_mixed.c2
-rw-r--r--xorg-server/exa/exa_unaccel.c5
-rw-r--r--xorg-server/glx/glxdri2.c2
-rw-r--r--xorg-server/glx/unpack.h2
-rw-r--r--xorg-server/hw/dmx/glxProxy/unpack.h2
-rw-r--r--xorg-server/hw/xfree86/common/xf86AutoConfig.c2
-rw-r--r--xorg-server/hw/xfree86/common/xf86Module.h2
-rw-r--r--xorg-server/hw/xfree86/common/xf86VGAarbiter.c5
-rw-r--r--xorg-server/hw/xfree86/common/xf86VGAarbiterPriv.h2
-rw-r--r--xorg-server/hw/xfree86/dixmods/extmod/modinit.c2
-rw-r--r--xorg-server/hw/xfree86/dixmods/extmod/modinit.h168
-rw-r--r--xorg-server/hw/xfree86/dri/dri.c2
-rw-r--r--xorg-server/hw/xfree86/dri2/dri2.c11
-rw-r--r--xorg-server/hw/xfree86/loader/loadmod.c2
-rw-r--r--xorg-server/hw/xfree86/modes/xf86EdidModes.c2432
-rw-r--r--xorg-server/hw/xfree86/modes/xf86Modes.c33
-rw-r--r--xorg-server/hw/xfree86/os-support/linux/lnx_agp.c2
-rw-r--r--xorg-server/hw/xfree86/os-support/linux/lnx_video.c2
-rw-r--r--xorg-server/hw/xfree86/x86emu/ops.c63
-rw-r--r--xorg-server/hw/xfree86/xaa/xaaBitBlt.c6
-rw-r--r--xorg-server/include/exevents.h2
-rw-r--r--xorg-server/include/input.h20
-rw-r--r--xorg-server/include/inpututils.h8
-rw-r--r--xorg-server/include/resource.h2
-rw-r--r--xorg-server/include/scrnintstr.h3
-rw-r--r--xorg-server/include/windowstr.h3
-rw-r--r--xorg-server/mi/micopy.c6
-rw-r--r--xorg-server/mi/misprite.c122
-rw-r--r--xorg-server/miext/damage/damage.c20
-rw-r--r--xorg-server/miext/rootless/rootlessScreen.c5
-rw-r--r--xorg-server/os/access.c4182
-rw-r--r--xorg-server/os/connection.c1
-rw-r--r--xorg-server/os/osdep.h4
-rw-r--r--xorg-server/render/animcur.c26
-rw-r--r--xorg-server/render/mipict.c3
50 files changed, 6858 insertions, 6646 deletions
diff --git a/xorg-server/Xext/geext.c b/xorg-server/Xext/geext.c
index 993b3b2ec..951daf682 100644
--- a/xorg-server/Xext/geext.c
+++ b/xorg-server/Xext/geext.c
@@ -33,8 +33,6 @@
#include "geext.h"
#include "protocol-versions.h"
-#define rClient(obj) (clients[CLIENT_ID((obj)->resource)])
-
DevPrivateKeyRec GEClientPrivateKeyRec;
int RT_GECLIENT = 0;
diff --git a/xorg-server/Xext/security.c b/xorg-server/Xext/security.c
index 183fa06c7..d687926c6 100644
--- a/xorg-server/Xext/security.c
+++ b/xorg-server/Xext/security.c
@@ -154,8 +154,6 @@ SecurityLookupRequestName(ClientPtr client)
}
-#define rClient(obj) (clients[CLIENT_ID((obj)->resource)])
-
/* SecurityDeleteAuthorization
*
* Arguments:
diff --git a/xorg-server/Xext/sync.c b/xorg-server/Xext/sync.c
index d495116dc..4f80c7f30 100644
--- a/xorg-server/Xext/sync.c
+++ b/xorg-server/Xext/sync.c
@@ -1,2895 +1,2925 @@
-/*
-
-Copyright 1991, 1993, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall
-not be used in advertising or otherwise to promote the sale, use or
-other dealings in this Software without prior written authorization
-from The Open Group.
-
-
-Copyright 1991, 1993 by Digital Equipment Corporation, Maynard, Massachusetts,
-and Olivetti Research Limited, Cambridge, England.
-
- All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the names of Digital or Olivetti
-not be used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission. Digital and Olivetti
-make no representations about the suitability of this software
-for any purpose. It is provided "as is" without express or implied warranty.
-
-DIGITAL AND OLIVETTI DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
-SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
-FITNESS, IN NO EVENT SHALL THEY BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
-USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
-OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-
-*/
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <string.h>
-
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include <X11/Xmd.h>
-#include "scrnintstr.h"
-#include "os.h"
-#include "extnsionst.h"
-#include "dixstruct.h"
-#include "pixmapstr.h"
-#include "resource.h"
-#include "opaque.h"
-#include <X11/extensions/syncproto.h>
-#include "syncsrv.h"
-#include "syncsdk.h"
-#include "protocol-versions.h"
-
-#include <stdio.h>
-#if !defined(WIN32)
-#include <sys/time.h>
-#endif
-
-#include "modinit.h"
-
-/*
- * Local Global Variables
- */
-static int SyncEventBase;
-static int SyncErrorBase;
-static RESTYPE RTCounter = 0;
-static RESTYPE RTAwait;
-static RESTYPE RTAlarm;
-static RESTYPE RTAlarmClient;
-static RESTYPE RTFence;
-static int SyncNumSystemCounters = 0;
-static SyncCounter **SysCounterList = NULL;
-
-#define IsSystemCounter(pCounter) \
- (pCounter && (pCounter->sync.client == NULL))
-
-/* these are all the alarm attributes that pertain to the alarm's trigger */
-#define XSyncCAAllTrigger \
- (XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType)
-
-static void SyncComputeBracketValues(SyncCounter *);
-
-static void SyncInitServerTime(void);
-
-static void SyncInitIdleTime(void);
-
-
-/* Each counter maintains a simple linked list of triggers that are
- * interested in the counter. The two functions below are used to
- * delete and add triggers on this list.
- */
-static void
-SyncDeleteTriggerFromSyncObject(SyncTrigger *pTrigger)
-{
- SyncTriggerList *pCur;
- SyncTriggerList *pPrev;
- SyncCounter *pCounter;
-
- /* pSync needs to be stored in pTrigger before calling here. */
-
- if (!pTrigger->pSync)
- return;
-
- pPrev = NULL;
- pCur = pTrigger->pSync->pTriglist;
-
- while (pCur)
- {
- if (pCur->pTrigger == pTrigger)
- {
- if (pPrev)
- pPrev->next = pCur->next;
- else
- pTrigger->pSync->pTriglist = pCur->next;
-
- free(pCur);
- break;
- }
-
- pPrev = pCur;
- pCur = pCur->next;
- }
-
- if (SYNC_COUNTER == pTrigger->pSync->type)
- {
- pCounter = (SyncCounter *)pTrigger->pSync;
-
- if (IsSystemCounter(pCounter))
- SyncComputeBracketValues(pCounter);
- } else if (SYNC_FENCE == pTrigger->pSync->type) {
- SyncFence* pFence = (SyncFence*) pTrigger->pSync;
- pFence->funcs.DeleteTrigger(pTrigger);
- }
-}
-
-
-static int
-SyncAddTriggerToSyncObject(SyncTrigger *pTrigger)
-{
- SyncTriggerList *pCur;
- SyncCounter *pCounter;
-
- if (!pTrigger->pSync)
- return Success;
-
- /* don't do anything if it's already there */
- for (pCur = pTrigger->pSync->pTriglist; pCur; pCur = pCur->next)
- {
- if (pCur->pTrigger == pTrigger)
- return Success;
- }
-
- if (!(pCur = malloc(sizeof(SyncTriggerList))))
- return BadAlloc;
-
- pCur->pTrigger = pTrigger;
- pCur->next = pTrigger->pSync->pTriglist;
- pTrigger->pSync->pTriglist = pCur;
-
- if (SYNC_COUNTER == pTrigger->pSync->type)
- {
- pCounter = (SyncCounter *)pTrigger->pSync;
-
- if (IsSystemCounter(pCounter))
- SyncComputeBracketValues(pCounter);
- } else if (SYNC_FENCE == pTrigger->pSync->type) {
- SyncFence* pFence = (SyncFence*) pTrigger->pSync;
- pFence->funcs.AddTrigger(pTrigger);
- }
-
- return Success;
-}
-
-
-/* Below are five possible functions that can be plugged into
- * pTrigger->CheckTrigger for counter sync objects, corresponding to
- * the four possible test-types, and the one possible function that
- * can be plugged into pTrigger->CheckTrigger for fence sync objects.
- * These functions are called after the sync object's state changes
- * but are also passed the old state so they can inspect both the old
- * and new values. (PositiveTransition and NegativeTransition need to
- * see both pieces of information.) These functions return the truth
- * value of the trigger.
- *
- * All of them include the condition pTrigger->pSync == NULL.
- * This is because the spec says that a trigger with a sync value
- * of None is always TRUE.
- */
-
-static Bool
-SyncCheckTriggerPositiveComparison(SyncTrigger *pTrigger, CARD64 oldval)
-{
- SyncCounter *pCounter;
-
- assert(!pTrigger->pSync || (SYNC_COUNTER == pTrigger->pSync->type));
- pCounter = (SyncCounter *)pTrigger->pSync;
-
- return (pCounter == NULL ||
- XSyncValueGreaterOrEqual(pCounter->value, pTrigger->test_value));
-}
-
-static Bool
-SyncCheckTriggerNegativeComparison(SyncTrigger *pTrigger, CARD64 oldval)
-{
- SyncCounter *pCounter;
-
- assert(!pTrigger->pSync || (SYNC_COUNTER == pTrigger->pSync->type));
- pCounter = (SyncCounter *)pTrigger->pSync;
-
- return (pCounter == NULL ||
- XSyncValueLessOrEqual(pCounter->value, pTrigger->test_value));
-}
-
-static Bool
-SyncCheckTriggerPositiveTransition(SyncTrigger *pTrigger, CARD64 oldval)
-{
- SyncCounter *pCounter;
-
- assert(!pTrigger->pSync || (SYNC_COUNTER == pTrigger->pSync->type));
- pCounter = (SyncCounter *)pTrigger->pSync;
-
- return (pCounter == NULL ||
- (XSyncValueLessThan(oldval, pTrigger->test_value) &&
- XSyncValueGreaterOrEqual(pCounter->value, pTrigger->test_value)));
-}
-
-static Bool
-SyncCheckTriggerNegativeTransition(SyncTrigger *pTrigger, CARD64 oldval)
-{
- SyncCounter *pCounter;
-
- assert(!pTrigger->pSync || (SYNC_COUNTER == pTrigger->pSync->type));
- pCounter = (SyncCounter *)pTrigger->pSync;
-
- return (pCounter == NULL ||
- (XSyncValueGreaterThan(oldval, pTrigger->test_value) &&
- XSyncValueLessOrEqual(pCounter->value, pTrigger->test_value)));
-}
-
-static Bool
-SyncCheckTriggerFence(SyncTrigger *pTrigger, CARD64 unused)
-{
- SyncFence* pFence = (SyncFence*) pTrigger->pSync;
- (void)unused;
-
- return (pFence == NULL ||
- pFence->funcs.CheckTriggered(pFence));
-}
-
-static int
-SyncInitTrigger(ClientPtr client, SyncTrigger *pTrigger, XID syncObject,
- RESTYPE resType, Mask changes)
-{
- SyncObject *pSync = pTrigger->pSync;
- SyncCounter *pCounter = NULL;
- int rc;
- Bool newSyncObject = FALSE;
-
- if (changes & XSyncCACounter)
- {
- if (syncObject == None)
- pSync = NULL;
- else if (Success != (rc = dixLookupResourceByType ((pointer *)&pSync,
- syncObject, resType, client, DixReadAccess)))
- {
- client->errorValue = syncObject;
- return rc;
- }
- if (pSync != pTrigger->pSync)
- { /* new counter for trigger */
- SyncDeleteTriggerFromSyncObject(pTrigger);
- pTrigger->pSync = pSync;
- newSyncObject = TRUE;
- }
- }
-
- /* if system counter, ask it what the current value is */
-
- if (pSync && SYNC_COUNTER == pSync->type)
- {
- pCounter = (SyncCounter *)pSync;
-
- if (IsSystemCounter(pCounter))
- {
- (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter,
- &pCounter->value);
- }
- }
-
- if (changes & XSyncCAValueType)
- {
- if (pTrigger->value_type != XSyncRelative &&
- pTrigger->value_type != XSyncAbsolute)
- {
- client->errorValue = pTrigger->value_type;
- return BadValue;
- }
- }
-
- if (changes & XSyncCATestType)
- {
-
- if (pSync && SYNC_FENCE == pSync->type)
- {
- pTrigger->CheckTrigger = SyncCheckTriggerFence;
- }
- else
- {
- if (pTrigger->test_type != XSyncPositiveTransition &&
- pTrigger->test_type != XSyncNegativeTransition &&
- pTrigger->test_type != XSyncPositiveComparison &&
- pTrigger->test_type != XSyncNegativeComparison)
- {
- client->errorValue = pTrigger->test_type;
- return BadValue;
- }
- /* select appropriate CheckTrigger function */
-
- switch (pTrigger->test_type)
- {
- case XSyncPositiveTransition:
- pTrigger->CheckTrigger = SyncCheckTriggerPositiveTransition;
- break;
- case XSyncNegativeTransition:
- pTrigger->CheckTrigger = SyncCheckTriggerNegativeTransition;
- break;
- case XSyncPositiveComparison:
- pTrigger->CheckTrigger = SyncCheckTriggerPositiveComparison;
- break;
- case XSyncNegativeComparison:
- pTrigger->CheckTrigger = SyncCheckTriggerNegativeComparison;
- break;
- }
- }
- }
-
- if (changes & (XSyncCAValueType | XSyncCAValue))
- {
- if (pTrigger->value_type == XSyncAbsolute)
- pTrigger->test_value = pTrigger->wait_value;
- else /* relative */
- {
- Bool overflow;
- if (pCounter == NULL)
- return BadMatch;
-
- XSyncValueAdd(&pTrigger->test_value, pCounter->value,
- pTrigger->wait_value, &overflow);
- if (overflow)
- {
- client->errorValue = XSyncValueHigh32(pTrigger->wait_value);
- return BadValue;
- }
- }
- }
-
- /* we wait until we're sure there are no errors before registering
- * a new counter on a trigger
- */
- if (newSyncObject)
- {
- if ((rc = SyncAddTriggerToSyncObject(pTrigger)) != Success)
- return rc;
- }
- else if (pCounter && IsSystemCounter(pCounter))
- {
- SyncComputeBracketValues(pCounter);
- }
-
- return Success;
-}
-
-/* AlarmNotify events happen in response to actions taken on an Alarm or
- * the counter used by the alarm. AlarmNotify may be sent to multiple
- * clients. The alarm maintains a list of clients interested in events.
- */
-static void
-SyncSendAlarmNotifyEvents(SyncAlarm *pAlarm)
-{
- SyncAlarmClientList *pcl;
- xSyncAlarmNotifyEvent ane;
- SyncTrigger *pTrigger = &pAlarm->trigger;
- SyncCounter *pCounter;
-
- assert(!pTrigger->pSync || (SYNC_COUNTER == pTrigger->pSync->type));
-
- pCounter = (SyncCounter *)pTrigger->pSync;
-
- UpdateCurrentTime();
-
- ane.type = SyncEventBase + XSyncAlarmNotify;
- ane.kind = XSyncAlarmNotify;
- ane.alarm = pAlarm->alarm_id;
- if (pTrigger->pSync && SYNC_COUNTER == pTrigger->pSync->type)
- {
- ane.counter_value_hi = XSyncValueHigh32(pCounter->value);
- ane.counter_value_lo = XSyncValueLow32(pCounter->value);
- }
- else
- { /* XXX what else can we do if there's no counter? */
- ane.counter_value_hi = ane.counter_value_lo = 0;
- }
-
- ane.alarm_value_hi = XSyncValueHigh32(pTrigger->test_value);
- ane.alarm_value_lo = XSyncValueLow32(pTrigger->test_value);
- ane.time = currentTime.milliseconds;
- ane.state = pAlarm->state;
-
- /* send to owner */
- if (pAlarm->events)
- WriteEventsToClient(pAlarm->client, 1, (xEvent *) &ane);
-
- /* send to other interested clients */
- for (pcl = pAlarm->pEventClients; pcl; pcl = pcl->next)
- WriteEventsToClient(pcl->client, 1, (xEvent *) &ane);
-}
-
-
-/* CounterNotify events only occur in response to an Await. The events
- * go only to the Awaiting client.
- */
-static void
-SyncSendCounterNotifyEvents(ClientPtr client, SyncAwait **ppAwait,
- int num_events)
-{
- xSyncCounterNotifyEvent *pEvents, *pev;
- int i;
-
- if (client->clientGone)
- return;
- pev = pEvents = malloc(num_events * sizeof(xSyncCounterNotifyEvent));
- if (!pEvents)
- return;
- UpdateCurrentTime();
- for (i = 0; i < num_events; i++, ppAwait++, pev++)
- {
- SyncTrigger *pTrigger = &(*ppAwait)->trigger;
- pev->type = SyncEventBase + XSyncCounterNotify;
- pev->kind = XSyncCounterNotify;
- pev->counter = pTrigger->pSync->id;
- pev->wait_value_lo = XSyncValueLow32(pTrigger->test_value);
- pev->wait_value_hi = XSyncValueHigh32(pTrigger->test_value);
- if (SYNC_COUNTER == pTrigger->pSync->type)
- {
- SyncCounter *pCounter = (SyncCounter *)pTrigger->pSync;
-
- pev->counter_value_lo = XSyncValueLow32(pCounter->value);
- pev->counter_value_hi = XSyncValueHigh32(pCounter->value);
- }
- else
- {
- pev->counter_value_lo = 0;
- pev->counter_value_hi = 0;
- }
-
- pev->time = currentTime.milliseconds;
- pev->count = num_events - i - 1; /* events remaining */
- pev->destroyed = pTrigger->pSync->beingDestroyed;
- }
- /* swapping will be taken care of by this */
- WriteEventsToClient(client, num_events, (xEvent *)pEvents);
- free(pEvents);
-}
-
-
-/* This function is called when an alarm's counter is destroyed.
- * It is plugged into pTrigger->CounterDestroyed (for alarm triggers).
- */
-static void
-SyncAlarmCounterDestroyed(SyncTrigger *pTrigger)
-{
- SyncAlarm *pAlarm = (SyncAlarm *)pTrigger;
-
- pAlarm->state = XSyncAlarmInactive;
- SyncSendAlarmNotifyEvents(pAlarm);
- pTrigger->pSync = NULL;
-}
-
-
-/* This function is called when an alarm "goes off."
- * It is plugged into pTrigger->TriggerFired (for alarm triggers).
- */
-static void
-SyncAlarmTriggerFired(SyncTrigger *pTrigger)
-{
- SyncAlarm *pAlarm = (SyncAlarm *)pTrigger;
- SyncCounter *pCounter;
- CARD64 new_test_value;
-
- assert(!pTrigger->pSync || (SYNC_COUNTER == pTrigger->pSync->type));
- pCounter = (SyncCounter *)pTrigger->pSync;
-
- /* no need to check alarm unless it's active */
- if (pAlarm->state != XSyncAlarmActive)
- return;
-
- /* " if the counter value is None, or if the delta is 0 and
- * the test-type is PositiveComparison or NegativeComparison,
- * no change is made to value (test-value) and the alarm
- * state is changed to Inactive before the event is generated."
- */
- if (pCounter == NULL
- || (XSyncValueIsZero(pAlarm->delta)
- && (pAlarm->trigger.test_type == XSyncPositiveComparison
- || pAlarm->trigger.test_type == XSyncNegativeComparison)))
- pAlarm->state = XSyncAlarmInactive;
-
- new_test_value = pAlarm->trigger.test_value;
-
- if (pAlarm->state == XSyncAlarmActive)
- {
- Bool overflow;
- CARD64 oldvalue;
- SyncTrigger *paTrigger = &pAlarm->trigger;
- SyncCounter *paCounter;
-
- assert(!paTrigger->pSync || (SYNC_COUNTER == paTrigger->pSync->type));
- paCounter = (SyncCounter *)pTrigger->pSync;
-
- /* "The alarm is updated by repeatedly adding delta to the
- * value of the trigger and re-initializing it until it
- * becomes FALSE."
- */
- oldvalue = paTrigger->test_value;
-
- /* XXX really should do something smarter here */
-
- do
- {
- XSyncValueAdd(&paTrigger->test_value, paTrigger->test_value,
- pAlarm->delta, &overflow);
- } while (!overflow &&
- (*paTrigger->CheckTrigger)(paTrigger,
- paCounter->value));
-
- new_test_value = paTrigger->test_value;
- paTrigger->test_value = oldvalue;
-
- /* "If this update would cause value to fall outside the range
- * for an INT64...no change is made to value (test-value) and
- * the alarm state is changed to Inactive before the event is
- * generated."
- */
- if (overflow)
- {
- new_test_value = oldvalue;
- pAlarm->state = XSyncAlarmInactive;
- }
- }
- /* The AlarmNotify event has to have the "new state of the alarm"
- * which we can't be sure of until this point. However, it has
- * to have the "old" trigger test value. That's the reason for
- * all the newvalue/oldvalue shuffling above. After we send the
- * events, give the trigger its new test value.
- */
- SyncSendAlarmNotifyEvents(pAlarm);
- pTrigger->test_value = new_test_value;
-}
-
-
-/* This function is called when an Await unblocks, either as a result
- * of the trigger firing OR the counter being destroyed.
- * It goes into pTrigger->TriggerFired AND pTrigger->CounterDestroyed
- * (for Await triggers).
- */
-static void
-SyncAwaitTriggerFired(SyncTrigger *pTrigger)
-{
- SyncAwait *pAwait = (SyncAwait *)pTrigger;
- int numwaits;
- SyncAwaitUnion *pAwaitUnion;
- SyncAwait **ppAwait;
- int num_events = 0;
-
- pAwaitUnion = (SyncAwaitUnion *)pAwait->pHeader;
- numwaits = pAwaitUnion->header.num_waitconditions;
- ppAwait = malloc(numwaits * sizeof(SyncAwait *));
- if (!ppAwait)
- goto bail;
-
- pAwait = &(pAwaitUnion+1)->await;
-
- /* "When a client is unblocked, all the CounterNotify events for
- * the Await request are generated contiguously. If count is 0
- * there are no more events to follow for this request. If
- * count is n, there are at least n more events to follow."
- *
- * Thus, it is best to find all the counters for which events
- * need to be sent first, so that an accurate count field can
- * be stored in the events.
- */
- for ( ; numwaits; numwaits--, pAwait++)
- {
- CARD64 diff;
- Bool overflow, diffgreater, diffequal;
-
- /* "A CounterNotify event with the destroyed flag set to TRUE is
- * always generated if the counter for one of the triggers is
- * destroyed."
- */
- if (pAwait->trigger.pSync->beingDestroyed)
- {
- ppAwait[num_events++] = pAwait;
- continue;
- }
-
- if (SYNC_COUNTER == pAwait->trigger.pSync->type)
- {
- SyncCounter *pCounter = (SyncCounter *) pAwait->trigger.pSync;
-
- /* "The difference between the counter and the test value is
- * calculated by subtracting the test value from the value of
- * the counter."
- */
- XSyncValueSubtract(&diff, pCounter->value,
- pAwait->trigger.test_value, &overflow);
-
- /* "If the difference lies outside the range for an INT64, an
- * event is not generated."
- */
- if (overflow)
- continue;
- diffgreater = XSyncValueGreaterThan(diff, pAwait->event_threshold);
- diffequal = XSyncValueEqual(diff, pAwait->event_threshold);
-
- /* "If the test-type is PositiveTransition or
- * PositiveComparison, a CounterNotify event is generated if
- * the difference is at least event-threshold. If the test-type
- * is NegativeTransition or NegativeComparison, a CounterNotify
- * event is generated if the difference is at most
- * event-threshold."
- */
-
- if ( ((pAwait->trigger.test_type == XSyncPositiveComparison ||
- pAwait->trigger.test_type == XSyncPositiveTransition)
- && (diffgreater || diffequal))
- ||
- ((pAwait->trigger.test_type == XSyncNegativeComparison ||
- pAwait->trigger.test_type == XSyncNegativeTransition)
- && (!diffgreater) /* less or equal */
- )
- )
- {
- ppAwait[num_events++] = pAwait;
- }
- }
- }
- if (num_events)
- SyncSendCounterNotifyEvents(pAwaitUnion->header.client, ppAwait,
- num_events);
- free(ppAwait);
-
-bail:
- /* unblock the client */
- AttendClient(pAwaitUnion->header.client);
- /* delete the await */
- FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
-}
-
-
-/* This function should always be used to change a counter's value so that
- * any triggers depending on the counter will be checked.
- */
-void
-SyncChangeCounter(SyncCounter *pCounter, CARD64 newval)
-{
- SyncTriggerList *ptl, *pnext;
- CARD64 oldval;
-
- oldval = pCounter->value;
- pCounter->value = newval;
-
- /* run through triggers to see if any become true */
- for (ptl = pCounter->sync.pTriglist; ptl; ptl = pnext)
- {
- pnext = ptl->next;
- if ((*ptl->pTrigger->CheckTrigger)(ptl->pTrigger, oldval))
- (*ptl->pTrigger->TriggerFired)(ptl->pTrigger);
- }
-
- if (IsSystemCounter(pCounter))
- {
- SyncComputeBracketValues(pCounter);
- }
-}
-
-
-/* loosely based on dix/events.c/EventSelectForWindow */
-static Bool
-SyncEventSelectForAlarm(SyncAlarm *pAlarm, ClientPtr client, Bool wantevents)
-{
- SyncAlarmClientList *pClients;
-
- if (client == pAlarm->client) /* alarm owner */
- {
- pAlarm->events = wantevents;
- return Success;
- }
-
- /* see if the client is already on the list (has events selected) */
-
- for (pClients = pAlarm->pEventClients; pClients;
- pClients = pClients->next)
- {
- if (pClients->client == client)
- {
- /* client's presence on the list indicates desire for
- * events. If the client doesn't want events, remove it
- * from the list. If the client does want events, do
- * nothing, since it's already got them.
- */
- if (!wantevents)
- {
- FreeResource(pClients->delete_id, RT_NONE);
- }
- return Success;
- }
- }
-
- /* if we get here, this client does not currently have
- * events selected on the alarm
- */
-
- if (!wantevents)
- /* client doesn't want events, and we just discovered that it
- * doesn't have them, so there's nothing to do.
- */
- return Success;
-
- /* add new client to pAlarm->pEventClients */
-
- pClients = malloc(sizeof(SyncAlarmClientList));
- if (!pClients)
- return BadAlloc;
-
- /* register it as a resource so it will be cleaned up
- * if the client dies
- */
-
- pClients->delete_id = FakeClientID(client->index);
- if (!AddResource(pClients->delete_id, RTAlarmClient, pAlarm))
- {
- free(pClients);
- return BadAlloc;
- }
-
- /* link it into list after we know all the allocations succeed */
-
- pClients->next = pAlarm->pEventClients;
- pAlarm->pEventClients = pClients;
- pClients->client = client;
- return Success;
-}
-
-/*
- * ** SyncChangeAlarmAttributes ** This is used by CreateAlarm and ChangeAlarm
- */
-static int
-SyncChangeAlarmAttributes(ClientPtr client, SyncAlarm *pAlarm, Mask mask,
- CARD32 *values)
-{
- int status;
- XSyncCounter counter;
- Mask origmask = mask;
-
- counter =
- pAlarm->trigger.pSync ? pAlarm->trigger.pSync->id : None;
-
- while (mask)
- {
- int index2 = lowbit(mask);
- mask &= ~index2;
- switch (index2)
- {
- case XSyncCACounter:
- mask &= ~XSyncCACounter;
- /* sanity check in SyncInitTrigger */
- counter = *values++;
- break;
-
- case XSyncCAValueType:
- mask &= ~XSyncCAValueType;
- /* sanity check in SyncInitTrigger */
- pAlarm->trigger.value_type = *values++;
- break;
-
- case XSyncCAValue:
- mask &= ~XSyncCAValue;
- XSyncIntsToValue(&pAlarm->trigger.wait_value, values[1], values[0]);
- values += 2;
- break;
-
- case XSyncCATestType:
- mask &= ~XSyncCATestType;
- /* sanity check in SyncInitTrigger */
- pAlarm->trigger.test_type = *values++;
- break;
-
- case XSyncCADelta:
- mask &= ~XSyncCADelta;
- XSyncIntsToValue(&pAlarm->delta, values[1], values[0]);
- values += 2;
- break;
-
- case XSyncCAEvents:
- mask &= ~XSyncCAEvents;
- if ((*values != xTrue) && (*values != xFalse))
- {
- client->errorValue = *values;
- return BadValue;
- }
- status = SyncEventSelectForAlarm(pAlarm, client,
- (Bool)(*values++));
- if (status != Success)
- return status;
- break;
-
- default:
- client->errorValue = mask;
- return BadValue;
- }
- }
-
- /* "If the test-type is PositiveComparison or PositiveTransition
- * and delta is less than zero, or if the test-type is
- * NegativeComparison or NegativeTransition and delta is
- * greater than zero, a Match error is generated."
- */
- if (origmask & (XSyncCADelta|XSyncCATestType))
- {
- CARD64 zero;
- XSyncIntToValue(&zero, 0);
- if ((((pAlarm->trigger.test_type == XSyncPositiveComparison) ||
- (pAlarm->trigger.test_type == XSyncPositiveTransition))
- && XSyncValueLessThan(pAlarm->delta, zero))
- ||
- (((pAlarm->trigger.test_type == XSyncNegativeComparison) ||
- (pAlarm->trigger.test_type == XSyncNegativeTransition))
- && XSyncValueGreaterThan(pAlarm->delta, zero))
- )
- {
- return BadMatch;
- }
- }
-
- /* postpone this until now, when we're sure nothing else can go wrong */
- if ((status = SyncInitTrigger(client, &pAlarm->trigger, counter, RTCounter,
- origmask & XSyncCAAllTrigger)) != Success)
- return status;
-
- /* XXX spec does not really say to do this - needs clarification */
- pAlarm->state = XSyncAlarmActive;
- return Success;
-}
-
-static SyncObject *
-SyncCreate(ClientPtr client, XID id, unsigned char type)
-{
- SyncObject *pSync;
- RESTYPE resType;
-
- switch (type) {
- case SYNC_COUNTER:
- resType = RTCounter;
- pSync = malloc(sizeof(SyncCounter));
- break;
- case SYNC_FENCE:
- resType = RTFence;
- pSync = dixAllocateObjectWithPrivates(SyncFence,
- PRIVATE_SYNC_FENCE);
- break;
- default:
- return NULL;
- }
-
- if (!pSync)
- return NULL;
-
- if (!AddResource(id, resType, (pointer) pSync))
- {
- switch (type) {
- case SYNC_FENCE:
- dixFreeObjectWithPrivates((SyncFence *)pSync, PRIVATE_SYNC_FENCE);
- break;
- default:
- free(pSync);
- }
-
- return NULL;
- }
-
- pSync->client = client;
- pSync->id = id;
- pSync->pTriglist = NULL;
- pSync->beingDestroyed = FALSE;
- pSync->type = type;
-
- return pSync;
-}
-
-
-static SyncCounter *
-SyncCreateCounter(ClientPtr client, XSyncCounter id, CARD64 initialvalue)
-{
- SyncCounter *pCounter;
-
- if (!(pCounter = (SyncCounter *)SyncCreate(client,
- id,
- SYNC_COUNTER)))
- return NULL;
-
- pCounter->value = initialvalue;
- pCounter->pSysCounterInfo = NULL;
- return pCounter;
-}
-
-static int FreeCounter(void *, XID);
-
-/*
- * ***** System Counter utilities
- */
-
-pointer
-SyncCreateSystemCounter(
- char *name,
- CARD64 initial,
- CARD64 resolution,
- SyncCounterType counterType,
- void (*QueryValue)(pointer /* pCounter */,
- CARD64 * /* pValue_return */),
- void (*BracketValues)(pointer /* pCounter */,
- CARD64 * /* pbracket_less */,
- CARD64 * /* pbracket_greater */)
- )
-{
- SyncCounter *pCounter;
-
- SysCounterList = realloc(SysCounterList,
- (SyncNumSystemCounters+1)*sizeof(SyncCounter *));
- if (!SysCounterList)
- return NULL;
-
- /* this function may be called before SYNC has been initialized, so we
- * have to make sure RTCounter is created.
- */
- if (RTCounter == 0)
- {
- RTCounter = CreateNewResourceType(FreeCounter, "SyncCounter");
- if (RTCounter == 0)
- {
- return NULL;
- }
- }
-
- pCounter = SyncCreateCounter(NULL, FakeClientID(0), initial);
-
- if (pCounter)
- {
- SysCounterInfo *psci;
-
- psci = malloc(sizeof(SysCounterInfo));
- if (!psci)
- {
- FreeResource(pCounter->sync.id, RT_NONE);
- return pCounter;
- }
- pCounter->pSysCounterInfo = psci;
- psci->name = name;
- psci->resolution = resolution;
- psci->counterType = counterType;
- psci->QueryValue = QueryValue;
- psci->BracketValues = BracketValues;
- XSyncMaxValue(&psci->bracket_greater);
- XSyncMinValue(&psci->bracket_less);
- SysCounterList[SyncNumSystemCounters++] = pCounter;
- }
- return pCounter;
-}
-
-void
-SyncDestroySystemCounter(pointer pSysCounter)
-{
- SyncCounter *pCounter = (SyncCounter *)pSysCounter;
- FreeResource(pCounter->sync.id, RT_NONE);
-}
-
-static void
-SyncComputeBracketValues(SyncCounter *pCounter)
-{
- SyncTriggerList *pCur;
- SyncTrigger *pTrigger;
- SysCounterInfo *psci;
- CARD64 *pnewgtval = NULL;
- CARD64 *pnewltval = NULL;
- SyncCounterType ct;
-
- if (!pCounter)
- return;
-
- psci = pCounter->pSysCounterInfo;
- ct = pCounter->pSysCounterInfo->counterType;
- if (ct == XSyncCounterNeverChanges)
- return;
-
- XSyncMaxValue(&psci->bracket_greater);
- XSyncMinValue(&psci->bracket_less);
-
- for (pCur = pCounter->sync.pTriglist; pCur; pCur = pCur->next)
- {
- pTrigger = pCur->pTrigger;
-
- if (pTrigger->test_type == XSyncPositiveComparison &&
- ct != XSyncCounterNeverIncreases)
- {
- if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) &&
- XSyncValueLessThan(pTrigger->test_value,
- psci->bracket_greater))
- {
- psci->bracket_greater = pTrigger->test_value;
- pnewgtval = &psci->bracket_greater;
- }
- }
- else if (pTrigger->test_type == XSyncNegativeComparison &&
- ct != XSyncCounterNeverDecreases)
- {
- if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) &&
- XSyncValueGreaterThan(pTrigger->test_value,
- psci->bracket_less))
- {
- psci->bracket_less = pTrigger->test_value;
- pnewltval = &psci->bracket_less;
- }
- }
- else if (pTrigger->test_type == XSyncNegativeTransition &&
- ct != XSyncCounterNeverIncreases)
- {
- if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) &&
- XSyncValueGreaterThan(pTrigger->test_value, psci->bracket_less))
- {
- psci->bracket_less = pTrigger->test_value;
- pnewltval = &psci->bracket_less;
- } else if (XSyncValueEqual(pCounter->value, pTrigger->test_value) &&
- XSyncValueLessThan(pTrigger->test_value,
- psci->bracket_greater))
- {
- /*
- * The value is exactly equal to our threshold. We want one
- * more event in the positive direction to ensure we pick up
- * when the value *exceeds* this threshold.
- */
- psci->bracket_greater = pTrigger->test_value;
- pnewgtval = &psci->bracket_greater;
- }
- }
- else if (pTrigger->test_type == XSyncPositiveTransition &&
- ct != XSyncCounterNeverDecreases)
- {
- if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) &&
- XSyncValueLessThan(pTrigger->test_value, psci->bracket_greater))
- {
- psci->bracket_greater = pTrigger->test_value;
- pnewgtval = &psci->bracket_greater;
- } else if (XSyncValueEqual(pCounter->value, pTrigger->test_value) &&
- XSyncValueGreaterThan(pTrigger->test_value,
- psci->bracket_less))
- {
- /*
- * The value is exactly equal to our threshold. We want one
- * more event in the negative direction to ensure we pick up
- * when the value is less than this threshold.
- */
- psci->bracket_less = pTrigger->test_value;
- pnewltval = &psci->bracket_less;
- }
- }
- } /* end for each trigger */
-
- if (pnewgtval || pnewltval)
- {
- (*psci->BracketValues)((pointer)pCounter, pnewltval, pnewgtval);
- }
-}
-
-/*
- * ***** Resource delete functions
- */
-
-/* ARGSUSED */
-static int
-FreeAlarm(void *addr, XID id)
-{
- SyncAlarm *pAlarm = (SyncAlarm *) addr;
-
- pAlarm->state = XSyncAlarmDestroyed;
-
- SyncSendAlarmNotifyEvents(pAlarm);
-
- /* delete event selections */
-
- while (pAlarm->pEventClients)
- FreeResource(pAlarm->pEventClients->delete_id, RT_NONE);
-
- SyncDeleteTriggerFromSyncObject(&pAlarm->trigger);
-
- free(pAlarm);
- return Success;
-}
-
-
-/*
- * ** Cleanup after the destruction of a Counter
- */
-/* ARGSUSED */
-static int
-FreeCounter(void *env, XID id)
-{
- SyncCounter *pCounter = (SyncCounter *) env;
- SyncTriggerList *ptl, *pnext;
-
- pCounter->sync.beingDestroyed = TRUE;
- /* tell all the counter's triggers that the counter has been destroyed */
- for (ptl = pCounter->sync.pTriglist; ptl; ptl = pnext)
- {
- (*ptl->pTrigger->CounterDestroyed)(ptl->pTrigger);
- pnext = ptl->next;
- free(ptl); /* destroy the trigger list as we go */
- }
- if (IsSystemCounter(pCounter))
- {
- int i, found = 0;
-
- free(pCounter->pSysCounterInfo);
-
- /* find the counter in the list of system counters and remove it */
-
- if (SysCounterList)
- {
- for (i = 0; i < SyncNumSystemCounters; i++)
- {
- if (SysCounterList[i] == pCounter)
- {
- found = i;
- break;
- }
- }
- if (found < (SyncNumSystemCounters-1))
- {
- for (i = found; i < SyncNumSystemCounters-1; i++)
- {
- SysCounterList[i] = SysCounterList[i+1];
- }
- }
- }
- SyncNumSystemCounters--;
- }
- free(pCounter);
- return Success;
-}
-
-/*
- * ** Cleanup after Await
- */
-/* ARGSUSED */
-static int
-FreeAwait(void *addr, XID id)
-{
- SyncAwaitUnion *pAwaitUnion = (SyncAwaitUnion *) addr;
- SyncAwait *pAwait;
- int numwaits;
-
- pAwait = &(pAwaitUnion+1)->await; /* first await on list */
-
- /* remove triggers from counters */
-
- for (numwaits = pAwaitUnion->header.num_waitconditions; numwaits;
- numwaits--, pAwait++)
- {
- /* If the counter is being destroyed, FreeCounter will delete
- * the trigger list itself, so don't do it here.
- */
- SyncObject *pSync = pAwait->trigger.pSync;
- if (pSync && !pSync->beingDestroyed)
- SyncDeleteTriggerFromSyncObject(&pAwait->trigger);
- }
- free(pAwaitUnion);
- return Success;
-}
-
-/* loosely based on dix/events.c/OtherClientGone */
-static int
-FreeAlarmClient(void *value, XID id)
-{
- SyncAlarm *pAlarm = (SyncAlarm *)value;
- SyncAlarmClientList *pCur, *pPrev;
-
- for (pPrev = NULL, pCur = pAlarm->pEventClients;
- pCur;
- pPrev = pCur, pCur = pCur->next)
- {
- if (pCur->delete_id == id)
- {
- if (pPrev)
- pPrev->next = pCur->next;
- else
- pAlarm->pEventClients = pCur->next;
- free(pCur);
- return Success;
- }
- }
- FatalError("alarm client not on event list");
- /*NOTREACHED*/
-}
-
-
-/*
- * ***** Proc functions
- */
-
-
-/*
- * ** Initialize the extension
- */
-static int
-ProcSyncInitialize(ClientPtr client)
-{
- xSyncInitializeReply rep;
- int n;
-
- REQUEST_SIZE_MATCH(xSyncInitializeReq);
-
- memset(&rep, 0, sizeof(xSyncInitializeReply));
- rep.type = X_Reply;
- rep.sequenceNumber = client->sequence;
- rep.majorVersion = SERVER_SYNC_MAJOR_VERSION;
- rep.minorVersion = SERVER_SYNC_MINOR_VERSION;
- rep.length = 0;
-
- if (client->swapped)
- {
- swaps(&rep.sequenceNumber, n);
- }
- WriteToClient(client, sizeof(rep), (char *) &rep);
- return Success;
-}
-
-/*
- * ** Get list of system counters available through the extension
- */
-static int
-ProcSyncListSystemCounters(ClientPtr client)
-{
- xSyncListSystemCountersReply rep;
- int i, len;
- xSyncSystemCounter *list = NULL, *walklist = NULL;
-
- REQUEST_SIZE_MATCH(xSyncListSystemCountersReq);
-
- rep.type = X_Reply;
- rep.sequenceNumber = client->sequence;
- rep.nCounters = SyncNumSystemCounters;
-
- for (i = len = 0; i < SyncNumSystemCounters; i++)
- {
- char *name = SysCounterList[i]->pSysCounterInfo->name;
- /* pad to 4 byte boundary */
- len += pad_to_int32(sz_xSyncSystemCounter + strlen(name));
- }
-
- if (len)
- {
- walklist = list = malloc(len);
- if (!list)
- return BadAlloc;
- }
-
- rep.length = bytes_to_int32(len);
-
- if (client->swapped)
- {
- char n;
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
- swapl(&rep.nCounters, n);
- }
-
- for (i = 0; i < SyncNumSystemCounters; i++)
- {
- int namelen;
- char *pname_in_reply;
- SysCounterInfo *psci = SysCounterList[i]->pSysCounterInfo;
-
- walklist->counter = SysCounterList[i]->sync.id;
- walklist->resolution_hi = XSyncValueHigh32(psci->resolution);
- walklist->resolution_lo = XSyncValueLow32(psci->resolution);
- namelen = strlen(psci->name);
- walklist->name_length = namelen;
-
- if (client->swapped)
- {
- char n;
- swapl(&walklist->counter, n);
- swapl(&walklist->resolution_hi, n);
- swapl(&walklist->resolution_lo, n);
- swaps(&walklist->name_length, n);
- }
-
- pname_in_reply = ((char *)walklist) + sz_xSyncSystemCounter;
- strncpy(pname_in_reply, psci->name, namelen);
- walklist = (xSyncSystemCounter *) (((char *)walklist) +
- pad_to_int32(sz_xSyncSystemCounter + namelen));
- }
-
- WriteToClient(client, sizeof(rep), (char *) &rep);
- if (len)
- {
- WriteToClient(client, len, (char *) list);
- free(list);
- }
-
- return Success;
-}
-
-/*
- * ** Set client Priority
- */
-static int
-ProcSyncSetPriority(ClientPtr client)
-{
- REQUEST(xSyncSetPriorityReq);
- ClientPtr priorityclient;
- int rc;
-
- REQUEST_SIZE_MATCH(xSyncSetPriorityReq);
-
- if (stuff->id == None)
- priorityclient = client;
- else {
- rc = dixLookupClient(&priorityclient, stuff->id, client,
- DixSetAttrAccess);
- if (rc != Success)
- return rc;
- }
-
- if (priorityclient->priority != stuff->priority)
- {
- priorityclient->priority = stuff->priority;
-
- /* The following will force the server back into WaitForSomething
- * so that the change in this client's priority is immediately
- * reflected.
- */
- isItTimeToYield = TRUE;
- dispatchException |= DE_PRIORITYCHANGE;
- }
- return Success;
-}
-
-/*
- * ** Get client Priority
- */
-static int
-ProcSyncGetPriority(ClientPtr client)
-{
- REQUEST(xSyncGetPriorityReq);
- xSyncGetPriorityReply rep;
- ClientPtr priorityclient;
- int rc;
-
- REQUEST_SIZE_MATCH(xSyncGetPriorityReq);
-
- if (stuff->id == None)
- priorityclient = client;
- else {
- rc = dixLookupClient(&priorityclient, stuff->id, client,
- DixGetAttrAccess);
- if (rc != Success)
- return rc;
- }
-
- rep.type = X_Reply;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
- rep.priority = priorityclient->priority;
-
- if (client->swapped)
- {
- char n;
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.priority, n);
- }
-
- WriteToClient(client, sizeof(xSyncGetPriorityReply), (char *) &rep);
-
- return Success;
-}
-
-/*
- * ** Create a new counter
- */
-static int
-ProcSyncCreateCounter(ClientPtr client)
-{
- REQUEST(xSyncCreateCounterReq);
- CARD64 initial;
-
- REQUEST_SIZE_MATCH(xSyncCreateCounterReq);
-
- LEGAL_NEW_RESOURCE(stuff->cid, client);
-
- XSyncIntsToValue(&initial, stuff->initial_value_lo, stuff->initial_value_hi);
- if (!SyncCreateCounter(client, stuff->cid, initial))
- return BadAlloc;
-
- return Success;
-}
-
-/*
- * ** Set Counter value
- */
-static int
-ProcSyncSetCounter(ClientPtr client)
-{
- REQUEST(xSyncSetCounterReq);
- SyncCounter *pCounter;
- CARD64 newvalue;
- int rc;
-
- REQUEST_SIZE_MATCH(xSyncSetCounterReq);
-
- rc = dixLookupResourceByType((pointer *)&pCounter, stuff->cid, RTCounter,
- client, DixWriteAccess);
- if (rc != Success)
- return rc;
-
- if (IsSystemCounter(pCounter))
- {
- client->errorValue = stuff->cid;
- return BadAccess;
- }
-
- XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi);
- SyncChangeCounter(pCounter, newvalue);
- return Success;
-}
-
-/*
- * ** Change Counter value
- */
-static int
-ProcSyncChangeCounter(ClientPtr client)
-{
- REQUEST(xSyncChangeCounterReq);
- SyncCounter *pCounter;
- CARD64 newvalue;
- Bool overflow;
- int rc;
-
- REQUEST_SIZE_MATCH(xSyncChangeCounterReq);
-
- rc = dixLookupResourceByType((pointer *)&pCounter, stuff->cid, RTCounter,
- client, DixWriteAccess);
- if (rc != Success)
- return rc;
-
- if (IsSystemCounter(pCounter))
- {
- client->errorValue = stuff->cid;
- return BadAccess;
- }
-
- XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi);
- XSyncValueAdd(&newvalue, pCounter->value, newvalue, &overflow);
- if (overflow)
- {
- /* XXX 64 bit value can't fit in 32 bits; do the best we can */
- client->errorValue = stuff->value_hi;
- return BadValue;
- }
- SyncChangeCounter(pCounter, newvalue);
- return Success;
-}
-
-/*
- * ** Destroy a counter
- */
-static int
-ProcSyncDestroyCounter(ClientPtr client)
-{
- REQUEST(xSyncDestroyCounterReq);
- SyncCounter *pCounter;
- int rc;
-
- REQUEST_SIZE_MATCH(xSyncDestroyCounterReq);
-
- rc = dixLookupResourceByType((pointer *)&pCounter, stuff->counter, RTCounter,
- client, DixDestroyAccess);
- if (rc != Success)
- return rc;
-
- if (IsSystemCounter(pCounter))
- {
- client->errorValue = stuff->counter;
- return BadAccess;
- }
- FreeResource(pCounter->sync.id, RT_NONE);
- return Success;
-}
-
-static SyncAwaitUnion*
-SyncAwaitPrologue(ClientPtr client, int items)
-{
- SyncAwaitUnion *pAwaitUnion;
-
- /* all the memory for the entire await list is allocated
- * here in one chunk
- */
- pAwaitUnion = malloc((items+1) * sizeof(SyncAwaitUnion));
- if (!pAwaitUnion)
- return NULL;
-
- /* first item is the header, remainder are real wait conditions */
-
- pAwaitUnion->header.delete_id = FakeClientID(client->index);
- if (!AddResource(pAwaitUnion->header.delete_id, RTAwait, pAwaitUnion))
- {
- free(pAwaitUnion);
- return NULL;
- }
-
- pAwaitUnion->header.client = client;
- pAwaitUnion->header.num_waitconditions = 0;
-
- return pAwaitUnion;
-}
-
-static void
-SyncAwaitEpilogue(ClientPtr client, int items, SyncAwaitUnion *pAwaitUnion)
-{
- SyncAwait *pAwait;
- int i;
-
- IgnoreClient(client);
-
- /* see if any of the triggers are already true */
-
- pAwait = &(pAwaitUnion+1)->await; /* skip over header */
- for (i = 0; i < items; i++, pAwait++)
- {
- CARD64 value;
-
- /* don't have to worry about NULL counters because the request
- * errors before we get here out if they occur
- */
- switch (pAwait->trigger.pSync->type) {
- case SYNC_COUNTER:
- value = ((SyncCounter *)pAwait->trigger.pSync)->value;
- break;
- default:
- XSyncIntToValue(&value, 0);
- }
-
- if ((*pAwait->trigger.CheckTrigger)(&pAwait->trigger, value))
- {
- (*pAwait->trigger.TriggerFired)(&pAwait->trigger);
- break; /* once is enough */
- }
- }
-}
-
-/*
- * ** Await
- */
-static int
-ProcSyncAwait(ClientPtr client)
-{
- REQUEST(xSyncAwaitReq);
- int len, items;
- int i;
- xSyncWaitCondition *pProtocolWaitConds;
- SyncAwaitUnion *pAwaitUnion;
- SyncAwait *pAwait;
- int status;
-
- REQUEST_AT_LEAST_SIZE(xSyncAwaitReq);
-
- len = client->req_len << 2;
- len -= sz_xSyncAwaitReq;
- items = len / sz_xSyncWaitCondition;
-
- if (items * sz_xSyncWaitCondition != len)
- {
- return BadLength;
- }
- if (items == 0)
- {
- client->errorValue = items; /* XXX protocol change */
- return BadValue;
- }
-
- if (!(pAwaitUnion = SyncAwaitPrologue(client, items)))
- return BadAlloc;
-
- /* don't need to do any more memory allocation for this request! */
-
- pProtocolWaitConds = (xSyncWaitCondition *) & stuff[1];
-
- pAwait = &(pAwaitUnion+1)->await; /* skip over header */
- for (i = 0; i < items; i++, pProtocolWaitConds++, pAwait++)
- {
- if (pProtocolWaitConds->counter == None) /* XXX protocol change */
- {
- /* this should take care of removing any triggers created by
- * this request that have already been registered on sync objects
- */
- FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
- client->errorValue = pProtocolWaitConds->counter;
- return SyncErrorBase + XSyncBadCounter;
- }
-
- /* sanity checks are in SyncInitTrigger */
- pAwait->trigger.pSync = NULL;
- pAwait->trigger.value_type = pProtocolWaitConds->value_type;
- XSyncIntsToValue(&pAwait->trigger.wait_value,
- pProtocolWaitConds->wait_value_lo,
- pProtocolWaitConds->wait_value_hi);
- pAwait->trigger.test_type = pProtocolWaitConds->test_type;
-
- status = SyncInitTrigger(client, &pAwait->trigger,
- pProtocolWaitConds->counter, RTCounter,
- XSyncCAAllTrigger);
- if (status != Success)
- {
- /* this should take care of removing any triggers created by
- * this request that have already been registered on sync objects
- */
- FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
- return status;
- }
- /* this is not a mistake -- same function works for both cases */
- pAwait->trigger.TriggerFired = SyncAwaitTriggerFired;
- pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired;
- XSyncIntsToValue(&pAwait->event_threshold,
- pProtocolWaitConds->event_threshold_lo,
- pProtocolWaitConds->event_threshold_hi);
- pAwait->pHeader = &pAwaitUnion->header;
- pAwaitUnion->header.num_waitconditions++;
- }
-
- SyncAwaitEpilogue(client, items, pAwaitUnion);
-
- return Success;
-}
-
-
-/*
- * ** Query a counter
- */
-static int
-ProcSyncQueryCounter(ClientPtr client)
-{
- REQUEST(xSyncQueryCounterReq);
- xSyncQueryCounterReply rep;
- SyncCounter *pCounter;
- int rc;
-
- REQUEST_SIZE_MATCH(xSyncQueryCounterReq);
-
- rc = dixLookupResourceByType((pointer *)&pCounter, stuff->counter,
- RTCounter, client, DixReadAccess);
- if (rc != Success)
- return rc;
-
- rep.type = X_Reply;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
-
- /* if system counter, ask it what the current value is */
-
- if (IsSystemCounter(pCounter))
- {
- (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter,
- &pCounter->value);
- }
-
- rep.value_hi = XSyncValueHigh32(pCounter->value);
- rep.value_lo = XSyncValueLow32(pCounter->value);
- if (client->swapped)
- {
- char n;
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
- swapl(&rep.value_hi, n);
- swapl(&rep.value_lo, n);
- }
- WriteToClient(client, sizeof(xSyncQueryCounterReply), (char *) &rep);
- return Success;
-}
-
-
-/*
- * ** Create Alarm
- */
-static int
-ProcSyncCreateAlarm(ClientPtr client)
-{
- REQUEST(xSyncCreateAlarmReq);
- SyncAlarm *pAlarm;
- int status;
- unsigned long len, vmask;
- SyncTrigger *pTrigger;
-
- REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq);
-
- LEGAL_NEW_RESOURCE(stuff->id, client);
-
- vmask = stuff->valueMask;
- len = client->req_len - bytes_to_int32(sizeof(xSyncCreateAlarmReq));
- /* the "extra" call to Ones accounts for the presence of 64 bit values */
- if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta))))
- return BadLength;
-
- if (!(pAlarm = malloc(sizeof(SyncAlarm))))
- {
- return BadAlloc;
- }
-
- /* set up defaults */
-
- pTrigger = &pAlarm->trigger;
- pTrigger->pSync = NULL;
- pTrigger->value_type = XSyncAbsolute;
- XSyncIntToValue(&pTrigger->wait_value, 0L);
- pTrigger->test_type = XSyncPositiveComparison;
- pTrigger->TriggerFired = SyncAlarmTriggerFired;
- pTrigger->CounterDestroyed = SyncAlarmCounterDestroyed;
- status = SyncInitTrigger(client, pTrigger, None, RTCounter,
- XSyncCAAllTrigger);
- if (status != Success)
- {
- free(pAlarm);
- return status;
- }
-
- pAlarm->client = client;
- pAlarm->alarm_id = stuff->id;
- XSyncIntToValue(&pAlarm->delta, 1L);
- pAlarm->events = TRUE;
- pAlarm->state = XSyncAlarmInactive;
- pAlarm->pEventClients = NULL;
- status = SyncChangeAlarmAttributes(client, pAlarm, vmask,
- (CARD32 *)&stuff[1]);
- if (status != Success)
- {
- free(pAlarm);
- return status;
- }
-
- if (!AddResource(stuff->id, RTAlarm, pAlarm))
- {
- free(pAlarm);
- return BadAlloc;
- }
-
- /* see if alarm already triggered. NULL counter will not trigger
- * in CreateAlarm and sets alarm state to Inactive.
- */
-
- if (!pTrigger->pSync)
- {
- pAlarm->state = XSyncAlarmInactive; /* XXX protocol change */
- }
- else
- {
- SyncCounter *pCounter;
-
- assert(SYNC_COUNTER == pTrigger->pSync->type);
- pCounter = (SyncCounter *)pTrigger->pSync;
-
- if ((*pTrigger->CheckTrigger)(pTrigger, pCounter->value))
- (*pTrigger->TriggerFired)(pTrigger);
- }
-
- return Success;
-}
-
-/*
- * ** Change Alarm
- */
-static int
-ProcSyncChangeAlarm(ClientPtr client)
-{
- REQUEST(xSyncChangeAlarmReq);
- SyncAlarm *pAlarm;
- SyncCounter *pCounter = NULL;
- long vmask;
- int len, status;
-
- REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq);
-
- status = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm,
- client, DixWriteAccess);
- if (status != Success)
- return status;
-
- vmask = stuff->valueMask;
- len = client->req_len - bytes_to_int32(sizeof(xSyncChangeAlarmReq));
- /* the "extra" call to Ones accounts for the presence of 64 bit values */
- if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta))))
- return BadLength;
-
- if ((status = SyncChangeAlarmAttributes(client, pAlarm, vmask,
- (CARD32 *)&stuff[1])) != Success)
- return status;
-
- if (pAlarm->trigger.pSync)
- {
- assert(SYNC_COUNTER == pAlarm->trigger.pSync->type);
- pCounter = (SyncCounter *)pAlarm->trigger.pSync;
- }
-
- /* see if alarm already triggered. NULL counter WILL trigger
- * in ChangeAlarm.
- */
-
- if (!pCounter ||
- (*pAlarm->trigger.CheckTrigger)(&pAlarm->trigger, pCounter->value))
- {
- (*pAlarm->trigger.TriggerFired)(&pAlarm->trigger);
- }
- return Success;
-}
-
-static int
-ProcSyncQueryAlarm(ClientPtr client)
-{
- REQUEST(xSyncQueryAlarmReq);
- SyncAlarm *pAlarm;
- xSyncQueryAlarmReply rep;
- SyncTrigger *pTrigger;
- int rc;
-
- REQUEST_SIZE_MATCH(xSyncQueryAlarmReq);
-
- rc = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm,
- client, DixReadAccess);
- if (rc != Success)
- return rc;
-
- rep.type = X_Reply;
- rep.length = bytes_to_int32(sizeof(xSyncQueryAlarmReply) - sizeof(xGenericReply));
- rep.sequenceNumber = client->sequence;
-
- pTrigger = &pAlarm->trigger;
- rep.counter = (pTrigger->pSync) ? pTrigger->pSync->id : None;
-
-#if 0 /* XXX unclear what to do, depends on whether relative value-types
- * are "consumed" immediately and are considered absolute from then
- * on.
- */
- rep.value_type = pTrigger->value_type;
- rep.wait_value_hi = XSyncValueHigh32(pTrigger->wait_value);
- rep.wait_value_lo = XSyncValueLow32(pTrigger->wait_value);
-#else
- rep.value_type = XSyncAbsolute;
- rep.wait_value_hi = XSyncValueHigh32(pTrigger->test_value);
- rep.wait_value_lo = XSyncValueLow32(pTrigger->test_value);
-#endif
-
- rep.test_type = pTrigger->test_type;
- rep.delta_hi = XSyncValueHigh32(pAlarm->delta);
- rep.delta_lo = XSyncValueLow32(pAlarm->delta);
- rep.events = pAlarm->events;
- rep.state = pAlarm->state;
-
- if (client->swapped)
- {
- char n;
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
- swapl(&rep.counter, n);
- swapl(&rep.wait_value_hi, n);
- swapl(&rep.wait_value_lo, n);
- swapl(&rep.test_type, n);
- swapl(&rep.delta_hi, n);
- swapl(&rep.delta_lo, n);
- }
-
- WriteToClient(client, sizeof(xSyncQueryAlarmReply), (char *) &rep);
- return Success;
-}
-
-static int
-ProcSyncDestroyAlarm(ClientPtr client)
-{
- SyncAlarm *pAlarm;
- int rc;
- REQUEST(xSyncDestroyAlarmReq);
-
- REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq);
-
- rc = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm,
- client, DixDestroyAccess);
- if (rc != Success)
- return rc;
-
- FreeResource(stuff->alarm, RT_NONE);
- return Success;
-}
-
-static int
-ProcSyncCreateFence(ClientPtr client)
-{
- REQUEST(xSyncCreateFenceReq);
- DrawablePtr pDraw;
- SyncFence *pFence;
- int rc;
-
- REQUEST_SIZE_MATCH(xSyncCreateFenceReq);
-
- rc = dixLookupDrawable(&pDraw, stuff->d, client, M_ANY, DixGetAttrAccess);
- if (rc != Success)
- return rc;
-
- LEGAL_NEW_RESOURCE(stuff->fid, client);
-
- if (!(pFence = (SyncFence *)SyncCreate(client,
- stuff->fid,
- SYNC_FENCE)))
- return BadAlloc;
-
- miSyncInitFence(pDraw->pScreen, pFence, stuff->initially_triggered);
-
- return client->noClientException;
-}
-
-static int
-FreeFence(void *obj, XID id)
-{
- SyncFence *pFence = (SyncFence *) obj;
-
- miSyncDestroyFence(pFence);
-
- return Success;
-}
-
-int SyncVerifyFence(SyncFence **ppSyncFence, XID fid,
- ClientPtr client, Mask mode)
-{
- int rc = dixLookupResourceByType((pointer *)ppSyncFence, fid, RTFence,
- client, mode);
-
- if (rc != Success)
- client->errorValue = fid;
-
- return rc;
-}
-
-static int
-ProcSyncTriggerFence(ClientPtr client)
-{
- REQUEST(xSyncTriggerFenceReq);
- SyncFence *pFence;
- int rc;
-
- REQUEST_SIZE_MATCH(xSyncTriggerFenceReq);
-
- rc = dixLookupResourceByType((pointer *)&pFence, stuff->fid, RTFence,
- client, DixWriteAccess);
- if (rc != Success)
- return rc;
-
- miSyncTriggerFence(pFence);
-
- return client->noClientException;
-}
-
-static int
-ProcSyncResetFence(ClientPtr client)
-{
- REQUEST(xSyncResetFenceReq);
- SyncFence *pFence;
- int rc;
-
- REQUEST_SIZE_MATCH(xSyncResetFenceReq);
-
- rc = dixLookupResourceByType((pointer *)&pFence, stuff->fid, RTFence,
- client, DixWriteAccess);
- if (rc != Success)
- return rc;
-
- if (pFence->funcs.CheckTriggered(pFence) != TRUE)
- return BadMatch;
-
- pFence->funcs.Reset(pFence);
-
- return client->noClientException;
-}
-
-static int
-ProcSyncDestroyFence(ClientPtr client)
-{
- REQUEST(xSyncDestroyFenceReq);
- SyncFence *pFence;
- int rc;
-
- REQUEST_SIZE_MATCH(xSyncDestroyFenceReq);
-
- rc = dixLookupResourceByType((pointer *)&pFence, stuff->fid, RTFence,
- client, DixDestroyAccess);
- if (rc != Success)
- return rc;
-
- FreeResource(stuff->fid, RT_NONE);
- return client->noClientException;
-}
-
-static int
-ProcSyncQueryFence(ClientPtr client)
-{
- REQUEST(xSyncQueryFenceReq);
- xSyncQueryFenceReply rep;
- SyncFence *pFence;
- int rc;
-
- REQUEST_SIZE_MATCH(xSyncQueryFenceReq);
-
- rc = dixLookupResourceByType((pointer *)&pFence, stuff->fid,
- RTFence, client, DixReadAccess);
- if (rc != Success)
- return rc;
-
- rep.type = X_Reply;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
-
- rep.triggered = pFence->funcs.CheckTriggered(pFence);
-
- if (client->swapped)
- {
- char n;
- swaps(&rep.sequenceNumber, n);
- swapl(&rep.length, n);
- }
-
- WriteToClient(client, sizeof(xSyncQueryFenceReply), (char *) &rep);
- return client->noClientException;
-}
-
-static int
-ProcSyncAwaitFence(ClientPtr client)
-{
- REQUEST(xSyncAwaitFenceReq);
- SyncAwaitUnion *pAwaitUnion;
- SyncAwait *pAwait;
- /* Use CARD32 rather than XSyncFence because XIDs are hard-coded to
- * CARD32 in protocol definitions */
- CARD32 *pProtocolFences;
- int status;
- int len;
- int items;
- int i;
-
- REQUEST_AT_LEAST_SIZE(xSyncAwaitFenceReq);
-
- len = client->req_len << 2;
- len -= sz_xSyncAwaitFenceReq;
- items = len / sizeof(CARD32);
-
- if (items * sizeof(CARD32) != len)
- {
- return BadLength;
- }
- if (items == 0)
- {
- client->errorValue = items; /* XXX protocol change */
- return BadValue;
- }
-
- if (!(pAwaitUnion = SyncAwaitPrologue(client, items)))
- return BadAlloc;
-
- /* don't need to do any more memory allocation for this request! */
-
- pProtocolFences = (CARD32 *) & stuff[1];
-
- pAwait = &(pAwaitUnion+1)->await; /* skip over header */
- for (i = 0; i < items; i++, pProtocolFences++, pAwait++)
- {
- if (*pProtocolFences == None) /* XXX protocol change */
- {
- /* this should take care of removing any triggers created by
- * this request that have already been registered on sync objects
- */
- FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
- client->errorValue = *pProtocolFences;
- return SyncErrorBase + XSyncBadCounter;
- }
-
- pAwait->trigger.pSync = NULL;
- /* Provide acceptable values for these unused fields to
- * satisfy SyncInitTrigger's validation logic
- */
- pAwait->trigger.value_type = XSyncAbsolute;
- XSyncIntToValue(&pAwait->trigger.wait_value, 0);
- pAwait->trigger.test_type = 0;
-
- status = SyncInitTrigger(client, &pAwait->trigger,
- *pProtocolFences, RTFence,
- XSyncCAAllTrigger);
- if (status != Success)
- {
- /* this should take care of removing any triggers created by
- * this request that have already been registered on sync objects
- */
- FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
- return status;
- }
- /* this is not a mistake -- same function works for both cases */
- pAwait->trigger.TriggerFired = SyncAwaitTriggerFired;
- pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired;
- /* event_threshold is unused for fence syncs */
- XSyncIntToValue(&pAwait->event_threshold, 0);
- pAwait->pHeader = &pAwaitUnion->header;
- pAwaitUnion->header.num_waitconditions++;
- }
-
- SyncAwaitEpilogue(client, items, pAwaitUnion);
-
- return client->noClientException;
-}
-
-/*
- * ** Given an extension request, call the appropriate request procedure
- */
-static int
-ProcSyncDispatch(ClientPtr client)
-{
- REQUEST(xReq);
-
- switch (stuff->data)
- {
- case X_SyncInitialize:
- return ProcSyncInitialize(client);
- case X_SyncListSystemCounters:
- return ProcSyncListSystemCounters(client);
- case X_SyncCreateCounter:
- return ProcSyncCreateCounter(client);
- case X_SyncSetCounter:
- return ProcSyncSetCounter(client);
- case X_SyncChangeCounter:
- return ProcSyncChangeCounter(client);
- case X_SyncQueryCounter:
- return ProcSyncQueryCounter(client);
- case X_SyncDestroyCounter:
- return ProcSyncDestroyCounter(client);
- case X_SyncAwait:
- return ProcSyncAwait(client);
- case X_SyncCreateAlarm:
- return ProcSyncCreateAlarm(client);
- case X_SyncChangeAlarm:
- return ProcSyncChangeAlarm(client);
- case X_SyncQueryAlarm:
- return ProcSyncQueryAlarm(client);
- case X_SyncDestroyAlarm:
- return ProcSyncDestroyAlarm(client);
- case X_SyncSetPriority:
- return ProcSyncSetPriority(client);
- case X_SyncGetPriority:
- return ProcSyncGetPriority(client);
- case X_SyncCreateFence:
- return ProcSyncCreateFence(client);
- case X_SyncTriggerFence:
- return ProcSyncTriggerFence(client);
- case X_SyncResetFence:
- return ProcSyncResetFence(client);
- case X_SyncDestroyFence:
- return ProcSyncDestroyFence(client);
- case X_SyncQueryFence:
- return ProcSyncQueryFence(client);
- case X_SyncAwaitFence:
- return ProcSyncAwaitFence(client);
- default:
- return BadRequest;
- }
-}
-
-/*
- * Boring Swapping stuff ...
- */
-
-static int
-SProcSyncInitialize(ClientPtr client)
-{
- REQUEST(xSyncInitializeReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncInitializeReq);
-
- return ProcSyncInitialize(client);
-}
-
-static int
-SProcSyncListSystemCounters(ClientPtr client)
-{
- REQUEST(xSyncListSystemCountersReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncListSystemCountersReq);
-
- return ProcSyncListSystemCounters(client);
-}
-
-static int
-SProcSyncCreateCounter(ClientPtr client)
-{
- REQUEST(xSyncCreateCounterReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncCreateCounterReq);
- swapl(&stuff->cid, n);
- swapl(&stuff->initial_value_lo, n);
- swapl(&stuff->initial_value_hi, n);
-
- return ProcSyncCreateCounter(client);
-}
-
-static int
-SProcSyncSetCounter(ClientPtr client)
-{
- REQUEST(xSyncSetCounterReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncSetCounterReq);
- swapl(&stuff->cid, n);
- swapl(&stuff->value_lo, n);
- swapl(&stuff->value_hi, n);
-
- return ProcSyncSetCounter(client);
-}
-
-static int
-SProcSyncChangeCounter(ClientPtr client)
-{
- REQUEST(xSyncChangeCounterReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncChangeCounterReq);
- swapl(&stuff->cid, n);
- swapl(&stuff->value_lo, n);
- swapl(&stuff->value_hi, n);
-
- return ProcSyncChangeCounter(client);
-}
-
-static int
-SProcSyncQueryCounter(ClientPtr client)
-{
- REQUEST(xSyncQueryCounterReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncQueryCounterReq);
- swapl(&stuff->counter, n);
-
- return ProcSyncQueryCounter(client);
-}
-
-static int
-SProcSyncDestroyCounter(ClientPtr client)
-{
- REQUEST(xSyncDestroyCounterReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncDestroyCounterReq);
- swapl(&stuff->counter, n);
-
- return ProcSyncDestroyCounter(client);
-}
-
-static int
-SProcSyncAwait(ClientPtr client)
-{
- REQUEST(xSyncAwaitReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xSyncAwaitReq);
- SwapRestL(stuff);
-
- return ProcSyncAwait(client);
-}
-
-static int
-SProcSyncCreateAlarm(ClientPtr client)
-{
- REQUEST(xSyncCreateAlarmReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq);
- swapl(&stuff->id, n);
- swapl(&stuff->valueMask, n);
- SwapRestL(stuff);
-
- return ProcSyncCreateAlarm(client);
-}
-
-static int
-SProcSyncChangeAlarm(ClientPtr client)
-{
- REQUEST(xSyncChangeAlarmReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq);
- swapl(&stuff->alarm, n);
- swapl(&stuff->valueMask, n);
- SwapRestL(stuff);
- return ProcSyncChangeAlarm(client);
-}
-
-static int
-SProcSyncQueryAlarm(ClientPtr client)
-{
- REQUEST(xSyncQueryAlarmReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncQueryAlarmReq);
- swapl(&stuff->alarm, n);
-
- return ProcSyncQueryAlarm(client);
-}
-
-static int
-SProcSyncDestroyAlarm(ClientPtr client)
-{
- REQUEST(xSyncDestroyAlarmReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncDestroyAlarmReq);
- swapl(&stuff->alarm, n);
-
- return ProcSyncDestroyAlarm(client);
-}
-
-static int
-SProcSyncSetPriority(ClientPtr client)
-{
- REQUEST(xSyncSetPriorityReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncSetPriorityReq);
- swapl(&stuff->id, n);
- swapl(&stuff->priority, n);
-
- return ProcSyncSetPriority(client);
-}
-
-static int
-SProcSyncGetPriority(ClientPtr client)
-{
- REQUEST(xSyncGetPriorityReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncGetPriorityReq);
- swapl(&stuff->id, n);
-
- return ProcSyncGetPriority(client);
-}
-
-static int
-SProcSyncCreateFence(ClientPtr client)
-{
- REQUEST(xSyncCreateFenceReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncCreateFenceReq);
- swapl(&stuff->fid, n);
-
- return ProcSyncCreateFence(client);
-}
-
-static int
-SProcSyncTriggerFence(ClientPtr client)
-{
- REQUEST(xSyncTriggerFenceReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncTriggerFenceReq);
- swapl(&stuff->fid, n);
-
- return ProcSyncTriggerFence(client);
-}
-
-static int
-SProcSyncResetFence(ClientPtr client)
-{
- REQUEST(xSyncResetFenceReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncResetFenceReq);
- swapl(&stuff->fid, n);
-
- return ProcSyncResetFence(client);
-}
-
-static int
-SProcSyncDestroyFence(ClientPtr client)
-{
- REQUEST(xSyncDestroyFenceReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncDestroyFenceReq);
- swapl(&stuff->fid, n);
-
- return ProcSyncDestroyFence(client);
-}
-
-static int
-SProcSyncQueryFence(ClientPtr client)
-{
- REQUEST(xSyncQueryFenceReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xSyncQueryFenceReq);
- swapl(&stuff->fid, n);
-
- return ProcSyncQueryFence(client);
-}
-
-static int
-SProcSyncAwaitFence(ClientPtr client)
-{
- REQUEST(xSyncAwaitFenceReq);
- char n;
-
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xSyncAwaitFenceReq);
- SwapRestL(stuff);
-
- return ProcSyncAwaitFence(client);
-}
-
-static int
-SProcSyncDispatch(ClientPtr client)
-{
- REQUEST(xReq);
-
- switch (stuff->data)
- {
- case X_SyncInitialize:
- return SProcSyncInitialize(client);
- case X_SyncListSystemCounters:
- return SProcSyncListSystemCounters(client);
- case X_SyncCreateCounter:
- return SProcSyncCreateCounter(client);
- case X_SyncSetCounter:
- return SProcSyncSetCounter(client);
- case X_SyncChangeCounter:
- return SProcSyncChangeCounter(client);
- case X_SyncQueryCounter:
- return SProcSyncQueryCounter(client);
- case X_SyncDestroyCounter:
- return SProcSyncDestroyCounter(client);
- case X_SyncAwait:
- return SProcSyncAwait(client);
- case X_SyncCreateAlarm:
- return SProcSyncCreateAlarm(client);
- case X_SyncChangeAlarm:
- return SProcSyncChangeAlarm(client);
- case X_SyncQueryAlarm:
- return SProcSyncQueryAlarm(client);
- case X_SyncDestroyAlarm:
- return SProcSyncDestroyAlarm(client);
- case X_SyncSetPriority:
- return SProcSyncSetPriority(client);
- case X_SyncGetPriority:
- return SProcSyncGetPriority(client);
- case X_SyncCreateFence:
- return SProcSyncCreateFence(client);
- case X_SyncTriggerFence:
- return SProcSyncTriggerFence(client);
- case X_SyncResetFence:
- return SProcSyncResetFence(client);
- case X_SyncDestroyFence:
- return SProcSyncDestroyFence(client);
- case X_SyncQueryFence:
- return SProcSyncQueryFence(client);
- case X_SyncAwaitFence:
- return SProcSyncAwaitFence(client);
- default:
- return BadRequest;
- }
-}
-
-/*
- * Event Swapping
- */
-
-static void
-SCounterNotifyEvent(xSyncCounterNotifyEvent *from, xSyncCounterNotifyEvent *to)
-{
- to->type = from->type;
- to->kind = from->kind;
- cpswaps(from->sequenceNumber, to->sequenceNumber);
- cpswapl(from->counter, to->counter);
- cpswapl(from->wait_value_lo, to->wait_value_lo);
- cpswapl(from->wait_value_hi, to->wait_value_hi);
- cpswapl(from->counter_value_lo, to->counter_value_lo);
- cpswapl(from->counter_value_hi, to->counter_value_hi);
- cpswapl(from->time, to->time);
- cpswaps(from->count, to->count);
- to->destroyed = from->destroyed;
-}
-
-
-static void
-SAlarmNotifyEvent(xSyncAlarmNotifyEvent *from, xSyncAlarmNotifyEvent *to)
-{
- to->type = from->type;
- to->kind = from->kind;
- cpswaps(from->sequenceNumber, to->sequenceNumber);
- cpswapl(from->alarm, to->alarm);
- cpswapl(from->counter_value_lo, to->counter_value_lo);
- cpswapl(from->counter_value_hi, to->counter_value_hi);
- cpswapl(from->alarm_value_lo, to->alarm_value_lo);
- cpswapl(from->alarm_value_hi, to->alarm_value_hi);
- cpswapl(from->time, to->time);
- to->state = from->state;
-}
-
-/*
- * ** Close everything down. ** This is fairly simple for now.
- */
-/* ARGSUSED */
-static void
-SyncResetProc(ExtensionEntry *extEntry)
-{
- free(SysCounterList);
- SysCounterList = NULL;
- RTCounter = 0;
-}
-
-/*
- * ** Initialise the extension.
- */
-void
-SyncExtensionInit(void)
-{
- ExtensionEntry *extEntry;
- int s;
-
- for (s = 0; s < screenInfo.numScreens; s++)
- miSyncSetup(screenInfo.screens[s]);
-
- if (RTCounter == 0)
- {
- RTCounter = CreateNewResourceType(FreeCounter, "SyncCounter");
- }
- RTAlarm = CreateNewResourceType(FreeAlarm, "SyncAlarm");
- RTAwait = CreateNewResourceType(FreeAwait, "SyncAwait");
- RTFence = CreateNewResourceType(FreeFence, "SyncFence");
- if (RTAwait)
- RTAwait |= RC_NEVERRETAIN;
- RTAlarmClient = CreateNewResourceType(FreeAlarmClient, "SyncAlarmClient");
- if (RTAlarmClient)
- RTAlarmClient |= RC_NEVERRETAIN;
-
- if (RTCounter == 0 || RTAwait == 0 || RTAlarm == 0 ||
- RTAlarmClient == 0 ||
- (extEntry = AddExtension(SYNC_NAME,
- XSyncNumberEvents, XSyncNumberErrors,
- ProcSyncDispatch, SProcSyncDispatch,
- SyncResetProc,
- StandardMinorOpcode)) == NULL)
- {
- ErrorF("Sync Extension %d.%d failed to Initialise\n",
- SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION);
- return;
- }
-
- SyncEventBase = extEntry->eventBase;
- SyncErrorBase = extEntry->errorBase;
- EventSwapVector[SyncEventBase + XSyncCounterNotify] = (EventSwapPtr) SCounterNotifyEvent;
- EventSwapVector[SyncEventBase + XSyncAlarmNotify] = (EventSwapPtr) SAlarmNotifyEvent;
-
- SetResourceTypeErrorValue(RTCounter, SyncErrorBase + XSyncBadCounter);
- SetResourceTypeErrorValue(RTAlarm, SyncErrorBase + XSyncBadAlarm);
- SetResourceTypeErrorValue(RTFence, SyncErrorBase + XSyncBadFence);
-
- /*
- * Although SERVERTIME is implemented by the OS layer, we initialise it
- * here because doing it in OsInit() is too early. The resource database
- * is not initialised when OsInit() is called. This is just about OK
- * because there is always a servertime counter.
- */
- SyncInitServerTime();
- SyncInitIdleTime();
-
-#ifdef DEBUG
- fprintf(stderr, "Sync Extension %d.%d\n",
- SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION);
-#endif
-}
-
-
-/*
- * ***** SERVERTIME implementation - should go in its own file in OS directory?
- */
-
-
-
-static pointer ServertimeCounter;
-static XSyncValue Now;
-static XSyncValue *pnext_time;
-
-#define GetTime()\
-{\
- unsigned long millis = GetTimeInMillis();\
- unsigned long maxis = XSyncValueHigh32(Now);\
- if (millis < XSyncValueLow32(Now)) maxis++;\
- XSyncIntsToValue(&Now, millis, maxis);\
-}
-
-/*
-*** Server Block Handler
-*** code inspired by multibuffer extension (now deprecated)
- */
-/*ARGSUSED*/
-static void
-ServertimeBlockHandler(void *env, struct timeval **wt, void *LastSelectMask)
-{
- XSyncValue delay;
- unsigned long timeout;
-
- if (pnext_time)
- {
- GetTime();
-
- if (XSyncValueGreaterOrEqual(Now, *pnext_time))
- {
- timeout = 0;
- }
- else
- {
- Bool overflow;
- XSyncValueSubtract(&delay, *pnext_time, Now, &overflow);
- (void)overflow;
- timeout = XSyncValueLow32(delay);
- }
- AdjustWaitForDelay(wt, timeout); /* os/utils.c */
- }
-}
-
-/*
-*** Wakeup Handler
- */
-/*ARGSUSED*/
-static void
-ServertimeWakeupHandler(void *env, int rc, void *LastSelectMask)
-{
- if (pnext_time)
- {
- GetTime();
-
- if (XSyncValueGreaterOrEqual(Now, *pnext_time))
- {
- SyncChangeCounter(ServertimeCounter, Now);
- }
- }
-}
-
-static void
-ServertimeQueryValue(void *pCounter, CARD64 *pValue_return)
-{
- GetTime();
- *pValue_return = Now;
-}
-
-static void
-ServertimeBracketValues(void *pCounter, CARD64 *pbracket_less,
- CARD64 *pbracket_greater)
-{
- if (!pnext_time && pbracket_greater)
- {
- RegisterBlockAndWakeupHandlers(ServertimeBlockHandler,
- ServertimeWakeupHandler,
- NULL);
- }
- else if (pnext_time && !pbracket_greater)
- {
- RemoveBlockAndWakeupHandlers(ServertimeBlockHandler,
- ServertimeWakeupHandler,
- NULL);
- }
- pnext_time = pbracket_greater;
-}
-
-static void
-SyncInitServerTime(void)
-{
- CARD64 resolution;
-
- XSyncIntsToValue(&Now, GetTimeInMillis(), 0);
- XSyncIntToValue(&resolution, 4);
- ServertimeCounter = SyncCreateSystemCounter("SERVERTIME", Now, resolution,
- XSyncCounterNeverDecreases,
- ServertimeQueryValue, ServertimeBracketValues);
- pnext_time = NULL;
-}
-
-
-
-/*
- * IDLETIME implementation
- */
-
-static SyncCounter *IdleTimeCounter;
-static XSyncValue *pIdleTimeValueLess;
-static XSyncValue *pIdleTimeValueGreater;
-
-static void
-IdleTimeQueryValue (pointer pCounter, CARD64 *pValue_return)
-{
- CARD32 idle = GetTimeInMillis() - lastDeviceEventTime.milliseconds;
- XSyncIntsToValue (pValue_return, idle, 0);
-}
-
-static void
-IdleTimeBlockHandler(pointer env, struct timeval **wt, pointer LastSelectMask)
-{
- XSyncValue idle, old_idle;
- SyncTriggerList *list = IdleTimeCounter->sync.pTriglist;
- SyncTrigger *trig;
-
- if (!pIdleTimeValueLess && !pIdleTimeValueGreater)
- return;
-
- old_idle = IdleTimeCounter->value;
- IdleTimeQueryValue (NULL, &idle);
- IdleTimeCounter->value = idle; /* push, so CheckTrigger works */
-
- if (pIdleTimeValueLess &&
- XSyncValueLessOrEqual (idle, *pIdleTimeValueLess))
- {
- /*
- * We've been idle for less than the threshold value, and someone
- * wants to know about that, but now we need to know whether they
- * want level or edge trigger. Check the trigger list against the
- * current idle time, and if any succeed, bomb out of select()
- * immediately so we can reschedule.
- */
-
- for (list = IdleTimeCounter->sync.pTriglist; list; list = list->next) {
- trig = list->pTrigger;
- if (trig->CheckTrigger(trig, old_idle)) {
- AdjustWaitForDelay(wt, 0);
- break;
- }
- }
- /*
- * We've been called exactly on the idle time, but we have a
- * NegativeTransition trigger which requires a transition from an
- * idle time greater than this. Schedule a wakeup for the next
- * millisecond so we won't miss a transition.
- */
- if (XSyncValueEqual (idle, *pIdleTimeValueLess))
- AdjustWaitForDelay(wt, 1);
- }
- else if (pIdleTimeValueGreater)
- {
- /*
- * There's a threshold in the positive direction. If we've been
- * idle less than it, schedule a wakeup for sometime in the future.
- * If we've been idle more than it, and someone wants to know about
- * that level-triggered, schedule an immediate wakeup.
- */
- unsigned long timeout = -1;
-
- if (XSyncValueLessThan (idle, *pIdleTimeValueGreater)) {
- XSyncValue value;
- Bool overflow;
-
- XSyncValueSubtract (&value, *pIdleTimeValueGreater,
- idle, &overflow);
- timeout = min(timeout, XSyncValueLow32 (value));
- } else {
- for (list = IdleTimeCounter->sync.pTriglist; list; list = list->next) {
- trig = list->pTrigger;
- if (trig->CheckTrigger(trig, old_idle)) {
- timeout = min(timeout, 0);
- break;
- }
- }
- }
-
- AdjustWaitForDelay (wt, timeout);
- }
-
- IdleTimeCounter->value = old_idle; /* pop */
-}
-
-static void
-IdleTimeWakeupHandler (pointer env, int rc, pointer LastSelectMask)
-{
- XSyncValue idle;
-
- if (!pIdleTimeValueLess && !pIdleTimeValueGreater)
- return;
-
- IdleTimeQueryValue (NULL, &idle);
-
- if ((pIdleTimeValueGreater &&
- XSyncValueGreaterOrEqual (idle, *pIdleTimeValueGreater)) ||
- (pIdleTimeValueLess &&
- XSyncValueLessOrEqual (idle, *pIdleTimeValueLess)))
- {
- SyncChangeCounter (IdleTimeCounter, idle);
- }
-}
-
-static void
-IdleTimeBracketValues (pointer pCounter, CARD64 *pbracket_less,
- CARD64 *pbracket_greater)
-{
- Bool registered = (pIdleTimeValueLess || pIdleTimeValueGreater);
-
- if (registered && !pbracket_less && !pbracket_greater)
- {
- RemoveBlockAndWakeupHandlers(IdleTimeBlockHandler,
- IdleTimeWakeupHandler,
- NULL);
- }
- else if (!registered && (pbracket_less || pbracket_greater))
- {
- RegisterBlockAndWakeupHandlers(IdleTimeBlockHandler,
- IdleTimeWakeupHandler,
- NULL);
- }
-
- pIdleTimeValueGreater = pbracket_greater;
- pIdleTimeValueLess = pbracket_less;
-}
-
-static void
-SyncInitIdleTime (void)
-{
- CARD64 resolution;
- XSyncValue idle;
-
- IdleTimeQueryValue (NULL, &idle);
- XSyncIntToValue (&resolution, 4);
-
- IdleTimeCounter = SyncCreateSystemCounter ("IDLETIME", idle, resolution,
- XSyncCounterUnrestricted,
- IdleTimeQueryValue,
- IdleTimeBracketValues);
-
- pIdleTimeValueLess = pIdleTimeValueGreater = NULL;
-}
+/*
+
+Copyright 1991, 1993, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+
+Copyright 1991, 1993 by Digital Equipment Corporation, Maynard, Massachusetts,
+and Olivetti Research Limited, Cambridge, England.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the names of Digital or Olivetti
+not be used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission. Digital and Olivetti
+make no representations about the suitability of this software
+for any purpose. It is provided "as is" without express or implied warranty.
+
+DIGITAL AND OLIVETTI DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL THEY BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+*/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <string.h>
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include <X11/Xmd.h>
+#include "scrnintstr.h"
+#include "os.h"
+#include "extnsionst.h"
+#include "dixstruct.h"
+#include "pixmapstr.h"
+#include "resource.h"
+#include "opaque.h"
+#include <X11/extensions/syncproto.h>
+#include "syncsrv.h"
+#include "syncsdk.h"
+#include "protocol-versions.h"
+
+#include <stdio.h>
+#if !defined(WIN32)
+#include <sys/time.h>
+#endif
+
+#include "modinit.h"
+
+/*
+ * Local Global Variables
+ */
+static int SyncEventBase;
+static int SyncErrorBase;
+static RESTYPE RTCounter = 0;
+static RESTYPE RTAwait;
+static RESTYPE RTAlarm;
+static RESTYPE RTAlarmClient;
+static RESTYPE RTFence;
+static int SyncNumSystemCounters = 0;
+static SyncCounter **SysCounterList = NULL;
+static int SyncNumInvalidCounterWarnings = 0;
+#define MAX_INVALID_COUNTER_WARNINGS 5
+
+static const char *WARN_INVALID_COUNTER_COMPARE =
+"Warning: Non-counter XSync object using Counter-only\n"
+" comparison. Result will never be true.\n";
+
+static const char *WARN_INVALID_COUNTER_ALARM =
+"Warning: Non-counter XSync object used in alarm. This is\n"
+" the result of a programming error in the X server.\n";
+
+#define IsSystemCounter(pCounter) \
+ (pCounter && (pCounter->sync.client == NULL))
+
+/* these are all the alarm attributes that pertain to the alarm's trigger */
+#define XSyncCAAllTrigger \
+ (XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType)
+
+static void SyncComputeBracketValues(SyncCounter *);
+
+static void SyncInitServerTime(void);
+
+static void SyncInitIdleTime(void);
+
+static Bool
+SyncCheckWarnIsCounter(const SyncObject* pSync, const char *warning)
+{
+ if (pSync && (SYNC_COUNTER != pSync->type))
+ {
+ if (SyncNumInvalidCounterWarnings++ < MAX_INVALID_COUNTER_WARNINGS)
+ {
+ ErrorF("%s", warning);
+ ErrorF(" Counter type: %d\n", pSync->type);
+ }
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* Each counter maintains a simple linked list of triggers that are
+ * interested in the counter. The two functions below are used to
+ * delete and add triggers on this list.
+ */
+static void
+SyncDeleteTriggerFromSyncObject(SyncTrigger *pTrigger)
+{
+ SyncTriggerList *pCur;
+ SyncTriggerList *pPrev;
+ SyncCounter *pCounter;
+
+ /* pSync needs to be stored in pTrigger before calling here. */
+
+ if (!pTrigger->pSync)
+ return;
+
+ pPrev = NULL;
+ pCur = pTrigger->pSync->pTriglist;
+
+ while (pCur)
+ {
+ if (pCur->pTrigger == pTrigger)
+ {
+ if (pPrev)
+ pPrev->next = pCur->next;
+ else
+ pTrigger->pSync->pTriglist = pCur->next;
+
+ free(pCur);
+ break;
+ }
+
+ pPrev = pCur;
+ pCur = pCur->next;
+ }
+
+ if (SYNC_COUNTER == pTrigger->pSync->type)
+ {
+ pCounter = (SyncCounter *)pTrigger->pSync;
+
+ if (IsSystemCounter(pCounter))
+ SyncComputeBracketValues(pCounter);
+ } else if (SYNC_FENCE == pTrigger->pSync->type) {
+ SyncFence* pFence = (SyncFence*) pTrigger->pSync;
+ pFence->funcs.DeleteTrigger(pTrigger);
+ }
+}
+
+
+static int
+SyncAddTriggerToSyncObject(SyncTrigger *pTrigger)
+{
+ SyncTriggerList *pCur;
+ SyncCounter *pCounter;
+
+ if (!pTrigger->pSync)
+ return Success;
+
+ /* don't do anything if it's already there */
+ for (pCur = pTrigger->pSync->pTriglist; pCur; pCur = pCur->next)
+ {
+ if (pCur->pTrigger == pTrigger)
+ return Success;
+ }
+
+ if (!(pCur = malloc(sizeof(SyncTriggerList))))
+ return BadAlloc;
+
+ pCur->pTrigger = pTrigger;
+ pCur->next = pTrigger->pSync->pTriglist;
+ pTrigger->pSync->pTriglist = pCur;
+
+ if (SYNC_COUNTER == pTrigger->pSync->type)
+ {
+ pCounter = (SyncCounter *)pTrigger->pSync;
+
+ if (IsSystemCounter(pCounter))
+ SyncComputeBracketValues(pCounter);
+ } else if (SYNC_FENCE == pTrigger->pSync->type) {
+ SyncFence* pFence = (SyncFence*) pTrigger->pSync;
+ pFence->funcs.AddTrigger(pTrigger);
+ }
+
+ return Success;
+}
+
+
+/* Below are five possible functions that can be plugged into
+ * pTrigger->CheckTrigger for counter sync objects, corresponding to
+ * the four possible test-types, and the one possible function that
+ * can be plugged into pTrigger->CheckTrigger for fence sync objects.
+ * These functions are called after the sync object's state changes
+ * but are also passed the old state so they can inspect both the old
+ * and new values. (PositiveTransition and NegativeTransition need to
+ * see both pieces of information.) These functions return the truth
+ * value of the trigger.
+ *
+ * All of them include the condition pTrigger->pSync == NULL.
+ * This is because the spec says that a trigger with a sync value
+ * of None is always TRUE.
+ */
+
+static Bool
+SyncCheckTriggerPositiveComparison(SyncTrigger *pTrigger, CARD64 oldval)
+{
+ SyncCounter *pCounter;
+
+ /* Non-counter sync objects should never get here because they
+ * never trigger this comparison. */
+ if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_COMPARE))
+ return FALSE;
+
+ pCounter = (SyncCounter *)pTrigger->pSync;
+
+ return (pCounter == NULL ||
+ XSyncValueGreaterOrEqual(pCounter->value, pTrigger->test_value));
+}
+
+static Bool
+SyncCheckTriggerNegativeComparison(SyncTrigger *pTrigger, CARD64 oldval)
+{
+ SyncCounter *pCounter;
+
+ /* Non-counter sync objects should never get here because they
+ * never trigger this comparison. */
+ if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_COMPARE))
+ return FALSE;
+
+ pCounter = (SyncCounter *)pTrigger->pSync;
+
+ return (pCounter == NULL ||
+ XSyncValueLessOrEqual(pCounter->value, pTrigger->test_value));
+}
+
+static Bool
+SyncCheckTriggerPositiveTransition(SyncTrigger *pTrigger, CARD64 oldval)
+{
+ SyncCounter *pCounter;
+
+ /* Non-counter sync objects should never get here because they
+ * never trigger this comparison. */
+ if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_COMPARE))
+ return FALSE;
+
+ pCounter = (SyncCounter *)pTrigger->pSync;
+
+ return (pCounter == NULL ||
+ (XSyncValueLessThan(oldval, pTrigger->test_value) &&
+ XSyncValueGreaterOrEqual(pCounter->value, pTrigger->test_value)));
+}
+
+static Bool
+SyncCheckTriggerNegativeTransition(SyncTrigger *pTrigger, CARD64 oldval)
+{
+ SyncCounter *pCounter;
+
+ /* Non-counter sync objects should never get here because they
+ * never trigger this comparison. */
+ if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_COMPARE))
+ return FALSE;
+
+ pCounter = (SyncCounter *)pTrigger->pSync;
+
+ return (pCounter == NULL ||
+ (XSyncValueGreaterThan(oldval, pTrigger->test_value) &&
+ XSyncValueLessOrEqual(pCounter->value, pTrigger->test_value)));
+}
+
+static Bool
+SyncCheckTriggerFence(SyncTrigger *pTrigger, CARD64 unused)
+{
+ SyncFence* pFence = (SyncFence*) pTrigger->pSync;
+ (void)unused;
+
+ return (pFence == NULL ||
+ pFence->funcs.CheckTriggered(pFence));
+}
+
+static int
+SyncInitTrigger(ClientPtr client, SyncTrigger *pTrigger, XID syncObject,
+ RESTYPE resType, Mask changes)
+{
+ SyncObject *pSync = pTrigger->pSync;
+ SyncCounter *pCounter = NULL;
+ int rc;
+ Bool newSyncObject = FALSE;
+
+ if (changes & XSyncCACounter)
+ {
+ if (syncObject == None)
+ pSync = NULL;
+ else if (Success != (rc = dixLookupResourceByType ((pointer *)&pSync,
+ syncObject, resType, client, DixReadAccess)))
+ {
+ client->errorValue = syncObject;
+ return rc;
+ }
+ if (pSync != pTrigger->pSync)
+ { /* new counter for trigger */
+ SyncDeleteTriggerFromSyncObject(pTrigger);
+ pTrigger->pSync = pSync;
+ newSyncObject = TRUE;
+ }
+ }
+
+ /* if system counter, ask it what the current value is */
+
+ if (pSync && SYNC_COUNTER == pSync->type)
+ {
+ pCounter = (SyncCounter *)pSync;
+
+ if (IsSystemCounter(pCounter))
+ {
+ (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter,
+ &pCounter->value);
+ }
+ }
+
+ if (changes & XSyncCAValueType)
+ {
+ if (pTrigger->value_type != XSyncRelative &&
+ pTrigger->value_type != XSyncAbsolute)
+ {
+ client->errorValue = pTrigger->value_type;
+ return BadValue;
+ }
+ }
+
+ if (changes & XSyncCATestType)
+ {
+
+ if (pSync && SYNC_FENCE == pSync->type)
+ {
+ pTrigger->CheckTrigger = SyncCheckTriggerFence;
+ }
+ else
+ {
+ /* select appropriate CheckTrigger function */
+
+ switch (pTrigger->test_type)
+ {
+ case XSyncPositiveTransition:
+ pTrigger->CheckTrigger = SyncCheckTriggerPositiveTransition;
+ break;
+ case XSyncNegativeTransition:
+ pTrigger->CheckTrigger = SyncCheckTriggerNegativeTransition;
+ break;
+ case XSyncPositiveComparison:
+ pTrigger->CheckTrigger = SyncCheckTriggerPositiveComparison;
+ break;
+ case XSyncNegativeComparison:
+ pTrigger->CheckTrigger = SyncCheckTriggerNegativeComparison;
+ break;
+ default:
+ client->errorValue = pTrigger->test_type;
+ return BadValue;
+ }
+ }
+ }
+
+ if (changes & (XSyncCAValueType | XSyncCAValue))
+ {
+ if (pTrigger->value_type == XSyncAbsolute)
+ pTrigger->test_value = pTrigger->wait_value;
+ else /* relative */
+ {
+ Bool overflow;
+ if (pCounter == NULL)
+ return BadMatch;
+
+ XSyncValueAdd(&pTrigger->test_value, pCounter->value,
+ pTrigger->wait_value, &overflow);
+ if (overflow)
+ {
+ client->errorValue = XSyncValueHigh32(pTrigger->wait_value);
+ return BadValue;
+ }
+ }
+ }
+
+ /* we wait until we're sure there are no errors before registering
+ * a new counter on a trigger
+ */
+ if (newSyncObject)
+ {
+ if ((rc = SyncAddTriggerToSyncObject(pTrigger)) != Success)
+ return rc;
+ }
+ else if (pCounter && IsSystemCounter(pCounter))
+ {
+ SyncComputeBracketValues(pCounter);
+ }
+
+ return Success;
+}
+
+/* AlarmNotify events happen in response to actions taken on an Alarm or
+ * the counter used by the alarm. AlarmNotify may be sent to multiple
+ * clients. The alarm maintains a list of clients interested in events.
+ */
+static void
+SyncSendAlarmNotifyEvents(SyncAlarm *pAlarm)
+{
+ SyncAlarmClientList *pcl;
+ xSyncAlarmNotifyEvent ane;
+ SyncTrigger *pTrigger = &pAlarm->trigger;
+ SyncCounter *pCounter;
+
+ if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_ALARM))
+ return;
+
+ pCounter = (SyncCounter *)pTrigger->pSync;
+
+ UpdateCurrentTime();
+
+ ane.type = SyncEventBase + XSyncAlarmNotify;
+ ane.kind = XSyncAlarmNotify;
+ ane.alarm = pAlarm->alarm_id;
+ if (pTrigger->pSync && SYNC_COUNTER == pTrigger->pSync->type)
+ {
+ ane.counter_value_hi = XSyncValueHigh32(pCounter->value);
+ ane.counter_value_lo = XSyncValueLow32(pCounter->value);
+ }
+ else
+ { /* XXX what else can we do if there's no counter? */
+ ane.counter_value_hi = ane.counter_value_lo = 0;
+ }
+
+ ane.alarm_value_hi = XSyncValueHigh32(pTrigger->test_value);
+ ane.alarm_value_lo = XSyncValueLow32(pTrigger->test_value);
+ ane.time = currentTime.milliseconds;
+ ane.state = pAlarm->state;
+
+ /* send to owner */
+ if (pAlarm->events)
+ WriteEventsToClient(pAlarm->client, 1, (xEvent *) &ane);
+
+ /* send to other interested clients */
+ for (pcl = pAlarm->pEventClients; pcl; pcl = pcl->next)
+ WriteEventsToClient(pcl->client, 1, (xEvent *) &ane);
+}
+
+
+/* CounterNotify events only occur in response to an Await. The events
+ * go only to the Awaiting client.
+ */
+static void
+SyncSendCounterNotifyEvents(ClientPtr client, SyncAwait **ppAwait,
+ int num_events)
+{
+ xSyncCounterNotifyEvent *pEvents, *pev;
+ int i;
+
+ if (client->clientGone)
+ return;
+ pev = pEvents = malloc(num_events * sizeof(xSyncCounterNotifyEvent));
+ if (!pEvents)
+ return;
+ UpdateCurrentTime();
+ for (i = 0; i < num_events; i++, ppAwait++, pev++)
+ {
+ SyncTrigger *pTrigger = &(*ppAwait)->trigger;
+ pev->type = SyncEventBase + XSyncCounterNotify;
+ pev->kind = XSyncCounterNotify;
+ pev->counter = pTrigger->pSync->id;
+ pev->wait_value_lo = XSyncValueLow32(pTrigger->test_value);
+ pev->wait_value_hi = XSyncValueHigh32(pTrigger->test_value);
+ if (SYNC_COUNTER == pTrigger->pSync->type)
+ {
+ SyncCounter *pCounter = (SyncCounter *)pTrigger->pSync;
+
+ pev->counter_value_lo = XSyncValueLow32(pCounter->value);
+ pev->counter_value_hi = XSyncValueHigh32(pCounter->value);
+ }
+ else
+ {
+ pev->counter_value_lo = 0;
+ pev->counter_value_hi = 0;
+ }
+
+ pev->time = currentTime.milliseconds;
+ pev->count = num_events - i - 1; /* events remaining */
+ pev->destroyed = pTrigger->pSync->beingDestroyed;
+ }
+ /* swapping will be taken care of by this */
+ WriteEventsToClient(client, num_events, (xEvent *)pEvents);
+ free(pEvents);
+}
+
+
+/* This function is called when an alarm's counter is destroyed.
+ * It is plugged into pTrigger->CounterDestroyed (for alarm triggers).
+ */
+static void
+SyncAlarmCounterDestroyed(SyncTrigger *pTrigger)
+{
+ SyncAlarm *pAlarm = (SyncAlarm *)pTrigger;
+
+ pAlarm->state = XSyncAlarmInactive;
+ SyncSendAlarmNotifyEvents(pAlarm);
+ pTrigger->pSync = NULL;
+}
+
+
+/* This function is called when an alarm "goes off."
+ * It is plugged into pTrigger->TriggerFired (for alarm triggers).
+ */
+static void
+SyncAlarmTriggerFired(SyncTrigger *pTrigger)
+{
+ SyncAlarm *pAlarm = (SyncAlarm *)pTrigger;
+ SyncCounter *pCounter;
+ CARD64 new_test_value;
+
+ if (!SyncCheckWarnIsCounter(pTrigger->pSync, WARN_INVALID_COUNTER_ALARM))
+ return;
+
+ pCounter = (SyncCounter *)pTrigger->pSync;
+
+ /* no need to check alarm unless it's active */
+ if (pAlarm->state != XSyncAlarmActive)
+ return;
+
+ /* " if the counter value is None, or if the delta is 0 and
+ * the test-type is PositiveComparison or NegativeComparison,
+ * no change is made to value (test-value) and the alarm
+ * state is changed to Inactive before the event is generated."
+ */
+ if (pCounter == NULL
+ || (XSyncValueIsZero(pAlarm->delta)
+ && (pAlarm->trigger.test_type == XSyncPositiveComparison
+ || pAlarm->trigger.test_type == XSyncNegativeComparison)))
+ pAlarm->state = XSyncAlarmInactive;
+
+ new_test_value = pAlarm->trigger.test_value;
+
+ if (pAlarm->state == XSyncAlarmActive)
+ {
+ Bool overflow;
+ CARD64 oldvalue;
+ SyncTrigger *paTrigger = &pAlarm->trigger;
+ SyncCounter *paCounter;
+
+ if (!SyncCheckWarnIsCounter(paTrigger->pSync,
+ WARN_INVALID_COUNTER_ALARM))
+ return;
+
+ paCounter = (SyncCounter *)pTrigger->pSync;
+
+ /* "The alarm is updated by repeatedly adding delta to the
+ * value of the trigger and re-initializing it until it
+ * becomes FALSE."
+ */
+ oldvalue = paTrigger->test_value;
+
+ /* XXX really should do something smarter here */
+
+ do
+ {
+ XSyncValueAdd(&paTrigger->test_value, paTrigger->test_value,
+ pAlarm->delta, &overflow);
+ } while (!overflow &&
+ (*paTrigger->CheckTrigger)(paTrigger,
+ paCounter->value));
+
+ new_test_value = paTrigger->test_value;
+ paTrigger->test_value = oldvalue;
+
+ /* "If this update would cause value to fall outside the range
+ * for an INT64...no change is made to value (test-value) and
+ * the alarm state is changed to Inactive before the event is
+ * generated."
+ */
+ if (overflow)
+ {
+ new_test_value = oldvalue;
+ pAlarm->state = XSyncAlarmInactive;
+ }
+ }
+ /* The AlarmNotify event has to have the "new state of the alarm"
+ * which we can't be sure of until this point. However, it has
+ * to have the "old" trigger test value. That's the reason for
+ * all the newvalue/oldvalue shuffling above. After we send the
+ * events, give the trigger its new test value.
+ */
+ SyncSendAlarmNotifyEvents(pAlarm);
+ pTrigger->test_value = new_test_value;
+}
+
+
+/* This function is called when an Await unblocks, either as a result
+ * of the trigger firing OR the counter being destroyed.
+ * It goes into pTrigger->TriggerFired AND pTrigger->CounterDestroyed
+ * (for Await triggers).
+ */
+static void
+SyncAwaitTriggerFired(SyncTrigger *pTrigger)
+{
+ SyncAwait *pAwait = (SyncAwait *)pTrigger;
+ int numwaits;
+ SyncAwaitUnion *pAwaitUnion;
+ SyncAwait **ppAwait;
+ int num_events = 0;
+
+ pAwaitUnion = (SyncAwaitUnion *)pAwait->pHeader;
+ numwaits = pAwaitUnion->header.num_waitconditions;
+ ppAwait = malloc(numwaits * sizeof(SyncAwait *));
+ if (!ppAwait)
+ goto bail;
+
+ pAwait = &(pAwaitUnion+1)->await;
+
+ /* "When a client is unblocked, all the CounterNotify events for
+ * the Await request are generated contiguously. If count is 0
+ * there are no more events to follow for this request. If
+ * count is n, there are at least n more events to follow."
+ *
+ * Thus, it is best to find all the counters for which events
+ * need to be sent first, so that an accurate count field can
+ * be stored in the events.
+ */
+ for ( ; numwaits; numwaits--, pAwait++)
+ {
+ CARD64 diff;
+ Bool overflow, diffgreater, diffequal;
+
+ /* "A CounterNotify event with the destroyed flag set to TRUE is
+ * always generated if the counter for one of the triggers is
+ * destroyed."
+ */
+ if (pAwait->trigger.pSync->beingDestroyed)
+ {
+ ppAwait[num_events++] = pAwait;
+ continue;
+ }
+
+ if (SYNC_COUNTER == pAwait->trigger.pSync->type)
+ {
+ SyncCounter *pCounter = (SyncCounter *) pAwait->trigger.pSync;
+
+ /* "The difference between the counter and the test value is
+ * calculated by subtracting the test value from the value of
+ * the counter."
+ */
+ XSyncValueSubtract(&diff, pCounter->value,
+ pAwait->trigger.test_value, &overflow);
+
+ /* "If the difference lies outside the range for an INT64, an
+ * event is not generated."
+ */
+ if (overflow)
+ continue;
+ diffgreater = XSyncValueGreaterThan(diff, pAwait->event_threshold);
+ diffequal = XSyncValueEqual(diff, pAwait->event_threshold);
+
+ /* "If the test-type is PositiveTransition or
+ * PositiveComparison, a CounterNotify event is generated if
+ * the difference is at least event-threshold. If the test-type
+ * is NegativeTransition or NegativeComparison, a CounterNotify
+ * event is generated if the difference is at most
+ * event-threshold."
+ */
+
+ if ( ((pAwait->trigger.test_type == XSyncPositiveComparison ||
+ pAwait->trigger.test_type == XSyncPositiveTransition)
+ && (diffgreater || diffequal))
+ ||
+ ((pAwait->trigger.test_type == XSyncNegativeComparison ||
+ pAwait->trigger.test_type == XSyncNegativeTransition)
+ && (!diffgreater) /* less or equal */
+ )
+ )
+ {
+ ppAwait[num_events++] = pAwait;
+ }
+ }
+ }
+ if (num_events)
+ SyncSendCounterNotifyEvents(pAwaitUnion->header.client, ppAwait,
+ num_events);
+ free(ppAwait);
+
+bail:
+ /* unblock the client */
+ AttendClient(pAwaitUnion->header.client);
+ /* delete the await */
+ FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
+}
+
+
+/* This function should always be used to change a counter's value so that
+ * any triggers depending on the counter will be checked.
+ */
+void
+SyncChangeCounter(SyncCounter *pCounter, CARD64 newval)
+{
+ SyncTriggerList *ptl, *pnext;
+ CARD64 oldval;
+
+ oldval = pCounter->value;
+ pCounter->value = newval;
+
+ /* run through triggers to see if any become true */
+ for (ptl = pCounter->sync.pTriglist; ptl; ptl = pnext)
+ {
+ pnext = ptl->next;
+ if ((*ptl->pTrigger->CheckTrigger)(ptl->pTrigger, oldval))
+ (*ptl->pTrigger->TriggerFired)(ptl->pTrigger);
+ }
+
+ if (IsSystemCounter(pCounter))
+ {
+ SyncComputeBracketValues(pCounter);
+ }
+}
+
+
+/* loosely based on dix/events.c/EventSelectForWindow */
+static Bool
+SyncEventSelectForAlarm(SyncAlarm *pAlarm, ClientPtr client, Bool wantevents)
+{
+ SyncAlarmClientList *pClients;
+
+ if (client == pAlarm->client) /* alarm owner */
+ {
+ pAlarm->events = wantevents;
+ return Success;
+ }
+
+ /* see if the client is already on the list (has events selected) */
+
+ for (pClients = pAlarm->pEventClients; pClients;
+ pClients = pClients->next)
+ {
+ if (pClients->client == client)
+ {
+ /* client's presence on the list indicates desire for
+ * events. If the client doesn't want events, remove it
+ * from the list. If the client does want events, do
+ * nothing, since it's already got them.
+ */
+ if (!wantevents)
+ {
+ FreeResource(pClients->delete_id, RT_NONE);
+ }
+ return Success;
+ }
+ }
+
+ /* if we get here, this client does not currently have
+ * events selected on the alarm
+ */
+
+ if (!wantevents)
+ /* client doesn't want events, and we just discovered that it
+ * doesn't have them, so there's nothing to do.
+ */
+ return Success;
+
+ /* add new client to pAlarm->pEventClients */
+
+ pClients = malloc(sizeof(SyncAlarmClientList));
+ if (!pClients)
+ return BadAlloc;
+
+ /* register it as a resource so it will be cleaned up
+ * if the client dies
+ */
+
+ pClients->delete_id = FakeClientID(client->index);
+
+ /* link it into list after we know all the allocations succeed */
+ pClients->next = pAlarm->pEventClients;
+ pAlarm->pEventClients = pClients;
+ pClients->client = client;
+
+ if (!AddResource(pClients->delete_id, RTAlarmClient, pAlarm))
+ return BadAlloc;
+
+ return Success;
+}
+
+/*
+ * ** SyncChangeAlarmAttributes ** This is used by CreateAlarm and ChangeAlarm
+ */
+static int
+SyncChangeAlarmAttributes(ClientPtr client, SyncAlarm *pAlarm, Mask mask,
+ CARD32 *values)
+{
+ int status;
+ XSyncCounter counter;
+ Mask origmask = mask;
+
+ counter =
+ pAlarm->trigger.pSync ? pAlarm->trigger.pSync->id : None;
+
+ while (mask)
+ {
+ int index2 = lowbit(mask);
+ mask &= ~index2;
+ switch (index2)
+ {
+ case XSyncCACounter:
+ mask &= ~XSyncCACounter;
+ /* sanity check in SyncInitTrigger */
+ counter = *values++;
+ break;
+
+ case XSyncCAValueType:
+ mask &= ~XSyncCAValueType;
+ /* sanity check in SyncInitTrigger */
+ pAlarm->trigger.value_type = *values++;
+ break;
+
+ case XSyncCAValue:
+ mask &= ~XSyncCAValue;
+ XSyncIntsToValue(&pAlarm->trigger.wait_value, values[1], values[0]);
+ values += 2;
+ break;
+
+ case XSyncCATestType:
+ mask &= ~XSyncCATestType;
+ /* sanity check in SyncInitTrigger */
+ pAlarm->trigger.test_type = *values++;
+ break;
+
+ case XSyncCADelta:
+ mask &= ~XSyncCADelta;
+ XSyncIntsToValue(&pAlarm->delta, values[1], values[0]);
+ values += 2;
+ break;
+
+ case XSyncCAEvents:
+ mask &= ~XSyncCAEvents;
+ if ((*values != xTrue) && (*values != xFalse))
+ {
+ client->errorValue = *values;
+ return BadValue;
+ }
+ status = SyncEventSelectForAlarm(pAlarm, client,
+ (Bool)(*values++));
+ if (status != Success)
+ return status;
+ break;
+
+ default:
+ client->errorValue = mask;
+ return BadValue;
+ }
+ }
+
+ /* "If the test-type is PositiveComparison or PositiveTransition
+ * and delta is less than zero, or if the test-type is
+ * NegativeComparison or NegativeTransition and delta is
+ * greater than zero, a Match error is generated."
+ */
+ if (origmask & (XSyncCADelta|XSyncCATestType))
+ {
+ CARD64 zero;
+ XSyncIntToValue(&zero, 0);
+ if ((((pAlarm->trigger.test_type == XSyncPositiveComparison) ||
+ (pAlarm->trigger.test_type == XSyncPositiveTransition))
+ && XSyncValueLessThan(pAlarm->delta, zero))
+ ||
+ (((pAlarm->trigger.test_type == XSyncNegativeComparison) ||
+ (pAlarm->trigger.test_type == XSyncNegativeTransition))
+ && XSyncValueGreaterThan(pAlarm->delta, zero))
+ )
+ {
+ return BadMatch;
+ }
+ }
+
+ /* postpone this until now, when we're sure nothing else can go wrong */
+ if ((status = SyncInitTrigger(client, &pAlarm->trigger, counter, RTCounter,
+ origmask & XSyncCAAllTrigger)) != Success)
+ return status;
+
+ /* XXX spec does not really say to do this - needs clarification */
+ pAlarm->state = XSyncAlarmActive;
+ return Success;
+}
+
+static SyncObject *
+SyncCreate(ClientPtr client, XID id, unsigned char type)
+{
+ SyncObject *pSync;
+
+ switch (type) {
+ case SYNC_COUNTER:
+ pSync = malloc(sizeof(SyncCounter));
+ break;
+ case SYNC_FENCE:
+ pSync = (SyncObject*)dixAllocateObjectWithPrivates(SyncFence,
+ PRIVATE_SYNC_FENCE);
+ break;
+ default:
+ return NULL;
+ }
+
+ if (!pSync)
+ return NULL;
+
+ pSync->client = client;
+ pSync->id = id;
+ pSync->pTriglist = NULL;
+ pSync->beingDestroyed = FALSE;
+ pSync->type = type;
+
+ return pSync;
+}
+
+
+static SyncCounter *
+SyncCreateCounter(ClientPtr client, XSyncCounter id, CARD64 initialvalue)
+{
+ SyncCounter *pCounter;
+
+ if (!(pCounter = (SyncCounter *)SyncCreate(client,
+ id,
+ SYNC_COUNTER)))
+ return NULL;
+
+ pCounter->value = initialvalue;
+ pCounter->pSysCounterInfo = NULL;
+
+ if (!AddResource(id, RTCounter, (pointer) pCounter))
+ return NULL;
+
+ return pCounter;
+}
+
+static int FreeCounter(void *, XID);
+
+/*
+ * ***** System Counter utilities
+ */
+
+pointer
+SyncCreateSystemCounter(
+ char *name,
+ CARD64 initial,
+ CARD64 resolution,
+ SyncCounterType counterType,
+ void (*QueryValue)(pointer /* pCounter */,
+ CARD64 * /* pValue_return */),
+ void (*BracketValues)(pointer /* pCounter */,
+ CARD64 * /* pbracket_less */,
+ CARD64 * /* pbracket_greater */)
+ )
+{
+ SyncCounter *pCounter;
+
+ SysCounterList = realloc(SysCounterList,
+ (SyncNumSystemCounters+1)*sizeof(SyncCounter *));
+ if (!SysCounterList)
+ return NULL;
+
+ /* this function may be called before SYNC has been initialized, so we
+ * have to make sure RTCounter is created.
+ */
+ if (RTCounter == 0)
+ {
+ RTCounter = CreateNewResourceType(FreeCounter, "SyncCounter");
+ if (RTCounter == 0)
+ {
+ return NULL;
+ }
+ }
+
+ pCounter = SyncCreateCounter(NULL, FakeClientID(0), initial);
+
+ if (pCounter)
+ {
+ SysCounterInfo *psci;
+
+ psci = malloc(sizeof(SysCounterInfo));
+ if (!psci)
+ {
+ FreeResource(pCounter->sync.id, RT_NONE);
+ return pCounter;
+ }
+ pCounter->pSysCounterInfo = psci;
+ psci->name = name;
+ psci->resolution = resolution;
+ psci->counterType = counterType;
+ psci->QueryValue = QueryValue;
+ psci->BracketValues = BracketValues;
+ XSyncMaxValue(&psci->bracket_greater);
+ XSyncMinValue(&psci->bracket_less);
+ SysCounterList[SyncNumSystemCounters++] = pCounter;
+ }
+ return pCounter;
+}
+
+void
+SyncDestroySystemCounter(pointer pSysCounter)
+{
+ SyncCounter *pCounter = (SyncCounter *)pSysCounter;
+ FreeResource(pCounter->sync.id, RT_NONE);
+}
+
+static void
+SyncComputeBracketValues(SyncCounter *pCounter)
+{
+ SyncTriggerList *pCur;
+ SyncTrigger *pTrigger;
+ SysCounterInfo *psci;
+ CARD64 *pnewgtval = NULL;
+ CARD64 *pnewltval = NULL;
+ SyncCounterType ct;
+
+ if (!pCounter)
+ return;
+
+ psci = pCounter->pSysCounterInfo;
+ ct = pCounter->pSysCounterInfo->counterType;
+ if (ct == XSyncCounterNeverChanges)
+ return;
+
+ XSyncMaxValue(&psci->bracket_greater);
+ XSyncMinValue(&psci->bracket_less);
+
+ for (pCur = pCounter->sync.pTriglist; pCur; pCur = pCur->next)
+ {
+ pTrigger = pCur->pTrigger;
+
+ if (pTrigger->test_type == XSyncPositiveComparison &&
+ ct != XSyncCounterNeverIncreases)
+ {
+ if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) &&
+ XSyncValueLessThan(pTrigger->test_value,
+ psci->bracket_greater))
+ {
+ psci->bracket_greater = pTrigger->test_value;
+ pnewgtval = &psci->bracket_greater;
+ }
+ }
+ else if (pTrigger->test_type == XSyncNegativeComparison &&
+ ct != XSyncCounterNeverDecreases)
+ {
+ if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) &&
+ XSyncValueGreaterThan(pTrigger->test_value,
+ psci->bracket_less))
+ {
+ psci->bracket_less = pTrigger->test_value;
+ pnewltval = &psci->bracket_less;
+ }
+ }
+ else if (pTrigger->test_type == XSyncNegativeTransition &&
+ ct != XSyncCounterNeverIncreases)
+ {
+ if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) &&
+ XSyncValueGreaterThan(pTrigger->test_value, psci->bracket_less))
+ {
+ psci->bracket_less = pTrigger->test_value;
+ pnewltval = &psci->bracket_less;
+ } else if (XSyncValueEqual(pCounter->value, pTrigger->test_value) &&
+ XSyncValueLessThan(pTrigger->test_value,
+ psci->bracket_greater))
+ {
+ /*
+ * The value is exactly equal to our threshold. We want one
+ * more event in the positive direction to ensure we pick up
+ * when the value *exceeds* this threshold.
+ */
+ psci->bracket_greater = pTrigger->test_value;
+ pnewgtval = &psci->bracket_greater;
+ }
+ }
+ else if (pTrigger->test_type == XSyncPositiveTransition &&
+ ct != XSyncCounterNeverDecreases)
+ {
+ if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) &&
+ XSyncValueLessThan(pTrigger->test_value, psci->bracket_greater))
+ {
+ psci->bracket_greater = pTrigger->test_value;
+ pnewgtval = &psci->bracket_greater;
+ } else if (XSyncValueEqual(pCounter->value, pTrigger->test_value) &&
+ XSyncValueGreaterThan(pTrigger->test_value,
+ psci->bracket_less))
+ {
+ /*
+ * The value is exactly equal to our threshold. We want one
+ * more event in the negative direction to ensure we pick up
+ * when the value is less than this threshold.
+ */
+ psci->bracket_less = pTrigger->test_value;
+ pnewltval = &psci->bracket_less;
+ }
+ }
+ } /* end for each trigger */
+
+ if (pnewgtval || pnewltval)
+ {
+ (*psci->BracketValues)((pointer)pCounter, pnewltval, pnewgtval);
+ }
+}
+
+/*
+ * ***** Resource delete functions
+ */
+
+/* ARGSUSED */
+static int
+FreeAlarm(void *addr, XID id)
+{
+ SyncAlarm *pAlarm = (SyncAlarm *) addr;
+
+ pAlarm->state = XSyncAlarmDestroyed;
+
+ SyncSendAlarmNotifyEvents(pAlarm);
+
+ /* delete event selections */
+
+ while (pAlarm->pEventClients)
+ FreeResource(pAlarm->pEventClients->delete_id, RT_NONE);
+
+ SyncDeleteTriggerFromSyncObject(&pAlarm->trigger);
+
+ free(pAlarm);
+ return Success;
+}
+
+
+/*
+ * ** Cleanup after the destruction of a Counter
+ */
+/* ARGSUSED */
+static int
+FreeCounter(void *env, XID id)
+{
+ SyncCounter *pCounter = (SyncCounter *) env;
+ SyncTriggerList *ptl, *pnext;
+
+ pCounter->sync.beingDestroyed = TRUE;
+ /* tell all the counter's triggers that the counter has been destroyed */
+ for (ptl = pCounter->sync.pTriglist; ptl; ptl = pnext)
+ {
+ (*ptl->pTrigger->CounterDestroyed)(ptl->pTrigger);
+ pnext = ptl->next;
+ free(ptl); /* destroy the trigger list as we go */
+ }
+ if (IsSystemCounter(pCounter))
+ {
+ int i, found = 0;
+
+ free(pCounter->pSysCounterInfo);
+
+ /* find the counter in the list of system counters and remove it */
+
+ if (SysCounterList)
+ {
+ for (i = 0; i < SyncNumSystemCounters; i++)
+ {
+ if (SysCounterList[i] == pCounter)
+ {
+ found = i;
+ break;
+ }
+ }
+ if (found < (SyncNumSystemCounters-1))
+ {
+ for (i = found; i < SyncNumSystemCounters-1; i++)
+ {
+ SysCounterList[i] = SysCounterList[i+1];
+ }
+ }
+ }
+ SyncNumSystemCounters--;
+ }
+ free(pCounter);
+ return Success;
+}
+
+/*
+ * ** Cleanup after Await
+ */
+/* ARGSUSED */
+static int
+FreeAwait(void *addr, XID id)
+{
+ SyncAwaitUnion *pAwaitUnion = (SyncAwaitUnion *) addr;
+ SyncAwait *pAwait;
+ int numwaits;
+
+ pAwait = &(pAwaitUnion+1)->await; /* first await on list */
+
+ /* remove triggers from counters */
+
+ for (numwaits = pAwaitUnion->header.num_waitconditions; numwaits;
+ numwaits--, pAwait++)
+ {
+ /* If the counter is being destroyed, FreeCounter will delete
+ * the trigger list itself, so don't do it here.
+ */
+ SyncObject *pSync = pAwait->trigger.pSync;
+ if (pSync && !pSync->beingDestroyed)
+ SyncDeleteTriggerFromSyncObject(&pAwait->trigger);
+ }
+ free(pAwaitUnion);
+ return Success;
+}
+
+/* loosely based on dix/events.c/OtherClientGone */
+static int
+FreeAlarmClient(void *value, XID id)
+{
+ SyncAlarm *pAlarm = (SyncAlarm *)value;
+ SyncAlarmClientList *pCur, *pPrev;
+
+ for (pPrev = NULL, pCur = pAlarm->pEventClients;
+ pCur;
+ pPrev = pCur, pCur = pCur->next)
+ {
+ if (pCur->delete_id == id)
+ {
+ if (pPrev)
+ pPrev->next = pCur->next;
+ else
+ pAlarm->pEventClients = pCur->next;
+ free(pCur);
+ return Success;
+ }
+ }
+ FatalError("alarm client not on event list");
+ /*NOTREACHED*/
+}
+
+
+/*
+ * ***** Proc functions
+ */
+
+
+/*
+ * ** Initialize the extension
+ */
+static int
+ProcSyncInitialize(ClientPtr client)
+{
+ xSyncInitializeReply rep;
+ int n;
+
+ REQUEST_SIZE_MATCH(xSyncInitializeReq);
+
+ memset(&rep, 0, sizeof(xSyncInitializeReply));
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.majorVersion = SERVER_SYNC_MAJOR_VERSION;
+ rep.minorVersion = SERVER_SYNC_MINOR_VERSION;
+ rep.length = 0;
+
+ if (client->swapped)
+ {
+ swaps(&rep.sequenceNumber, n);
+ }
+ WriteToClient(client, sizeof(rep), (char *) &rep);
+ return Success;
+}
+
+/*
+ * ** Get list of system counters available through the extension
+ */
+static int
+ProcSyncListSystemCounters(ClientPtr client)
+{
+ xSyncListSystemCountersReply rep;
+ int i, len;
+ xSyncSystemCounter *list = NULL, *walklist = NULL;
+
+ REQUEST_SIZE_MATCH(xSyncListSystemCountersReq);
+
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.nCounters = SyncNumSystemCounters;
+
+ for (i = len = 0; i < SyncNumSystemCounters; i++)
+ {
+ char *name = SysCounterList[i]->pSysCounterInfo->name;
+ /* pad to 4 byte boundary */
+ len += pad_to_int32(sz_xSyncSystemCounter + strlen(name));
+ }
+
+ if (len)
+ {
+ walklist = list = malloc(len);
+ if (!list)
+ return BadAlloc;
+ }
+
+ rep.length = bytes_to_int32(len);
+
+ if (client->swapped)
+ {
+ char n;
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swapl(&rep.nCounters, n);
+ }
+
+ for (i = 0; i < SyncNumSystemCounters; i++)
+ {
+ int namelen;
+ char *pname_in_reply;
+ SysCounterInfo *psci = SysCounterList[i]->pSysCounterInfo;
+
+ walklist->counter = SysCounterList[i]->sync.id;
+ walklist->resolution_hi = XSyncValueHigh32(psci->resolution);
+ walklist->resolution_lo = XSyncValueLow32(psci->resolution);
+ namelen = strlen(psci->name);
+ walklist->name_length = namelen;
+
+ if (client->swapped)
+ {
+ char n;
+ swapl(&walklist->counter, n);
+ swapl(&walklist->resolution_hi, n);
+ swapl(&walklist->resolution_lo, n);
+ swaps(&walklist->name_length, n);
+ }
+
+ pname_in_reply = ((char *)walklist) + sz_xSyncSystemCounter;
+ strncpy(pname_in_reply, psci->name, namelen);
+ walklist = (xSyncSystemCounter *) (((char *)walklist) +
+ pad_to_int32(sz_xSyncSystemCounter + namelen));
+ }
+
+ WriteToClient(client, sizeof(rep), (char *) &rep);
+ if (len)
+ {
+ WriteToClient(client, len, (char *) list);
+ free(list);
+ }
+
+ return Success;
+}
+
+/*
+ * ** Set client Priority
+ */
+static int
+ProcSyncSetPriority(ClientPtr client)
+{
+ REQUEST(xSyncSetPriorityReq);
+ ClientPtr priorityclient;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncSetPriorityReq);
+
+ if (stuff->id == None)
+ priorityclient = client;
+ else {
+ rc = dixLookupClient(&priorityclient, stuff->id, client,
+ DixSetAttrAccess);
+ if (rc != Success)
+ return rc;
+ }
+
+ if (priorityclient->priority != stuff->priority)
+ {
+ priorityclient->priority = stuff->priority;
+
+ /* The following will force the server back into WaitForSomething
+ * so that the change in this client's priority is immediately
+ * reflected.
+ */
+ isItTimeToYield = TRUE;
+ dispatchException |= DE_PRIORITYCHANGE;
+ }
+ return Success;
+}
+
+/*
+ * ** Get client Priority
+ */
+static int
+ProcSyncGetPriority(ClientPtr client)
+{
+ REQUEST(xSyncGetPriorityReq);
+ xSyncGetPriorityReply rep;
+ ClientPtr priorityclient;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncGetPriorityReq);
+
+ if (stuff->id == None)
+ priorityclient = client;
+ else {
+ rc = dixLookupClient(&priorityclient, stuff->id, client,
+ DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+ }
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.priority = priorityclient->priority;
+
+ if (client->swapped)
+ {
+ char n;
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.priority, n);
+ }
+
+ WriteToClient(client, sizeof(xSyncGetPriorityReply), (char *) &rep);
+
+ return Success;
+}
+
+/*
+ * ** Create a new counter
+ */
+static int
+ProcSyncCreateCounter(ClientPtr client)
+{
+ REQUEST(xSyncCreateCounterReq);
+ CARD64 initial;
+
+ REQUEST_SIZE_MATCH(xSyncCreateCounterReq);
+
+ LEGAL_NEW_RESOURCE(stuff->cid, client);
+
+ XSyncIntsToValue(&initial, stuff->initial_value_lo, stuff->initial_value_hi);
+ if (!SyncCreateCounter(client, stuff->cid, initial))
+ return BadAlloc;
+
+ return Success;
+}
+
+/*
+ * ** Set Counter value
+ */
+static int
+ProcSyncSetCounter(ClientPtr client)
+{
+ REQUEST(xSyncSetCounterReq);
+ SyncCounter *pCounter;
+ CARD64 newvalue;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncSetCounterReq);
+
+ rc = dixLookupResourceByType((pointer *)&pCounter, stuff->cid, RTCounter,
+ client, DixWriteAccess);
+ if (rc != Success)
+ return rc;
+
+ if (IsSystemCounter(pCounter))
+ {
+ client->errorValue = stuff->cid;
+ return BadAccess;
+ }
+
+ XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi);
+ SyncChangeCounter(pCounter, newvalue);
+ return Success;
+}
+
+/*
+ * ** Change Counter value
+ */
+static int
+ProcSyncChangeCounter(ClientPtr client)
+{
+ REQUEST(xSyncChangeCounterReq);
+ SyncCounter *pCounter;
+ CARD64 newvalue;
+ Bool overflow;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncChangeCounterReq);
+
+ rc = dixLookupResourceByType((pointer *)&pCounter, stuff->cid, RTCounter,
+ client, DixWriteAccess);
+ if (rc != Success)
+ return rc;
+
+ if (IsSystemCounter(pCounter))
+ {
+ client->errorValue = stuff->cid;
+ return BadAccess;
+ }
+
+ XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi);
+ XSyncValueAdd(&newvalue, pCounter->value, newvalue, &overflow);
+ if (overflow)
+ {
+ /* XXX 64 bit value can't fit in 32 bits; do the best we can */
+ client->errorValue = stuff->value_hi;
+ return BadValue;
+ }
+ SyncChangeCounter(pCounter, newvalue);
+ return Success;
+}
+
+/*
+ * ** Destroy a counter
+ */
+static int
+ProcSyncDestroyCounter(ClientPtr client)
+{
+ REQUEST(xSyncDestroyCounterReq);
+ SyncCounter *pCounter;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncDestroyCounterReq);
+
+ rc = dixLookupResourceByType((pointer *)&pCounter, stuff->counter, RTCounter,
+ client, DixDestroyAccess);
+ if (rc != Success)
+ return rc;
+
+ if (IsSystemCounter(pCounter))
+ {
+ client->errorValue = stuff->counter;
+ return BadAccess;
+ }
+ FreeResource(pCounter->sync.id, RT_NONE);
+ return Success;
+}
+
+static SyncAwaitUnion*
+SyncAwaitPrologue(ClientPtr client, int items)
+{
+ SyncAwaitUnion *pAwaitUnion;
+
+ /* all the memory for the entire await list is allocated
+ * here in one chunk
+ */
+ pAwaitUnion = malloc((items+1) * sizeof(SyncAwaitUnion));
+ if (!pAwaitUnion)
+ return NULL;
+
+ /* first item is the header, remainder are real wait conditions */
+
+ pAwaitUnion->header.delete_id = FakeClientID(client->index);
+ pAwaitUnion->header.client = client;
+ pAwaitUnion->header.num_waitconditions = 0;
+
+ if (!AddResource(pAwaitUnion->header.delete_id, RTAwait, pAwaitUnion))
+ return NULL;
+
+ return pAwaitUnion;
+}
+
+static void
+SyncAwaitEpilogue(ClientPtr client, int items, SyncAwaitUnion *pAwaitUnion)
+{
+ SyncAwait *pAwait;
+ int i;
+
+ IgnoreClient(client);
+
+ /* see if any of the triggers are already true */
+
+ pAwait = &(pAwaitUnion+1)->await; /* skip over header */
+ for (i = 0; i < items; i++, pAwait++)
+ {
+ CARD64 value;
+
+ /* don't have to worry about NULL counters because the request
+ * errors before we get here out if they occur
+ */
+ switch (pAwait->trigger.pSync->type) {
+ case SYNC_COUNTER:
+ value = ((SyncCounter *)pAwait->trigger.pSync)->value;
+ break;
+ default:
+ XSyncIntToValue(&value, 0);
+ }
+
+ if ((*pAwait->trigger.CheckTrigger)(&pAwait->trigger, value))
+ {
+ (*pAwait->trigger.TriggerFired)(&pAwait->trigger);
+ break; /* once is enough */
+ }
+ }
+}
+
+/*
+ * ** Await
+ */
+static int
+ProcSyncAwait(ClientPtr client)
+{
+ REQUEST(xSyncAwaitReq);
+ int len, items;
+ int i;
+ xSyncWaitCondition *pProtocolWaitConds;
+ SyncAwaitUnion *pAwaitUnion;
+ SyncAwait *pAwait;
+ int status;
+
+ REQUEST_AT_LEAST_SIZE(xSyncAwaitReq);
+
+ len = client->req_len << 2;
+ len -= sz_xSyncAwaitReq;
+ items = len / sz_xSyncWaitCondition;
+
+ if (items * sz_xSyncWaitCondition != len)
+ {
+ return BadLength;
+ }
+ if (items == 0)
+ {
+ client->errorValue = items; /* XXX protocol change */
+ return BadValue;
+ }
+
+ if (!(pAwaitUnion = SyncAwaitPrologue(client, items)))
+ return BadAlloc;
+
+ /* don't need to do any more memory allocation for this request! */
+
+ pProtocolWaitConds = (xSyncWaitCondition *) & stuff[1];
+
+ pAwait = &(pAwaitUnion+1)->await; /* skip over header */
+ for (i = 0; i < items; i++, pProtocolWaitConds++, pAwait++)
+ {
+ if (pProtocolWaitConds->counter == None) /* XXX protocol change */
+ {
+ /* this should take care of removing any triggers created by
+ * this request that have already been registered on sync objects
+ */
+ FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
+ client->errorValue = pProtocolWaitConds->counter;
+ return SyncErrorBase + XSyncBadCounter;
+ }
+
+ /* sanity checks are in SyncInitTrigger */
+ pAwait->trigger.pSync = NULL;
+ pAwait->trigger.value_type = pProtocolWaitConds->value_type;
+ XSyncIntsToValue(&pAwait->trigger.wait_value,
+ pProtocolWaitConds->wait_value_lo,
+ pProtocolWaitConds->wait_value_hi);
+ pAwait->trigger.test_type = pProtocolWaitConds->test_type;
+
+ status = SyncInitTrigger(client, &pAwait->trigger,
+ pProtocolWaitConds->counter, RTCounter,
+ XSyncCAAllTrigger);
+ if (status != Success)
+ {
+ /* this should take care of removing any triggers created by
+ * this request that have already been registered on sync objects
+ */
+ FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
+ return status;
+ }
+ /* this is not a mistake -- same function works for both cases */
+ pAwait->trigger.TriggerFired = SyncAwaitTriggerFired;
+ pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired;
+ XSyncIntsToValue(&pAwait->event_threshold,
+ pProtocolWaitConds->event_threshold_lo,
+ pProtocolWaitConds->event_threshold_hi);
+ pAwait->pHeader = &pAwaitUnion->header;
+ pAwaitUnion->header.num_waitconditions++;
+ }
+
+ SyncAwaitEpilogue(client, items, pAwaitUnion);
+
+ return Success;
+}
+
+
+/*
+ * ** Query a counter
+ */
+static int
+ProcSyncQueryCounter(ClientPtr client)
+{
+ REQUEST(xSyncQueryCounterReq);
+ xSyncQueryCounterReply rep;
+ SyncCounter *pCounter;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncQueryCounterReq);
+
+ rc = dixLookupResourceByType((pointer *)&pCounter, stuff->counter,
+ RTCounter, client, DixReadAccess);
+ if (rc != Success)
+ return rc;
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+
+ /* if system counter, ask it what the current value is */
+
+ if (IsSystemCounter(pCounter))
+ {
+ (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter,
+ &pCounter->value);
+ }
+
+ rep.value_hi = XSyncValueHigh32(pCounter->value);
+ rep.value_lo = XSyncValueLow32(pCounter->value);
+ if (client->swapped)
+ {
+ char n;
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swapl(&rep.value_hi, n);
+ swapl(&rep.value_lo, n);
+ }
+ WriteToClient(client, sizeof(xSyncQueryCounterReply), (char *) &rep);
+ return Success;
+}
+
+
+/*
+ * ** Create Alarm
+ */
+static int
+ProcSyncCreateAlarm(ClientPtr client)
+{
+ REQUEST(xSyncCreateAlarmReq);
+ SyncAlarm *pAlarm;
+ int status;
+ unsigned long len, vmask;
+ SyncTrigger *pTrigger;
+
+ REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq);
+
+ LEGAL_NEW_RESOURCE(stuff->id, client);
+
+ vmask = stuff->valueMask;
+ len = client->req_len - bytes_to_int32(sizeof(xSyncCreateAlarmReq));
+ /* the "extra" call to Ones accounts for the presence of 64 bit values */
+ if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta))))
+ return BadLength;
+
+ if (!(pAlarm = malloc(sizeof(SyncAlarm))))
+ {
+ return BadAlloc;
+ }
+
+ /* set up defaults */
+
+ pTrigger = &pAlarm->trigger;
+ pTrigger->pSync = NULL;
+ pTrigger->value_type = XSyncAbsolute;
+ XSyncIntToValue(&pTrigger->wait_value, 0L);
+ pTrigger->test_type = XSyncPositiveComparison;
+ pTrigger->TriggerFired = SyncAlarmTriggerFired;
+ pTrigger->CounterDestroyed = SyncAlarmCounterDestroyed;
+ status = SyncInitTrigger(client, pTrigger, None, RTCounter,
+ XSyncCAAllTrigger);
+ if (status != Success)
+ {
+ free(pAlarm);
+ return status;
+ }
+
+ pAlarm->client = client;
+ pAlarm->alarm_id = stuff->id;
+ XSyncIntToValue(&pAlarm->delta, 1L);
+ pAlarm->events = TRUE;
+ pAlarm->state = XSyncAlarmInactive;
+ pAlarm->pEventClients = NULL;
+ status = SyncChangeAlarmAttributes(client, pAlarm, vmask,
+ (CARD32 *)&stuff[1]);
+ if (status != Success)
+ {
+ free(pAlarm);
+ return status;
+ }
+
+ if (!AddResource(stuff->id, RTAlarm, pAlarm))
+ return BadAlloc;
+
+ /* see if alarm already triggered. NULL counter will not trigger
+ * in CreateAlarm and sets alarm state to Inactive.
+ */
+
+ if (!pTrigger->pSync)
+ {
+ pAlarm->state = XSyncAlarmInactive; /* XXX protocol change */
+ }
+ else
+ {
+ SyncCounter *pCounter;
+
+ if (!SyncCheckWarnIsCounter(pTrigger->pSync,
+ WARN_INVALID_COUNTER_ALARM))
+ {
+ FreeResource(stuff->id, RT_NONE);
+ return BadAlloc;
+ }
+
+ pCounter = (SyncCounter *)pTrigger->pSync;
+
+ if ((*pTrigger->CheckTrigger)(pTrigger, pCounter->value))
+ (*pTrigger->TriggerFired)(pTrigger);
+ }
+
+ return Success;
+}
+
+/*
+ * ** Change Alarm
+ */
+static int
+ProcSyncChangeAlarm(ClientPtr client)
+{
+ REQUEST(xSyncChangeAlarmReq);
+ SyncAlarm *pAlarm;
+ SyncCounter *pCounter = NULL;
+ long vmask;
+ int len, status;
+
+ REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq);
+
+ status = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm,
+ client, DixWriteAccess);
+ if (status != Success)
+ return status;
+
+ vmask = stuff->valueMask;
+ len = client->req_len - bytes_to_int32(sizeof(xSyncChangeAlarmReq));
+ /* the "extra" call to Ones accounts for the presence of 64 bit values */
+ if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta))))
+ return BadLength;
+
+ if ((status = SyncChangeAlarmAttributes(client, pAlarm, vmask,
+ (CARD32 *)&stuff[1])) != Success)
+ return status;
+
+ if (SyncCheckWarnIsCounter(pAlarm->trigger.pSync,
+ WARN_INVALID_COUNTER_ALARM))
+ pCounter = (SyncCounter *)pAlarm->trigger.pSync;
+
+ /* see if alarm already triggered. NULL counter WILL trigger
+ * in ChangeAlarm.
+ */
+
+ if (!pCounter ||
+ (*pAlarm->trigger.CheckTrigger)(&pAlarm->trigger, pCounter->value))
+ {
+ (*pAlarm->trigger.TriggerFired)(&pAlarm->trigger);
+ }
+ return Success;
+}
+
+static int
+ProcSyncQueryAlarm(ClientPtr client)
+{
+ REQUEST(xSyncQueryAlarmReq);
+ SyncAlarm *pAlarm;
+ xSyncQueryAlarmReply rep;
+ SyncTrigger *pTrigger;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncQueryAlarmReq);
+
+ rc = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm,
+ client, DixReadAccess);
+ if (rc != Success)
+ return rc;
+
+ rep.type = X_Reply;
+ rep.length = bytes_to_int32(sizeof(xSyncQueryAlarmReply) - sizeof(xGenericReply));
+ rep.sequenceNumber = client->sequence;
+
+ pTrigger = &pAlarm->trigger;
+ rep.counter = (pTrigger->pSync) ? pTrigger->pSync->id : None;
+
+#if 0 /* XXX unclear what to do, depends on whether relative value-types
+ * are "consumed" immediately and are considered absolute from then
+ * on.
+ */
+ rep.value_type = pTrigger->value_type;
+ rep.wait_value_hi = XSyncValueHigh32(pTrigger->wait_value);
+ rep.wait_value_lo = XSyncValueLow32(pTrigger->wait_value);
+#else
+ rep.value_type = XSyncAbsolute;
+ rep.wait_value_hi = XSyncValueHigh32(pTrigger->test_value);
+ rep.wait_value_lo = XSyncValueLow32(pTrigger->test_value);
+#endif
+
+ rep.test_type = pTrigger->test_type;
+ rep.delta_hi = XSyncValueHigh32(pAlarm->delta);
+ rep.delta_lo = XSyncValueLow32(pAlarm->delta);
+ rep.events = pAlarm->events;
+ rep.state = pAlarm->state;
+
+ if (client->swapped)
+ {
+ char n;
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swapl(&rep.counter, n);
+ swapl(&rep.wait_value_hi, n);
+ swapl(&rep.wait_value_lo, n);
+ swapl(&rep.test_type, n);
+ swapl(&rep.delta_hi, n);
+ swapl(&rep.delta_lo, n);
+ }
+
+ WriteToClient(client, sizeof(xSyncQueryAlarmReply), (char *) &rep);
+ return Success;
+}
+
+static int
+ProcSyncDestroyAlarm(ClientPtr client)
+{
+ SyncAlarm *pAlarm;
+ int rc;
+ REQUEST(xSyncDestroyAlarmReq);
+
+ REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq);
+
+ rc = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm,
+ client, DixDestroyAccess);
+ if (rc != Success)
+ return rc;
+
+ FreeResource(stuff->alarm, RT_NONE);
+ return Success;
+}
+
+static int
+ProcSyncCreateFence(ClientPtr client)
+{
+ REQUEST(xSyncCreateFenceReq);
+ DrawablePtr pDraw;
+ SyncFence *pFence;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncCreateFenceReq);
+
+ rc = dixLookupDrawable(&pDraw, stuff->d, client, M_ANY, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ LEGAL_NEW_RESOURCE(stuff->fid, client);
+
+ if (!(pFence = (SyncFence *)SyncCreate(client,
+ stuff->fid,
+ SYNC_FENCE)))
+ return BadAlloc;
+
+ miSyncInitFence(pDraw->pScreen, pFence, stuff->initially_triggered);
+
+ if (!AddResource(stuff->fid, RTFence, (pointer) pFence))
+ return BadAlloc;
+
+ return client->noClientException;
+}
+
+static int
+FreeFence(void *obj, XID id)
+{
+ SyncFence *pFence = (SyncFence *) obj;
+
+ miSyncDestroyFence(pFence);
+
+ return Success;
+}
+
+int SyncVerifyFence(SyncFence **ppSyncFence, XID fid,
+ ClientPtr client, Mask mode)
+{
+ int rc = dixLookupResourceByType((pointer *)ppSyncFence, fid, RTFence,
+ client, mode);
+
+ if (rc != Success)
+ client->errorValue = fid;
+
+ return rc;
+}
+
+static int
+ProcSyncTriggerFence(ClientPtr client)
+{
+ REQUEST(xSyncTriggerFenceReq);
+ SyncFence *pFence;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncTriggerFenceReq);
+
+ rc = dixLookupResourceByType((pointer *)&pFence, stuff->fid, RTFence,
+ client, DixWriteAccess);
+ if (rc != Success)
+ return rc;
+
+ miSyncTriggerFence(pFence);
+
+ return client->noClientException;
+}
+
+static int
+ProcSyncResetFence(ClientPtr client)
+{
+ REQUEST(xSyncResetFenceReq);
+ SyncFence *pFence;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncResetFenceReq);
+
+ rc = dixLookupResourceByType((pointer *)&pFence, stuff->fid, RTFence,
+ client, DixWriteAccess);
+ if (rc != Success)
+ return rc;
+
+ if (pFence->funcs.CheckTriggered(pFence) != TRUE)
+ return BadMatch;
+
+ pFence->funcs.Reset(pFence);
+
+ return client->noClientException;
+}
+
+static int
+ProcSyncDestroyFence(ClientPtr client)
+{
+ REQUEST(xSyncDestroyFenceReq);
+ SyncFence *pFence;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncDestroyFenceReq);
+
+ rc = dixLookupResourceByType((pointer *)&pFence, stuff->fid, RTFence,
+ client, DixDestroyAccess);
+ if (rc != Success)
+ return rc;
+
+ FreeResource(stuff->fid, RT_NONE);
+ return client->noClientException;
+}
+
+static int
+ProcSyncQueryFence(ClientPtr client)
+{
+ REQUEST(xSyncQueryFenceReq);
+ xSyncQueryFenceReply rep;
+ SyncFence *pFence;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xSyncQueryFenceReq);
+
+ rc = dixLookupResourceByType((pointer *)&pFence, stuff->fid,
+ RTFence, client, DixReadAccess);
+ if (rc != Success)
+ return rc;
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+
+ rep.triggered = pFence->funcs.CheckTriggered(pFence);
+
+ if (client->swapped)
+ {
+ char n;
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ }
+
+ WriteToClient(client, sizeof(xSyncQueryFenceReply), (char *) &rep);
+ return client->noClientException;
+}
+
+static int
+ProcSyncAwaitFence(ClientPtr client)
+{
+ REQUEST(xSyncAwaitFenceReq);
+ SyncAwaitUnion *pAwaitUnion;
+ SyncAwait *pAwait;
+ /* Use CARD32 rather than XSyncFence because XIDs are hard-coded to
+ * CARD32 in protocol definitions */
+ CARD32 *pProtocolFences;
+ int status;
+ int len;
+ int items;
+ int i;
+
+ REQUEST_AT_LEAST_SIZE(xSyncAwaitFenceReq);
+
+ len = client->req_len << 2;
+ len -= sz_xSyncAwaitFenceReq;
+ items = len / sizeof(CARD32);
+
+ if (items * sizeof(CARD32) != len)
+ {
+ return BadLength;
+ }
+ if (items == 0)
+ {
+ client->errorValue = items;
+ return BadValue;
+ }
+
+ if (!(pAwaitUnion = SyncAwaitPrologue(client, items)))
+ return BadAlloc;
+
+ /* don't need to do any more memory allocation for this request! */
+
+ pProtocolFences = (CARD32 *) & stuff[1];
+
+ pAwait = &(pAwaitUnion+1)->await; /* skip over header */
+ for (i = 0; i < items; i++, pProtocolFences++, pAwait++)
+ {
+ if (*pProtocolFences == None)
+ {
+ /* this should take care of removing any triggers created by
+ * this request that have already been registered on sync objects
+ */
+ FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
+ client->errorValue = *pProtocolFences;
+ return SyncErrorBase + XSyncBadFence;
+ }
+
+ pAwait->trigger.pSync = NULL;
+ /* Provide acceptable values for these unused fields to
+ * satisfy SyncInitTrigger's validation logic
+ */
+ pAwait->trigger.value_type = XSyncAbsolute;
+ XSyncIntToValue(&pAwait->trigger.wait_value, 0);
+ pAwait->trigger.test_type = 0;
+
+ status = SyncInitTrigger(client, &pAwait->trigger,
+ *pProtocolFences, RTFence,
+ XSyncCAAllTrigger);
+ if (status != Success)
+ {
+ /* this should take care of removing any triggers created by
+ * this request that have already been registered on sync objects
+ */
+ FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
+ return status;
+ }
+ /* this is not a mistake -- same function works for both cases */
+ pAwait->trigger.TriggerFired = SyncAwaitTriggerFired;
+ pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired;
+ /* event_threshold is unused for fence syncs */
+ XSyncIntToValue(&pAwait->event_threshold, 0);
+ pAwait->pHeader = &pAwaitUnion->header;
+ pAwaitUnion->header.num_waitconditions++;
+ }
+
+ SyncAwaitEpilogue(client, items, pAwaitUnion);
+
+ return client->noClientException;
+}
+
+/*
+ * ** Given an extension request, call the appropriate request procedure
+ */
+static int
+ProcSyncDispatch(ClientPtr client)
+{
+ REQUEST(xReq);
+
+ switch (stuff->data)
+ {
+ case X_SyncInitialize:
+ return ProcSyncInitialize(client);
+ case X_SyncListSystemCounters:
+ return ProcSyncListSystemCounters(client);
+ case X_SyncCreateCounter:
+ return ProcSyncCreateCounter(client);
+ case X_SyncSetCounter:
+ return ProcSyncSetCounter(client);
+ case X_SyncChangeCounter:
+ return ProcSyncChangeCounter(client);
+ case X_SyncQueryCounter:
+ return ProcSyncQueryCounter(client);
+ case X_SyncDestroyCounter:
+ return ProcSyncDestroyCounter(client);
+ case X_SyncAwait:
+ return ProcSyncAwait(client);
+ case X_SyncCreateAlarm:
+ return ProcSyncCreateAlarm(client);
+ case X_SyncChangeAlarm:
+ return ProcSyncChangeAlarm(client);
+ case X_SyncQueryAlarm:
+ return ProcSyncQueryAlarm(client);
+ case X_SyncDestroyAlarm:
+ return ProcSyncDestroyAlarm(client);
+ case X_SyncSetPriority:
+ return ProcSyncSetPriority(client);
+ case X_SyncGetPriority:
+ return ProcSyncGetPriority(client);
+ case X_SyncCreateFence:
+ return ProcSyncCreateFence(client);
+ case X_SyncTriggerFence:
+ return ProcSyncTriggerFence(client);
+ case X_SyncResetFence:
+ return ProcSyncResetFence(client);
+ case X_SyncDestroyFence:
+ return ProcSyncDestroyFence(client);
+ case X_SyncQueryFence:
+ return ProcSyncQueryFence(client);
+ case X_SyncAwaitFence:
+ return ProcSyncAwaitFence(client);
+ default:
+ return BadRequest;
+ }
+}
+
+/*
+ * Boring Swapping stuff ...
+ */
+
+static int
+SProcSyncInitialize(ClientPtr client)
+{
+ REQUEST(xSyncInitializeReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncInitializeReq);
+
+ return ProcSyncInitialize(client);
+}
+
+static int
+SProcSyncListSystemCounters(ClientPtr client)
+{
+ REQUEST(xSyncListSystemCountersReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncListSystemCountersReq);
+
+ return ProcSyncListSystemCounters(client);
+}
+
+static int
+SProcSyncCreateCounter(ClientPtr client)
+{
+ REQUEST(xSyncCreateCounterReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncCreateCounterReq);
+ swapl(&stuff->cid, n);
+ swapl(&stuff->initial_value_lo, n);
+ swapl(&stuff->initial_value_hi, n);
+
+ return ProcSyncCreateCounter(client);
+}
+
+static int
+SProcSyncSetCounter(ClientPtr client)
+{
+ REQUEST(xSyncSetCounterReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncSetCounterReq);
+ swapl(&stuff->cid, n);
+ swapl(&stuff->value_lo, n);
+ swapl(&stuff->value_hi, n);
+
+ return ProcSyncSetCounter(client);
+}
+
+static int
+SProcSyncChangeCounter(ClientPtr client)
+{
+ REQUEST(xSyncChangeCounterReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncChangeCounterReq);
+ swapl(&stuff->cid, n);
+ swapl(&stuff->value_lo, n);
+ swapl(&stuff->value_hi, n);
+
+ return ProcSyncChangeCounter(client);
+}
+
+static int
+SProcSyncQueryCounter(ClientPtr client)
+{
+ REQUEST(xSyncQueryCounterReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncQueryCounterReq);
+ swapl(&stuff->counter, n);
+
+ return ProcSyncQueryCounter(client);
+}
+
+static int
+SProcSyncDestroyCounter(ClientPtr client)
+{
+ REQUEST(xSyncDestroyCounterReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncDestroyCounterReq);
+ swapl(&stuff->counter, n);
+
+ return ProcSyncDestroyCounter(client);
+}
+
+static int
+SProcSyncAwait(ClientPtr client)
+{
+ REQUEST(xSyncAwaitReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xSyncAwaitReq);
+ SwapRestL(stuff);
+
+ return ProcSyncAwait(client);
+}
+
+static int
+SProcSyncCreateAlarm(ClientPtr client)
+{
+ REQUEST(xSyncCreateAlarmReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq);
+ swapl(&stuff->id, n);
+ swapl(&stuff->valueMask, n);
+ SwapRestL(stuff);
+
+ return ProcSyncCreateAlarm(client);
+}
+
+static int
+SProcSyncChangeAlarm(ClientPtr client)
+{
+ REQUEST(xSyncChangeAlarmReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq);
+ swapl(&stuff->alarm, n);
+ swapl(&stuff->valueMask, n);
+ SwapRestL(stuff);
+ return ProcSyncChangeAlarm(client);
+}
+
+static int
+SProcSyncQueryAlarm(ClientPtr client)
+{
+ REQUEST(xSyncQueryAlarmReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncQueryAlarmReq);
+ swapl(&stuff->alarm, n);
+
+ return ProcSyncQueryAlarm(client);
+}
+
+static int
+SProcSyncDestroyAlarm(ClientPtr client)
+{
+ REQUEST(xSyncDestroyAlarmReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncDestroyAlarmReq);
+ swapl(&stuff->alarm, n);
+
+ return ProcSyncDestroyAlarm(client);
+}
+
+static int
+SProcSyncSetPriority(ClientPtr client)
+{
+ REQUEST(xSyncSetPriorityReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncSetPriorityReq);
+ swapl(&stuff->id, n);
+ swapl(&stuff->priority, n);
+
+ return ProcSyncSetPriority(client);
+}
+
+static int
+SProcSyncGetPriority(ClientPtr client)
+{
+ REQUEST(xSyncGetPriorityReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncGetPriorityReq);
+ swapl(&stuff->id, n);
+
+ return ProcSyncGetPriority(client);
+}
+
+static int
+SProcSyncCreateFence(ClientPtr client)
+{
+ REQUEST(xSyncCreateFenceReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncCreateFenceReq);
+ swapl(&stuff->fid, n);
+
+ return ProcSyncCreateFence(client);
+}
+
+static int
+SProcSyncTriggerFence(ClientPtr client)
+{
+ REQUEST(xSyncTriggerFenceReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncTriggerFenceReq);
+ swapl(&stuff->fid, n);
+
+ return ProcSyncTriggerFence(client);
+}
+
+static int
+SProcSyncResetFence(ClientPtr client)
+{
+ REQUEST(xSyncResetFenceReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncResetFenceReq);
+ swapl(&stuff->fid, n);
+
+ return ProcSyncResetFence(client);
+}
+
+static int
+SProcSyncDestroyFence(ClientPtr client)
+{
+ REQUEST(xSyncDestroyFenceReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncDestroyFenceReq);
+ swapl(&stuff->fid, n);
+
+ return ProcSyncDestroyFence(client);
+}
+
+static int
+SProcSyncQueryFence(ClientPtr client)
+{
+ REQUEST(xSyncQueryFenceReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncQueryFenceReq);
+ swapl(&stuff->fid, n);
+
+ return ProcSyncQueryFence(client);
+}
+
+static int
+SProcSyncAwaitFence(ClientPtr client)
+{
+ REQUEST(xSyncAwaitFenceReq);
+ char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xSyncAwaitFenceReq);
+ SwapRestL(stuff);
+
+ return ProcSyncAwaitFence(client);
+}
+
+static int
+SProcSyncDispatch(ClientPtr client)
+{
+ REQUEST(xReq);
+
+ switch (stuff->data)
+ {
+ case X_SyncInitialize:
+ return SProcSyncInitialize(client);
+ case X_SyncListSystemCounters:
+ return SProcSyncListSystemCounters(client);
+ case X_SyncCreateCounter:
+ return SProcSyncCreateCounter(client);
+ case X_SyncSetCounter:
+ return SProcSyncSetCounter(client);
+ case X_SyncChangeCounter:
+ return SProcSyncChangeCounter(client);
+ case X_SyncQueryCounter:
+ return SProcSyncQueryCounter(client);
+ case X_SyncDestroyCounter:
+ return SProcSyncDestroyCounter(client);
+ case X_SyncAwait:
+ return SProcSyncAwait(client);
+ case X_SyncCreateAlarm:
+ return SProcSyncCreateAlarm(client);
+ case X_SyncChangeAlarm:
+ return SProcSyncChangeAlarm(client);
+ case X_SyncQueryAlarm:
+ return SProcSyncQueryAlarm(client);
+ case X_SyncDestroyAlarm:
+ return SProcSyncDestroyAlarm(client);
+ case X_SyncSetPriority:
+ return SProcSyncSetPriority(client);
+ case X_SyncGetPriority:
+ return SProcSyncGetPriority(client);
+ case X_SyncCreateFence:
+ return SProcSyncCreateFence(client);
+ case X_SyncTriggerFence:
+ return SProcSyncTriggerFence(client);
+ case X_SyncResetFence:
+ return SProcSyncResetFence(client);
+ case X_SyncDestroyFence:
+ return SProcSyncDestroyFence(client);
+ case X_SyncQueryFence:
+ return SProcSyncQueryFence(client);
+ case X_SyncAwaitFence:
+ return SProcSyncAwaitFence(client);
+ default:
+ return BadRequest;
+ }
+}
+
+/*
+ * Event Swapping
+ */
+
+static void
+SCounterNotifyEvent(xSyncCounterNotifyEvent *from, xSyncCounterNotifyEvent *to)
+{
+ to->type = from->type;
+ to->kind = from->kind;
+ cpswaps(from->sequenceNumber, to->sequenceNumber);
+ cpswapl(from->counter, to->counter);
+ cpswapl(from->wait_value_lo, to->wait_value_lo);
+ cpswapl(from->wait_value_hi, to->wait_value_hi);
+ cpswapl(from->counter_value_lo, to->counter_value_lo);
+ cpswapl(from->counter_value_hi, to->counter_value_hi);
+ cpswapl(from->time, to->time);
+ cpswaps(from->count, to->count);
+ to->destroyed = from->destroyed;
+}
+
+
+static void
+SAlarmNotifyEvent(xSyncAlarmNotifyEvent *from, xSyncAlarmNotifyEvent *to)
+{
+ to->type = from->type;
+ to->kind = from->kind;
+ cpswaps(from->sequenceNumber, to->sequenceNumber);
+ cpswapl(from->alarm, to->alarm);
+ cpswapl(from->counter_value_lo, to->counter_value_lo);
+ cpswapl(from->counter_value_hi, to->counter_value_hi);
+ cpswapl(from->alarm_value_lo, to->alarm_value_lo);
+ cpswapl(from->alarm_value_hi, to->alarm_value_hi);
+ cpswapl(from->time, to->time);
+ to->state = from->state;
+}
+
+/*
+ * ** Close everything down. ** This is fairly simple for now.
+ */
+/* ARGSUSED */
+static void
+SyncResetProc(ExtensionEntry *extEntry)
+{
+ free(SysCounterList);
+ SysCounterList = NULL;
+ RTCounter = 0;
+}
+
+/*
+ * ** Initialise the extension.
+ */
+void
+SyncExtensionInit(void)
+{
+ ExtensionEntry *extEntry;
+ int s;
+
+ for (s = 0; s < screenInfo.numScreens; s++)
+ miSyncSetup(screenInfo.screens[s]);
+
+ if (RTCounter == 0)
+ {
+ RTCounter = CreateNewResourceType(FreeCounter, "SyncCounter");
+ }
+ RTAlarm = CreateNewResourceType(FreeAlarm, "SyncAlarm");
+ RTAwait = CreateNewResourceType(FreeAwait, "SyncAwait");
+ RTFence = CreateNewResourceType(FreeFence, "SyncFence");
+ if (RTAwait)
+ RTAwait |= RC_NEVERRETAIN;
+ RTAlarmClient = CreateNewResourceType(FreeAlarmClient, "SyncAlarmClient");
+ if (RTAlarmClient)
+ RTAlarmClient |= RC_NEVERRETAIN;
+
+ if (RTCounter == 0 || RTAwait == 0 || RTAlarm == 0 ||
+ RTAlarmClient == 0 ||
+ (extEntry = AddExtension(SYNC_NAME,
+ XSyncNumberEvents, XSyncNumberErrors,
+ ProcSyncDispatch, SProcSyncDispatch,
+ SyncResetProc,
+ StandardMinorOpcode)) == NULL)
+ {
+ ErrorF("Sync Extension %d.%d failed to Initialise\n",
+ SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION);
+ return;
+ }
+
+ SyncEventBase = extEntry->eventBase;
+ SyncErrorBase = extEntry->errorBase;
+ EventSwapVector[SyncEventBase + XSyncCounterNotify] = (EventSwapPtr) SCounterNotifyEvent;
+ EventSwapVector[SyncEventBase + XSyncAlarmNotify] = (EventSwapPtr) SAlarmNotifyEvent;
+
+ SetResourceTypeErrorValue(RTCounter, SyncErrorBase + XSyncBadCounter);
+ SetResourceTypeErrorValue(RTAlarm, SyncErrorBase + XSyncBadAlarm);
+ SetResourceTypeErrorValue(RTFence, SyncErrorBase + XSyncBadFence);
+
+ /*
+ * Although SERVERTIME is implemented by the OS layer, we initialise it
+ * here because doing it in OsInit() is too early. The resource database
+ * is not initialised when OsInit() is called. This is just about OK
+ * because there is always a servertime counter.
+ */
+ SyncInitServerTime();
+ SyncInitIdleTime();
+
+#ifdef DEBUG
+ fprintf(stderr, "Sync Extension %d.%d\n",
+ SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION);
+#endif
+}
+
+
+/*
+ * ***** SERVERTIME implementation - should go in its own file in OS directory?
+ */
+
+
+
+static pointer ServertimeCounter;
+static XSyncValue Now;
+static XSyncValue *pnext_time;
+
+#define GetTime()\
+{\
+ unsigned long millis = GetTimeInMillis();\
+ unsigned long maxis = XSyncValueHigh32(Now);\
+ if (millis < XSyncValueLow32(Now)) maxis++;\
+ XSyncIntsToValue(&Now, millis, maxis);\
+}
+
+/*
+*** Server Block Handler
+*** code inspired by multibuffer extension (now deprecated)
+ */
+/*ARGSUSED*/
+static void
+ServertimeBlockHandler(void *env, struct timeval **wt, void *LastSelectMask)
+{
+ XSyncValue delay;
+ unsigned long timeout;
+
+ if (pnext_time)
+ {
+ GetTime();
+
+ if (XSyncValueGreaterOrEqual(Now, *pnext_time))
+ {
+ timeout = 0;
+ }
+ else
+ {
+ Bool overflow;
+ XSyncValueSubtract(&delay, *pnext_time, Now, &overflow);
+ (void)overflow;
+ timeout = XSyncValueLow32(delay);
+ }
+ AdjustWaitForDelay(wt, timeout); /* os/utils.c */
+ }
+}
+
+/*
+*** Wakeup Handler
+ */
+/*ARGSUSED*/
+static void
+ServertimeWakeupHandler(void *env, int rc, void *LastSelectMask)
+{
+ if (pnext_time)
+ {
+ GetTime();
+
+ if (XSyncValueGreaterOrEqual(Now, *pnext_time))
+ {
+ SyncChangeCounter(ServertimeCounter, Now);
+ }
+ }
+}
+
+static void
+ServertimeQueryValue(void *pCounter, CARD64 *pValue_return)
+{
+ GetTime();
+ *pValue_return = Now;
+}
+
+static void
+ServertimeBracketValues(void *pCounter, CARD64 *pbracket_less,
+ CARD64 *pbracket_greater)
+{
+ if (!pnext_time && pbracket_greater)
+ {
+ RegisterBlockAndWakeupHandlers(ServertimeBlockHandler,
+ ServertimeWakeupHandler,
+ NULL);
+ }
+ else if (pnext_time && !pbracket_greater)
+ {
+ RemoveBlockAndWakeupHandlers(ServertimeBlockHandler,
+ ServertimeWakeupHandler,
+ NULL);
+ }
+ pnext_time = pbracket_greater;
+}
+
+static void
+SyncInitServerTime(void)
+{
+ CARD64 resolution;
+
+ XSyncIntsToValue(&Now, GetTimeInMillis(), 0);
+ XSyncIntToValue(&resolution, 4);
+ ServertimeCounter = SyncCreateSystemCounter("SERVERTIME", Now, resolution,
+ XSyncCounterNeverDecreases,
+ ServertimeQueryValue, ServertimeBracketValues);
+ pnext_time = NULL;
+}
+
+
+
+/*
+ * IDLETIME implementation
+ */
+
+static SyncCounter *IdleTimeCounter;
+static XSyncValue *pIdleTimeValueLess;
+static XSyncValue *pIdleTimeValueGreater;
+
+static void
+IdleTimeQueryValue (pointer pCounter, CARD64 *pValue_return)
+{
+ CARD32 idle = GetTimeInMillis() - lastDeviceEventTime.milliseconds;
+ XSyncIntsToValue (pValue_return, idle, 0);
+}
+
+static void
+IdleTimeBlockHandler(pointer env, struct timeval **wt, pointer LastSelectMask)
+{
+ XSyncValue idle, old_idle;
+ SyncTriggerList *list = IdleTimeCounter->sync.pTriglist;
+ SyncTrigger *trig;
+
+ if (!pIdleTimeValueLess && !pIdleTimeValueGreater)
+ return;
+
+ old_idle = IdleTimeCounter->value;
+ IdleTimeQueryValue (NULL, &idle);
+ IdleTimeCounter->value = idle; /* push, so CheckTrigger works */
+
+ if (pIdleTimeValueLess &&
+ XSyncValueLessOrEqual (idle, *pIdleTimeValueLess))
+ {
+ /*
+ * We've been idle for less than the threshold value, and someone
+ * wants to know about that, but now we need to know whether they
+ * want level or edge trigger. Check the trigger list against the
+ * current idle time, and if any succeed, bomb out of select()
+ * immediately so we can reschedule.
+ */
+
+ for (list = IdleTimeCounter->sync.pTriglist; list; list = list->next) {
+ trig = list->pTrigger;
+ if (trig->CheckTrigger(trig, old_idle)) {
+ AdjustWaitForDelay(wt, 0);
+ break;
+ }
+ }
+ /*
+ * We've been called exactly on the idle time, but we have a
+ * NegativeTransition trigger which requires a transition from an
+ * idle time greater than this. Schedule a wakeup for the next
+ * millisecond so we won't miss a transition.
+ */
+ if (XSyncValueEqual (idle, *pIdleTimeValueLess))
+ AdjustWaitForDelay(wt, 1);
+ }
+ else if (pIdleTimeValueGreater)
+ {
+ /*
+ * There's a threshold in the positive direction. If we've been
+ * idle less than it, schedule a wakeup for sometime in the future.
+ * If we've been idle more than it, and someone wants to know about
+ * that level-triggered, schedule an immediate wakeup.
+ */
+ unsigned long timeout = -1;
+
+ if (XSyncValueLessThan (idle, *pIdleTimeValueGreater)) {
+ XSyncValue value;
+ Bool overflow;
+
+ XSyncValueSubtract (&value, *pIdleTimeValueGreater,
+ idle, &overflow);
+ timeout = min(timeout, XSyncValueLow32 (value));
+ } else {
+ for (list = IdleTimeCounter->sync.pTriglist; list; list = list->next) {
+ trig = list->pTrigger;
+ if (trig->CheckTrigger(trig, old_idle)) {
+ timeout = min(timeout, 0);
+ break;
+ }
+ }
+ }
+
+ AdjustWaitForDelay (wt, timeout);
+ }
+
+ IdleTimeCounter->value = old_idle; /* pop */
+}
+
+static void
+IdleTimeWakeupHandler (pointer env, int rc, pointer LastSelectMask)
+{
+ XSyncValue idle;
+
+ if (!pIdleTimeValueLess && !pIdleTimeValueGreater)
+ return;
+
+ IdleTimeQueryValue (NULL, &idle);
+
+ if ((pIdleTimeValueGreater &&
+ XSyncValueGreaterOrEqual (idle, *pIdleTimeValueGreater)) ||
+ (pIdleTimeValueLess &&
+ XSyncValueLessOrEqual (idle, *pIdleTimeValueLess)))
+ {
+ SyncChangeCounter (IdleTimeCounter, idle);
+ }
+}
+
+static void
+IdleTimeBracketValues (pointer pCounter, CARD64 *pbracket_less,
+ CARD64 *pbracket_greater)
+{
+ Bool registered = (pIdleTimeValueLess || pIdleTimeValueGreater);
+
+ if (registered && !pbracket_less && !pbracket_greater)
+ {
+ RemoveBlockAndWakeupHandlers(IdleTimeBlockHandler,
+ IdleTimeWakeupHandler,
+ NULL);
+ }
+ else if (!registered && (pbracket_less || pbracket_greater))
+ {
+ RegisterBlockAndWakeupHandlers(IdleTimeBlockHandler,
+ IdleTimeWakeupHandler,
+ NULL);
+ }
+
+ pIdleTimeValueGreater = pbracket_greater;
+ pIdleTimeValueLess = pbracket_less;
+}
+
+static void
+SyncInitIdleTime (void)
+{
+ CARD64 resolution;
+ XSyncValue idle;
+
+ IdleTimeQueryValue (NULL, &idle);
+ XSyncIntToValue (&resolution, 4);
+
+ IdleTimeCounter = SyncCreateSystemCounter ("IDLETIME", idle, resolution,
+ XSyncCounterUnrestricted,
+ IdleTimeQueryValue,
+ IdleTimeBracketValues);
+
+ pIdleTimeValueLess = pIdleTimeValueGreater = NULL;
+}
diff --git a/xorg-server/Xi/xigrabdev.c b/xorg-server/Xi/xigrabdev.c
index 24ededcb1..05c732c89 100644
--- a/xorg-server/Xi/xigrabdev.c
+++ b/xorg-server/Xi/xigrabdev.c
@@ -1,161 +1,161 @@
-/*
- * Copyright © 2009 Red Hat, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Author: Peter Hutterer
- */
-
-/***********************************************************************
- *
- * Request to grab or ungrab input device.
- *
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "inputstr.h" /* DeviceIntPtr */
-#include "windowstr.h" /* window structure */
-#include <X11/extensions/XI2.h>
-#include <X11/extensions/XI2proto.h>
-
-#include "exglobals.h" /* BadDevice */
-#include "exevents.h"
-#include "xigrabdev.h"
-
-int
-SProcXIGrabDevice(ClientPtr client)
-{
- char n;
-
- REQUEST(xXIGrabDeviceReq);
-
- swaps(&stuff->length, n);
- swaps(&stuff->deviceid, n);
- swapl(&stuff->grab_window, n);
- swapl(&stuff->cursor, n);
- swapl(&stuff->time, n);
- swaps(&stuff->mask_len, n);
-
- return ProcXIGrabDevice(client);
-}
-
-int
-ProcXIGrabDevice(ClientPtr client)
-{
- DeviceIntPtr dev;
- xXIGrabDeviceReply rep;
- int ret = Success;
- uint8_t status;
- GrabMask mask;
- int mask_len;
-
- REQUEST(xXIGrabDeviceReq);
- REQUEST_AT_LEAST_SIZE(xXIGrabDeviceReq);
-
- ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess);
- if (ret != Success)
- return ret;
-
- if (!IsMaster(dev))
- stuff->paired_device_mode = GrabModeAsync;
-
- if (XICheckInvalidMaskBits((unsigned char*)&stuff[1],
- stuff->mask_len * 4) != Success)
- return BadValue;
-
- mask_len = min(sizeof(mask.xi2mask[stuff->deviceid]), stuff->mask_len * 4);
- memset(mask.xi2mask, 0, sizeof(mask.xi2mask));
- memcpy(mask.xi2mask, (char*)&stuff[1], mask_len);
-
- ret = GrabDevice(client, dev, stuff->grab_mode,
- stuff->paired_device_mode,
- stuff->grab_window,
- stuff->owner_events,
- stuff->time,
- &mask,
- GRABTYPE_XI2,
- stuff->cursor,
- None /* confineTo */,
- &status);
-
- if (ret != Success)
- return ret;
-
- rep.repType = X_Reply;
- rep.RepType = X_XIGrabDevice;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
- rep.status = status;
-
-
- WriteReplyToClient(client, sizeof(rep), &rep);
- return ret;
-}
-
-int
-SProcXIUngrabDevice(ClientPtr client)
-{
- char n;
-
- REQUEST(xXIUngrabDeviceReq);
-
- swaps(&stuff->length, n);
- swaps(&stuff->deviceid, n);
- swapl(&stuff->time, n);
-
- return ProcXIUngrabDevice(client);
-}
-
-int
-ProcXIUngrabDevice(ClientPtr client)
-{
- DeviceIntPtr dev;
- GrabPtr grab;
- int ret = Success;
- TimeStamp time;
-
- REQUEST(xXIUngrabDeviceReq);
-
- ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGetAttrAccess);
- if (ret != Success)
- return ret;
-
- grab = dev->deviceGrab.grab;
-
- time = ClientTimeToServerTime(stuff->time);
- if ((CompareTimeStamps(time, currentTime) != LATER) &&
- (CompareTimeStamps(time, dev->deviceGrab.grabTime) != EARLIER) &&
- (grab) && SameClient(grab, client) && grab->grabtype == GRABTYPE_XI2)
- (*dev->deviceGrab.DeactivateGrab) (dev);
-
- return Success;
-}
-
-void SRepXIGrabDevice(ClientPtr client, int size, xXIGrabDeviceReply * rep)
-{
- char n;
-
- swaps(&rep->sequenceNumber, n);
- swapl(&rep->length, n);
- WriteToClient(client, size, (char *)rep);
-}
+/*
+ * Copyright © 2009 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Peter Hutterer
+ */
+
+/***********************************************************************
+ *
+ * Request to grab or ungrab input device.
+ *
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "inputstr.h" /* DeviceIntPtr */
+#include "windowstr.h" /* window structure */
+#include <X11/extensions/XI2.h>
+#include <X11/extensions/XI2proto.h>
+
+#include "exglobals.h" /* BadDevice */
+#include "exevents.h"
+#include "xigrabdev.h"
+
+int
+SProcXIGrabDevice(ClientPtr client)
+{
+ char n;
+
+ REQUEST(xXIGrabDeviceReq);
+
+ swaps(&stuff->length, n);
+ swaps(&stuff->deviceid, n);
+ swapl(&stuff->grab_window, n);
+ swapl(&stuff->cursor, n);
+ swapl(&stuff->time, n);
+ swaps(&stuff->mask_len, n);
+
+ return ProcXIGrabDevice(client);
+}
+
+int
+ProcXIGrabDevice(ClientPtr client)
+{
+ DeviceIntPtr dev;
+ xXIGrabDeviceReply rep;
+ int ret = Success;
+ uint8_t status;
+ GrabMask mask;
+ int mask_len;
+
+ REQUEST(xXIGrabDeviceReq);
+ REQUEST_AT_LEAST_SIZE(xXIGrabDeviceReq);
+
+ ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess);
+ if (ret != Success)
+ return ret;
+
+ if (!IsMaster(dev))
+ stuff->paired_device_mode = GrabModeAsync;
+
+ if (XICheckInvalidMaskBits(client, (unsigned char*)&stuff[1],
+ stuff->mask_len * 4) != Success)
+ return BadValue;
+
+ mask_len = min(sizeof(mask.xi2mask[stuff->deviceid]), stuff->mask_len * 4);
+ memset(mask.xi2mask, 0, sizeof(mask.xi2mask));
+ memcpy(mask.xi2mask, (char*)&stuff[1], mask_len);
+
+ ret = GrabDevice(client, dev, stuff->grab_mode,
+ stuff->paired_device_mode,
+ stuff->grab_window,
+ stuff->owner_events,
+ stuff->time,
+ &mask,
+ GRABTYPE_XI2,
+ stuff->cursor,
+ None /* confineTo */,
+ &status);
+
+ if (ret != Success)
+ return ret;
+
+ rep.repType = X_Reply;
+ rep.RepType = X_XIGrabDevice;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.status = status;
+
+
+ WriteReplyToClient(client, sizeof(rep), &rep);
+ return ret;
+}
+
+int
+SProcXIUngrabDevice(ClientPtr client)
+{
+ char n;
+
+ REQUEST(xXIUngrabDeviceReq);
+
+ swaps(&stuff->length, n);
+ swaps(&stuff->deviceid, n);
+ swapl(&stuff->time, n);
+
+ return ProcXIUngrabDevice(client);
+}
+
+int
+ProcXIUngrabDevice(ClientPtr client)
+{
+ DeviceIntPtr dev;
+ GrabPtr grab;
+ int ret = Success;
+ TimeStamp time;
+
+ REQUEST(xXIUngrabDeviceReq);
+
+ ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGetAttrAccess);
+ if (ret != Success)
+ return ret;
+
+ grab = dev->deviceGrab.grab;
+
+ time = ClientTimeToServerTime(stuff->time);
+ if ((CompareTimeStamps(time, currentTime) != LATER) &&
+ (CompareTimeStamps(time, dev->deviceGrab.grabTime) != EARLIER) &&
+ (grab) && SameClient(grab, client) && grab->grabtype == GRABTYPE_XI2)
+ (*dev->deviceGrab.DeactivateGrab) (dev);
+
+ return Success;
+}
+
+void SRepXIGrabDevice(ClientPtr client, int size, xXIGrabDeviceReply * rep)
+{
+ char n;
+
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+ WriteToClient(client, size, (char *)rep);
+}
diff --git a/xorg-server/Xi/xipassivegrab.c b/xorg-server/Xi/xipassivegrab.c
index fc3b9e7eb..6b689f45e 100644
--- a/xorg-server/Xi/xipassivegrab.c
+++ b/xorg-server/Xi/xipassivegrab.c
@@ -118,7 +118,7 @@ ProcXIPassiveGrabDevice(ClientPtr client)
return BadValue;
}
- if (XICheckInvalidMaskBits((unsigned char*)&stuff[1],
+ if (XICheckInvalidMaskBits(client, (unsigned char*)&stuff[1],
stuff->mask_len * 4) != Success)
return BadValue;
diff --git a/xorg-server/Xi/xiselectev.c b/xorg-server/Xi/xiselectev.c
index 6a810bce4..6f26b3d08 100644
--- a/xorg-server/Xi/xiselectev.c
+++ b/xorg-server/Xi/xiselectev.c
@@ -42,14 +42,19 @@
*
* @return BadValue if at least one invalid bit is set or Success otherwise.
*/
-int XICheckInvalidMaskBits(unsigned char *mask, int len)
+int XICheckInvalidMaskBits(ClientPtr client, unsigned char *mask, int len)
{
if (len >= XIMaskLen(XI2LASTEVENT))
{
int i;
for (i = XI2LASTEVENT + 1; i < len * 8; i++)
+ {
if (BitIsOn(mask, i))
+ {
+ client->errorValue = i;
return BadValue;
+ }
+ }
}
return Success;
@@ -126,7 +131,10 @@ ProcXISelectEvents(ClientPtr client)
{
unsigned char *bits = (unsigned char*)&evmask[1];
if (BitIsOn(bits, XI_HierarchyChanged))
+ {
+ client->errorValue = XI_HierarchyChanged;
return BadValue;
+ }
}
/* Raw events may only be selected on root windows */
@@ -138,10 +146,13 @@ ProcXISelectEvents(ClientPtr client)
BitIsOn(bits, XI_RawButtonPress) ||
BitIsOn(bits, XI_RawButtonRelease) ||
BitIsOn(bits, XI_RawMotion))
+ {
+ client->errorValue = XI_RawKeyPress;
return BadValue;
+ }
}
- if (XICheckInvalidMaskBits((unsigned char*)&evmask[1],
+ if (XICheckInvalidMaskBits(client, (unsigned char*)&evmask[1],
evmask->mask_len * 4) != Success)
return BadValue;
diff --git a/xorg-server/composite/compalloc.c b/xorg-server/composite/compalloc.c
index 4d0d4ad1c..745166621 100644
--- a/xorg-server/composite/compalloc.c
+++ b/xorg-server/composite/compalloc.c
@@ -48,6 +48,30 @@
#include "compint.h"
static void
+compScreenUpdate (ScreenPtr pScreen)
+{
+ compCheckTree (pScreen);
+ compPaintChildrenToWindow (pScreen->root);
+}
+
+static void
+compBlockHandler (int i,
+ pointer blockData,
+ pointer pTimeout,
+ pointer pReadmask)
+{
+ ScreenPtr pScreen = screenInfo.screens[i];
+ CompScreenPtr cs = GetCompScreen (pScreen);
+
+ pScreen->BlockHandler = cs->BlockHandler;
+ compScreenUpdate (pScreen);
+ (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
+
+ /* Next damage will restore the block handler */
+ cs->BlockHandler = NULL;
+}
+
+static void
compReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
{
WindowPtr pWin = (WindowPtr) closure;
@@ -55,8 +79,20 @@ compReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
CompScreenPtr cs = GetCompScreen (pScreen);
CompWindowPtr cw = GetCompWindow (pWin);
- cs->damaged = TRUE;
+ if (!cs->BlockHandler) {
+ cs->BlockHandler = pScreen->BlockHandler;
+ pScreen->BlockHandler = compBlockHandler;
+ }
cw->damaged = TRUE;
+
+ /* Mark the ancestors */
+ pWin = pWin->parent;
+ while (pWin) {
+ if (pWin->damagedDescendants)
+ break;
+ pWin->damagedDescendants = TRUE;
+ pWin = pWin->parent;
+ }
}
static void
diff --git a/xorg-server/composite/compinit.c b/xorg-server/composite/compinit.c
index 98b8d0565..291b759be 100644
--- a/xorg-server/composite/compinit.c
+++ b/xorg-server/composite/compinit.c
@@ -61,7 +61,6 @@ compCloseScreen (int index, ScreenPtr pScreen)
free(cs->alternateVisuals);
pScreen->CloseScreen = cs->CloseScreen;
- pScreen->BlockHandler = cs->BlockHandler;
pScreen->InstallColormap = cs->InstallColormap;
pScreen->ChangeWindowAttributes = cs->ChangeWindowAttributes;
pScreen->ReparentWindow = cs->ReparentWindow;
@@ -78,6 +77,9 @@ compCloseScreen (int index, ScreenPtr pScreen)
pScreen->CopyWindow = cs->CopyWindow;
pScreen->PositionWindow = cs->PositionWindow;
+ pScreen->GetImage = cs->GetImage;
+ pScreen->SourceValidate = cs->SourceValidate;
+
free(cs);
dixSetPrivate(&pScreen->devPrivates, CompScreenPrivateKey, NULL);
ret = (*pScreen->CloseScreen) (index, pScreen);
@@ -131,32 +133,40 @@ compChangeWindowAttributes(WindowPtr pWin, unsigned long mask)
}
static void
-compScreenUpdate (ScreenPtr pScreen)
+compGetImage (DrawablePtr pDrawable,
+ int sx, int sy,
+ int w, int h,
+ unsigned int format,
+ unsigned long planemask,
+ char *pdstLine)
{
- CompScreenPtr cs = GetCompScreen (pScreen);
+ ScreenPtr pScreen = pDrawable->pScreen;
+ CompScreenPtr cs = GetCompScreen (pScreen);
- compCheckTree (pScreen);
- if (cs->damaged)
- {
- compWindowUpdate (pScreen->root);
- cs->damaged = FALSE;
- }
+ pScreen->GetImage = cs->GetImage;
+ if (pDrawable->type == DRAWABLE_WINDOW)
+ compPaintChildrenToWindow ((WindowPtr) pDrawable);
+ (*pScreen->GetImage) (pDrawable, sx, sy, w, h, format, planemask, pdstLine);
+ cs->GetImage = pScreen->GetImage;
+ pScreen->GetImage = compGetImage;
}
-static void
-compBlockHandler (int i,
- pointer blockData,
- pointer pTimeout,
- pointer pReadmask)
+static void compSourceValidate(DrawablePtr pDrawable,
+ int x, int y,
+ int width, int height,
+ unsigned int subWindowMode)
{
- ScreenPtr pScreen = screenInfo.screens[i];
- CompScreenPtr cs = GetCompScreen (pScreen);
+ ScreenPtr pScreen = pDrawable->pScreen;
+ CompScreenPtr cs = GetCompScreen (pScreen);
- pScreen->BlockHandler = cs->BlockHandler;
- compScreenUpdate (pScreen);
- (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
- cs->BlockHandler = pScreen->BlockHandler;
- pScreen->BlockHandler = compBlockHandler;
+ pScreen->SourceValidate = cs->SourceValidate;
+ if (pDrawable->type == DRAWABLE_WINDOW && subWindowMode == IncludeInferiors)
+ compPaintChildrenToWindow ((WindowPtr) pDrawable);
+ if (pScreen->SourceValidate)
+ (*pScreen->SourceValidate) (pDrawable, x, y, width, height,
+ subWindowMode);
+ cs->SourceValidate = pScreen->SourceValidate;
+ pScreen->SourceValidate = compSourceValidate;
}
/*
@@ -331,7 +341,6 @@ compScreenInit (ScreenPtr pScreen)
if (!cs)
return FALSE;
- cs->damaged = FALSE;
cs->overlayWid = FakeClientID(0);
cs->pOverlayWin = NULL;
cs->pOverlayClients = NULL;
@@ -387,12 +396,17 @@ compScreenInit (ScreenPtr pScreen)
cs->ChangeWindowAttributes = pScreen->ChangeWindowAttributes;
pScreen->ChangeWindowAttributes = compChangeWindowAttributes;
- cs->BlockHandler = pScreen->BlockHandler;
- pScreen->BlockHandler = compBlockHandler;
+ cs->BlockHandler = NULL;
cs->CloseScreen = pScreen->CloseScreen;
pScreen->CloseScreen = compCloseScreen;
+ cs->GetImage = pScreen->GetImage;
+ pScreen->GetImage = compGetImage;
+
+ cs->SourceValidate = pScreen->SourceValidate;
+ pScreen->SourceValidate = compSourceValidate;
+
dixSetPrivate(&pScreen->devPrivates, CompScreenPrivateKey, cs);
RegisterRealChildHeadProc(CompositeRealChildHead);
diff --git a/xorg-server/composite/compint.h b/xorg-server/composite/compint.h
index a85d62faa..55cd6459e 100644
--- a/xorg-server/composite/compint.h
+++ b/xorg-server/composite/compint.h
@@ -152,7 +152,6 @@ typedef struct _CompScreen {
ScreenBlockHandlerProcPtr BlockHandler;
CloseScreenProcPtr CloseScreen;
- Bool damaged;
int numAlternateVisuals;
VisualID *alternateVisuals;
@@ -160,6 +159,8 @@ typedef struct _CompScreen {
Window overlayWid;
CompOverlayClientPtr pOverlayClients;
+ GetImageProcPtr GetImage;
+ SourceValidateProcPtr SourceValidate;
} CompScreenRec, *CompScreenPtr;
extern DevPrivateKeyRec CompScreenPrivateKeyRec;
@@ -314,7 +315,7 @@ void
compCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc);
void
-compWindowUpdate (WindowPtr pWin);
+compPaintChildrenToWindow (WindowPtr pWin);
WindowPtr
CompositeRealChildHead (WindowPtr pWin);
diff --git a/xorg-server/composite/compwindow.c b/xorg-server/composite/compwindow.c
index 11df8b39d..ef1f7f154 100644
--- a/xorg-server/composite/compwindow.c
+++ b/xorg-server/composite/compwindow.c
@@ -653,9 +653,10 @@ compWindowFormat (WindowPtr pWin)
}
static void
-compWindowUpdateAutomatic (WindowPtr pWin, ScreenPtr pScreen)
+compWindowUpdateAutomatic (WindowPtr pWin)
{
CompWindowPtr cw = GetCompWindow (pWin);
+ ScreenPtr pScreen = pWin->drawable.pScreen;
WindowPtr pParent = pWin->parent;
PixmapPtr pSrcPixmap = (*pScreen->GetWindowPixmap) (pWin);
PictFormatPtr pSrcFormat = compWindowFormat (pWin);
@@ -678,7 +679,8 @@ compWindowUpdateAutomatic (WindowPtr pWin, ScreenPtr pScreen)
/*
* First move the region from window to screen coordinates
*/
- RegionTranslate(pRegion, pWin->drawable.x, pWin->drawable.y);
+ RegionTranslate(pRegion,
+ pWin->drawable.x, pWin->drawable.y);
/*
* Clip against the "real" border clip
@@ -688,7 +690,8 @@ compWindowUpdateAutomatic (WindowPtr pWin, ScreenPtr pScreen)
/*
* Now translate from screen to dest coordinates
*/
- RegionTranslate(pRegion, -pParent->drawable.x, -pParent->drawable.y);
+ RegionTranslate(pRegion,
+ -pParent->drawable.x, -pParent->drawable.y);
/*
* Clip the picture
@@ -717,26 +720,35 @@ compWindowUpdateAutomatic (WindowPtr pWin, ScreenPtr pScreen)
DamageEmpty (cw->damage);
}
-static int
-compWindowUpdateVisit(WindowPtr pWin, void *data)
+static void
+compPaintWindowToParent (WindowPtr pWin)
{
+ compPaintChildrenToWindow (pWin);
+
if (pWin->redirectDraw != RedirectDrawNone)
{
- CompWindowPtr cw = GetCompWindow(pWin);
+ CompWindowPtr cw = GetCompWindow(pWin);
+
if (cw->damaged)
{
- compWindowUpdateAutomatic(pWin, data);
+ compWindowUpdateAutomatic (pWin);
cw->damaged = FALSE;
}
}
-
- return WT_WALKCHILDREN;
}
void
-compWindowUpdate (WindowPtr pWin)
+compPaintChildrenToWindow (WindowPtr pWin)
{
- TraverseTree(pWin, compWindowUpdateVisit, pWin->drawable.pScreen);
+ WindowPtr pChild;
+
+ if (!pWin->damagedDescendants)
+ return;
+
+ for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib)
+ compPaintWindowToParent (pChild);
+
+ pWin->damagedDescendants = FALSE;
}
WindowPtr
diff --git a/xorg-server/config/udev.c b/xorg-server/config/udev.c
index 43e653d2b..eeacff162 100644
--- a/xorg-server/config/udev.c
+++ b/xorg-server/config/udev.c
@@ -94,6 +94,7 @@ device_added(struct udev_device *udev_device)
if (parent) {
const char *ppath = udev_device_get_devnode(parent);
const char *product = udev_device_get_property_value(parent, "PRODUCT");
+ const char *pnp_id = udev_device_get_sysattr_value(parent, "id");
unsigned int usb_vendor, usb_model;
name = udev_device_get_sysattr_value(parent, "name");
@@ -103,8 +104,9 @@ device_added(struct udev_device *udev_device)
LOG_PROPERTY(ppath, "NAME", name);
}
- attrs.pnp_id = udev_device_get_sysattr_value(parent, "id");
- LOG_SYSATTR(ppath, "id", attrs.pnp_id);
+ if (pnp_id)
+ attrs.pnp_id = strdup(pnp_id);
+ LOG_SYSATTR(ppath, "id", pnp_id);
/* construct USB ID in lowercase hex - "0000:ffff" */
if (product && sscanf(product, "%*x/%4x/%4x/%*x", &usb_vendor, &usb_model) == 2) {
@@ -118,12 +120,13 @@ device_added(struct udev_device *udev_device)
if (!name)
name = "(unnamed)";
else
- attrs.product = name;
+ attrs.product = strdup(name);
add_option(&options, "name", name);
add_option(&options, "path", path);
add_option(&options, "device", path);
- attrs.device = path;
+ if (path)
+ attrs.device = strdup(path);
tags_prop = udev_device_get_property_value(udev_device, "ID_INPUT.tags");
LOG_PROPERTY(path, "ID_INPUT.tags", tags_prop);
@@ -162,7 +165,7 @@ device_added(struct udev_device *udev_device)
add_option(&options, "xkb_options", value);
} else if (!strcmp(key, "ID_VENDOR")) {
LOG_PROPERTY(path, key, value);
- attrs.vendor = value;
+ attrs.vendor = strdup(value);
} else if (!strcmp(key, "ID_INPUT_KEY")) {
LOG_PROPERTY(path, key, value);
attrs.flags |= ATTR_KEYBOARD;
@@ -202,6 +205,10 @@ device_added(struct udev_device *udev_device)
}
free(attrs.usb_id);
+ free(attrs.pnp_id);
+ free(attrs.product);
+ free(attrs.device);
+ free(attrs.vendor);
if (attrs.tags) {
char **tag = attrs.tags;
while (*tag) {
@@ -307,7 +314,7 @@ config_udev_fini(void)
udev = udev_monitor_get_udev(udev_monitor);
RemoveGeneralSocket(udev_monitor_get_fd(udev_monitor));
- RemoveBlockAndWakeupHandlers(block_handler, wakeup_handler, udev_monitor);
+ RemoveBlockAndWakeupHandlers(block_handler, wakeup_handler, NULL);
udev_monitor_unref(udev_monitor);
udev_monitor = NULL;
udev_unref(udev);
diff --git a/xorg-server/dix/events.c b/xorg-server/dix/events.c
index 0667cc293..361d6102a 100644
--- a/xorg-server/dix/events.c
+++ b/xorg-server/dix/events.c
@@ -195,8 +195,6 @@ typedef const char *string;
#define XE_KBPTR (xE->u.keyButtonPointer)
-#define rClient(obj) (clients[CLIENT_ID((obj)->resource)])
-
CallbackListPtr EventCallback;
CallbackListPtr DeviceEventCallback;
@@ -2292,17 +2290,6 @@ FixUpEventFromWindow(
}
/**
- * Return masks for EventIsDeliverable.
- * @defgroup EventIsDeliverable return flags
- * @{
- */
-#define XI_MASK (1 << 0) /**< XI mask set on window */
-#define CORE_MASK (1 << 1) /**< Core mask set on window */
-#define DONT_PROPAGATE_MASK (1 << 2) /**< DontPropagate mask set on window */
-#define XI2_MASK (1 << 3) /**< XI2 mask set on window */
-/* @} */
-
-/**
* Check if a given event is deliverable at all on a given window.
*
* This function only checks if any client wants it, not for a specific
@@ -2315,7 +2302,7 @@ FixUpEventFromWindow(
* @return Bitmask of ::XI2_MASK, ::XI_MASK, ::CORE_MASK, and
* ::DONT_PROPAGATE_MASK.
*/
-static int
+int
EventIsDeliverable(DeviceIntPtr dev, InternalEvent* event, WindowPtr win)
{
int rc = 0;
diff --git a/xorg-server/dix/property.c b/xorg-server/dix/property.c
index 2ba3f4419..53b9821a9 100644
--- a/xorg-server/dix/property.c
+++ b/xorg-server/dix/property.c
@@ -424,6 +424,9 @@ DeleteAllWindowProperties(WindowPtr pWin)
dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
pProp = pNextProp;
}
+
+ if (pWin->optional)
+ pWin->optional->userProps = NULL;
}
static int
diff --git a/xorg-server/dix/window.c b/xorg-server/dix/window.c
index 399e08635..c2cee9198 100644
--- a/xorg-server/dix/window.c
+++ b/xorg-server/dix/window.c
@@ -298,6 +298,10 @@ SetWindowToDefaults(WindowPtr pWin)
#ifdef ROOTLESS
pWin->rootlessUnhittable = FALSE;
#endif
+
+#ifdef COMPOSITE
+ pWin->damagedDescendants = FALSE;
+#endif
}
static void
diff --git a/xorg-server/doc/xml/Xserver-spec.xml b/xorg-server/doc/xml/Xserver-spec.xml
index c31a8c4e2..a48e88754 100644
--- a/xorg-server/doc/xml/Xserver-spec.xml
+++ b/xorg-server/doc/xml/Xserver-spec.xml
@@ -2954,16 +2954,17 @@ The sample server implementation is in Xserver/fb/fbscreen.c.</para>
pScreen->SourceValidate(pDrawable, x, y, width, height)
DrawablePtr pDrawable;
int x, y, width, height;
+ unsigned int subWindowMode;
</programlisting></blockquote>
SourceValidate should be called by CopyArea/CopyPlane primitives when
-the source drawable is not the same as the destination, and the
-SourceValidate function pointer in the screen is non-null. If you know that
+the SourceValidate function pointer in the screen is non-null. If you know that
you will never need SourceValidate, you can avoid this check. Currently,
SourceValidate is used by the mi software cursor code to remove the cursor
from the screen when the source rectangle overlaps the cursor position.
x,y,width,height describe the source rectangle (source relative, that is)
-for the copy operation.</para>
+for the copy operation. subWindowMode comes from the GC or source Picture.
+</para>
<para>
<blockquote><programlisting>
diff --git a/xorg-server/exa/exa_mixed.c b/xorg-server/exa/exa_mixed.c
index 52144c9ad..9ab9c0dcf 100644
--- a/xorg-server/exa/exa_mixed.c
+++ b/xorg-server/exa/exa_mixed.c
@@ -98,7 +98,7 @@ exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth,
pExaPixmap->use_gpu_copy = FALSE;
if (w == 1 && h == 1) {
- pExaPixmap->sys_ptr = malloc((pPixmap->drawable.bitsPerPixel + 7) / 8);
+ pExaPixmap->sys_ptr = malloc(paddedWidth);
/* Set up damage tracking */
pExaPixmap->pDamage = DamageCreate(exaDamageReport_mixed, NULL,
diff --git a/xorg-server/exa/exa_unaccel.c b/xorg-server/exa/exa_unaccel.c
index e53a371a7..354733921 100644
--- a/xorg-server/exa/exa_unaccel.c
+++ b/xorg-server/exa/exa_unaccel.c
@@ -438,7 +438,8 @@ ExaSrcValidate(DrawablePtr pDrawable,
int x,
int y,
int width,
- int height)
+ int height,
+ unsigned int subWindowMode)
{
ScreenPtr pScreen = pDrawable->pScreen;
ExaScreenPriv(pScreen);
@@ -464,7 +465,7 @@ ExaSrcValidate(DrawablePtr pDrawable,
if (pExaScr->SavedSourceValidate) {
swap(pExaScr, pScreen, SourceValidate);
- pScreen->SourceValidate(pDrawable, x, y, width, height);
+ pScreen->SourceValidate(pDrawable, x, y, width, height, subWindowMode);
swap(pExaScr, pScreen, SourceValidate);
}
}
diff --git a/xorg-server/glx/glxdri2.c b/xorg-server/glx/glxdri2.c
index ce8014396..c9c316be5 100644
--- a/xorg-server/glx/glxdri2.c
+++ b/xorg-server/glx/glxdri2.c
@@ -594,7 +594,7 @@ static const __DRIextension *loader_extensions[] = {
&systemTimeExtension.base,
&loaderExtension.base,
#ifdef __DRI_USE_INVALIDATE
- &dri2UseInvalidate,
+ &dri2UseInvalidate.base,
#endif
NULL
};
diff --git a/xorg-server/glx/unpack.h b/xorg-server/glx/unpack.h
index 7e6a55105..a5f211555 100644
--- a/xorg-server/glx/unpack.h
+++ b/xorg-server/glx/unpack.h
@@ -47,7 +47,7 @@
** Fetch a double from potentially unaligned memory.
*/
#ifdef __GLX_ALIGN64
-#define __GLX_MEM_COPY(dst,src,n) if (src != NULL && dst != NULL) memcpy(dst,src,n)
+#define __GLX_MEM_COPY(dst,src,n) memmove(dst,src,n)
#define __GLX_GET_DOUBLE(dst,src) __GLX_MEM_COPY(&dst,src,8)
#else
#define __GLX_GET_DOUBLE(dst,src) (dst) = *((GLdouble*)(src))
diff --git a/xorg-server/hw/dmx/glxProxy/unpack.h b/xorg-server/hw/dmx/glxProxy/unpack.h
index b89a53411..c592c3d92 100644
--- a/xorg-server/hw/dmx/glxProxy/unpack.h
+++ b/xorg-server/hw/dmx/glxProxy/unpack.h
@@ -43,7 +43,7 @@
** Fetch a double from potentially unaligned memory.
*/
#ifdef __GLX_ALIGN64
-#define __GLX_MEM_COPY(dst,src,n) memcpy(dst,src,n)
+#define __GLX_MEM_COPY(dst,src,n) memmove(dst,src,n)
#define __GLX_GET_DOUBLE(dst,src) __GLX_MEM_COPY(&dst,src,8)
#else
#define __GLX_GET_DOUBLE(dst,src) (dst) = *((GLdouble*)(src))
diff --git a/xorg-server/hw/xfree86/common/xf86AutoConfig.c b/xorg-server/hw/xfree86/common/xf86AutoConfig.c
index 384f08103..1b9253269 100644
--- a/xorg-server/hw/xfree86/common/xf86AutoConfig.c
+++ b/xorg-server/hw/xfree86/common/xf86AutoConfig.c
@@ -120,7 +120,7 @@ FreeList(const char ***list, int *lines)
int i;
for (i = 0; i < *lines; i++) {
- free((*list)[i]);
+ free((char *)((*list)[i]));
}
free(*list);
*list = NULL;
diff --git a/xorg-server/hw/xfree86/common/xf86Module.h b/xorg-server/hw/xfree86/common/xf86Module.h
index fb6f9673d..0e7be4dd7 100644
--- a/xorg-server/hw/xfree86/common/xf86Module.h
+++ b/xorg-server/hw/xfree86/common/xf86Module.h
@@ -83,7 +83,7 @@ typedef enum {
*/
#define ABI_ANSIC_VERSION SET_ABI_VERSION(0, 4)
#define ABI_VIDEODRV_VERSION SET_ABI_VERSION(9, 0)
-#define ABI_XINPUT_VERSION SET_ABI_VERSION(12, 0)
+#define ABI_XINPUT_VERSION SET_ABI_VERSION(12, 1)
#define ABI_EXTENSION_VERSION SET_ABI_VERSION(5, 0)
#define ABI_FONT_VERSION SET_ABI_VERSION(0, 6)
diff --git a/xorg-server/hw/xfree86/common/xf86VGAarbiter.c b/xorg-server/hw/xfree86/common/xf86VGAarbiter.c
index 50ea6ca9e..0aa6f2cf4 100644
--- a/xorg-server/hw/xfree86/common/xf86VGAarbiter.c
+++ b/xorg-server/hw/xfree86/common/xf86VGAarbiter.c
@@ -325,13 +325,14 @@ VGAarbiterGetSpans (
static void
VGAarbiterSourceValidate (
DrawablePtr pDrawable,
- int x, int y, int width, int height )
+ int x, int y, int width, int height,
+ unsigned int subWindowMode )
{
ScreenPtr pScreen = pDrawable->pScreen;
SCREEN_PROLOG (SourceValidate);
VGAGet(pScreen);
if (pScreen->SourceValidate)
- (*pScreen->SourceValidate) (pDrawable, x, y, width, height);
+ (*pScreen->SourceValidate) (pDrawable, x, y, width, height, subWindowMode);
VGAPut();
SCREEN_EPILOG (SourceValidate, VGAarbiterSourceValidate);
}
diff --git a/xorg-server/hw/xfree86/common/xf86VGAarbiterPriv.h b/xorg-server/hw/xfree86/common/xf86VGAarbiterPriv.h
index 0107a4952..13fde5e79 100644
--- a/xorg-server/hw/xfree86/common/xf86VGAarbiterPriv.h
+++ b/xorg-server/hw/xfree86/common/xf86VGAarbiterPriv.h
@@ -149,7 +149,7 @@ static void VGAarbiterGetImage (DrawablePtr pDrawable, int sx, int sy, int w,
static void VGAarbiterGetSpans (DrawablePtr pDrawable, int wMax, DDXPointPtr
ppt, int *pwidth, int nspans, char *pdstStart);
static void VGAarbiterSourceValidate (DrawablePtr pDrawable, int x, int y,
- int width, int height);
+ int width, int height, unsigned int subWindowMode);
static void VGAarbiterCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
RegionPtr prgnSrc);
static void VGAarbiterClearToBackground (WindowPtr pWin, int x, int y, int w,
diff --git a/xorg-server/hw/xfree86/dixmods/extmod/modinit.c b/xorg-server/hw/xfree86/dixmods/extmod/modinit.c
index ee3e52855..632454f37 100644
--- a/xorg-server/hw/xfree86/dixmods/extmod/modinit.c
+++ b/xorg-server/hw/xfree86/dixmods/extmod/modinit.c
@@ -146,7 +146,7 @@ extmodSetup(pointer module, pointer opts, int *errmaj, int *errmin)
for (i = 0; extensionModules[i].name != NULL; i++) {
if (opts) {
char *s;
- if (Xasprinf(&s, "omit%s", extensionModules[i].name) != -1) {
+ if (asprintf(&s, "omit%s", extensionModules[i].name) != -1) {
pointer o;
o = xf86FindOption(opts, s);
free(s);
diff --git a/xorg-server/hw/xfree86/dixmods/extmod/modinit.h b/xorg-server/hw/xfree86/dixmods/extmod/modinit.h
index 1154e4601..9753e6f14 100644
--- a/xorg-server/hw/xfree86/dixmods/extmod/modinit.h
+++ b/xorg-server/hw/xfree86/dixmods/extmod/modinit.h
@@ -1,82 +1,86 @@
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#ifndef INITARGS
-#define INITARGS void
-#endif
-
-#include <X11/extensions/shapeproto.h>
-
-#ifdef XTEST
-extern void XTestExtensionInit(INITARGS);
-#include <X11/extensions/xtestproto.h>
-#endif
-
-#if 1
-extern void XTestExtension1Init(INITARGS);
-#endif
-
-#ifdef SCREENSAVER
-extern void ScreenSaverExtensionInit (INITARGS);
-#include <X11/extensions/saver.h>
-#endif
-
-#ifdef XF86VIDMODE
-extern void XFree86VidModeExtensionInit(INITARGS);
-#include <X11/extensions/xf86vmproto.h>
-#endif
-
-#ifdef XFreeXDGA
-extern void XFree86DGAExtensionInit(INITARGS);
-extern void XFree86DGARegister(INITARGS);
-#include <X11/extensions/xf86dgaproto.h>
-#endif
-
-#ifdef DPMSExtension
-extern void DPMSExtensionInit(INITARGS);
-#include <X11/extensions/dpmsconst.h>
-#endif
-
-#ifdef XV
-extern void XvExtensionInit(INITARGS);
-extern void XvMCExtensionInit(INITARGS);
-extern void XvRegister(INITARGS);
-#include <X11/extensions/Xv.h>
-#include <X11/extensions/XvMC.h>
-#endif
-
-#ifdef RES
-extern void ResExtensionInit(INITARGS);
-#include <X11/extensions/XResproto.h>
-#endif
-
-#ifdef SHM
-extern void ShmExtensionInit(INITARGS);
-#include <X11/extensions/shmproto.h>
-extern void ShmRegisterFuncs(
- ScreenPtr pScreen,
- ShmFuncsPtr funcs);
-#endif
-
-#ifdef XSELINUX
-extern void SELinuxExtensionInit(INITARGS);
-#include "xselinux.h"
-#endif
-
-#ifdef XEVIE
-extern void XevieExtensionInit(INITARGS);
-#endif
-
-#if 1
-extern void SecurityExtensionInit(INITARGS);
-#endif
-
-#if 1
-extern void PanoramiXExtensionInit(int argc, char *argv[]);
-#endif
-
-#if 1
-extern void XkbExtensionInit(INITARGS);
-#endif
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef INITARGS
+#define INITARGS void
+#endif
+
+#include <X11/extensions/shapeproto.h>
+
+#ifdef XTEST
+extern void XTestExtensionInit(INITARGS);
+#include <X11/extensions/xtestproto.h>
+#endif
+
+#if 1
+extern void XTestExtension1Init(INITARGS);
+#endif
+
+#if 1
+extern void XCMiscExtensionInit(INITARGS);
+#endif
+
+#ifdef SCREENSAVER
+extern void ScreenSaverExtensionInit (INITARGS);
+#include <X11/extensions/saver.h>
+#endif
+
+#ifdef XF86VIDMODE
+extern void XFree86VidModeExtensionInit(INITARGS);
+#include <X11/extensions/xf86vmproto.h>
+#endif
+
+#ifdef XFreeXDGA
+extern void XFree86DGAExtensionInit(INITARGS);
+extern void XFree86DGARegister(INITARGS);
+#include <X11/extensions/xf86dgaproto.h>
+#endif
+
+#ifdef DPMSExtension
+extern void DPMSExtensionInit(INITARGS);
+#include <X11/extensions/dpmsconst.h>
+#endif
+
+#ifdef XV
+extern void XvExtensionInit(INITARGS);
+extern void XvMCExtensionInit(INITARGS);
+extern void XvRegister(INITARGS);
+#include <X11/extensions/Xv.h>
+#include <X11/extensions/XvMC.h>
+#endif
+
+#ifdef RES
+extern void ResExtensionInit(INITARGS);
+#include <X11/extensions/XResproto.h>
+#endif
+
+#ifdef SHM
+extern void ShmExtensionInit(INITARGS);
+#include <X11/extensions/shmproto.h>
+extern void ShmRegisterFuncs(
+ ScreenPtr pScreen,
+ ShmFuncsPtr funcs);
+#endif
+
+#ifdef XSELINUX
+extern void SELinuxExtensionInit(INITARGS);
+#include "xselinux.h"
+#endif
+
+#ifdef XEVIE
+extern void XevieExtensionInit(INITARGS);
+#endif
+
+#if 1
+extern void SecurityExtensionInit(INITARGS);
+#endif
+
+#if 1
+extern void PanoramiXExtensionInit(int argc, char *argv[]);
+#endif
+
+#if 1
+extern void XkbExtensionInit(INITARGS);
+#endif
diff --git a/xorg-server/hw/xfree86/dri/dri.c b/xorg-server/hw/xfree86/dri/dri.c
index 9ca5ecd0b..38241f904 100644
--- a/xorg-server/hw/xfree86/dri/dri.c
+++ b/xorg-server/hw/xfree86/dri/dri.c
@@ -431,7 +431,7 @@ DRIScreenInit(ScreenPtr pScreen, DRIInfoPtr pDRIInfo, int *pDRMFD)
if (!pDRIPriv->pDriverInfo->dontMapFrameBuffer)
{
if (drmAddMap( pDRIPriv->drmFD,
- (drm_handle_t)pDRIPriv->pDriverInfo->frameBufferPhysicalAddress,
+ (uintptr_t)pDRIPriv->pDriverInfo->frameBufferPhysicalAddress,
pDRIPriv->pDriverInfo->frameBufferSize,
DRM_FRAME_BUFFER,
0,
diff --git a/xorg-server/hw/xfree86/dri2/dri2.c b/xorg-server/hw/xfree86/dri2/dri2.c
index 578773a5a..aba2202d6 100644
--- a/xorg-server/hw/xfree86/dri2/dri2.c
+++ b/xorg-server/hw/xfree86/dri2/dri2.c
@@ -640,6 +640,17 @@ DRI2CanFlip(DrawablePtr pDraw)
if (!RegionEqual(&pWin->clipList, &pRoot->winSize))
return FALSE;
+ /* Does the window match the pixmap exactly? */
+ if (pDraw->x != 0 ||
+ pDraw->y != 0 ||
+#ifdef COMPOSITE
+ pDraw->x != pWinPixmap->screen_x ||
+ pDraw->y != pWinPixmap->screen_y ||
+#endif
+ pDraw->width != pWinPixmap->drawable.width ||
+ pDraw->height != pWinPixmap->drawable.height)
+ return FALSE;
+
return TRUE;
}
diff --git a/xorg-server/hw/xfree86/loader/loadmod.c b/xorg-server/hw/xfree86/loader/loadmod.c
index dbc16eab7..271cb5b79 100644
--- a/xorg-server/hw/xfree86/loader/loadmod.c
+++ b/xorg-server/hw/xfree86/loader/loadmod.c
@@ -374,7 +374,7 @@ FreeSubdirs(const char **subdirs)
if (subdirs) {
for (s = subdirs; *s; s++)
- free(*s);
+ free((char *)*s);
free(subdirs);
}
}
diff --git a/xorg-server/hw/xfree86/modes/xf86EdidModes.c b/xorg-server/hw/xfree86/modes/xf86EdidModes.c
index d9ece7a14..9e0dc9d32 100644
--- a/xorg-server/hw/xfree86/modes/xf86EdidModes.c
+++ b/xorg-server/hw/xfree86/modes/xf86EdidModes.c
@@ -1,1216 +1,1216 @@
-/*
- * Copyright 2006 Luc Verhaegen.
- * Copyright 2008 Red Hat, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sub license,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * @file This file covers code to convert a xf86MonPtr containing EDID-probed
- * information into a list of modes, including applying monitor-specific
- * quirks to fix broken EDID data.
- */
-#ifdef HAVE_XORG_CONFIG_H
-#include <xorg-config.h>
-#else
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#endif
-
-#define _PARSE_EDID_
-#include "xf86.h"
-#include "xf86DDC.h"
-#include <X11/Xatom.h>
-#include "property.h"
-#include "propertyst.h"
-#include "xf86Crtc.h"
-#include <string.h>
-#include <math.h>
-
-static void handle_detailed_rblank(struct detailed_monitor_section *det_mon,
- void *data)
-{
- if (det_mon->type == DS_RANGES)
- if (det_mon->section.ranges.supported_blanking & CVT_REDUCED)
- *(Bool*)data = TRUE;
-}
-
-static Bool
-xf86MonitorSupportsReducedBlanking(xf86MonPtr DDC)
-{
- /* EDID 1.4 explicitly defines RB support */
- if (DDC->ver.revision >= 4) {
- Bool ret = FALSE;
-
- xf86ForEachDetailedBlock(DDC, handle_detailed_rblank, &ret);
- return ret;
- }
-
- /* For anything older, assume digital means RB support. Boo. */
- if (DDC->features.input_type)
- return TRUE;
-
- return FALSE;
-}
-
-static Bool quirk_prefer_large_60 (int scrnIndex, xf86MonPtr DDC)
-{
- /* Belinea 10 15 55 */
- if (memcmp (DDC->vendor.name, "MAX", 4) == 0 &&
- ((DDC->vendor.prod_id == 1516) ||
- (DDC->vendor.prod_id == 0x77e)))
- return TRUE;
-
- /* Acer AL1706 */
- if (memcmp (DDC->vendor.name, "ACR", 4) == 0 &&
- DDC->vendor.prod_id == 44358)
- return TRUE;
-
- /* Bug #10814: Samsung SyncMaster 225BW */
- if (memcmp (DDC->vendor.name, "SAM", 4) == 0 &&
- DDC->vendor.prod_id == 596)
- return TRUE;
-
- /* Bug #10545: Samsung SyncMaster 226BW */
- if (memcmp (DDC->vendor.name, "SAM", 4) == 0 &&
- DDC->vendor.prod_id == 638)
- return TRUE;
-
- /* Acer F51 */
- if (memcmp (DDC->vendor.name, "API", 4) == 0 &&
- DDC->vendor.prod_id == 0x7602)
- return TRUE;
-
-
- return FALSE;
-}
-
-static Bool quirk_prefer_large_75 (int scrnIndex, xf86MonPtr DDC)
-{
- /* Bug #11603: Funai Electronics PM36B */
- if (memcmp (DDC->vendor.name, "FCM", 4) == 0 &&
- DDC->vendor.prod_id == 13600)
- return TRUE;
-
- return FALSE;
-}
-
-static Bool quirk_detailed_h_in_cm (int scrnIndex, xf86MonPtr DDC)
-{
- /* Bug #11603: Funai Electronics PM36B */
- if (memcmp (DDC->vendor.name, "FCM", 4) == 0 &&
- DDC->vendor.prod_id == 13600)
- return TRUE;
-
- return FALSE;
-}
-
-static Bool quirk_detailed_v_in_cm (int scrnIndex, xf86MonPtr DDC)
-{
- /* Bug #11603: Funai Electronics PM36B */
- if (memcmp (DDC->vendor.name, "FCM", 4) == 0 &&
- DDC->vendor.prod_id == 13600)
- return TRUE;
-
- /* Bug #21000: LGPhilipsLCD LP154W01-TLAJ */
- if (memcmp (DDC->vendor.name, "LPL", 4) == 0 &&
- DDC->vendor.prod_id == 47360)
- return TRUE;
-
- /* Bug #10304: LGPhilipsLCD LP154W01-A5 */
- if (memcmp(DDC->vendor.name, "LPL", 4) == 0 &&
- DDC->vendor.prod_id == 0)
- return TRUE;
-
- /* Bug #24482: LGPhilipsLCD LP154W01-TLA1 */
- if (memcmp(DDC->vendor.name, "LPL", 4) == 0 &&
- DDC->vendor.prod_id == 0x2a00)
- return TRUE;
-
- /* Bug #28414: HP Compaq NC8430 LP154W01-TLA8 */
- if (memcmp (DDC->vendor.name, "LPL", 4) == 0 &&
- DDC->vendor.prod_id == 5750)
- return TRUE;
-
- /* Bug #21750: Samsung Syncmaster 2333HD */
- if (memcmp (DDC->vendor.name, "SAM", 4) == 0 &&
- DDC->vendor.prod_id == 1157)
- return TRUE;
-
- return FALSE;
-}
-
-static Bool quirk_detailed_use_maximum_size (int scrnIndex, xf86MonPtr DDC)
-{
- /* Bug #21324: Iiyama Vision Master 450 */
- if (memcmp (DDC->vendor.name, "IVM", 4) == 0 &&
- DDC->vendor.prod_id == 6400)
- return TRUE;
-
- return FALSE;
-}
-
-static Bool quirk_135_clock_too_high (int scrnIndex, xf86MonPtr DDC)
-{
- /* Envision Peripherals, Inc. EN-7100e. See bug #9550. */
- if (memcmp (DDC->vendor.name, "EPI", 4) == 0 &&
- DDC->vendor.prod_id == 59264)
- return TRUE;
-
- return FALSE;
-}
-
-static Bool quirk_first_detailed_preferred (int scrnIndex, xf86MonPtr DDC)
-{
- /* Philips 107p5 CRT. Reported on xorg@ with pastebin. */
- if (memcmp (DDC->vendor.name, "PHL", 4) == 0 &&
- DDC->vendor.prod_id == 57364)
- return TRUE;
-
- /* Proview AY765C 17" LCD. See bug #15160*/
- if (memcmp (DDC->vendor.name, "PTS", 4) == 0 &&
- DDC->vendor.prod_id == 765)
- return TRUE;
-
- /* ACR of some sort RH #284231 */
- if (memcmp (DDC->vendor.name, "ACR", 4) == 0 &&
- DDC->vendor.prod_id == 2423)
- return TRUE;
-
- /* Peacock Ergovision 19. See rh#492359 */
- if (memcmp (DDC->vendor.name, "PEA", 4) == 0 &&
- DDC->vendor.prod_id == 9003)
- return TRUE;
-
- return FALSE;
-}
-
-static Bool quirk_detailed_sync_pp(int scrnIndex, xf86MonPtr DDC)
-{
- /* Bug #12439: Samsung SyncMaster 205BW */
- if (memcmp (DDC->vendor.name, "SAM", 4) == 0 &&
- DDC->vendor.prod_id == 541)
- return TRUE;
- return FALSE;
-}
-
-/* This should probably be made more generic */
-static Bool quirk_dvi_single_link(int scrnIndex, xf86MonPtr DDC)
-{
- /* Red Hat bug #453106: Apple 23" Cinema Display */
- if (memcmp (DDC->vendor.name, "APL", 4) == 0 &&
- DDC->vendor.prod_id == 0x921c)
- return TRUE;
- return FALSE;
-}
-
-typedef struct {
- Bool (*detect) (int scrnIndex, xf86MonPtr DDC);
- ddc_quirk_t quirk;
- char *description;
-} ddc_quirk_map_t;
-
-static const ddc_quirk_map_t ddc_quirks[] = {
- {
- quirk_prefer_large_60, DDC_QUIRK_PREFER_LARGE_60,
- "Detailed timing is not preferred, use largest mode at 60Hz"
- },
- {
- quirk_135_clock_too_high, DDC_QUIRK_135_CLOCK_TOO_HIGH,
- "Recommended 135MHz pixel clock is too high"
- },
- {
- quirk_prefer_large_75, DDC_QUIRK_PREFER_LARGE_75,
- "Detailed timing is not preferred, use largest mode at 75Hz"
- },
- {
- quirk_detailed_h_in_cm, DDC_QUIRK_DETAILED_H_IN_CM,
- "Detailed timings give horizontal size in cm."
- },
- {
- quirk_detailed_v_in_cm, DDC_QUIRK_DETAILED_V_IN_CM,
- "Detailed timings give vertical size in cm."
- },
- {
- quirk_detailed_use_maximum_size, DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE,
- "Use maximum size instead of detailed timing sizes."
- },
- {
- quirk_first_detailed_preferred, DDC_QUIRK_FIRST_DETAILED_PREFERRED,
- "First detailed timing was not marked as preferred."
- },
- {
- quirk_detailed_sync_pp, DDC_QUIRK_DETAILED_SYNC_PP,
- "Use +hsync +vsync for detailed timing."
- },
- {
- quirk_dvi_single_link, DDC_QUIRK_DVI_SINGLE_LINK,
- "Forcing maximum pixel clock to single DVI link."
- },
- {
- NULL, DDC_QUIRK_NONE,
- "No known quirks"
- },
-};
-
-/*
- * These more or less come from the DMT spec. The 720x400 modes are
- * inferred from historical 80x25 practice. The 640x480@67 and 832x624@75
- * modes are old-school Mac modes. The EDID spec says the 1152x864@75 mode
- * should be 1152x870, again for the Mac, but instead we use the x864 DMT
- * mode.
- *
- * The DMT modes have been fact-checked; the rest are mild guesses.
- */
-#define MODEPREFIX NULL, NULL, NULL, 0, M_T_DRIVER
-#define MODESUFFIX 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,FALSE,FALSE,0,NULL,0,0.0,0.0
-
-static const DisplayModeRec DDCEstablishedModes[17] = {
- { MODEPREFIX, 40000, 800, 840, 968, 1056, 0, 600, 601, 605, 628, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@60Hz */
- { MODEPREFIX, 36000, 800, 824, 896, 1024, 0, 600, 601, 603, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@56Hz */
- { MODEPREFIX, 31500, 640, 656, 720, 840, 0, 480, 481, 484, 500, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@75Hz */
- { MODEPREFIX, 31500, 640, 664, 704, 832, 0, 480, 489, 492, 520, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@72Hz */
- { MODEPREFIX, 30240, 640, 704, 768, 864, 0, 480, 483, 486, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@67Hz */
- { MODEPREFIX, 25175, 640, 656, 752, 800, 0, 480, 490, 492, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@60Hz */
- { MODEPREFIX, 35500, 720, 738, 846, 900, 0, 400, 421, 423, 449, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 720x400@88Hz */
- { MODEPREFIX, 28320, 720, 738, 846, 900, 0, 400, 412, 414, 449, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 720x400@70Hz */
- { MODEPREFIX, 135000, 1280, 1296, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024@75Hz */
- { MODEPREFIX, 78750, 1024, 1040, 1136, 1312, 0, 768, 769, 772, 800, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1024x768@75Hz */
- { MODEPREFIX, 75000, 1024, 1048, 1184, 1328, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@70Hz */
- { MODEPREFIX, 65000, 1024, 1048, 1184, 1344, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@60Hz */
- { MODEPREFIX, 44900, 1024, 1032, 1208, 1264, 0, 768, 768, 772, 817, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* 1024x768@43Hz */
- { MODEPREFIX, 57284, 832, 864, 928, 1152, 0, 624, 625, 628, 667, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 832x624@75Hz */
- { MODEPREFIX, 49500, 800, 816, 896, 1056, 0, 600, 601, 604, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@75Hz */
- { MODEPREFIX, 50000, 800, 856, 976, 1040, 0, 600, 637, 643, 666, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@72Hz */
- { MODEPREFIX, 108000, 1152, 1216, 1344, 1600, 0, 864, 865, 868, 900, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1152x864@75Hz */
-};
-
-static DisplayModePtr
-DDCModesFromEstablished(int scrnIndex, struct established_timings *timing,
- ddc_quirk_t quirks)
-{
- DisplayModePtr Modes = NULL, Mode = NULL;
- CARD32 bits = (timing->t1) | (timing->t2 << 8) |
- ((timing->t_manu & 0x80) << 9);
- int i;
-
- for (i = 0; i < 17; i++) {
- if (bits & (0x01 << i)) {
- Mode = xf86DuplicateMode(&DDCEstablishedModes[i]);
- Modes = xf86ModesAdd(Modes, Mode);
- }
- }
-
- return Modes;
-}
-
-/* Autogenerated from the DMT spec */
-const DisplayModeRec DMTModes[] = {
- { MODEPREFIX, 31500, 640, 672, 736, 832, 0, 350, 382, 385, 445, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x350@85Hz */
- { MODEPREFIX, 31500, 640, 672, 736, 832, 0, 400, 401, 404, 445, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 640x400@85Hz */
- { MODEPREFIX, 35500, 720, 756, 828, 936, 0, 400, 401, 404, 446, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 720x400@85Hz */
- { MODEPREFIX, 25175, 640, 656, 752, 800, 0, 480, 490, 492, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@60Hz */
- { MODEPREFIX, 31500, 640, 664, 704, 832, 0, 480, 489, 492, 520, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@72Hz */
- { MODEPREFIX, 31500, 640, 656, 720, 840, 0, 480, 481, 484, 500, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@75Hz */
- { MODEPREFIX, 36000, 640, 696, 752, 832, 0, 480, 481, 484, 509, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@85Hz */
- { MODEPREFIX, 36000, 800, 824, 896, 1024, 0, 600, 601, 603, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@56Hz */
- { MODEPREFIX, 40000, 800, 840, 968, 1056, 0, 600, 601, 605, 628, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@60Hz */
- { MODEPREFIX, 50000, 800, 856, 976, 1040, 0, 600, 637, 643, 666, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@72Hz */
- { MODEPREFIX, 49500, 800, 816, 896, 1056, 0, 600, 601, 604, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@75Hz */
- { MODEPREFIX, 56250, 800, 832, 896, 1048, 0, 600, 601, 604, 631, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@85Hz */
- { MODEPREFIX, 73250, 800, 848, 880, 960, 0, 600, 603, 607, 636, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 800x600@120Hz RB */
- { MODEPREFIX, 33750, 848, 864, 976, 1088, 0, 480, 486, 494, 517, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 848x480@60Hz */
- { MODEPREFIX, 44900, 1024, 1032, 1208, 1264, 0, 768, 768, 772, 817, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* 1024x768@43Hz (interlaced) */
- { MODEPREFIX, 65000, 1024, 1048, 1184, 1344, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@60Hz */
- { MODEPREFIX, 75000, 1024, 1048, 1184, 1328, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@70Hz */
- { MODEPREFIX, 78750, 1024, 1040, 1136, 1312, 0, 768, 769, 772, 800, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1024x768@75Hz */
- { MODEPREFIX, 94500, 1024, 1072, 1168, 1376, 0, 768, 769, 772, 808, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1024x768@85Hz */
- { MODEPREFIX, 115500, 1024, 1072, 1104, 1184, 0, 768, 771, 775, 813, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@120Hz RB */
- { MODEPREFIX, 108000, 1152, 1216, 1344, 1600, 0, 864, 865, 868, 900, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1152x864@75Hz */
- { MODEPREFIX, 68250, 1280, 1328, 1360, 1440, 0, 768, 771, 778, 790, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x768@60Hz RB */
- { MODEPREFIX, 79500, 1280, 1344, 1472, 1664, 0, 768, 771, 778, 798, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x768@60Hz */
- { MODEPREFIX, 102250, 1280, 1360, 1488, 1696, 0, 768, 771, 778, 805, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x768@75Hz */
- { MODEPREFIX, 117500, 1280, 1360, 1496, 1712, 0, 768, 771, 778, 809, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x768@85Hz */
- { MODEPREFIX, 140250, 1280, 1328, 1360, 1440, 0, 768, 771, 778, 813, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x768@120Hz RB */
- { MODEPREFIX, 71000, 1280, 1328, 1360, 1440, 0, 800, 803, 809, 823, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x800@60Hz RB */
- { MODEPREFIX, 83500, 1280, 1352, 1480, 1680, 0, 800, 803, 809, 831, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x800@60Hz */
- { MODEPREFIX, 106500, 1280, 1360, 1488, 1696, 0, 800, 803, 809, 838, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x800@75Hz */
- { MODEPREFIX, 122500, 1280, 1360, 1496, 1712, 0, 800, 803, 809, 843, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x800@85Hz */
- { MODEPREFIX, 146250, 1280, 1328, 1360, 1440, 0, 800, 803, 809, 847, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x800@120Hz RB */
- { MODEPREFIX, 108000, 1280, 1376, 1488, 1800, 0, 960, 961, 964, 1000, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x960@60Hz */
- { MODEPREFIX, 148500, 1280, 1344, 1504, 1728, 0, 960, 961, 964, 1011, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x960@85Hz */
- { MODEPREFIX, 175500, 1280, 1328, 1360, 1440, 0, 960, 963, 967, 1017, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x960@120Hz RB */
- { MODEPREFIX, 108000, 1280, 1328, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024@60Hz */
- { MODEPREFIX, 135000, 1280, 1296, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024@75Hz */
- { MODEPREFIX, 157500, 1280, 1344, 1504, 1728, 0, 1024, 1025, 1028, 1072, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024@85Hz */
- { MODEPREFIX, 187250, 1280, 1328, 1360, 1440, 0, 1024, 1027, 1034, 1084, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x1024@120Hz RB */
- { MODEPREFIX, 85500, 1360, 1424, 1536, 1792, 0, 768, 771, 777, 795, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1360x768@60Hz */
- { MODEPREFIX, 148250, 1360, 1408, 1440, 1520, 0, 768, 771, 776, 813, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1360x768@120Hz RB */
- { MODEPREFIX, 101000, 1400, 1448, 1480, 1560, 0, 1050, 1053, 1057, 1080, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1400x1050@60Hz RB */
- { MODEPREFIX, 121750, 1400, 1488, 1632, 1864, 0, 1050, 1053, 1057, 1089, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1400x1050@60Hz */
- { MODEPREFIX, 156000, 1400, 1504, 1648, 1896, 0, 1050, 1053, 1057, 1099, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1400x1050@75Hz */
- { MODEPREFIX, 179500, 1400, 1504, 1656, 1912, 0, 1050, 1053, 1057, 1105, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1400x1050@85Hz */
- { MODEPREFIX, 208000, 1400, 1448, 1480, 1560, 0, 1050, 1053, 1057, 1112, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1400x1050@120Hz RB */
- { MODEPREFIX, 88750, 1440, 1488, 1520, 1600, 0, 900, 903, 909, 926, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1440x900@60Hz RB */
- { MODEPREFIX, 106500, 1440, 1520, 1672, 1904, 0, 900, 903, 909, 934, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1440x900@60Hz */
- { MODEPREFIX, 136750, 1440, 1536, 1688, 1936, 0, 900, 903, 909, 942, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1440x900@75Hz */
- { MODEPREFIX, 157000, 1440, 1544, 1696, 1952, 0, 900, 903, 909, 948, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1440x900@85Hz */
- { MODEPREFIX, 182750, 1440, 1488, 1520, 1600, 0, 900, 903, 909, 953, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1440x900@120Hz RB */
- { MODEPREFIX, 162000, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1600x1200@60Hz */
- { MODEPREFIX, 175500, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1600x1200@65Hz */
- { MODEPREFIX, 189000, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1600x1200@70Hz */
- { MODEPREFIX, 202500, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1600x1200@75Hz */
- { MODEPREFIX, 229500, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1600x1200@85Hz */
- { MODEPREFIX, 268250, 1600, 1648, 1680, 1760, 0, 1200, 1203, 1207, 1271, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1600x1200@120Hz RB */
- { MODEPREFIX, 119000, 1680, 1728, 1760, 1840, 0, 1050, 1053, 1059, 1080, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1680x1050@60Hz RB */
- { MODEPREFIX, 146250, 1680, 1784, 1960, 2240, 0, 1050, 1053, 1059, 1089, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1680x1050@60Hz */
- { MODEPREFIX, 187000, 1680, 1800, 1976, 2272, 0, 1050, 1053, 1059, 1099, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1680x1050@75Hz */
- { MODEPREFIX, 214750, 1680, 1808, 1984, 2288, 0, 1050, 1053, 1059, 1105, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1680x1050@85Hz */
- { MODEPREFIX, 245500, 1680, 1728, 1760, 1840, 0, 1050, 1053, 1059, 1112, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1680x1050@120Hz RB */
- { MODEPREFIX, 204750, 1792, 1920, 2120, 2448, 0, 1344, 1345, 1348, 1394, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1792x1344@60Hz */
- { MODEPREFIX, 261000, 1792, 1888, 2104, 2456, 0, 1344, 1345, 1348, 1417, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1792x1344@75Hz */
- { MODEPREFIX, 333250, 1792, 1840, 1872, 1952, 0, 1344, 1347, 1351, 1423, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1792x1344@120Hz RB */
- { MODEPREFIX, 218250, 1856, 1952, 2176, 2528, 0, 1392, 1393, 1396, 1439, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1856x1392@60Hz */
- { MODEPREFIX, 288000, 1856, 1984, 2208, 2560, 0, 1392, 1393, 1396, 1500, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1856x1392@75Hz */
- { MODEPREFIX, 356500, 1856, 1904, 1936, 2016, 0, 1392, 1395, 1399, 1474, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1856x1392@120Hz RB */
- { MODEPREFIX, 154000, 1920, 1968, 2000, 2080, 0, 1200, 1203, 1209, 1235, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1920x1200@60Hz RB */
- { MODEPREFIX, 193250, 1920, 2056, 2256, 2592, 0, 1200, 1203, 1209, 1245, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1920x1200@60Hz */
- { MODEPREFIX, 245250, 1920, 2056, 2264, 2608, 0, 1200, 1203, 1209, 1255, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1920x1200@75Hz */
- { MODEPREFIX, 281250, 1920, 2064, 2272, 2624, 0, 1200, 1203, 1209, 1262, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1920x1200@85Hz */
- { MODEPREFIX, 317000, 1920, 1968, 2000, 2080, 0, 1200, 1203, 1209, 1271, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1920x1200@120Hz RB */
- { MODEPREFIX, 234000, 1920, 2048, 2256, 2600, 0, 1440, 1441, 1444, 1500, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1920x1440@60Hz */
- { MODEPREFIX, 297000, 1920, 2064, 2288, 2640, 0, 1440, 1441, 1444, 1500, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1920x1440@75Hz */
- { MODEPREFIX, 380500, 1920, 1968, 2000, 2080, 0, 1440, 1443, 1447, 1525, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1920x1440@120Hz RB */
- { MODEPREFIX, 268500, 2560, 2608, 2640, 2720, 0, 1600, 1603, 1609, 1646, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 2560x1600@60Hz RB */
- { MODEPREFIX, 348500, 2560, 2752, 3032, 3504, 0, 1600, 1603, 1609, 1658, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 2560x1600@60Hz */
- { MODEPREFIX, 443250, 2560, 2768, 3048, 3536, 0, 1600, 1603, 1609, 1672, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 2560x1600@75Hz */
- { MODEPREFIX, 505250, 2560, 2768, 3048, 3536, 0, 1600, 1603, 1609, 1682, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 2560x1600@85Hz */
- { MODEPREFIX, 552750, 2560, 2608, 2640, 2720, 0, 1600, 1603, 1609, 1694, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 2560x1600@120Hz RB */
-};
-
-#define LEVEL_DMT 0
-#define LEVEL_GTF 1
-#define LEVEL_CVT 2
-
-static int
-MonitorStandardTimingLevel(xf86MonPtr DDC)
-{
- if (DDC->ver.revision >= 2) {
- if (DDC->ver.revision >= 4 && CVT_SUPPORTED(DDC->features.msc)) {
- return LEVEL_CVT;
- }
- return LEVEL_GTF;
- }
- return LEVEL_DMT;
-}
-
-static int
-ModeRefresh(const DisplayModeRec *mode)
-{
- return (int)(xf86ModeVRefresh(mode) + 0.5);
-}
-
-/*
- * If rb is not set, then we'll not consider reduced-blanking modes as
- * part of the DMT pool. For the 'standard' EDID mode descriptor there's
- * no way to specify whether the mode should be RB or not.
- */
-DisplayModePtr
-FindDMTMode(int hsize, int vsize, int refresh, Bool rb)
-{
- int i;
- const DisplayModeRec *ret;
-
- for (i = 0; i < sizeof(DMTModes) / sizeof(DisplayModeRec); i++) {
- ret = &DMTModes[i];
-
- if (!rb && xf86ModeIsReduced(ret))
- continue;
-
- if (ret->HDisplay == hsize &&
- ret->VDisplay == vsize &&
- refresh == ModeRefresh(ret))
- return xf86DuplicateMode(ret);
- }
-
- return NULL;
-}
-
-/*
- * Appendix B of the EDID 1.4 spec defines the right thing to do here.
- * If the timing given here matches a mode defined in the VESA DMT standard,
- * we _must_ use that. If the device supports CVT modes, then we should
- * generate a CVT timing. If both of the above fail, use GTF.
- *
- * There are some wrinkles here. EDID 1.1 and 1.0 sinks can't really
- * "support" GTF, since it wasn't a standard yet; so if they ask for a
- * timing in this section that isn't defined in DMT, returning a GTF mode
- * may not actually be valid. EDID 1.3 sinks often report support for
- * some CVT modes, but they are not required to support CVT timings for
- * modes in the standard timing descriptor, so we should _not_ treat them
- * as CVT-compliant (unless specified in an extension block I suppose).
- *
- * EDID 1.4 requires that all sink devices support both GTF and CVT timings
- * for modes in this section, but does say that CVT is preferred.
- */
-static DisplayModePtr
-DDCModesFromStandardTiming(struct std_timings *timing, ddc_quirk_t quirks,
- int timing_level, Bool rb)
-{
- DisplayModePtr Modes = NULL, Mode = NULL;
- int i, hsize, vsize, refresh;
-
- for (i = 0; i < STD_TIMINGS; i++) {
- hsize = timing[i].hsize;
- vsize = timing[i].vsize;
- refresh = timing[i].refresh;
-
- /* HDTV hack, because you can't say 1366 */
- if (refresh == 60 &&
- ((hsize == 1360 && vsize == 765) ||
- (hsize == 1368 && vsize == 769))) {
- Mode = xf86CVTMode(1366, 768, 60, FALSE, FALSE);
- Mode->HDisplay = 1366;
- Mode->HSyncStart--;
- Mode->HSyncEnd--;
- } else if (hsize && vsize && refresh) {
- Mode = FindDMTMode(hsize, vsize, refresh, rb);
-
- if (!Mode) {
- if (timing_level == LEVEL_CVT)
- /* pass rb here too? */
- Mode = xf86CVTMode(hsize, vsize, refresh, FALSE, FALSE);
- else if (timing_level == LEVEL_GTF)
- Mode = xf86GTFMode(hsize, vsize, refresh, FALSE, FALSE);
- }
-
- }
-
- if (Mode) {
- Mode->type = M_T_DRIVER;
- Modes = xf86ModesAdd(Modes, Mode);
- }
- Mode = NULL;
- }
-
- return Modes;
-}
-
-static void
-DDCModeDoInterlaceQuirks(DisplayModePtr mode)
-{
- /*
- * EDID is delightfully ambiguous about how interlaced modes are to be
- * encoded. X's internal representation is of frame height, but some
- * HDTV detailed timings are encoded as field height.
- *
- * The format list here is from CEA, in frame size. Technically we
- * should be checking refresh rate too. Whatever.
- */
- static const struct {
- int w, h;
- } cea_interlaced[] = {
- { 1920, 1080 },
- { 720, 480 },
- { 1440, 480 },
- { 2880, 480 },
- { 720, 576 },
- { 1440, 576 },
- { 2880, 576 },
- };
- static const int n_modes = sizeof(cea_interlaced)/sizeof(cea_interlaced[0]);
- int i;
-
- for (i = 0; i < n_modes; i++) {
- if ((mode->HDisplay == cea_interlaced[i].w) &&
- (mode->VDisplay == cea_interlaced[i].h / 2)) {
- mode->VDisplay *= 2;
- mode->VSyncStart *= 2;
- mode->VSyncEnd *= 2;
- mode->VTotal *= 2;
- mode->VTotal |= 1;
- }
- }
-
- mode->Flags |= V_INTERLACE;
-}
-
-/*
- *
- */
-static DisplayModePtr
-DDCModeFromDetailedTiming(int scrnIndex, struct detailed_timings *timing,
- Bool preferred, ddc_quirk_t quirks)
-{
- DisplayModePtr Mode;
-
- /*
- * Refuse to create modes that are insufficiently large. 64 is a random
- * number, maybe the spec says something about what the minimum is. In
- * particular I see this frequently with _old_ EDID, 1.0 or so, so maybe
- * our parser is just being too aggresive there.
- */
- if (timing->h_active < 64 || timing->v_active < 64) {
- xf86DrvMsg(scrnIndex, X_INFO,
- "%s: Ignoring tiny %dx%d mode\n", __func__,
- timing->h_active, timing->v_active);
- return NULL;
- }
-
- /* We don't do stereo */
- if (timing->stereo) {
- xf86DrvMsg(scrnIndex, X_INFO,
- "%s: Ignoring: We don't handle stereo.\n", __func__);
- return NULL;
- }
-
- /* We only do seperate sync currently */
- if (timing->sync != 0x03) {
- xf86DrvMsg(scrnIndex, X_INFO,
- "%s: %dx%d Warning: We only handle separate"
- " sync.\n", __func__, timing->h_active, timing->v_active);
- }
-
- Mode = xnfcalloc(1, sizeof(DisplayModeRec));
-
- Mode->type = M_T_DRIVER;
- if (preferred)
- Mode->type |= M_T_PREFERRED;
-
- if( ( quirks & DDC_QUIRK_135_CLOCK_TOO_HIGH ) &&
- timing->clock == 135000000 )
- Mode->Clock = 108880;
- else
- Mode->Clock = timing->clock / 1000.0;
-
- Mode->HDisplay = timing->h_active;
- Mode->HSyncStart = timing->h_active + timing->h_sync_off;
- Mode->HSyncEnd = Mode->HSyncStart + timing->h_sync_width;
- Mode->HTotal = timing->h_active + timing->h_blanking;
-
- Mode->VDisplay = timing->v_active;
- Mode->VSyncStart = timing->v_active + timing->v_sync_off;
- Mode->VSyncEnd = Mode->VSyncStart + timing->v_sync_width;
- Mode->VTotal = timing->v_active + timing->v_blanking;
-
- /* perform basic check on the detail timing */
- if (Mode->HSyncEnd > Mode->HTotal || Mode->VSyncEnd > Mode->VTotal) {
- free(Mode);
- return NULL;
- }
-
- /* We ignore h/v_size and h/v_border for now. */
-
- if (timing->interlaced)
- DDCModeDoInterlaceQuirks(Mode);
-
- if (quirks & DDC_QUIRK_DETAILED_SYNC_PP)
- Mode->Flags |= V_PVSYNC | V_PHSYNC;
- else {
- if (timing->misc & 0x02)
- Mode->Flags |= V_PVSYNC;
- else
- Mode->Flags |= V_NVSYNC;
-
- if (timing->misc & 0x01)
- Mode->Flags |= V_PHSYNC;
- else
- Mode->Flags |= V_NHSYNC;
- }
-
- xf86SetModeDefaultName(Mode);
-
- return Mode;
-}
-
-static DisplayModePtr
-DDCModesFromCVT(int scrnIndex, struct cvt_timings *t)
-{
- DisplayModePtr modes = NULL;
- int i;
-
- for (i = 0; i < 4; i++) {
- if (t[i].height) {
- if (t[i].rates & 0x10)
- modes = xf86ModesAdd(modes,
- xf86CVTMode(t[i].width, t[i].height, 50, 0, 0));
- if (t[i].rates & 0x08)
- modes = xf86ModesAdd(modes,
- xf86CVTMode(t[i].width, t[i].height, 60, 0, 0));
- if (t[i].rates & 0x04)
- modes = xf86ModesAdd(modes,
- xf86CVTMode(t[i].width, t[i].height, 75, 0, 0));
- if (t[i].rates & 0x02)
- modes = xf86ModesAdd(modes,
- xf86CVTMode(t[i].width, t[i].height, 85, 0, 0));
- if (t[i].rates & 0x01)
- modes = xf86ModesAdd(modes,
- xf86CVTMode(t[i].width, t[i].height, 60, 1, 0));
- } else break;
- }
-
- return modes;
-}
-
-static const struct {
- short w;
- short h;
- short r;
- short rb;
-} EstIIIModes[] = {
- /* byte 6 */
- { 640, 350, 85, 0 },
- { 640, 400, 85, 0 },
- { 720, 400, 85, 0 },
- { 640, 480, 85, 0 },
- { 848, 480, 60, 0 },
- { 800, 600, 85, 0 },
- { 1024, 768, 85, 0 },
- { 1152, 864, 75, 0 },
- /* byte 7 */
- { 1280, 768, 60, 1 },
- { 1280, 768, 60, 0 },
- { 1280, 768, 75, 0 },
- { 1280, 768, 85, 0 },
- { 1280, 960, 60, 0 },
- { 1280, 960, 85, 0 },
- { 1280, 1024, 60, 0 },
- { 1280, 1024, 85, 0 },
- /* byte 8 */
- { 1360, 768, 60, 0 },
- { 1440, 900, 60, 1 },
- { 1440, 900, 60, 0 },
- { 1440, 900, 75, 0 },
- { 1440, 900, 85, 0 },
- { 1400, 1050, 60, 1 },
- { 1400, 1050, 60, 0 },
- { 1400, 1050, 75, 0 },
- /* byte 9 */
- { 1400, 1050, 85, 0 },
- { 1680, 1050, 60, 1 },
- { 1680, 1050, 60, 0 },
- { 1680, 1050, 75, 0 },
- { 1680, 1050, 85, 0 },
- { 1600, 1200, 60, 0 },
- { 1600, 1200, 65, 0 },
- { 1600, 1200, 70, 0 },
- /* byte 10 */
- { 1600, 1200, 75, 0 },
- { 1600, 1200, 85, 0 },
- { 1792, 1344, 60, 0 },
- { 1792, 1344, 85, 0 },
- { 1856, 1392, 60, 0 },
- { 1856, 1392, 75, 0 },
- { 1920, 1200, 60, 1 },
- { 1920, 1200, 60, 0 },
- /* byte 11 */
- { 1920, 1200, 75, 0 },
- { 1920, 1200, 85, 0 },
- { 1920, 1440, 60, 0 },
- { 1920, 1440, 75, 0 },
-};
-
-static DisplayModePtr
-DDCModesFromEstIII(unsigned char *est)
-{
- DisplayModePtr modes = NULL;
- int i, j, m;
-
- for (i = 0; i < 6; i++) {
- for (j = 7; j > 0; j--) {
- if (est[i] & (1 << j)) {
- m = (i * 8) + (7 - j);
- modes = xf86ModesAdd(modes,
- FindDMTMode(EstIIIModes[m].w,
- EstIIIModes[m].h,
- EstIIIModes[m].r,
- EstIIIModes[m].rb));
- }
- }
- }
-
- return modes;
-}
-
-/*
- * This is only valid when the sink claims to be continuous-frequency
- * but does not supply a detailed range descriptor. Such sinks are
- * arguably broken. Currently the mode validation code isn't aware of
- * this; the non-RANDR code even punts the decision of optional sync
- * range checking to the driver. Loss.
- */
-static void
-DDCGuessRangesFromModes(int scrnIndex, MonPtr Monitor, DisplayModePtr Modes)
-{
- DisplayModePtr Mode = Modes;
-
- if (!Monitor || !Modes)
- return;
-
- /* set up the ranges for scanning through the modes */
- Monitor->nHsync = 1;
- Monitor->hsync[0].lo = 1024.0;
- Monitor->hsync[0].hi = 0.0;
-
- Monitor->nVrefresh = 1;
- Monitor->vrefresh[0].lo = 1024.0;
- Monitor->vrefresh[0].hi = 0.0;
-
- while (Mode) {
- if (!Mode->HSync)
- Mode->HSync = ((float) Mode->Clock ) / ((float) Mode->HTotal);
-
- if (!Mode->VRefresh)
- Mode->VRefresh = (1000.0 * ((float) Mode->Clock)) /
- ((float) (Mode->HTotal * Mode->VTotal));
-
- if (Mode->HSync < Monitor->hsync[0].lo)
- Monitor->hsync[0].lo = Mode->HSync;
-
- if (Mode->HSync > Monitor->hsync[0].hi)
- Monitor->hsync[0].hi = Mode->HSync;
-
- if (Mode->VRefresh < Monitor->vrefresh[0].lo)
- Monitor->vrefresh[0].lo = Mode->VRefresh;
-
- if (Mode->VRefresh > Monitor->vrefresh[0].hi)
- Monitor->vrefresh[0].hi = Mode->VRefresh;
-
- Mode = Mode->next;
- }
-}
-
-ddc_quirk_t
-xf86DDCDetectQuirks(int scrnIndex, xf86MonPtr DDC, Bool verbose)
-{
- ddc_quirk_t quirks;
- int i;
-
- quirks = DDC_QUIRK_NONE;
- for (i = 0; ddc_quirks[i].detect; i++) {
- if (ddc_quirks[i].detect (scrnIndex, DDC)) {
- if (verbose) {
- xf86DrvMsg (scrnIndex, X_INFO, " EDID quirk: %s\n",
- ddc_quirks[i].description);
- }
- quirks |= ddc_quirks[i].quirk;
- }
- }
-
- return quirks;
-}
-
-void xf86DetTimingApplyQuirks(struct detailed_monitor_section *det_mon,
- ddc_quirk_t quirks,
- int hsize, int vsize)
-{
- if (det_mon->type != DT)
- return;
-
- if (quirks & DDC_QUIRK_DETAILED_H_IN_CM)
- det_mon->section.d_timings.h_size *= 10;
-
- if (quirks & DDC_QUIRK_DETAILED_V_IN_CM)
- det_mon->section.d_timings.v_size *= 10;
-
- if (quirks & DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE) {
- det_mon->section.d_timings.h_size = 10 * hsize;
- det_mon->section.d_timings.v_size = 10 * vsize;
- }
-}
-
-/**
- * Applies monitor-specific quirks to the decoded EDID information.
- *
- * Note that some quirks applying to the mode list are still implemented in
- * xf86DDCGetModes.
- */
-void
-xf86DDCApplyQuirks(int scrnIndex, xf86MonPtr DDC)
-{
- ddc_quirk_t quirks = xf86DDCDetectQuirks (scrnIndex, DDC, FALSE);
- int i;
-
- for (i = 0; i < DET_TIMINGS; i++) {
- xf86DetTimingApplyQuirks(DDC->det_mon + i, quirks,
- DDC->features.hsize,
- DDC->features.vsize);
- }
-}
-
-/**
- * Walks the modes list, finding the mode with the largest area which is
- * closest to the target refresh rate, and marks it as the only preferred mode.
-*/
-static void
-xf86DDCSetPreferredRefresh(int scrnIndex, DisplayModePtr modes,
- float target_refresh)
-{
- DisplayModePtr mode, best = modes;
-
- for (mode = modes; mode; mode = mode->next)
- {
- mode->type &= ~M_T_PREFERRED;
-
- if (mode == best) continue;
-
- if (mode->HDisplay * mode->VDisplay >
- best->HDisplay * best->VDisplay)
- {
- best = mode;
- continue;
- }
- if (mode->HDisplay * mode->VDisplay ==
- best->HDisplay * best->VDisplay)
- {
- double mode_refresh = xf86ModeVRefresh (mode);
- double best_refresh = xf86ModeVRefresh (best);
- double mode_dist = fabs(mode_refresh - target_refresh);
- double best_dist = fabs(best_refresh - target_refresh);
-
- if (mode_dist < best_dist)
- {
- best = mode;
- continue;
- }
- }
- }
- if (best)
- best->type |= M_T_PREFERRED;
-}
-
-#define CEA_VIDEO_MODES_NUM 64
-static const DisplayModeRec CEAVideoModes[CEA_VIDEO_MODES_NUM] = {
- { MODEPREFIX, 25175, 640, 656, 752, 800, 0, 480, 490, 492, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 1:640x480@60Hz */
- { MODEPREFIX, 27000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 2:720x480@60Hz */
- { MODEPREFIX, 27000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 3:720x480@60Hz */
- { MODEPREFIX, 74250, 1280, 1390, 1430, 1650, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 4: 1280x720@60Hz */
- { MODEPREFIX, 74250, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 5:1920x1080i@60Hz */
- { MODEPREFIX, 27000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 6:1440x480i@60Hz */
- { MODEPREFIX, 27000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 7:1440x480i@60Hz */
- { MODEPREFIX, 27000, 1440, 1478, 1602, 1716, 0, 240, 244, 247, 262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 8:1440x240@60Hz */
- { MODEPREFIX, 27000, 1440, 1478, 1602, 1716, 0, 240, 244, 247, 262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 9:1440x240@60Hz */
- { MODEPREFIX, 54000, 2880, 2956, 3204, 3432, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 10:2880x480i@60Hz */
- { MODEPREFIX, 54000, 2880, 2956, 3204, 3432, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 11:2880x480i@60Hz */
- { MODEPREFIX, 54000, 2880, 2956, 3204, 3432, 0, 240, 244, 247, 262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 12:2880x240@60Hz */
- { MODEPREFIX, 54000, 2880, 2956, 3204, 3432, 0, 240, 244, 247, 262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 13:2880x240@60Hz */
- { MODEPREFIX, 54000, 1440, 1472, 1596, 1716, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 14:1440x480@60Hz */
- { MODEPREFIX, 54000, 1440, 1472, 1596, 1716, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 15:1440x480@60Hz */
- { MODEPREFIX, 148500, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 16:1920x1080@60Hz */
- { MODEPREFIX, 27000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 17:720x576@50Hz */
- { MODEPREFIX, 27000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 18:720x576@50Hz */
- { MODEPREFIX, 74250, 1280, 1720, 1760, 1980, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 19: 1280x720@50Hz */
- { MODEPREFIX, 74250, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 20:1920x1080i@50Hz */
- { MODEPREFIX, 27000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 21:1440x576i@50Hz */
- { MODEPREFIX, 27000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 22:1440x576i@50Hz */
- { MODEPREFIX, 27000, 1440, 1464, 1590, 1728, 0, 288, 290, 293, 312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 23:1440x288@50Hz */
- { MODEPREFIX, 27000, 1440, 1464, 1590, 1728, 0, 288, 290, 293, 312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 24:1440x288@50Hz */
- { MODEPREFIX, 54000, 2880, 2928, 3180, 3456, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 25:2880x576i@50Hz */
- { MODEPREFIX, 54000, 2880, 2928, 3180, 3456, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 26:2880x576i@50Hz */
- { MODEPREFIX, 54000, 2880, 2928, 3180, 3456, 0, 288, 290, 293, 312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 27:2880x288@50Hz */
- { MODEPREFIX, 54000, 2880, 2928, 3180, 3456, 0, 288, 290, 293, 312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 28:2880x288@50Hz */
- { MODEPREFIX, 54000, 1440, 1464, 1592, 1728, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 29:1440x576@50Hz */
- { MODEPREFIX, 54000, 1440, 1464, 1592, 1728, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 30:1440x576@50Hz */
- { MODEPREFIX, 148500, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 31:1920x1080@50Hz */
- { MODEPREFIX, 74250, 1920, 2558, 2602, 2750, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 32:1920x1080@24Hz */
- { MODEPREFIX, 74250, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 33:1920x1080@25Hz */
- { MODEPREFIX, 74250, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 34:1920x1080@30Hz */
- { MODEPREFIX, 108000, 2880, 2944, 3192, 3432, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 35:2880x480@60Hz */
- { MODEPREFIX, 108000, 2880, 2944, 3192, 3432, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 36:2880x480@60Hz */
- { MODEPREFIX, 108000, 2880, 2928, 3184, 3456, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 37:2880x576@50Hz */
- { MODEPREFIX, 108000, 2880, 2928, 3184, 3456, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 38:2880x576@50Hz */
- { MODEPREFIX, 72000, 1920, 1952, 2120, 2304, 0, 1080, 1126, 1136, 1250, 0, V_PHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 39:1920x1080i@50Hz */
- { MODEPREFIX, 148500, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 40:1920x1080i@100Hz */
- { MODEPREFIX, 148500, 1280, 1720, 1760, 1980, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 41:1280x720@100Hz */
- { MODEPREFIX, 54000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 42:720x576@100Hz */
- { MODEPREFIX, 54000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 43:720x576@100Hz */
- { MODEPREFIX, 54000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 44:1440x576i@100Hz */
- { MODEPREFIX, 54000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 45:1440x576i@100Hz */
- { MODEPREFIX, 148500, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 46:1920x1080i@120Hz */
- { MODEPREFIX, 148500, 1280, 1390, 1430, 1650, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 47:1280x720@120Hz */
- { MODEPREFIX, 54000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 48:720x480@120Hz */
- { MODEPREFIX, 54000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 49:720x480@120Hz */
- { MODEPREFIX, 54000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 50:1440x480i@120Hz */
- { MODEPREFIX, 54000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 51:1440x480i@120Hz */
- { MODEPREFIX, 108000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 52:720x576@200Hz */
- { MODEPREFIX, 108000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 53:720x576@200Hz */
- { MODEPREFIX, 108000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 54:1440x576i@200Hz */
- { MODEPREFIX, 108000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 55:1440x576i@200Hz */
- { MODEPREFIX, 108000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 56:720x480@240Hz */
- { MODEPREFIX, 108000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 57:720x480@240Hz */
- { MODEPREFIX, 108000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 58:1440x480i@240 */
- { MODEPREFIX, 108000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 59:1440x480i@240 */
- { MODEPREFIX, 59400, 1280, 3040, 3080, 3300, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 60: 1280x720@24Hz */
- { MODEPREFIX, 74250, 3700, 3740, 1430, 3960, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 61: 1280x720@25Hz */
- { MODEPREFIX, 74250, 1280, 3040, 3080, 3300, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 62: 1280x720@30Hz */
- { MODEPREFIX, 297000, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 63: 1920x1080@120Hz */
- { MODEPREFIX, 297000, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 64:1920x1080@100Hz */
-};
-
-/* chose mode line by cea short video descriptor*/
-static void handle_cea_svd(struct cea_video_block *video, void *data)
-{
- DisplayModePtr Mode;
- DisplayModePtr *Modes = (DisplayModePtr *) data;
- int vid;
-
- vid = video ->video_code & 0x7f;
- if (vid < CEA_VIDEO_MODES_NUM) {
- Mode = xf86DuplicateMode(CEAVideoModes + vid);
- *Modes = xf86ModesAdd(*Modes, Mode);
- }
-}
-
-static DisplayModePtr
-DDCModesFromCEAExtension(int scrnIndex, xf86MonPtr MonPtr)
-{
- DisplayModePtr Modes = NULL;
-
- xf86ForEachVideoBlock(MonPtr,
- handle_cea_svd,
- &Modes);
-
- return Modes;
-}
-
-struct det_modes_parameter {
- xf86MonPtr DDC;
- ddc_quirk_t quirks;
- DisplayModePtr Modes;
- Bool rb;
- Bool preferred;
- int timing_level;
-};
-
-static void handle_detailed_modes(struct detailed_monitor_section *det_mon,
- void *data)
-{
- DisplayModePtr Mode;
- struct det_modes_parameter *p = (struct det_modes_parameter *)data;
-
- xf86DetTimingApplyQuirks(det_mon,p->quirks,
- p->DDC->features.hsize,
- p->DDC->features.vsize);
-
- switch (det_mon->type) {
- case DT:
- Mode = DDCModeFromDetailedTiming(p->DDC->scrnIndex,
- &det_mon->section.d_timings,
- p->preferred,
- p->quirks);
- p->preferred = FALSE;
- p->Modes = xf86ModesAdd(p->Modes, Mode);
- break;
- case DS_STD_TIMINGS:
- Mode = DDCModesFromStandardTiming(det_mon->section.std_t,
- p->quirks, p->timing_level,p->rb);
- p->Modes = xf86ModesAdd(p->Modes, Mode);
- break;
- case DS_CVT:
- Mode = DDCModesFromCVT(p->DDC->scrnIndex, det_mon->section.cvt);
- p->Modes = xf86ModesAdd(p->Modes, Mode);
- break;
- case DS_EST_III:
- Mode = DDCModesFromEstIII(det_mon->section.est_iii);
- p->Modes = xf86ModesAdd(p->Modes, Mode);
- break;
- default:
- break;
- }
-}
-
-DisplayModePtr
-xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
-{
- DisplayModePtr Modes = NULL, Mode;
- ddc_quirk_t quirks;
- Bool preferred, rb;
- int timing_level;
- struct det_modes_parameter p;
-
- xf86DrvMsg (scrnIndex, X_INFO, "EDID vendor \"%s\", prod id %d\n",
- DDC->vendor.name, DDC->vendor.prod_id);
-
- quirks = xf86DDCDetectQuirks(scrnIndex, DDC, TRUE);
-
- preferred = PREFERRED_TIMING_MODE(DDC->features.msc);
- if (DDC->ver.revision >= 4)
- preferred = TRUE;
- if (quirks & DDC_QUIRK_FIRST_DETAILED_PREFERRED)
- preferred = TRUE;
- if (quirks & (DDC_QUIRK_PREFER_LARGE_60 | DDC_QUIRK_PREFER_LARGE_75))
- preferred = FALSE;
-
- rb = xf86MonitorSupportsReducedBlanking(DDC);
-
- timing_level = MonitorStandardTimingLevel(DDC);
-
- p.quirks = quirks;
- p.DDC = DDC;
- p.Modes = Modes;
- p.rb = rb;
- p.preferred = preferred;
- p.timing_level = timing_level;
- xf86ForEachDetailedBlock(DDC, handle_detailed_modes, &p);
- Modes = p.Modes;
-
- /* Add established timings */
- Mode = DDCModesFromEstablished(scrnIndex, &DDC->timings1, quirks);
- Modes = xf86ModesAdd(Modes, Mode);
-
- /* Add standard timings */
- Mode = DDCModesFromStandardTiming(DDC->timings2, quirks, timing_level, rb);
- Modes = xf86ModesAdd(Modes, Mode);
-
- /* Add cea-extension mode timings */
- Mode = DDCModesFromCEAExtension(scrnIndex,DDC);
- Modes = xf86ModesAdd(Modes, Mode);
-
- if (quirks & DDC_QUIRK_PREFER_LARGE_60)
- xf86DDCSetPreferredRefresh(scrnIndex, Modes, 60);
-
- if (quirks & DDC_QUIRK_PREFER_LARGE_75)
- xf86DDCSetPreferredRefresh(scrnIndex, Modes, 75);
-
- Modes = xf86PruneDuplicateModes(Modes);
-
- return Modes;
-}
-
-struct det_mon_parameter {
- MonPtr Monitor;
- ddc_quirk_t quirks;
- Bool have_hsync;
- Bool have_vrefresh;
- Bool have_maxpixclock;
-};
-
-static void handle_detailed_monset(struct detailed_monitor_section *det_mon,
- void *data)
-{
- int clock;
- struct det_mon_parameter *p = (struct det_mon_parameter *)data;
- int scrnIndex = ((xf86MonPtr)(p->Monitor->DDC))->scrnIndex;
-
- switch (det_mon->type) {
- case DS_RANGES:
- if (!p->have_hsync) {
- if (!p->Monitor->nHsync)
- xf86DrvMsg(scrnIndex, X_INFO,
- "Using EDID range info for horizontal sync\n");
- p->Monitor->hsync[p->Monitor->nHsync].lo =
- det_mon->section.ranges.min_h;
- p->Monitor->hsync[p->Monitor->nHsync].hi =
- det_mon->section.ranges.max_h;
- p->Monitor->nHsync++;
- } else {
- xf86DrvMsg(scrnIndex, X_INFO,
- "Using hsync ranges from config file\n");
- }
-
- if (!p->have_vrefresh) {
- if (!p->Monitor->nVrefresh)
- xf86DrvMsg(scrnIndex, X_INFO,
- "Using EDID range info for vertical refresh\n");
- p->Monitor->vrefresh[p->Monitor->nVrefresh].lo =
- det_mon->section.ranges.min_v;
- p->Monitor->vrefresh[p->Monitor->nVrefresh].hi =
- det_mon->section.ranges.max_v;
- p->Monitor->nVrefresh++;
- } else {
- xf86DrvMsg(scrnIndex, X_INFO,
- "Using vrefresh ranges from config file\n");
- }
-
- clock = det_mon->section.ranges.max_clock * 1000;
- if (p->quirks & DDC_QUIRK_DVI_SINGLE_LINK)
- clock = min(clock, 165000);
- if (!p->have_maxpixclock && clock > p->Monitor->maxPixClock)
- p->Monitor->maxPixClock = clock;
-
- break;
- default:
- break;
- }
-}
-
-/*
- * Fill out MonPtr with xf86MonPtr information.
- */
-void
-xf86EdidMonitorSet(int scrnIndex, MonPtr Monitor, xf86MonPtr DDC)
-{
- DisplayModePtr Modes = NULL, Mode;
- struct det_mon_parameter p;
-
- if (!Monitor || !DDC)
- return;
-
- Monitor->DDC = DDC;
-
- if (Monitor->widthmm <= 0 || Monitor->heightmm <= 0) {
- Monitor->widthmm = 10 * DDC->features.hsize;
- Monitor->heightmm = 10 * DDC->features.vsize;
- }
-
- Monitor->reducedblanking = xf86MonitorSupportsReducedBlanking(DDC);
-
- Modes = xf86DDCGetModes(scrnIndex, DDC);
-
- /* Go through the detailed monitor sections */
- p.Monitor = Monitor;
- p.quirks = xf86DDCDetectQuirks(scrnIndex, Monitor->DDC, FALSE);
- p.have_hsync = (Monitor->nHsync != 0);
- p.have_vrefresh = (Monitor->nVrefresh != 0);
- p.have_maxpixclock = (Monitor->maxPixClock != 0);
- xf86ForEachDetailedBlock(DDC, handle_detailed_monset, &p);
-
- if (Modes) {
- /* Print Modes */
- xf86DrvMsg(scrnIndex, X_INFO, "Printing DDC gathered Modelines:\n");
-
- Mode = Modes;
- while (Mode) {
- xf86PrintModeline(scrnIndex, Mode);
- Mode = Mode->next;
- }
-
- /* Do we still need ranges to be filled in? */
- if (!Monitor->nHsync || !Monitor->nVrefresh)
- DDCGuessRangesFromModes(scrnIndex, Monitor, Modes);
-
- /* look for last Mode */
- Mode = Modes;
-
- while (Mode->next)
- Mode = Mode->next;
-
- /* add to MonPtr */
- if (Monitor->Modes) {
- Monitor->Last->next = Modes;
- Modes->prev = Monitor->Last;
- Monitor->Last = Mode;
- } else {
- Monitor->Modes = Modes;
- Monitor->Last = Mode;
- }
- }
-}
+/*
+ * Copyright 2006 Luc Verhaegen.
+ * Copyright 2008 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @file This file covers code to convert a xf86MonPtr containing EDID-probed
+ * information into a list of modes, including applying monitor-specific
+ * quirks to fix broken EDID data.
+ */
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#else
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#endif
+
+#define _PARSE_EDID_
+#include "xf86.h"
+#include "xf86DDC.h"
+#include <X11/Xatom.h>
+#include "property.h"
+#include "propertyst.h"
+#include "xf86Crtc.h"
+#include <string.h>
+#include <math.h>
+
+static void handle_detailed_rblank(struct detailed_monitor_section *det_mon,
+ void *data)
+{
+ if (det_mon->type == DS_RANGES)
+ if (det_mon->section.ranges.supported_blanking & CVT_REDUCED)
+ *(Bool*)data = TRUE;
+}
+
+static Bool
+xf86MonitorSupportsReducedBlanking(xf86MonPtr DDC)
+{
+ /* EDID 1.4 explicitly defines RB support */
+ if (DDC->ver.revision >= 4) {
+ Bool ret = FALSE;
+
+ xf86ForEachDetailedBlock(DDC, handle_detailed_rblank, &ret);
+ return ret;
+ }
+
+ /* For anything older, assume digital means RB support. Boo. */
+ if (DDC->features.input_type)
+ return TRUE;
+
+ return FALSE;
+}
+
+static Bool quirk_prefer_large_60 (int scrnIndex, xf86MonPtr DDC)
+{
+ /* Belinea 10 15 55 */
+ if (memcmp (DDC->vendor.name, "MAX", 4) == 0 &&
+ ((DDC->vendor.prod_id == 1516) ||
+ (DDC->vendor.prod_id == 0x77e)))
+ return TRUE;
+
+ /* Acer AL1706 */
+ if (memcmp (DDC->vendor.name, "ACR", 4) == 0 &&
+ DDC->vendor.prod_id == 44358)
+ return TRUE;
+
+ /* Bug #10814: Samsung SyncMaster 225BW */
+ if (memcmp (DDC->vendor.name, "SAM", 4) == 0 &&
+ DDC->vendor.prod_id == 596)
+ return TRUE;
+
+ /* Bug #10545: Samsung SyncMaster 226BW */
+ if (memcmp (DDC->vendor.name, "SAM", 4) == 0 &&
+ DDC->vendor.prod_id == 638)
+ return TRUE;
+
+ /* Acer F51 */
+ if (memcmp (DDC->vendor.name, "API", 4) == 0 &&
+ DDC->vendor.prod_id == 0x7602)
+ return TRUE;
+
+
+ return FALSE;
+}
+
+static Bool quirk_prefer_large_75 (int scrnIndex, xf86MonPtr DDC)
+{
+ /* Bug #11603: Funai Electronics PM36B */
+ if (memcmp (DDC->vendor.name, "FCM", 4) == 0 &&
+ DDC->vendor.prod_id == 13600)
+ return TRUE;
+
+ return FALSE;
+}
+
+static Bool quirk_detailed_h_in_cm (int scrnIndex, xf86MonPtr DDC)
+{
+ /* Bug #11603: Funai Electronics PM36B */
+ if (memcmp (DDC->vendor.name, "FCM", 4) == 0 &&
+ DDC->vendor.prod_id == 13600)
+ return TRUE;
+
+ return FALSE;
+}
+
+static Bool quirk_detailed_v_in_cm (int scrnIndex, xf86MonPtr DDC)
+{
+ /* Bug #11603: Funai Electronics PM36B */
+ if (memcmp (DDC->vendor.name, "FCM", 4) == 0 &&
+ DDC->vendor.prod_id == 13600)
+ return TRUE;
+
+ /* Bug #21000: LGPhilipsLCD LP154W01-TLAJ */
+ if (memcmp (DDC->vendor.name, "LPL", 4) == 0 &&
+ DDC->vendor.prod_id == 47360)
+ return TRUE;
+
+ /* Bug #10304: LGPhilipsLCD LP154W01-A5 */
+ if (memcmp(DDC->vendor.name, "LPL", 4) == 0 &&
+ DDC->vendor.prod_id == 0)
+ return TRUE;
+
+ /* Bug #24482: LGPhilipsLCD LP154W01-TLA1 */
+ if (memcmp(DDC->vendor.name, "LPL", 4) == 0 &&
+ DDC->vendor.prod_id == 0x2a00)
+ return TRUE;
+
+ /* Bug #28414: HP Compaq NC8430 LP154W01-TLA8 */
+ if (memcmp (DDC->vendor.name, "LPL", 4) == 0 &&
+ DDC->vendor.prod_id == 5750)
+ return TRUE;
+
+ /* Bug #21750: Samsung Syncmaster 2333HD */
+ if (memcmp (DDC->vendor.name, "SAM", 4) == 0 &&
+ DDC->vendor.prod_id == 1157)
+ return TRUE;
+
+ return FALSE;
+}
+
+static Bool quirk_detailed_use_maximum_size (int scrnIndex, xf86MonPtr DDC)
+{
+ /* Bug #21324: Iiyama Vision Master 450 */
+ if (memcmp (DDC->vendor.name, "IVM", 4) == 0 &&
+ DDC->vendor.prod_id == 6400)
+ return TRUE;
+
+ return FALSE;
+}
+
+static Bool quirk_135_clock_too_high (int scrnIndex, xf86MonPtr DDC)
+{
+ /* Envision Peripherals, Inc. EN-7100e. See bug #9550. */
+ if (memcmp (DDC->vendor.name, "EPI", 4) == 0 &&
+ DDC->vendor.prod_id == 59264)
+ return TRUE;
+
+ return FALSE;
+}
+
+static Bool quirk_first_detailed_preferred (int scrnIndex, xf86MonPtr DDC)
+{
+ /* Philips 107p5 CRT. Reported on xorg@ with pastebin. */
+ if (memcmp (DDC->vendor.name, "PHL", 4) == 0 &&
+ DDC->vendor.prod_id == 57364)
+ return TRUE;
+
+ /* Proview AY765C 17" LCD. See bug #15160*/
+ if (memcmp (DDC->vendor.name, "PTS", 4) == 0 &&
+ DDC->vendor.prod_id == 765)
+ return TRUE;
+
+ /* ACR of some sort RH #284231 */
+ if (memcmp (DDC->vendor.name, "ACR", 4) == 0 &&
+ DDC->vendor.prod_id == 2423)
+ return TRUE;
+
+ /* Peacock Ergovision 19. See rh#492359 */
+ if (memcmp (DDC->vendor.name, "PEA", 4) == 0 &&
+ DDC->vendor.prod_id == 9003)
+ return TRUE;
+
+ return FALSE;
+}
+
+static Bool quirk_detailed_sync_pp(int scrnIndex, xf86MonPtr DDC)
+{
+ /* Bug #12439: Samsung SyncMaster 205BW */
+ if (memcmp (DDC->vendor.name, "SAM", 4) == 0 &&
+ DDC->vendor.prod_id == 541)
+ return TRUE;
+ return FALSE;
+}
+
+/* This should probably be made more generic */
+static Bool quirk_dvi_single_link(int scrnIndex, xf86MonPtr DDC)
+{
+ /* Red Hat bug #453106: Apple 23" Cinema Display */
+ if (memcmp (DDC->vendor.name, "APL", 4) == 0 &&
+ DDC->vendor.prod_id == 0x921c)
+ return TRUE;
+ return FALSE;
+}
+
+typedef struct {
+ Bool (*detect) (int scrnIndex, xf86MonPtr DDC);
+ ddc_quirk_t quirk;
+ char *description;
+} ddc_quirk_map_t;
+
+static const ddc_quirk_map_t ddc_quirks[] = {
+ {
+ quirk_prefer_large_60, DDC_QUIRK_PREFER_LARGE_60,
+ "Detailed timing is not preferred, use largest mode at 60Hz"
+ },
+ {
+ quirk_135_clock_too_high, DDC_QUIRK_135_CLOCK_TOO_HIGH,
+ "Recommended 135MHz pixel clock is too high"
+ },
+ {
+ quirk_prefer_large_75, DDC_QUIRK_PREFER_LARGE_75,
+ "Detailed timing is not preferred, use largest mode at 75Hz"
+ },
+ {
+ quirk_detailed_h_in_cm, DDC_QUIRK_DETAILED_H_IN_CM,
+ "Detailed timings give horizontal size in cm."
+ },
+ {
+ quirk_detailed_v_in_cm, DDC_QUIRK_DETAILED_V_IN_CM,
+ "Detailed timings give vertical size in cm."
+ },
+ {
+ quirk_detailed_use_maximum_size, DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE,
+ "Use maximum size instead of detailed timing sizes."
+ },
+ {
+ quirk_first_detailed_preferred, DDC_QUIRK_FIRST_DETAILED_PREFERRED,
+ "First detailed timing was not marked as preferred."
+ },
+ {
+ quirk_detailed_sync_pp, DDC_QUIRK_DETAILED_SYNC_PP,
+ "Use +hsync +vsync for detailed timing."
+ },
+ {
+ quirk_dvi_single_link, DDC_QUIRK_DVI_SINGLE_LINK,
+ "Forcing maximum pixel clock to single DVI link."
+ },
+ {
+ NULL, DDC_QUIRK_NONE,
+ "No known quirks"
+ },
+};
+
+/*
+ * These more or less come from the DMT spec. The 720x400 modes are
+ * inferred from historical 80x25 practice. The 640x480@67 and 832x624@75
+ * modes are old-school Mac modes. The EDID spec says the 1152x864@75 mode
+ * should be 1152x870, again for the Mac, but instead we use the x864 DMT
+ * mode.
+ *
+ * The DMT modes have been fact-checked; the rest are mild guesses.
+ */
+#define MODEPREFIX NULL, NULL, NULL, 0, M_T_DRIVER
+#define MODESUFFIX 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,FALSE,FALSE,0,NULL,0,0.0,0.0
+
+static const DisplayModeRec DDCEstablishedModes[17] = {
+ { MODEPREFIX, 40000, 800, 840, 968, 1056, 0, 600, 601, 605, 628, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@60Hz */
+ { MODEPREFIX, 36000, 800, 824, 896, 1024, 0, 600, 601, 603, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@56Hz */
+ { MODEPREFIX, 31500, 640, 656, 720, 840, 0, 480, 481, 484, 500, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@75Hz */
+ { MODEPREFIX, 31500, 640, 664, 704, 832, 0, 480, 489, 492, 520, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@72Hz */
+ { MODEPREFIX, 30240, 640, 704, 768, 864, 0, 480, 483, 486, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@67Hz */
+ { MODEPREFIX, 25175, 640, 656, 752, 800, 0, 480, 490, 492, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@60Hz */
+ { MODEPREFIX, 35500, 720, 738, 846, 900, 0, 400, 421, 423, 449, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 720x400@88Hz */
+ { MODEPREFIX, 28320, 720, 738, 846, 900, 0, 400, 412, 414, 449, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 720x400@70Hz */
+ { MODEPREFIX, 135000, 1280, 1296, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024@75Hz */
+ { MODEPREFIX, 78750, 1024, 1040, 1136, 1312, 0, 768, 769, 772, 800, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1024x768@75Hz */
+ { MODEPREFIX, 75000, 1024, 1048, 1184, 1328, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@70Hz */
+ { MODEPREFIX, 65000, 1024, 1048, 1184, 1344, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@60Hz */
+ { MODEPREFIX, 44900, 1024, 1032, 1208, 1264, 0, 768, 768, 772, 817, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* 1024x768@43Hz */
+ { MODEPREFIX, 57284, 832, 864, 928, 1152, 0, 624, 625, 628, 667, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 832x624@75Hz */
+ { MODEPREFIX, 49500, 800, 816, 896, 1056, 0, 600, 601, 604, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@75Hz */
+ { MODEPREFIX, 50000, 800, 856, 976, 1040, 0, 600, 637, 643, 666, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@72Hz */
+ { MODEPREFIX, 108000, 1152, 1216, 1344, 1600, 0, 864, 865, 868, 900, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1152x864@75Hz */
+};
+
+static DisplayModePtr
+DDCModesFromEstablished(int scrnIndex, struct established_timings *timing,
+ ddc_quirk_t quirks)
+{
+ DisplayModePtr Modes = NULL, Mode = NULL;
+ CARD32 bits = (timing->t1) | (timing->t2 << 8) |
+ ((timing->t_manu & 0x80) << 9);
+ int i;
+
+ for (i = 0; i < 17; i++) {
+ if (bits & (0x01 << i)) {
+ Mode = xf86DuplicateMode(&DDCEstablishedModes[i]);
+ Modes = xf86ModesAdd(Modes, Mode);
+ }
+ }
+
+ return Modes;
+}
+
+/* Autogenerated from the DMT spec */
+const DisplayModeRec DMTModes[] = {
+ { MODEPREFIX, 31500, 640, 672, 736, 832, 0, 350, 382, 385, 445, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x350@85Hz */
+ { MODEPREFIX, 31500, 640, 672, 736, 832, 0, 400, 401, 404, 445, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 640x400@85Hz */
+ { MODEPREFIX, 35500, 720, 756, 828, 936, 0, 400, 401, 404, 446, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 720x400@85Hz */
+ { MODEPREFIX, 25175, 640, 656, 752, 800, 0, 480, 490, 492, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@60Hz */
+ { MODEPREFIX, 31500, 640, 664, 704, 832, 0, 480, 489, 492, 520, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@72Hz */
+ { MODEPREFIX, 31500, 640, 656, 720, 840, 0, 480, 481, 484, 500, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@75Hz */
+ { MODEPREFIX, 36000, 640, 696, 752, 832, 0, 480, 481, 484, 509, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 640x480@85Hz */
+ { MODEPREFIX, 36000, 800, 824, 896, 1024, 0, 600, 601, 603, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@56Hz */
+ { MODEPREFIX, 40000, 800, 840, 968, 1056, 0, 600, 601, 605, 628, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@60Hz */
+ { MODEPREFIX, 50000, 800, 856, 976, 1040, 0, 600, 637, 643, 666, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@72Hz */
+ { MODEPREFIX, 49500, 800, 816, 896, 1056, 0, 600, 601, 604, 625, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@75Hz */
+ { MODEPREFIX, 56250, 800, 832, 896, 1048, 0, 600, 601, 604, 631, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 800x600@85Hz */
+ { MODEPREFIX, 73250, 800, 848, 880, 960, 0, 600, 603, 607, 636, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 800x600@120Hz RB */
+ { MODEPREFIX, 33750, 848, 864, 976, 1088, 0, 480, 486, 494, 517, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 848x480@60Hz */
+ { MODEPREFIX, 44900, 1024, 1032, 1208, 1264, 0, 768, 768, 772, 817, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* 1024x768@43Hz (interlaced) */
+ { MODEPREFIX, 65000, 1024, 1048, 1184, 1344, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@60Hz */
+ { MODEPREFIX, 75000, 1024, 1048, 1184, 1328, 0, 768, 771, 777, 806, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@70Hz */
+ { MODEPREFIX, 78750, 1024, 1040, 1136, 1312, 0, 768, 769, 772, 800, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1024x768@75Hz */
+ { MODEPREFIX, 94500, 1024, 1072, 1168, 1376, 0, 768, 769, 772, 808, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1024x768@85Hz */
+ { MODEPREFIX, 115500, 1024, 1072, 1104, 1184, 0, 768, 771, 775, 813, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1024x768@120Hz RB */
+ { MODEPREFIX, 108000, 1152, 1216, 1344, 1600, 0, 864, 865, 868, 900, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1152x864@75Hz */
+ { MODEPREFIX, 68250, 1280, 1328, 1360, 1440, 0, 768, 771, 778, 790, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x768@60Hz RB */
+ { MODEPREFIX, 79500, 1280, 1344, 1472, 1664, 0, 768, 771, 778, 798, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x768@60Hz */
+ { MODEPREFIX, 102250, 1280, 1360, 1488, 1696, 0, 768, 771, 778, 805, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x768@75Hz */
+ { MODEPREFIX, 117500, 1280, 1360, 1496, 1712, 0, 768, 771, 778, 809, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x768@85Hz */
+ { MODEPREFIX, 140250, 1280, 1328, 1360, 1440, 0, 768, 771, 778, 813, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x768@120Hz RB */
+ { MODEPREFIX, 71000, 1280, 1328, 1360, 1440, 0, 800, 803, 809, 823, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x800@60Hz RB */
+ { MODEPREFIX, 83500, 1280, 1352, 1480, 1680, 0, 800, 803, 809, 831, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x800@60Hz */
+ { MODEPREFIX, 106500, 1280, 1360, 1488, 1696, 0, 800, 803, 809, 838, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x800@75Hz */
+ { MODEPREFIX, 122500, 1280, 1360, 1496, 1712, 0, 800, 803, 809, 843, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x800@85Hz */
+ { MODEPREFIX, 146250, 1280, 1328, 1360, 1440, 0, 800, 803, 809, 847, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x800@120Hz RB */
+ { MODEPREFIX, 108000, 1280, 1376, 1488, 1800, 0, 960, 961, 964, 1000, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x960@60Hz */
+ { MODEPREFIX, 148500, 1280, 1344, 1504, 1728, 0, 960, 961, 964, 1011, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x960@85Hz */
+ { MODEPREFIX, 175500, 1280, 1328, 1360, 1440, 0, 960, 963, 967, 1017, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x960@120Hz RB */
+ { MODEPREFIX, 108000, 1280, 1328, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024@60Hz */
+ { MODEPREFIX, 135000, 1280, 1296, 1440, 1688, 0, 1024, 1025, 1028, 1066, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024@75Hz */
+ { MODEPREFIX, 157500, 1280, 1344, 1504, 1728, 0, 1024, 1025, 1028, 1072, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1280x1024@85Hz */
+ { MODEPREFIX, 187250, 1280, 1328, 1360, 1440, 0, 1024, 1027, 1034, 1084, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1280x1024@120Hz RB */
+ { MODEPREFIX, 85500, 1360, 1424, 1536, 1792, 0, 768, 771, 777, 795, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1360x768@60Hz */
+ { MODEPREFIX, 148250, 1360, 1408, 1440, 1520, 0, 768, 771, 776, 813, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1360x768@120Hz RB */
+ { MODEPREFIX, 101000, 1400, 1448, 1480, 1560, 0, 1050, 1053, 1057, 1080, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1400x1050@60Hz RB */
+ { MODEPREFIX, 121750, 1400, 1488, 1632, 1864, 0, 1050, 1053, 1057, 1089, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1400x1050@60Hz */
+ { MODEPREFIX, 156000, 1400, 1504, 1648, 1896, 0, 1050, 1053, 1057, 1099, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1400x1050@75Hz */
+ { MODEPREFIX, 179500, 1400, 1504, 1656, 1912, 0, 1050, 1053, 1057, 1105, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1400x1050@85Hz */
+ { MODEPREFIX, 208000, 1400, 1448, 1480, 1560, 0, 1050, 1053, 1057, 1112, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1400x1050@120Hz RB */
+ { MODEPREFIX, 88750, 1440, 1488, 1520, 1600, 0, 900, 903, 909, 926, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1440x900@60Hz RB */
+ { MODEPREFIX, 106500, 1440, 1520, 1672, 1904, 0, 900, 903, 909, 934, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1440x900@60Hz */
+ { MODEPREFIX, 136750, 1440, 1536, 1688, 1936, 0, 900, 903, 909, 942, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1440x900@75Hz */
+ { MODEPREFIX, 157000, 1440, 1544, 1696, 1952, 0, 900, 903, 909, 948, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1440x900@85Hz */
+ { MODEPREFIX, 182750, 1440, 1488, 1520, 1600, 0, 900, 903, 909, 953, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1440x900@120Hz RB */
+ { MODEPREFIX, 162000, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1600x1200@60Hz */
+ { MODEPREFIX, 175500, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1600x1200@65Hz */
+ { MODEPREFIX, 189000, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1600x1200@70Hz */
+ { MODEPREFIX, 202500, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1600x1200@75Hz */
+ { MODEPREFIX, 229500, 1600, 1664, 1856, 2160, 0, 1200, 1201, 1204, 1250, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* 1600x1200@85Hz */
+ { MODEPREFIX, 268250, 1600, 1648, 1680, 1760, 0, 1200, 1203, 1207, 1271, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1600x1200@120Hz RB */
+ { MODEPREFIX, 119000, 1680, 1728, 1760, 1840, 0, 1050, 1053, 1059, 1080, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1680x1050@60Hz RB */
+ { MODEPREFIX, 146250, 1680, 1784, 1960, 2240, 0, 1050, 1053, 1059, 1089, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1680x1050@60Hz */
+ { MODEPREFIX, 187000, 1680, 1800, 1976, 2272, 0, 1050, 1053, 1059, 1099, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1680x1050@75Hz */
+ { MODEPREFIX, 214750, 1680, 1808, 1984, 2288, 0, 1050, 1053, 1059, 1105, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1680x1050@85Hz */
+ { MODEPREFIX, 245500, 1680, 1728, 1760, 1840, 0, 1050, 1053, 1059, 1112, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1680x1050@120Hz RB */
+ { MODEPREFIX, 204750, 1792, 1920, 2120, 2448, 0, 1344, 1345, 1348, 1394, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1792x1344@60Hz */
+ { MODEPREFIX, 261000, 1792, 1888, 2104, 2456, 0, 1344, 1345, 1348, 1417, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1792x1344@75Hz */
+ { MODEPREFIX, 333250, 1792, 1840, 1872, 1952, 0, 1344, 1347, 1351, 1423, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1792x1344@120Hz RB */
+ { MODEPREFIX, 218250, 1856, 1952, 2176, 2528, 0, 1392, 1393, 1396, 1439, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1856x1392@60Hz */
+ { MODEPREFIX, 288000, 1856, 1984, 2208, 2560, 0, 1392, 1393, 1396, 1500, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1856x1392@75Hz */
+ { MODEPREFIX, 356500, 1856, 1904, 1936, 2016, 0, 1392, 1395, 1399, 1474, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1856x1392@120Hz RB */
+ { MODEPREFIX, 154000, 1920, 1968, 2000, 2080, 0, 1200, 1203, 1209, 1235, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1920x1200@60Hz RB */
+ { MODEPREFIX, 193250, 1920, 2056, 2256, 2592, 0, 1200, 1203, 1209, 1245, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1920x1200@60Hz */
+ { MODEPREFIX, 245250, 1920, 2056, 2264, 2608, 0, 1200, 1203, 1209, 1255, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1920x1200@75Hz */
+ { MODEPREFIX, 281250, 1920, 2064, 2272, 2624, 0, 1200, 1203, 1209, 1262, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1920x1200@85Hz */
+ { MODEPREFIX, 317000, 1920, 1968, 2000, 2080, 0, 1200, 1203, 1209, 1271, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1920x1200@120Hz RB */
+ { MODEPREFIX, 234000, 1920, 2048, 2256, 2600, 0, 1440, 1441, 1444, 1500, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1920x1440@60Hz */
+ { MODEPREFIX, 297000, 1920, 2064, 2288, 2640, 0, 1440, 1441, 1444, 1500, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 1920x1440@75Hz */
+ { MODEPREFIX, 380500, 1920, 1968, 2000, 2080, 0, 1440, 1443, 1447, 1525, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 1920x1440@120Hz RB */
+ { MODEPREFIX, 268500, 2560, 2608, 2640, 2720, 0, 1600, 1603, 1609, 1646, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 2560x1600@60Hz RB */
+ { MODEPREFIX, 348500, 2560, 2752, 3032, 3504, 0, 1600, 1603, 1609, 1658, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 2560x1600@60Hz */
+ { MODEPREFIX, 443250, 2560, 2768, 3048, 3536, 0, 1600, 1603, 1609, 1672, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 2560x1600@75Hz */
+ { MODEPREFIX, 505250, 2560, 2768, 3048, 3536, 0, 1600, 1603, 1609, 1682, 0, V_NHSYNC | V_PVSYNC, MODESUFFIX }, /* 2560x1600@85Hz */
+ { MODEPREFIX, 552750, 2560, 2608, 2640, 2720, 0, 1600, 1603, 1609, 1694, 0, V_PHSYNC | V_NVSYNC, MODESUFFIX }, /* 2560x1600@120Hz RB */
+};
+
+#define LEVEL_DMT 0
+#define LEVEL_GTF 1
+#define LEVEL_CVT 2
+
+static int
+MonitorStandardTimingLevel(xf86MonPtr DDC)
+{
+ if (DDC->ver.revision >= 2) {
+ if (DDC->ver.revision >= 4 && CVT_SUPPORTED(DDC->features.msc)) {
+ return LEVEL_CVT;
+ }
+ return LEVEL_GTF;
+ }
+ return LEVEL_DMT;
+}
+
+static int
+ModeRefresh(const DisplayModeRec *mode)
+{
+ return (int)(xf86ModeVRefresh(mode) + 0.5);
+}
+
+/*
+ * If rb is not set, then we'll not consider reduced-blanking modes as
+ * part of the DMT pool. For the 'standard' EDID mode descriptor there's
+ * no way to specify whether the mode should be RB or not.
+ */
+DisplayModePtr
+FindDMTMode(int hsize, int vsize, int refresh, Bool rb)
+{
+ int i;
+ const DisplayModeRec *ret;
+
+ for (i = 0; i < sizeof(DMTModes) / sizeof(DisplayModeRec); i++) {
+ ret = &DMTModes[i];
+
+ if (!rb && xf86ModeIsReduced(ret))
+ continue;
+
+ if (ret->HDisplay == hsize &&
+ ret->VDisplay == vsize &&
+ refresh == ModeRefresh(ret))
+ return xf86DuplicateMode(ret);
+ }
+
+ return NULL;
+}
+
+/*
+ * Appendix B of the EDID 1.4 spec defines the right thing to do here.
+ * If the timing given here matches a mode defined in the VESA DMT standard,
+ * we _must_ use that. If the device supports CVT modes, then we should
+ * generate a CVT timing. If both of the above fail, use GTF.
+ *
+ * There are some wrinkles here. EDID 1.1 and 1.0 sinks can't really
+ * "support" GTF, since it wasn't a standard yet; so if they ask for a
+ * timing in this section that isn't defined in DMT, returning a GTF mode
+ * may not actually be valid. EDID 1.3 sinks often report support for
+ * some CVT modes, but they are not required to support CVT timings for
+ * modes in the standard timing descriptor, so we should _not_ treat them
+ * as CVT-compliant (unless specified in an extension block I suppose).
+ *
+ * EDID 1.4 requires that all sink devices support both GTF and CVT timings
+ * for modes in this section, but does say that CVT is preferred.
+ */
+static DisplayModePtr
+DDCModesFromStandardTiming(struct std_timings *timing, ddc_quirk_t quirks,
+ int timing_level, Bool rb)
+{
+ DisplayModePtr Modes = NULL, Mode = NULL;
+ int i, hsize, vsize, refresh;
+
+ for (i = 0; i < STD_TIMINGS; i++) {
+ hsize = timing[i].hsize;
+ vsize = timing[i].vsize;
+ refresh = timing[i].refresh;
+
+ /* HDTV hack, because you can't say 1366 */
+ if (refresh == 60 &&
+ ((hsize == 1360 && vsize == 765) ||
+ (hsize == 1368 && vsize == 769))) {
+ Mode = xf86CVTMode(1366, 768, 60, FALSE, FALSE);
+ Mode->HDisplay = 1366;
+ Mode->HSyncStart--;
+ Mode->HSyncEnd--;
+ } else if (hsize && vsize && refresh) {
+ Mode = FindDMTMode(hsize, vsize, refresh, rb);
+
+ if (!Mode) {
+ if (timing_level == LEVEL_CVT)
+ /* pass rb here too? */
+ Mode = xf86CVTMode(hsize, vsize, refresh, FALSE, FALSE);
+ else if (timing_level == LEVEL_GTF)
+ Mode = xf86GTFMode(hsize, vsize, refresh, FALSE, FALSE);
+ }
+
+ }
+
+ if (Mode) {
+ Mode->type = M_T_DRIVER;
+ Modes = xf86ModesAdd(Modes, Mode);
+ }
+ Mode = NULL;
+ }
+
+ return Modes;
+}
+
+static void
+DDCModeDoInterlaceQuirks(DisplayModePtr mode)
+{
+ /*
+ * EDID is delightfully ambiguous about how interlaced modes are to be
+ * encoded. X's internal representation is of frame height, but some
+ * HDTV detailed timings are encoded as field height.
+ *
+ * The format list here is from CEA, in frame size. Technically we
+ * should be checking refresh rate too. Whatever.
+ */
+ static const struct {
+ int w, h;
+ } cea_interlaced[] = {
+ { 1920, 1080 },
+ { 720, 480 },
+ { 1440, 480 },
+ { 2880, 480 },
+ { 720, 576 },
+ { 1440, 576 },
+ { 2880, 576 },
+ };
+ static const int n_modes = sizeof(cea_interlaced)/sizeof(cea_interlaced[0]);
+ int i;
+
+ for (i = 0; i < n_modes; i++) {
+ if ((mode->HDisplay == cea_interlaced[i].w) &&
+ (mode->VDisplay == cea_interlaced[i].h / 2)) {
+ mode->VDisplay *= 2;
+ mode->VSyncStart *= 2;
+ mode->VSyncEnd *= 2;
+ mode->VTotal *= 2;
+ mode->VTotal |= 1;
+ }
+ }
+
+ mode->Flags |= V_INTERLACE;
+}
+
+/*
+ *
+ */
+static DisplayModePtr
+DDCModeFromDetailedTiming(int scrnIndex, struct detailed_timings *timing,
+ Bool preferred, ddc_quirk_t quirks)
+{
+ DisplayModePtr Mode;
+
+ /*
+ * Refuse to create modes that are insufficiently large. 64 is a random
+ * number, maybe the spec says something about what the minimum is. In
+ * particular I see this frequently with _old_ EDID, 1.0 or so, so maybe
+ * our parser is just being too aggresive there.
+ */
+ if (timing->h_active < 64 || timing->v_active < 64) {
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "%s: Ignoring tiny %dx%d mode\n", __func__,
+ timing->h_active, timing->v_active);
+ return NULL;
+ }
+
+ /* We don't do stereo */
+ if (timing->stereo) {
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "%s: Ignoring: We don't handle stereo.\n", __func__);
+ return NULL;
+ }
+
+ /* We only do seperate sync currently */
+ if (timing->sync != 0x03) {
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "%s: %dx%d Warning: We only handle separate"
+ " sync.\n", __func__, timing->h_active, timing->v_active);
+ }
+
+ Mode = xnfcalloc(1, sizeof(DisplayModeRec));
+
+ Mode->type = M_T_DRIVER;
+ if (preferred)
+ Mode->type |= M_T_PREFERRED;
+
+ if( ( quirks & DDC_QUIRK_135_CLOCK_TOO_HIGH ) &&
+ timing->clock == 135000000 )
+ Mode->Clock = 108880;
+ else
+ Mode->Clock = timing->clock / 1000.0;
+
+ Mode->HDisplay = timing->h_active;
+ Mode->HSyncStart = timing->h_active + timing->h_sync_off;
+ Mode->HSyncEnd = Mode->HSyncStart + timing->h_sync_width;
+ Mode->HTotal = timing->h_active + timing->h_blanking;
+
+ Mode->VDisplay = timing->v_active;
+ Mode->VSyncStart = timing->v_active + timing->v_sync_off;
+ Mode->VSyncEnd = Mode->VSyncStart + timing->v_sync_width;
+ Mode->VTotal = timing->v_active + timing->v_blanking;
+
+ /* perform basic check on the detail timing */
+ if (Mode->HSyncEnd > Mode->HTotal || Mode->VSyncEnd > Mode->VTotal) {
+ free(Mode);
+ return NULL;
+ }
+
+ /* We ignore h/v_size and h/v_border for now. */
+
+ if (timing->interlaced)
+ DDCModeDoInterlaceQuirks(Mode);
+
+ if (quirks & DDC_QUIRK_DETAILED_SYNC_PP)
+ Mode->Flags |= V_PVSYNC | V_PHSYNC;
+ else {
+ if (timing->misc & 0x02)
+ Mode->Flags |= V_PVSYNC;
+ else
+ Mode->Flags |= V_NVSYNC;
+
+ if (timing->misc & 0x01)
+ Mode->Flags |= V_PHSYNC;
+ else
+ Mode->Flags |= V_NHSYNC;
+ }
+
+ xf86SetModeDefaultName(Mode);
+
+ return Mode;
+}
+
+static DisplayModePtr
+DDCModesFromCVT(int scrnIndex, struct cvt_timings *t)
+{
+ DisplayModePtr modes = NULL;
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (t[i].height) {
+ if (t[i].rates & 0x10)
+ modes = xf86ModesAdd(modes,
+ xf86CVTMode(t[i].width, t[i].height, 50, 0, 0));
+ if (t[i].rates & 0x08)
+ modes = xf86ModesAdd(modes,
+ xf86CVTMode(t[i].width, t[i].height, 60, 0, 0));
+ if (t[i].rates & 0x04)
+ modes = xf86ModesAdd(modes,
+ xf86CVTMode(t[i].width, t[i].height, 75, 0, 0));
+ if (t[i].rates & 0x02)
+ modes = xf86ModesAdd(modes,
+ xf86CVTMode(t[i].width, t[i].height, 85, 0, 0));
+ if (t[i].rates & 0x01)
+ modes = xf86ModesAdd(modes,
+ xf86CVTMode(t[i].width, t[i].height, 60, 1, 0));
+ } else break;
+ }
+
+ return modes;
+}
+
+static const struct {
+ short w;
+ short h;
+ short r;
+ short rb;
+} EstIIIModes[] = {
+ /* byte 6 */
+ { 640, 350, 85, 0 },
+ { 640, 400, 85, 0 },
+ { 720, 400, 85, 0 },
+ { 640, 480, 85, 0 },
+ { 848, 480, 60, 0 },
+ { 800, 600, 85, 0 },
+ { 1024, 768, 85, 0 },
+ { 1152, 864, 75, 0 },
+ /* byte 7 */
+ { 1280, 768, 60, 1 },
+ { 1280, 768, 60, 0 },
+ { 1280, 768, 75, 0 },
+ { 1280, 768, 85, 0 },
+ { 1280, 960, 60, 0 },
+ { 1280, 960, 85, 0 },
+ { 1280, 1024, 60, 0 },
+ { 1280, 1024, 85, 0 },
+ /* byte 8 */
+ { 1360, 768, 60, 0 },
+ { 1440, 900, 60, 1 },
+ { 1440, 900, 60, 0 },
+ { 1440, 900, 75, 0 },
+ { 1440, 900, 85, 0 },
+ { 1400, 1050, 60, 1 },
+ { 1400, 1050, 60, 0 },
+ { 1400, 1050, 75, 0 },
+ /* byte 9 */
+ { 1400, 1050, 85, 0 },
+ { 1680, 1050, 60, 1 },
+ { 1680, 1050, 60, 0 },
+ { 1680, 1050, 75, 0 },
+ { 1680, 1050, 85, 0 },
+ { 1600, 1200, 60, 0 },
+ { 1600, 1200, 65, 0 },
+ { 1600, 1200, 70, 0 },
+ /* byte 10 */
+ { 1600, 1200, 75, 0 },
+ { 1600, 1200, 85, 0 },
+ { 1792, 1344, 60, 0 },
+ { 1792, 1344, 85, 0 },
+ { 1856, 1392, 60, 0 },
+ { 1856, 1392, 75, 0 },
+ { 1920, 1200, 60, 1 },
+ { 1920, 1200, 60, 0 },
+ /* byte 11 */
+ { 1920, 1200, 75, 0 },
+ { 1920, 1200, 85, 0 },
+ { 1920, 1440, 60, 0 },
+ { 1920, 1440, 75, 0 },
+};
+
+static DisplayModePtr
+DDCModesFromEstIII(unsigned char *est)
+{
+ DisplayModePtr modes = NULL;
+ int i, j, m;
+
+ for (i = 0; i < 6; i++) {
+ for (j = 7; j > 0; j--) {
+ if (est[i] & (1 << j)) {
+ m = (i * 8) + (7 - j);
+ modes = xf86ModesAdd(modes,
+ FindDMTMode(EstIIIModes[m].w,
+ EstIIIModes[m].h,
+ EstIIIModes[m].r,
+ EstIIIModes[m].rb));
+ }
+ }
+ }
+
+ return modes;
+}
+
+/*
+ * This is only valid when the sink claims to be continuous-frequency
+ * but does not supply a detailed range descriptor. Such sinks are
+ * arguably broken. Currently the mode validation code isn't aware of
+ * this; the non-RANDR code even punts the decision of optional sync
+ * range checking to the driver. Loss.
+ */
+static void
+DDCGuessRangesFromModes(int scrnIndex, MonPtr Monitor, DisplayModePtr Modes)
+{
+ DisplayModePtr Mode = Modes;
+
+ if (!Monitor || !Modes)
+ return;
+
+ /* set up the ranges for scanning through the modes */
+ Monitor->nHsync = 1;
+ Monitor->hsync[0].lo = 1024.0;
+ Monitor->hsync[0].hi = 0.0;
+
+ Monitor->nVrefresh = 1;
+ Monitor->vrefresh[0].lo = 1024.0;
+ Monitor->vrefresh[0].hi = 0.0;
+
+ while (Mode) {
+ if (!Mode->HSync)
+ Mode->HSync = ((float) Mode->Clock ) / ((float) Mode->HTotal);
+
+ if (!Mode->VRefresh)
+ Mode->VRefresh = (1000.0 * ((float) Mode->Clock)) /
+ ((float) (Mode->HTotal * Mode->VTotal));
+
+ if (Mode->HSync < Monitor->hsync[0].lo)
+ Monitor->hsync[0].lo = Mode->HSync;
+
+ if (Mode->HSync > Monitor->hsync[0].hi)
+ Monitor->hsync[0].hi = Mode->HSync;
+
+ if (Mode->VRefresh < Monitor->vrefresh[0].lo)
+ Monitor->vrefresh[0].lo = Mode->VRefresh;
+
+ if (Mode->VRefresh > Monitor->vrefresh[0].hi)
+ Monitor->vrefresh[0].hi = Mode->VRefresh;
+
+ Mode = Mode->next;
+ }
+}
+
+ddc_quirk_t
+xf86DDCDetectQuirks(int scrnIndex, xf86MonPtr DDC, Bool verbose)
+{
+ ddc_quirk_t quirks;
+ int i;
+
+ quirks = DDC_QUIRK_NONE;
+ for (i = 0; ddc_quirks[i].detect; i++) {
+ if (ddc_quirks[i].detect (scrnIndex, DDC)) {
+ if (verbose) {
+ xf86DrvMsg (scrnIndex, X_INFO, " EDID quirk: %s\n",
+ ddc_quirks[i].description);
+ }
+ quirks |= ddc_quirks[i].quirk;
+ }
+ }
+
+ return quirks;
+}
+
+void xf86DetTimingApplyQuirks(struct detailed_monitor_section *det_mon,
+ ddc_quirk_t quirks,
+ int hsize, int vsize)
+{
+ if (det_mon->type != DT)
+ return;
+
+ if (quirks & DDC_QUIRK_DETAILED_H_IN_CM)
+ det_mon->section.d_timings.h_size *= 10;
+
+ if (quirks & DDC_QUIRK_DETAILED_V_IN_CM)
+ det_mon->section.d_timings.v_size *= 10;
+
+ if (quirks & DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE) {
+ det_mon->section.d_timings.h_size = 10 * hsize;
+ det_mon->section.d_timings.v_size = 10 * vsize;
+ }
+}
+
+/**
+ * Applies monitor-specific quirks to the decoded EDID information.
+ *
+ * Note that some quirks applying to the mode list are still implemented in
+ * xf86DDCGetModes.
+ */
+void
+xf86DDCApplyQuirks(int scrnIndex, xf86MonPtr DDC)
+{
+ ddc_quirk_t quirks = xf86DDCDetectQuirks (scrnIndex, DDC, FALSE);
+ int i;
+
+ for (i = 0; i < DET_TIMINGS; i++) {
+ xf86DetTimingApplyQuirks(DDC->det_mon + i, quirks,
+ DDC->features.hsize,
+ DDC->features.vsize);
+ }
+}
+
+/**
+ * Walks the modes list, finding the mode with the largest area which is
+ * closest to the target refresh rate, and marks it as the only preferred mode.
+*/
+static void
+xf86DDCSetPreferredRefresh(int scrnIndex, DisplayModePtr modes,
+ float target_refresh)
+{
+ DisplayModePtr mode, best = modes;
+
+ for (mode = modes; mode; mode = mode->next)
+ {
+ mode->type &= ~M_T_PREFERRED;
+
+ if (mode == best) continue;
+
+ if (mode->HDisplay * mode->VDisplay >
+ best->HDisplay * best->VDisplay)
+ {
+ best = mode;
+ continue;
+ }
+ if (mode->HDisplay * mode->VDisplay ==
+ best->HDisplay * best->VDisplay)
+ {
+ double mode_refresh = xf86ModeVRefresh (mode);
+ double best_refresh = xf86ModeVRefresh (best);
+ double mode_dist = fabs(mode_refresh - target_refresh);
+ double best_dist = fabs(best_refresh - target_refresh);
+
+ if (mode_dist < best_dist)
+ {
+ best = mode;
+ continue;
+ }
+ }
+ }
+ if (best)
+ best->type |= M_T_PREFERRED;
+}
+
+#define CEA_VIDEO_MODES_NUM 64
+static const DisplayModeRec CEAVideoModes[CEA_VIDEO_MODES_NUM] = {
+ { MODEPREFIX, 25175, 640, 656, 752, 800, 0, 480, 490, 492, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 1:640x480@60Hz */
+ { MODEPREFIX, 27000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 2:720x480@60Hz */
+ { MODEPREFIX, 27000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 3:720x480@60Hz */
+ { MODEPREFIX, 74250, 1280, 1390, 1430, 1650, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 4: 1280x720@60Hz */
+ { MODEPREFIX, 74250, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 5:1920x1080i@60Hz */
+ { MODEPREFIX, 27000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 6:1440x480i@60Hz */
+ { MODEPREFIX, 27000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 7:1440x480i@60Hz */
+ { MODEPREFIX, 27000, 1440, 1478, 1602, 1716, 0, 240, 244, 247, 262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 8:1440x240@60Hz */
+ { MODEPREFIX, 27000, 1440, 1478, 1602, 1716, 0, 240, 244, 247, 262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 9:1440x240@60Hz */
+ { MODEPREFIX, 54000, 2880, 2956, 3204, 3432, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 10:2880x480i@60Hz */
+ { MODEPREFIX, 54000, 2880, 2956, 3204, 3432, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 11:2880x480i@60Hz */
+ { MODEPREFIX, 54000, 2880, 2956, 3204, 3432, 0, 240, 244, 247, 262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 12:2880x240@60Hz */
+ { MODEPREFIX, 54000, 2880, 2956, 3204, 3432, 0, 240, 244, 247, 262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 13:2880x240@60Hz */
+ { MODEPREFIX, 54000, 1440, 1472, 1596, 1716, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 14:1440x480@60Hz */
+ { MODEPREFIX, 54000, 1440, 1472, 1596, 1716, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 15:1440x480@60Hz */
+ { MODEPREFIX, 148500, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 16:1920x1080@60Hz */
+ { MODEPREFIX, 27000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 17:720x576@50Hz */
+ { MODEPREFIX, 27000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 18:720x576@50Hz */
+ { MODEPREFIX, 74250, 1280, 1720, 1760, 1980, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 19: 1280x720@50Hz */
+ { MODEPREFIX, 74250, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 20:1920x1080i@50Hz */
+ { MODEPREFIX, 27000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 21:1440x576i@50Hz */
+ { MODEPREFIX, 27000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 22:1440x576i@50Hz */
+ { MODEPREFIX, 27000, 1440, 1464, 1590, 1728, 0, 288, 290, 293, 312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 23:1440x288@50Hz */
+ { MODEPREFIX, 27000, 1440, 1464, 1590, 1728, 0, 288, 290, 293, 312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 24:1440x288@50Hz */
+ { MODEPREFIX, 54000, 2880, 2928, 3180, 3456, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 25:2880x576i@50Hz */
+ { MODEPREFIX, 54000, 2880, 2928, 3180, 3456, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 26:2880x576i@50Hz */
+ { MODEPREFIX, 54000, 2880, 2928, 3180, 3456, 0, 288, 290, 293, 312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 27:2880x288@50Hz */
+ { MODEPREFIX, 54000, 2880, 2928, 3180, 3456, 0, 288, 290, 293, 312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 28:2880x288@50Hz */
+ { MODEPREFIX, 54000, 1440, 1464, 1592, 1728, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 29:1440x576@50Hz */
+ { MODEPREFIX, 54000, 1440, 1464, 1592, 1728, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 30:1440x576@50Hz */
+ { MODEPREFIX, 148500, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 31:1920x1080@50Hz */
+ { MODEPREFIX, 74250, 1920, 2558, 2602, 2750, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 32:1920x1080@24Hz */
+ { MODEPREFIX, 74250, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 33:1920x1080@25Hz */
+ { MODEPREFIX, 74250, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 34:1920x1080@30Hz */
+ { MODEPREFIX, 108000, 2880, 2944, 3192, 3432, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 35:2880x480@60Hz */
+ { MODEPREFIX, 108000, 2880, 2944, 3192, 3432, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 36:2880x480@60Hz */
+ { MODEPREFIX, 108000, 2880, 2928, 3184, 3456, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 37:2880x576@50Hz */
+ { MODEPREFIX, 108000, 2880, 2928, 3184, 3456, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 38:2880x576@50Hz */
+ { MODEPREFIX, 72000, 1920, 1952, 2120, 2304, 0, 1080, 1126, 1136, 1250, 0, V_PHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 39:1920x1080i@50Hz */
+ { MODEPREFIX, 148500, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 40:1920x1080i@100Hz */
+ { MODEPREFIX, 148500, 1280, 1720, 1760, 1980, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 41:1280x720@100Hz */
+ { MODEPREFIX, 54000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 42:720x576@100Hz */
+ { MODEPREFIX, 54000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 43:720x576@100Hz */
+ { MODEPREFIX, 54000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 44:1440x576i@100Hz */
+ { MODEPREFIX, 54000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 45:1440x576i@100Hz */
+ { MODEPREFIX, 148500, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 46:1920x1080i@120Hz */
+ { MODEPREFIX, 148500, 1280, 1390, 1430, 1650, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 47:1280x720@120Hz */
+ { MODEPREFIX, 54000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 48:720x480@120Hz */
+ { MODEPREFIX, 54000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 49:720x480@120Hz */
+ { MODEPREFIX, 54000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 50:1440x480i@120Hz */
+ { MODEPREFIX, 54000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 51:1440x480i@120Hz */
+ { MODEPREFIX, 108000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 52:720x576@200Hz */
+ { MODEPREFIX, 108000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 53:720x576@200Hz */
+ { MODEPREFIX, 108000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 54:1440x576i@200Hz */
+ { MODEPREFIX, 108000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 55:1440x576i@200Hz */
+ { MODEPREFIX, 108000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 56:720x480@240Hz */
+ { MODEPREFIX, 108000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 57:720x480@240Hz */
+ { MODEPREFIX, 108000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 58:1440x480i@240 */
+ { MODEPREFIX, 108000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 59:1440x480i@240 */
+ { MODEPREFIX, 59400, 1280, 3040, 3080, 3300, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 60: 1280x720@24Hz */
+ { MODEPREFIX, 74250, 1280, 3700, 3740, 3960, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 61: 1280x720@25Hz */
+ { MODEPREFIX, 74250, 1280, 3040, 3080, 3300, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 62: 1280x720@30Hz */
+ { MODEPREFIX, 297000, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 63: 1920x1080@120Hz */
+ { MODEPREFIX, 297000, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 64:1920x1080@100Hz */
+};
+
+/* chose mode line by cea short video descriptor*/
+static void handle_cea_svd(struct cea_video_block *video, void *data)
+{
+ DisplayModePtr Mode;
+ DisplayModePtr *Modes = (DisplayModePtr *) data;
+ int vid;
+
+ vid = video ->video_code & 0x7f;
+ if (vid < CEA_VIDEO_MODES_NUM) {
+ Mode = xf86DuplicateMode(CEAVideoModes + vid);
+ *Modes = xf86ModesAdd(*Modes, Mode);
+ }
+}
+
+static DisplayModePtr
+DDCModesFromCEAExtension(int scrnIndex, xf86MonPtr MonPtr)
+{
+ DisplayModePtr Modes = NULL;
+
+ xf86ForEachVideoBlock(MonPtr,
+ handle_cea_svd,
+ &Modes);
+
+ return Modes;
+}
+
+struct det_modes_parameter {
+ xf86MonPtr DDC;
+ ddc_quirk_t quirks;
+ DisplayModePtr Modes;
+ Bool rb;
+ Bool preferred;
+ int timing_level;
+};
+
+static void handle_detailed_modes(struct detailed_monitor_section *det_mon,
+ void *data)
+{
+ DisplayModePtr Mode;
+ struct det_modes_parameter *p = (struct det_modes_parameter *)data;
+
+ xf86DetTimingApplyQuirks(det_mon,p->quirks,
+ p->DDC->features.hsize,
+ p->DDC->features.vsize);
+
+ switch (det_mon->type) {
+ case DT:
+ Mode = DDCModeFromDetailedTiming(p->DDC->scrnIndex,
+ &det_mon->section.d_timings,
+ p->preferred,
+ p->quirks);
+ p->preferred = FALSE;
+ p->Modes = xf86ModesAdd(p->Modes, Mode);
+ break;
+ case DS_STD_TIMINGS:
+ Mode = DDCModesFromStandardTiming(det_mon->section.std_t,
+ p->quirks, p->timing_level,p->rb);
+ p->Modes = xf86ModesAdd(p->Modes, Mode);
+ break;
+ case DS_CVT:
+ Mode = DDCModesFromCVT(p->DDC->scrnIndex, det_mon->section.cvt);
+ p->Modes = xf86ModesAdd(p->Modes, Mode);
+ break;
+ case DS_EST_III:
+ Mode = DDCModesFromEstIII(det_mon->section.est_iii);
+ p->Modes = xf86ModesAdd(p->Modes, Mode);
+ break;
+ default:
+ break;
+ }
+}
+
+DisplayModePtr
+xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC)
+{
+ DisplayModePtr Modes = NULL, Mode;
+ ddc_quirk_t quirks;
+ Bool preferred, rb;
+ int timing_level;
+ struct det_modes_parameter p;
+
+ xf86DrvMsg (scrnIndex, X_INFO, "EDID vendor \"%s\", prod id %d\n",
+ DDC->vendor.name, DDC->vendor.prod_id);
+
+ quirks = xf86DDCDetectQuirks(scrnIndex, DDC, TRUE);
+
+ preferred = PREFERRED_TIMING_MODE(DDC->features.msc);
+ if (DDC->ver.revision >= 4)
+ preferred = TRUE;
+ if (quirks & DDC_QUIRK_FIRST_DETAILED_PREFERRED)
+ preferred = TRUE;
+ if (quirks & (DDC_QUIRK_PREFER_LARGE_60 | DDC_QUIRK_PREFER_LARGE_75))
+ preferred = FALSE;
+
+ rb = xf86MonitorSupportsReducedBlanking(DDC);
+
+ timing_level = MonitorStandardTimingLevel(DDC);
+
+ p.quirks = quirks;
+ p.DDC = DDC;
+ p.Modes = Modes;
+ p.rb = rb;
+ p.preferred = preferred;
+ p.timing_level = timing_level;
+ xf86ForEachDetailedBlock(DDC, handle_detailed_modes, &p);
+ Modes = p.Modes;
+
+ /* Add established timings */
+ Mode = DDCModesFromEstablished(scrnIndex, &DDC->timings1, quirks);
+ Modes = xf86ModesAdd(Modes, Mode);
+
+ /* Add standard timings */
+ Mode = DDCModesFromStandardTiming(DDC->timings2, quirks, timing_level, rb);
+ Modes = xf86ModesAdd(Modes, Mode);
+
+ /* Add cea-extension mode timings */
+ Mode = DDCModesFromCEAExtension(scrnIndex,DDC);
+ Modes = xf86ModesAdd(Modes, Mode);
+
+ if (quirks & DDC_QUIRK_PREFER_LARGE_60)
+ xf86DDCSetPreferredRefresh(scrnIndex, Modes, 60);
+
+ if (quirks & DDC_QUIRK_PREFER_LARGE_75)
+ xf86DDCSetPreferredRefresh(scrnIndex, Modes, 75);
+
+ Modes = xf86PruneDuplicateModes(Modes);
+
+ return Modes;
+}
+
+struct det_mon_parameter {
+ MonPtr Monitor;
+ ddc_quirk_t quirks;
+ Bool have_hsync;
+ Bool have_vrefresh;
+ Bool have_maxpixclock;
+};
+
+static void handle_detailed_monset(struct detailed_monitor_section *det_mon,
+ void *data)
+{
+ int clock;
+ struct det_mon_parameter *p = (struct det_mon_parameter *)data;
+ int scrnIndex = ((xf86MonPtr)(p->Monitor->DDC))->scrnIndex;
+
+ switch (det_mon->type) {
+ case DS_RANGES:
+ if (!p->have_hsync) {
+ if (!p->Monitor->nHsync)
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Using EDID range info for horizontal sync\n");
+ p->Monitor->hsync[p->Monitor->nHsync].lo =
+ det_mon->section.ranges.min_h;
+ p->Monitor->hsync[p->Monitor->nHsync].hi =
+ det_mon->section.ranges.max_h;
+ p->Monitor->nHsync++;
+ } else {
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Using hsync ranges from config file\n");
+ }
+
+ if (!p->have_vrefresh) {
+ if (!p->Monitor->nVrefresh)
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Using EDID range info for vertical refresh\n");
+ p->Monitor->vrefresh[p->Monitor->nVrefresh].lo =
+ det_mon->section.ranges.min_v;
+ p->Monitor->vrefresh[p->Monitor->nVrefresh].hi =
+ det_mon->section.ranges.max_v;
+ p->Monitor->nVrefresh++;
+ } else {
+ xf86DrvMsg(scrnIndex, X_INFO,
+ "Using vrefresh ranges from config file\n");
+ }
+
+ clock = det_mon->section.ranges.max_clock * 1000;
+ if (p->quirks & DDC_QUIRK_DVI_SINGLE_LINK)
+ clock = min(clock, 165000);
+ if (!p->have_maxpixclock && clock > p->Monitor->maxPixClock)
+ p->Monitor->maxPixClock = clock;
+
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+ * Fill out MonPtr with xf86MonPtr information.
+ */
+void
+xf86EdidMonitorSet(int scrnIndex, MonPtr Monitor, xf86MonPtr DDC)
+{
+ DisplayModePtr Modes = NULL, Mode;
+ struct det_mon_parameter p;
+
+ if (!Monitor || !DDC)
+ return;
+
+ Monitor->DDC = DDC;
+
+ if (Monitor->widthmm <= 0 || Monitor->heightmm <= 0) {
+ Monitor->widthmm = 10 * DDC->features.hsize;
+ Monitor->heightmm = 10 * DDC->features.vsize;
+ }
+
+ Monitor->reducedblanking = xf86MonitorSupportsReducedBlanking(DDC);
+
+ Modes = xf86DDCGetModes(scrnIndex, DDC);
+
+ /* Go through the detailed monitor sections */
+ p.Monitor = Monitor;
+ p.quirks = xf86DDCDetectQuirks(scrnIndex, Monitor->DDC, FALSE);
+ p.have_hsync = (Monitor->nHsync != 0);
+ p.have_vrefresh = (Monitor->nVrefresh != 0);
+ p.have_maxpixclock = (Monitor->maxPixClock != 0);
+ xf86ForEachDetailedBlock(DDC, handle_detailed_monset, &p);
+
+ if (Modes) {
+ /* Print Modes */
+ xf86DrvMsg(scrnIndex, X_INFO, "Printing DDC gathered Modelines:\n");
+
+ Mode = Modes;
+ while (Mode) {
+ xf86PrintModeline(scrnIndex, Mode);
+ Mode = Mode->next;
+ }
+
+ /* Do we still need ranges to be filled in? */
+ if (!Monitor->nHsync || !Monitor->nVrefresh)
+ DDCGuessRangesFromModes(scrnIndex, Monitor, Modes);
+
+ /* look for last Mode */
+ Mode = Modes;
+
+ while (Mode->next)
+ Mode = Mode->next;
+
+ /* add to MonPtr */
+ if (Monitor->Modes) {
+ Monitor->Last->next = Modes;
+ Modes->prev = Monitor->Last;
+ Monitor->Last = Mode;
+ } else {
+ Monitor->Modes = Modes;
+ Monitor->Last = Mode;
+ }
+ }
+}
diff --git a/xorg-server/hw/xfree86/modes/xf86Modes.c b/xorg-server/hw/xfree86/modes/xf86Modes.c
index 335bb43ee..45308f484 100644
--- a/xorg-server/hw/xfree86/modes/xf86Modes.c
+++ b/xorg-server/hw/xfree86/modes/xf86Modes.c
@@ -355,15 +355,32 @@ xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList,
{
DisplayModePtr mode;
- for (mode = modeList; mode != NULL; mode = mode->next) {
- if (maxPitch > 0 && mode->HDisplay > maxPitch)
- mode->status = MODE_BAD_WIDTH;
-
- if (maxX > 0 && mode->HDisplay > maxX)
- mode->status = MODE_VIRTUAL_X;
+ if (maxPitch <= 0)
+ maxPitch = MAXINT;
+ if (maxX <= 0)
+ maxX = MAXINT;
+ if (maxY <= 0)
+ maxY = MAXINT;
- if (maxY > 0 && mode->VDisplay > maxY)
- mode->status = MODE_VIRTUAL_Y;
+ for (mode = modeList; mode != NULL; mode = mode->next) {
+ if ((xf86ModeWidth(mode, RR_Rotate_0) > maxPitch ||
+ xf86ModeWidth(mode, RR_Rotate_0) > maxX ||
+ xf86ModeHeight(mode, RR_Rotate_0) > maxY) &&
+ (xf86ModeWidth(mode, RR_Rotate_90) > maxPitch ||
+ xf86ModeWidth(mode, RR_Rotate_90) > maxX ||
+ xf86ModeHeight(mode, RR_Rotate_90) > maxY)) {
+ if (xf86ModeWidth(mode, RR_Rotate_0) > maxPitch ||
+ xf86ModeWidth(mode, RR_Rotate_90) > maxPitch)
+ mode->status = MODE_BAD_WIDTH;
+
+ if (xf86ModeWidth(mode, RR_Rotate_0) > maxX ||
+ xf86ModeWidth(mode, RR_Rotate_90) > maxX)
+ mode->status = MODE_VIRTUAL_X;
+
+ if (xf86ModeHeight(mode, RR_Rotate_0) > maxY ||
+ xf86ModeHeight(mode, RR_Rotate_90) > maxY)
+ mode->status = MODE_VIRTUAL_Y;
+ }
if (mode->next == modeList)
break;
diff --git a/xorg-server/hw/xfree86/os-support/linux/lnx_agp.c b/xorg-server/hw/xfree86/os-support/linux/lnx_agp.c
index 705bb5ea0..dcc878060 100644
--- a/xorg-server/hw/xfree86/os-support/linux/lnx_agp.c
+++ b/xorg-server/hw/xfree86/os-support/linux/lnx_agp.c
@@ -264,7 +264,7 @@ xf86DeallocateGARTMemory(int screenNum, int key)
}
#ifdef __linux__
- if (ioctl(gartFd, AGPIOC_DEALLOCATE, (int *)key) != 0) {
+ if (ioctl(gartFd, AGPIOC_DEALLOCATE, (int *)(uintptr_t)key) != 0) {
#else
if (ioctl(gartFd, AGPIOC_DEALLOCATE, &key) != 0) {
#endif
diff --git a/xorg-server/hw/xfree86/os-support/linux/lnx_video.c b/xorg-server/hw/xfree86/os-support/linux/lnx_video.c
index 0311bdf15..697c9fe30 100644
--- a/xorg-server/hw/xfree86/os-support/linux/lnx_video.c
+++ b/xorg-server/hw/xfree86/os-support/linux/lnx_video.c
@@ -461,7 +461,7 @@ mapVidMem(int ScreenNum, unsigned long Base, unsigned long Size, int flags)
" (0x%08lx,0x%lx) (%s)\n", Base, Size,
strerror(errno));
}
- DebugF("base: %lx aligned base: %lx\n",base, base + alignOff);
+ DebugF("base: %lx aligned base: %lx\n",base, (char *)base + alignOff);
return (char *)base + alignOff;
}
#endif /* !(__sparc__) */
diff --git a/xorg-server/hw/xfree86/x86emu/ops.c b/xorg-server/hw/xfree86/x86emu/ops.c
index c0cfbd8c1..a55398275 100644
--- a/xorg-server/hw/xfree86/x86emu/ops.c
+++ b/xorg-server/hw/xfree86/x86emu/ops.c
@@ -7065,15 +7065,20 @@ Handles opcode 0x9a
****************************************************************************/
static void x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1))
{
- u16 farseg, faroff;
+ u32 farseg, faroff;
START_OF_INSTR();
- DECODE_PRINTF("CALL\t");
+ DECODE_PRINTF("CALL\t");
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ faroff = fetch_long_imm();
+ farseg = fetch_word_imm();
+ } else {
faroff = fetch_word_imm();
farseg = fetch_word_imm();
- DECODE_PRINTF2("%04x:", farseg);
- DECODE_PRINTF2("%04x\n", faroff);
- CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, farseg, faroff, "FAR ");
+ }
+ DECODE_PRINTF2("%04x:", farseg);
+ DECODE_PRINTF2("%04x\n", faroff);
+ CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, farseg, faroff, "FAR ");
/* XXX
*
@@ -7084,8 +7089,12 @@ static void x86emuOp_call_far_IMM(u8 X86EMU_UNUSED(op1))
TRACE_AND_STEP();
push_word(M.x86.R_CS);
M.x86.R_CS = farseg;
- push_word(M.x86.R_IP);
- M.x86.R_IP = faroff;
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ push_long(M.x86.R_EIP);
+ } else {
+ push_word(M.x86.R_IP);
+ }
+ M.x86.R_EIP = faroff & 0xffff;
DECODE_CLEAR_SEGOVR();
END_OF_INSTR();
}
@@ -9670,17 +9679,30 @@ Handles opcode 0xe8
****************************************************************************/
static void x86emuOp_call_near_IMM(u8 X86EMU_UNUSED(op1))
{
- s16 ip;
+ s16 ip16;
+ s32 ip32;
START_OF_INSTR();
- DECODE_PRINTF("CALL\t");
- ip = (s16) fetch_word_imm();
- ip += (s16) M.x86.R_IP; /* CHECK SIGN */
- DECODE_PRINTF2("%04x\n", (u16)ip);
- CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip, "");
+ DECODE_PRINTF("CALL\t");
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ ip32 = (s32) fetch_long_imm();
+ ip32 += (s16) M.x86.R_IP; /* CHECK SIGN */
+ DECODE_PRINTF2("%04x\n", (u16)ip32);
+ CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip32, "");
+ } else {
+ ip16 = (s16) fetch_word_imm();
+ ip16 += (s16) M.x86.R_IP; /* CHECK SIGN */
+ DECODE_PRINTF2("%04x\n", (u16)ip16);
+ CALL_TRACE(M.x86.saved_cs, M.x86.saved_ip, M.x86.R_CS, ip16, "");
+ }
TRACE_AND_STEP();
- push_word(M.x86.R_IP);
- M.x86.R_IP = ip;
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ push_long(M.x86.R_EIP);
+ M.x86.R_EIP = ip32 & 0xffff;
+ } else {
+ push_word(M.x86.R_IP);
+ M.x86.R_EIP = ip16;
+ }
DECODE_CLEAR_SEGOVR();
END_OF_INSTR();
}
@@ -9718,16 +9740,21 @@ Handles opcode 0xea
****************************************************************************/
static void x86emuOp_jump_far_IMM(u8 X86EMU_UNUSED(op1))
{
- u16 cs, ip;
+ u16 cs;
+ u32 ip;
START_OF_INSTR();
DECODE_PRINTF("JMP\tFAR ");
- ip = fetch_word_imm();
+ if (M.x86.mode & SYSMODE_PREFIX_DATA) {
+ ip = fetch_long_imm();
+ } else {
+ ip = fetch_word_imm();
+ }
cs = fetch_word_imm();
DECODE_PRINTF2("%04x:", cs);
DECODE_PRINTF2("%04x\n", ip);
TRACE_AND_STEP();
- M.x86.R_IP = ip;
+ M.x86.R_EIP = ip & 0xffff;
M.x86.R_CS = cs;
DECODE_CLEAR_SEGOVR();
END_OF_INSTR();
diff --git a/xorg-server/hw/xfree86/xaa/xaaBitBlt.c b/xorg-server/hw/xfree86/xaa/xaaBitBlt.c
index cc7e810ca..126a4ee65 100644
--- a/xorg-server/hw/xfree86/xaa/xaaBitBlt.c
+++ b/xorg-server/hw/xfree86/xaa/xaaBitBlt.c
@@ -54,10 +54,10 @@ XAABitBlt(
origDest.x = dstx;
origDest.y = dsty;
- if((pSrcDrawable != pDstDrawable) &&
- pSrcDrawable->pScreen->SourceValidate) {
+ if (pSrcDrawable->pScreen->SourceValidate) {
(*pSrcDrawable->pScreen->SourceValidate) (
- pSrcDrawable, srcx, srcy, width, height);
+ pSrcDrawable, srcx, srcy, width, height,
+ pGC->subWindowMode);
}
srcx += pSrcDrawable->x;
diff --git a/xorg-server/include/exevents.h b/xorg-server/include/exevents.h
index b972cbedf..2b859a3bd 100644
--- a/xorg-server/include/exevents.h
+++ b/xorg-server/include/exevents.h
@@ -307,6 +307,6 @@ XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
unsigned int len, unsigned char* mask);
extern int
-XICheckInvalidMaskBits(unsigned char *mask, int len);
+XICheckInvalidMaskBits(ClientPtr client, unsigned char *mask, int len);
#endif /* EXEVENTS_H */
diff --git a/xorg-server/include/input.h b/xorg-server/include/input.h
index a7fdc6671..31aad9aa4 100644
--- a/xorg-server/include/input.h
+++ b/xorg-server/include/input.h
@@ -532,6 +532,18 @@ void FixUpEventFromWindow(DeviceIntPtr pDev,
WindowPtr pWin,
Window child,
Bool calcChild);
+extern int EventIsDeliverable(DeviceIntPtr dev, InternalEvent* event,
+ WindowPtr win);
+/**
+ * Return masks for EventIsDeliverable.
+ * @defgroup EventIsDeliverable return flags
+ * @{
+ */
+#define XI_MASK (1 << 0) /**< XI mask set on window */
+#define CORE_MASK (1 << 1) /**< Core mask set on window */
+#define DONT_PROPAGATE_MASK (1 << 2) /**< DontPropagate mask set on window */
+#define XI2_MASK (1 << 3) /**< XI2 mask set on window */
+/* @} */
/* Implemented by the DDX. */
extern _X_EXPORT int NewInputDeviceRequest(
@@ -554,7 +566,6 @@ extern _X_HIDDEN void valuator_set_mode(DeviceIntPtr dev, int axis, int mode);
xfixes/cursor.c uses it to determine if the cursor is enabled */
extern Bool EnableCursor;
-/* For server-internal functions, see inpututil.h */
extern _X_EXPORT ValuatorMask *valuator_mask_new(int num_valuators);
extern _X_EXPORT void valuator_mask_set_range(ValuatorMask *mask,
int first_valuator, int num_valuators,
@@ -563,5 +574,12 @@ extern _X_EXPORT void valuator_mask_set(ValuatorMask *mask,
int valuator,
int data);
extern _X_EXPORT void valuator_mask_zero(ValuatorMask *mask);
+extern _X_EXPORT int valuator_mask_size(const ValuatorMask *mask);
+extern _X_EXPORT int valuator_mask_isset(const ValuatorMask *mask, int bit);
+extern _X_EXPORT void valuator_mask_unset(ValuatorMask *mask, int bit);
+extern _X_EXPORT int valuator_mask_num_valuators(const ValuatorMask *mask);
+extern _X_EXPORT void valuator_mask_copy(ValuatorMask *dest,
+ const ValuatorMask *src);
+extern _X_EXPORT int valuator_mask_get(const ValuatorMask *mask, int valnum);
#endif /* INPUT_H */
diff --git a/xorg-server/include/inpututils.h b/xorg-server/include/inpututils.h
index e59bf2860..af07afeb0 100644
--- a/xorg-server/include/inpututils.h
+++ b/xorg-server/include/inpututils.h
@@ -37,12 +37,4 @@ struct _ValuatorMask {
int valuators[MAX_VALUATORS]; /* valuator data */
};
-/* server-internal */
-extern _X_HIDDEN int valuator_mask_size(const ValuatorMask *mask);
-extern _X_HIDDEN int valuator_mask_isset(const ValuatorMask *mask, int bit);
-extern _X_HIDDEN void valuator_mask_unset(ValuatorMask *mask, int bit);
-extern _X_HIDDEN int valuator_mask_num_valuators(const ValuatorMask *mask);
-extern _X_HIDDEN void valuator_mask_copy(ValuatorMask *dest, const ValuatorMask *src);
-extern _X_HIDDEN int valuator_mask_get(const ValuatorMask *mask, int valnum);
-
#endif
diff --git a/xorg-server/include/resource.h b/xorg-server/include/resource.h
index aa719aa0a..a09679ad6 100644
--- a/xorg-server/include/resource.h
+++ b/xorg-server/include/resource.h
@@ -121,6 +121,8 @@ typedef unsigned long RESTYPE;
#define BAD_RESOURCE 0xe0000000
+#define rClient(obj) (clients[CLIENT_ID((obj)->resource)])
+
/* Resource state callback */
extern _X_EXPORT CallbackListPtr ResourceStateCallback;
diff --git a/xorg-server/include/scrnintstr.h b/xorg-server/include/scrnintstr.h
index 8d7c7db8b..fdb904fa2 100644
--- a/xorg-server/include/scrnintstr.h
+++ b/xorg-server/include/scrnintstr.h
@@ -135,7 +135,8 @@ typedef void (* SourceValidateProcPtr)(
int /*x*/,
int /*y*/,
int /*width*/,
- int /*height*/);
+ int /*height*/,
+ unsigned int /*subWindowMode*/);
typedef Bool (* CreateWindowProcPtr)(
WindowPtr /*pWindow*/);
diff --git a/xorg-server/include/windowstr.h b/xorg-server/include/windowstr.h
index fd97c3a55..e967223b4 100644
--- a/xorg-server/include/windowstr.h
+++ b/xorg-server/include/windowstr.h
@@ -167,6 +167,9 @@ typedef struct _Window {
#ifdef ROOTLESS
unsigned rootlessUnhittable:1; /* doesn't hit-test */
#endif
+#ifdef COMPOSITE
+ unsigned damagedDescendants:1; /* some descendants are damaged */
+#endif
} WindowRec;
/*
diff --git a/xorg-server/mi/micopy.c b/xorg-server/mi/micopy.c
index da52bc659..ce01249e8 100644
--- a/xorg-server/mi/micopy.c
+++ b/xorg-server/mi/micopy.c
@@ -183,10 +183,10 @@ miDoCopy (DrawablePtr pSrcDrawable,
return NULL;
}
- if ((pSrcDrawable != pDstDrawable) &&
- pSrcDrawable->pScreen->SourceValidate)
+ if (pSrcDrawable->pScreen->SourceValidate)
{
- (*pSrcDrawable->pScreen->SourceValidate) (pSrcDrawable, xIn, yIn, widthSrc, heightSrc);
+ (*pSrcDrawable->pScreen->SourceValidate) (pSrcDrawable, xIn, yIn, widthSrc, heightSrc,
+ pGC->subWindowMode);
}
/* Compute source clip region */
diff --git a/xorg-server/mi/misprite.c b/xorg-server/mi/misprite.c
index 9a4bf49c7..0dce0a266 100644
--- a/xorg-server/mi/misprite.c
+++ b/xorg-server/mi/misprite.c
@@ -96,6 +96,7 @@ typedef struct {
VisualPtr pVisual;
DamagePtr pDamage; /* damage tracking structure */
Bool damageRegistered;
+ int numberOfCursors;
} miSpriteScreenRec, *miSpriteScreenPtr;
#define SOURCE_COLOR 0
@@ -184,6 +185,8 @@ miSpriteIsDown(miCursorInfoPtr pDevCursor)
static DevPrivateKeyRec miSpriteScreenKeyRec;
#define miSpriteScreenKey (&miSpriteScreenKeyRec)
+#define GetSpriteScreen(pScreen) \
+ (dixLookupPrivate(&(pScreen)->devPrivates, miSpriteScreenKey))
static DevPrivateKeyRec miSpriteDevPrivatesKeyRec;
#define miSpriteDevPrivatesKey (&miSpriteDevPrivatesKeyRec)
@@ -195,7 +198,8 @@ static void miSpriteGetSpans(DrawablePtr pDrawable, int wMax,
DDXPointPtr ppt, int *pwidth, int nspans,
char *pdstStart);
static void miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y,
- int width, int height);
+ int width, int height,
+ unsigned int subWindowMode);
static void miSpriteCopyWindow (WindowPtr pWindow,
DDXPointRec ptOldOrg,
RegionPtr prgnSrc);
@@ -214,11 +218,10 @@ static Bool miSpriteDeviceCursorInitialize(DeviceIntPtr pDev,
static void miSpriteDeviceCursorCleanup(DeviceIntPtr pDev,
ScreenPtr pScreen);
-#define SCREEN_PROLOGUE(pScreen, field) ((pScreen)->field = \
- ((miSpriteScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, \
- miSpriteScreenKey))->field)
-#define SCREEN_EPILOGUE(pScreen, field)\
- ((pScreen)->field = miSprite##field)
+#define SCREEN_PROLOGUE(pPriv, pScreen, field) ((pScreen)->field = \
+ (pPriv)->field)
+#define SCREEN_EPILOGUE(pPriv, pScreen, field)\
+ ((pPriv)->field = (pScreen)->field, (pScreen)->field = miSprite##field)
/*
* pointer-sprite method table
@@ -254,6 +257,15 @@ static void miSpriteRestoreCursor(DeviceIntPtr pDev,
ScreenPtr pScreen);
static void
+miSpriteRegisterBlockHandler(ScreenPtr pScreen, miSpriteScreenPtr pScreenPriv)
+{
+ if (!pScreenPriv->BlockHandler) {
+ pScreenPriv->BlockHandler = pScreen->BlockHandler;
+ pScreen->BlockHandler = miSpriteBlockHandler;
+ }
+}
+
+static void
miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
{
ScreenPtr pScreen = closure;
@@ -330,7 +342,7 @@ miSpriteInitialize (ScreenPtr pScreen,
pScreenPriv->InstallColormap = pScreen->InstallColormap;
pScreenPriv->StoreColors = pScreen->StoreColors;
- pScreenPriv->BlockHandler = pScreen->BlockHandler;
+ pScreenPriv->BlockHandler = NULL;
pScreenPriv->DeviceCursorInitialize = pScreen->DeviceCursorInitialize;
pScreenPriv->DeviceCursorCleanup = pScreen->DeviceCursorCleanup;
@@ -344,6 +356,7 @@ miSpriteInitialize (ScreenPtr pScreen,
pScreenPriv->colors[MASK_COLOR].green = 0;
pScreenPriv->colors[MASK_COLOR].blue = 0;
pScreenPriv->damageRegistered = 0;
+ pScreenPriv->numberOfCursors = 0;
dixSetPrivate(&pScreen->devPrivates, miSpriteScreenKey, pScreenPriv);
@@ -356,8 +369,6 @@ miSpriteInitialize (ScreenPtr pScreen,
pScreen->InstallColormap = miSpriteInstallColormap;
pScreen->StoreColors = miSpriteStoreColors;
- pScreen->BlockHandler = miSpriteBlockHandler;
-
return TRUE;
}
@@ -373,14 +384,12 @@ miSpriteInitialize (ScreenPtr pScreen,
static Bool
miSpriteCloseScreen (int i, ScreenPtr pScreen)
{
- miSpriteScreenPtr pScreenPriv;
+ miSpriteScreenPtr pScreenPriv = GetSpriteScreen(pScreen);
- pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
pScreen->CloseScreen = pScreenPriv->CloseScreen;
pScreen->GetImage = pScreenPriv->GetImage;
pScreen->GetSpans = pScreenPriv->GetSpans;
pScreen->SourceValidate = pScreenPriv->SourceValidate;
- pScreen->BlockHandler = pScreenPriv->BlockHandler;
pScreen->InstallColormap = pScreenPriv->InstallColormap;
pScreen->StoreColors = pScreenPriv->StoreColors;
@@ -396,11 +405,12 @@ miSpriteGetImage (DrawablePtr pDrawable, int sx, int sy, int w, int h,
unsigned int format, unsigned long planemask,
char *pdstLine)
{
- ScreenPtr pScreen = pDrawable->pScreen;
- DeviceIntPtr pDev;
- miCursorInfoPtr pCursorInfo;
+ ScreenPtr pScreen = pDrawable->pScreen;
+ DeviceIntPtr pDev;
+ miCursorInfoPtr pCursorInfo;
+ miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
- SCREEN_PROLOGUE (pScreen, GetImage);
+ SCREEN_PROLOGUE (pPriv, pScreen, GetImage);
if (pDrawable->type == DRAWABLE_WINDOW)
{
@@ -423,7 +433,7 @@ miSpriteGetImage (DrawablePtr pDrawable, int sx, int sy, int w, int h,
(*pScreen->GetImage) (pDrawable, sx, sy, w, h,
format, planemask, pdstLine);
- SCREEN_EPILOGUE (pScreen, GetImage);
+ SCREEN_EPILOGUE (pPriv, pScreen, GetImage);
}
static void
@@ -433,8 +443,9 @@ miSpriteGetSpans (DrawablePtr pDrawable, int wMax, DDXPointPtr ppt,
ScreenPtr pScreen = pDrawable->pScreen;
DeviceIntPtr pDev;
miCursorInfoPtr pCursorInfo;
+ miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
- SCREEN_PROLOGUE (pScreen, GetSpans);
+ SCREEN_PROLOGUE (pPriv, pScreen, GetSpans);
if (pDrawable->type == DRAWABLE_WINDOW)
{
@@ -474,18 +485,19 @@ miSpriteGetSpans (DrawablePtr pDrawable, int wMax, DDXPointPtr ppt,
(*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
- SCREEN_EPILOGUE (pScreen, GetSpans);
+ SCREEN_EPILOGUE (pPriv, pScreen, GetSpans);
}
static void
miSpriteSourceValidate (DrawablePtr pDrawable, int x, int y, int width,
- int height)
+ int height, unsigned int subWindowMode)
{
ScreenPtr pScreen = pDrawable->pScreen;
DeviceIntPtr pDev;
miCursorInfoPtr pCursorInfo;
+ miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
- SCREEN_PROLOGUE (pScreen, SourceValidate);
+ SCREEN_PROLOGUE (pPriv, pScreen, SourceValidate);
if (pDrawable->type == DRAWABLE_WINDOW)
{
@@ -506,9 +518,9 @@ miSpriteSourceValidate (DrawablePtr pDrawable, int x, int y, int width,
}
if (pScreen->SourceValidate)
- (*pScreen->SourceValidate) (pDrawable, x, y, width, height);
+ (*pScreen->SourceValidate) (pDrawable, x, y, width, height, subWindowMode);
- SCREEN_EPILOGUE (pScreen, SourceValidate);
+ SCREEN_EPILOGUE (pPriv, pScreen, SourceValidate);
}
static void
@@ -517,8 +529,9 @@ miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
ScreenPtr pScreen = pWindow->drawable.pScreen;
DeviceIntPtr pDev;
miCursorInfoPtr pCursorInfo;
+ miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
- SCREEN_PROLOGUE (pScreen, CopyWindow);
+ SCREEN_PROLOGUE (pPriv, pScreen, CopyWindow);
for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
{
@@ -538,7 +551,7 @@ miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
}
(*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc);
- SCREEN_EPILOGUE (pScreen, CopyWindow);
+ SCREEN_EPILOGUE (pPriv, pScreen, CopyWindow);
}
static void
@@ -546,16 +559,10 @@ miSpriteBlockHandler (int i, pointer blockData, pointer pTimeout,
pointer pReadmask)
{
ScreenPtr pScreen = screenInfo.screens[i];
- miSpriteScreenPtr pPriv;
+ miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
DeviceIntPtr pDev;
miCursorInfoPtr pCursorInfo;
-
- pPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
- SCREEN_PROLOGUE(pScreen, BlockHandler);
-
- (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
-
- SCREEN_EPILOGUE(pScreen, BlockHandler);
+ Bool WorkToDo = FALSE;
for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
{
@@ -566,7 +573,7 @@ miSpriteBlockHandler (int i, pointer blockData, pointer pTimeout,
&& pCursorInfo->pScreen == pScreen
&& pCursorInfo->shouldBeUp)
{
- SPRITE_DEBUG (("BlockHandler restore\n"));
+ SPRITE_DEBUG (("BlockHandler save"));
miSpriteSaveUnderCursor (pDev, pScreen);
}
}
@@ -582,23 +589,33 @@ miSpriteBlockHandler (int i, pointer blockData, pointer pTimeout,
{
SPRITE_DEBUG (("BlockHandler restore\n"));
miSpriteRestoreCursor (pDev, pScreen);
+ if (!pCursorInfo->isUp)
+ WorkToDo = TRUE;
}
}
}
+
+ SCREEN_PROLOGUE(pPriv, pScreen, BlockHandler);
+
+ (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
+
+ if (WorkToDo)
+ SCREEN_EPILOGUE(pPriv, pScreen, BlockHandler);
+ else
+ pPriv->BlockHandler = NULL;
}
static void
miSpriteInstallColormap (ColormapPtr pMap)
{
ScreenPtr pScreen = pMap->pScreen;
- miSpriteScreenPtr pPriv;
+ miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
- pPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
- SCREEN_PROLOGUE(pScreen, InstallColormap);
+ SCREEN_PROLOGUE(pPriv, pScreen, InstallColormap);
(*pScreen->InstallColormap) (pMap);
- SCREEN_EPILOGUE(pScreen, InstallColormap);
+ SCREEN_EPILOGUE(pPriv, pScreen, InstallColormap);
/* InstallColormap can be called before devices are initialized. */
pPriv->pInstalledMap = pMap;
@@ -624,19 +641,18 @@ static void
miSpriteStoreColors (ColormapPtr pMap, int ndef, xColorItem *pdef)
{
ScreenPtr pScreen = pMap->pScreen;
- miSpriteScreenPtr pPriv;
+ miSpriteScreenPtr pPriv = GetSpriteScreen(pScreen);
int i;
int updated;
VisualPtr pVisual;
DeviceIntPtr pDev;
miCursorInfoPtr pCursorInfo;
- pPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
- SCREEN_PROLOGUE(pScreen, StoreColors);
+ SCREEN_PROLOGUE(pPriv, pScreen, StoreColors);
(*pScreen->StoreColors) (pMap, ndef, pdef);
- SCREEN_EPILOGUE(pScreen, StoreColors);
+ SCREEN_EPILOGUE(pPriv, pScreen, StoreColors);
if (pPriv->pColormap == pMap)
{
@@ -706,8 +722,7 @@ miSpriteStoreColors (ColormapPtr pMap, int ndef, xColorItem *pdef)
static void
miSpriteFindColors (miCursorInfoPtr pDevCursor, ScreenPtr pScreen)
{
- miSpriteScreenPtr pScreenPriv =
- dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
+ miSpriteScreenPtr pScreenPriv = GetSpriteScreen(pScreen);
CursorPtr pCursor;
xColorItem *sourceColor, *maskColor;
@@ -772,22 +787,32 @@ static void
miSpriteSetCursor (DeviceIntPtr pDev, ScreenPtr pScreen,
CursorPtr pCursor, int x, int y)
{
- miCursorInfoPtr pPointer;
+ miCursorInfoPtr pPointer;
+ miSpriteScreenPtr pScreenPriv;
if (!IsMaster(pDev) && !pDev->u.master)
return;
pPointer = MISPRITE(pDev);
+ pScreenPriv = GetSpriteScreen(pScreen);
if (!pCursor)
{
+ if (pPointer->shouldBeUp)
+ --pScreenPriv->numberOfCursors;
pPointer->shouldBeUp = FALSE;
if (pPointer->isUp)
miSpriteRemoveCursor (pDev, pScreen);
+ if (pScreenPriv->numberOfCursors == 0)
+ miSpriteDisableDamage(pScreen, pScreenPriv);
pPointer->pCursor = 0;
return;
}
+ if (!pPointer->shouldBeUp)
+ pScreenPriv->numberOfCursors++;
pPointer->shouldBeUp = TRUE;
+ if (!pPointer->isUp)
+ miSpriteRegisterBlockHandler(pScreen, pScreenPriv);
if (pPointer->x == x &&
pPointer->y == y &&
pPointer->pCursor == pCursor &&
@@ -884,10 +909,11 @@ miSpriteRemoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen)
return;
DamageDrawInternal (pScreen, TRUE);
- pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
+ pScreenPriv = GetSpriteScreen(pScreen);
pCursorInfo = MISPRITE(pDev);
miSpriteIsDown(pCursorInfo);
+ miSpriteRegisterBlockHandler(pScreen, pScreenPriv);
pCursorInfo->pCacheWin = NullWindow;
miSpriteDisableDamage(pScreen, pScreenPriv);
if (!miDCRestoreUnderCursor(pDev,
@@ -922,7 +948,7 @@ miSpriteSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen)
return;
DamageDrawInternal (pScreen, TRUE);
- pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
+ pScreenPriv = GetSpriteScreen(pScreen);
pCursorInfo = MISPRITE(pDev);
miSpriteComputeSaved (pDev, pScreen);
@@ -963,7 +989,7 @@ miSpriteRestoreCursor (DeviceIntPtr pDev, ScreenPtr pScreen)
return;
DamageDrawInternal (pScreen, TRUE);
- pScreenPriv = dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey);
+ pScreenPriv = GetSpriteScreen(pScreen);
pCursorInfo = MISPRITE(pDev);
miSpriteComputeSaved (pDev, pScreen);
diff --git a/xorg-server/miext/damage/damage.c b/xorg-server/miext/damage/damage.c
index 263ca8afa..0d5fab5bd 100644
--- a/xorg-server/miext/damage/damage.c
+++ b/xorg-server/miext/damage/damage.c
@@ -891,16 +891,6 @@ damageCopyArea(DrawablePtr pSrc,
RegionPtr ret;
DAMAGE_GC_OP_PROLOGUE(pGC, pDst);
- /* The driver will only call SourceValidate() when pSrc != pDst,
- * but the software sprite (misprite.c) always need to know when a
- * drawable is copied so it can remove the sprite. See #1030. */
- if ((pSrc == pDst) && pSrc->pScreen->SourceValidate &&
- pSrc->type == DRAWABLE_WINDOW &&
- ((WindowPtr)pSrc)->viewable)
- {
- (*pSrc->pScreen->SourceValidate) (pSrc, srcx, srcy, width, height);
- }
-
if (checkGCDamage (pDst, pGC))
{
BoxRec box;
@@ -937,16 +927,6 @@ damageCopyPlane(DrawablePtr pSrc,
RegionPtr ret;
DAMAGE_GC_OP_PROLOGUE(pGC, pDst);
- /* The driver will only call SourceValidate() when pSrc != pDst,
- * but the software sprite (misprite.c) always need to know when a
- * drawable is copied so it can remove the sprite. See #1030. */
- if ((pSrc == pDst) && pSrc->pScreen->SourceValidate &&
- pSrc->type == DRAWABLE_WINDOW &&
- ((WindowPtr)pSrc)->viewable)
- {
- (*pSrc->pScreen->SourceValidate) (pSrc, srcx, srcy, width, height);
- }
-
if (checkGCDamage (pDst, pGC))
{
BoxRec box;
diff --git a/xorg-server/miext/rootless/rootlessScreen.c b/xorg-server/miext/rootless/rootlessScreen.c
index 364a75ac8..ca4f00c3e 100644
--- a/xorg-server/miext/rootless/rootlessScreen.c
+++ b/xorg-server/miext/rootless/rootlessScreen.c
@@ -223,7 +223,8 @@ out:
* here and leave StopDrawing for the block handler.
*/
static void
-RootlessSourceValidate(DrawablePtr pDrawable, int x, int y, int w, int h)
+RootlessSourceValidate(DrawablePtr pDrawable, int x, int y, int w, int h,
+ unsigned int subWindowMode)
{
SCREEN_UNWRAP(pDrawable->pScreen, SourceValidate);
if (pDrawable->type == DRAWABLE_WINDOW) {
@@ -231,7 +232,7 @@ RootlessSourceValidate(DrawablePtr pDrawable, int x, int y, int w, int h)
RootlessStartDrawing(pWin);
}
if (pDrawable->pScreen->SourceValidate) {
- pDrawable->pScreen->SourceValidate(pDrawable, x, y, w, h);
+ pDrawable->pScreen->SourceValidate(pDrawable, x, y, w, h, subWindowMode);
}
SCREEN_WRAP(pDrawable->pScreen, SourceValidate);
}
diff --git a/xorg-server/os/access.c b/xorg-server/os/access.c
index d43fdf8e4..b7e698c3b 100644
--- a/xorg-server/os/access.c
+++ b/xorg-server/os/access.c
@@ -1,2087 +1,2095 @@
-/***********************************************************
-
-Copyright 1987, 1998 The Open Group
-
-All rights reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, and/or sell copies of the Software, and to permit persons
-to whom the Software is furnished to do so, provided that the above
-copyright notice(s) and this permission notice appear in all copies of
-the Software and that both the above copyright notice(s) and this
-permission notice appear in supporting documentation.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
-HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
-INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
-FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
-NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
-WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-Except as contained in this notice, the name of a copyright holder
-shall not be used in advertising or otherwise to promote the sale, use
-or other dealings in this Software without prior written authorization
-of the copyright holder.
-
-X Window System is a trademark of The Open Group.
-
-Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-******************************************************************/
-
-/*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#ifdef WIN32
-#include <X11/Xwinsock.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#define XSERV_t
-#define TRANS_SERVER
-#define TRANS_REOPEN
-#include <X11/Xtrans/Xtrans.h>
-#include <X11/Xauth.h>
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include "misc.h"
-#include "site.h"
-#include <errno.h>
-#include <sys/types.h>
-#ifndef WIN32
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <ctype.h>
-
-#if defined(TCPCONN) || defined(STREAMSCONN)
-#include <netinet/in.h>
-#endif /* TCPCONN || STREAMSCONN */
-
-#ifdef HAS_GETPEERUCRED
-# include <ucred.h>
-# ifdef sun
-# include <zone.h>
-# endif
-#endif
-
-#if defined(SVR4) || (defined(SYSV) && defined(__i386__)) || defined(__GNU__)
-# include <sys/utsname.h>
-#endif
-#if defined(SYSV) && defined(__i386__)
-# include <sys/stream.h>
-#endif
-#ifdef __GNU__
-#undef SIOCGIFCONF
-#include <netdb.h>
-#else /*!__GNU__*/
-# include <net/if.h>
-#endif /*__GNU__ */
-
-#ifdef SVR4
-#include <sys/sockio.h>
-#include <sys/stropts.h>
-#endif
-
-#include <netdb.h>
-
-#ifdef CSRG_BASED
-#include <sys/param.h>
-#if (BSD >= 199103)
-#define VARIABLE_IFREQ
-#endif
-#endif
-
-#ifdef BSD44SOCKETS
-#ifndef VARIABLE_IFREQ
-#define VARIABLE_IFREQ
-#endif
-#endif
-
-#ifdef HAS_GETIFADDRS
-#include <ifaddrs.h>
-#endif
-
-/* Solaris provides an extended interface SIOCGLIFCONF. Other systems
- * may have this as well, but the code has only been tested on Solaris
- * so far, so we only enable it there. Other platforms may be added as
- * needed.
- *
- * Test for Solaris commented out -- TSI @ UQV 2003.06.13
- */
-#ifdef SIOCGLIFCONF
-/* #if defined(sun) */
-#define USE_SIOCGLIFCONF
-/* #endif */
-#endif
-
-#endif /* WIN32 */
-
-#ifndef PATH_MAX
-#include <sys/param.h>
-#ifndef PATH_MAX
-#ifdef MAXPATHLEN
-#define PATH_MAX MAXPATHLEN
-#else
-#define PATH_MAX 1024
-#endif
-#endif
-#endif
-
-
-#define X_INCLUDE_NETDB_H
-#include <X11/Xos_r.h>
-
-#include "dixstruct.h"
-#include "osdep.h"
-
-#include "xace.h"
-
-#ifndef PATH_MAX
-#ifdef MAXPATHLEN
-#define PATH_MAX MAXPATHLEN
-#else
-#define PATH_MAX 1024
-#endif
-#endif
-
-Bool defeatAccessControl = FALSE;
-
-#define acmp(a1, a2, len) memcmp((char *)(a1), (char *)(a2), len)
-#define acopy(a1, a2, len) memmove((char *)(a2), (char *)(a1), len)
-#define addrEqual(fam, address, length, host) \
- ((fam) == (host)->family &&\
- (length) == (host)->len &&\
- !acmp (address, (host)->addr, length))
-
-static int ConvertAddr(struct sockaddr * /*saddr*/,
- int * /*len*/,
- pointer * /*addr*/);
-
-static int CheckAddr(int /*family*/,
- const void * /*pAddr*/,
- unsigned /*length*/);
-
-static Bool NewHost(int /*family*/,
- const void * /*addr*/,
- int /*len*/,
- int /* addingLocalHosts */);
-
-/* XFree86 bug #156: To keep track of which hosts were explicitly requested in
- /etc/X<display>.hosts, we've added a requested field to the HOST struct,
- and a LocalHostRequested variable. These default to FALSE, but are set
- to TRUE in ResetHosts when reading in /etc/X<display>.hosts. They are
- checked in DisableLocalHost(), which is called to disable the default
- local host entries when stronger authentication is turned on. */
-
-typedef struct _host {
- short family;
- short len;
- unsigned char *addr;
- struct _host *next;
- int requested;
-} HOST;
-
-#define MakeHost(h,l) (h)=malloc(sizeof *(h)+(l));\
- if (h) { \
- (h)->addr=(unsigned char *) ((h) + 1);\
- (h)->requested = FALSE; \
- }
-#define FreeHost(h) free(h)
-static HOST *selfhosts = NULL;
-static HOST *validhosts = NULL;
-static int AccessEnabled = DEFAULT_ACCESS_CONTROL;
-static int LocalHostEnabled = FALSE;
-static int LocalHostRequested = FALSE;
-static int UsingXdmcp = FALSE;
-
-/* FamilyServerInterpreted implementation */
-static Bool siAddrMatch(int family, pointer addr, int len, HOST *host,
- ClientPtr client);
-static int siCheckAddr(const char *addrString, int length);
-static void siTypesInitialize(void);
-
-/*
- * called when authorization is not enabled to add the
- * local host to the access list
- */
-
-void
-EnableLocalHost (void)
-{
- if (!UsingXdmcp)
- {
- LocalHostEnabled = TRUE;
- AddLocalHosts ();
- }
-}
-
-/*
- * called when authorization is enabled to keep us secure
- */
-void
-DisableLocalHost (void)
-{
- HOST *self;
-
- if (!LocalHostRequested) /* Fix for XFree86 bug #156 */
- LocalHostEnabled = FALSE;
- for (self = selfhosts; self; self = self->next) {
- if (!self->requested) /* Fix for XFree86 bug #156 */
- (void) RemoveHost ((ClientPtr)NULL, self->family, self->len, (pointer)self->addr);
- }
-}
-
-/*
- * called at init time when XDMCP will be used; xdmcp always
- * adds local hosts manually when needed
- */
-
-void
-AccessUsingXdmcp (void)
-{
- UsingXdmcp = TRUE;
- LocalHostEnabled = FALSE;
-}
-
-
-#if defined(SVR4) && !defined(sun) && defined(SIOCGIFCONF) && !defined(USE_SIOCGLIFCONF)
-
-/* Deal with different SIOCGIFCONF ioctl semantics on these OSs */
-
-static int
-ifioctl (int fd, int cmd, char *arg)
-{
- struct strioctl ioc;
- int ret;
-
- memset((char *) &ioc, 0, sizeof(ioc));
- ioc.ic_cmd = cmd;
- ioc.ic_timout = 0;
- if (cmd == SIOCGIFCONF)
- {
- ioc.ic_len = ((struct ifconf *) arg)->ifc_len;
- ioc.ic_dp = ((struct ifconf *) arg)->ifc_buf;
- }
- else
- {
- ioc.ic_len = sizeof(struct ifreq);
- ioc.ic_dp = arg;
- }
- ret = ioctl(fd, I_STR, (char *) &ioc);
- if (ret >= 0 && cmd == SIOCGIFCONF)
-#ifdef SVR4
- ((struct ifconf *) arg)->ifc_len = ioc.ic_len;
-#endif
- return ret;
-}
-#else
-#define ifioctl ioctl
-#endif
-
-/*
- * DefineSelf (fd):
- *
- * Define this host for access control. Find all the hosts the OS knows about
- * for this fd and add them to the selfhosts list.
- */
-
-#if !defined(SIOCGIFCONF)
-void
-DefineSelf (int fd)
-{
-#if !defined(TCPCONN) && !defined(STREAMSCONN) && !defined(UNIXCONN)
- return;
-#else
- register int n;
- int len;
- caddr_t addr;
- int family;
- register HOST *host;
-
-#ifndef WIN32
- struct utsname name;
-#else
- struct {
- char nodename[512];
- } name;
-#endif
-
- register struct hostent *hp;
-
- union {
- struct sockaddr sa;
- struct sockaddr_in in;
-#if defined(IPv6) && defined(AF_INET6)
- struct sockaddr_in6 in6;
-#endif
- } saddr;
-
- struct sockaddr_in *inetaddr;
- struct sockaddr_in6 *inet6addr;
- struct sockaddr_in broad_addr;
-#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
- _Xgethostbynameparams hparams;
-#endif
-
- /* Why not use gethostname()? Well, at least on my system, I've had to
- * make an ugly kernel patch to get a name longer than 8 characters, and
- * uname() lets me access to the whole string (it smashes release, you
- * see), whereas gethostname() kindly truncates it for me.
- */
-#ifndef WIN32
- uname(&name);
-#else
- gethostname(name.nodename, sizeof(name.nodename));
-#endif
-
- hp = _XGethostbyname(name.nodename, hparams);
- if (hp != NULL)
- {
- saddr.sa.sa_family = hp->h_addrtype;
- switch (hp->h_addrtype) {
- case AF_INET:
- inetaddr = (struct sockaddr_in *) (&(saddr.sa));
- acopy ( hp->h_addr, &(inetaddr->sin_addr), hp->h_length);
- len = sizeof(saddr.sa);
- break;
-#if defined(IPv6) && defined(AF_INET6)
- case AF_INET6:
- inet6addr = (struct sockaddr_in6 *) (&(saddr.sa));
- acopy ( hp->h_addr, &(inet6addr->sin6_addr), hp->h_length);
- len = sizeof(saddr.in6);
- break;
-#endif
- default:
- goto DefineLocalHost;
- }
- family = ConvertAddr ( &(saddr.sa), &len, (pointer *)&addr);
- if ( family != -1 && family != FamilyLocal )
- {
- for (host = selfhosts;
- host && !addrEqual (family, addr, len, host);
- host = host->next) ;
- if (!host)
- {
- /* add this host to the host list. */
- MakeHost(host,len)
- if (host)
- {
- host->family = family;
- host->len = len;
- acopy ( addr, host->addr, len);
- host->next = selfhosts;
- selfhosts = host;
- }
-#ifdef XDMCP
- /*
- * If this is an Internet Address, but not the localhost
- * address (127.0.0.1), nor the bogus address (0.0.0.0),
- * register it.
- */
- if (family == FamilyInternet &&
- !(len == 4 &&
- ((addr[0] == 127) ||
- (addr[0] == 0 && addr[1] == 0 &&
- addr[2] == 0 && addr[3] == 0)))
- )
- {
- XdmcpRegisterConnection (family, (char *)addr, len);
- broad_addr = *inetaddr;
- ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr =
- htonl (INADDR_BROADCAST);
- XdmcpRegisterBroadcastAddress ((struct sockaddr_in *)
- &broad_addr);
- }
-#if defined(IPv6) && defined(AF_INET6)
- else if (family == FamilyInternet6 &&
- !(IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr)))
- {
- XdmcpRegisterConnection (family, (char *)addr, len);
- }
-#endif
-
-#endif /* XDMCP */
- }
- }
- }
- /*
- * now add a host of family FamilyLocalHost...
- */
-DefineLocalHost:
- for (host = selfhosts;
- host && !addrEqual(FamilyLocalHost, "", 0, host);
- host = host->next);
- if (!host)
- {
- MakeHost(host, 0);
- if (host)
- {
- host->family = FamilyLocalHost;
- host->len = 0;
- acopy("", host->addr, 0);
- host->next = selfhosts;
- selfhosts = host;
- }
- }
-#endif /* !TCPCONN && !STREAMSCONN && !UNIXCONN */
-}
-
-#else
-
-#ifdef USE_SIOCGLIFCONF
-#define ifr_type struct lifreq
-#else
-#define ifr_type struct ifreq
-#endif
-
-#ifdef VARIABLE_IFREQ
-#define ifr_size(p) (sizeof (struct ifreq) + \
- (p->ifr_addr.sa_len > sizeof (p->ifr_addr) ? \
- p->ifr_addr.sa_len - sizeof (p->ifr_addr) : 0))
-#define ifraddr_size(a) (a.sa_len)
-#else
-#define ifr_size(p) (sizeof (ifr_type))
-#define ifraddr_size(a) (sizeof (a))
-#endif
-
-#if defined(IPv6) && defined(AF_INET6)
-#include <arpa/inet.h>
-#endif
-
-#if defined(IPv6) && defined(AF_INET6)
-static void
-in6_fillscopeid(struct sockaddr_in6 *sin6)
-{
-#if defined(__KAME__)
- if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
- sin6->sin6_scope_id =
- ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]);
- sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0;
- }
-#endif
-}
-#endif
-
-void
-DefineSelf (int fd)
-{
-#ifndef HAS_GETIFADDRS
- char *cp, *cplim;
-# ifdef USE_SIOCGLIFCONF
- struct sockaddr_storage buf[16];
- struct lifconf ifc;
- register struct lifreq *ifr;
-# ifdef SIOCGLIFNUM
- struct lifnum ifn;
-# endif
-# else /* !USE_SIOCGLIFCONF */
- char buf[2048];
- struct ifconf ifc;
- register struct ifreq *ifr;
-# endif
- void * bufptr = buf;
-#else /* HAS_GETIFADDRS */
- struct ifaddrs * ifap, *ifr;
-#endif
- int len;
- unsigned char * addr;
- int family;
- register HOST *host;
-
-#ifndef HAS_GETIFADDRS
-
- len = sizeof(buf);
-
-#ifdef USE_SIOCGLIFCONF
-
-#ifdef SIOCGLIFNUM
- ifn.lifn_family = AF_UNSPEC;
- ifn.lifn_flags = 0;
- if (ioctl (fd, SIOCGLIFNUM, (char *) &ifn) < 0)
- Error ("Getting interface count");
- if (len < (ifn.lifn_count * sizeof(struct lifreq))) {
- len = ifn.lifn_count * sizeof(struct lifreq);
- bufptr = malloc(len);
- }
-#endif
-
- ifc.lifc_family = AF_UNSPEC;
- ifc.lifc_flags = 0;
- ifc.lifc_len = len;
- ifc.lifc_buf = bufptr;
-
-#define IFC_IOCTL_REQ SIOCGLIFCONF
-#define IFC_IFC_REQ ifc.lifc_req
-#define IFC_IFC_LEN ifc.lifc_len
-#define IFR_IFR_ADDR ifr->lifr_addr
-#define IFR_IFR_NAME ifr->lifr_name
-
-#else /* Use SIOCGIFCONF */
- ifc.ifc_len = len;
- ifc.ifc_buf = bufptr;
-
-#define IFC_IOCTL_REQ SIOCGIFCONF
-#define IFC_IFC_REQ ifc.ifc_req
-#define IFC_IFC_LEN ifc.ifc_len
-#define IFR_IFR_ADDR ifr->ifr_addr
-#define IFR_IFR_NAME ifr->ifr_name
-#endif
-
- if (ifioctl (fd, IFC_IOCTL_REQ, (pointer) &ifc) < 0)
- Error ("Getting interface configuration (4)");
-
- cplim = (char *) IFC_IFC_REQ + IFC_IFC_LEN;
-
- for (cp = (char *) IFC_IFC_REQ; cp < cplim; cp += ifr_size (ifr))
- {
- ifr = (ifr_type *) cp;
- len = ifraddr_size (IFR_IFR_ADDR);
- family = ConvertAddr ((struct sockaddr *) &IFR_IFR_ADDR,
- &len, (pointer *)&addr);
- if (family == -1 || family == FamilyLocal)
- continue;
-#if defined(IPv6) && defined(AF_INET6)
- if (family == FamilyInternet6)
- in6_fillscopeid((struct sockaddr_in6 *)&IFR_IFR_ADDR);
-#endif
- for (host = selfhosts;
- host && !addrEqual (family, addr, len, host);
- host = host->next)
- ;
- if (host)
- continue;
- MakeHost(host,len)
- if (host)
- {
- host->family = family;
- host->len = len;
- acopy(addr, host->addr, len);
- host->next = selfhosts;
- selfhosts = host;
- }
-#ifdef XDMCP
- {
-#ifdef USE_SIOCGLIFCONF
- struct sockaddr_storage broad_addr;
-#else
- struct sockaddr broad_addr;
-#endif
-
- /*
- * If this isn't an Internet Address, don't register it.
- */
- if (family != FamilyInternet
-#if defined(IPv6) && defined(AF_INET6)
- && family != FamilyInternet6
-#endif
- )
- continue;
-
- /*
- * ignore 'localhost' entries as they're not useful
- * on the other end of the wire
- */
- if (family == FamilyInternet &&
- addr[0] == 127 && addr[1] == 0 &&
- addr[2] == 0 && addr[3] == 1)
- continue;
-#if defined(IPv6) && defined(AF_INET6)
- else if (family == FamilyInternet6 &&
- IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr))
- continue;
-#endif
-
- /*
- * Ignore '0.0.0.0' entries as they are
- * returned by some OSes for unconfigured NICs but they are
- * not useful on the other end of the wire.
- */
- if (len == 4 &&
- addr[0] == 0 && addr[1] == 0 &&
- addr[2] == 0 && addr[3] == 0)
- continue;
-
- XdmcpRegisterConnection (family, (char *)addr, len);
-
-#if defined(IPv6) && defined(AF_INET6)
- /* IPv6 doesn't support broadcasting, so we drop out here */
- if (family == FamilyInternet6)
- continue;
-#endif
-
- broad_addr = IFR_IFR_ADDR;
-
- ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr =
- htonl (INADDR_BROADCAST);
-#if defined(USE_SIOCGLIFCONF) && defined(SIOCGLIFBRDADDR)
- {
- struct lifreq broad_req;
-
- broad_req = *ifr;
- if (ioctl (fd, SIOCGLIFFLAGS, (char *) &broad_req) != -1 &&
- (broad_req.lifr_flags & IFF_BROADCAST) &&
- (broad_req.lifr_flags & IFF_UP)
- )
- {
- broad_req = *ifr;
- if (ioctl (fd, SIOCGLIFBRDADDR, &broad_req) != -1)
- broad_addr = broad_req.lifr_broadaddr;
- else
- continue;
- }
- else
- continue;
- }
-
-#elif defined(SIOCGIFBRDADDR)
- {
- struct ifreq broad_req;
-
- broad_req = *ifr;
- if (ifioctl (fd, SIOCGIFFLAGS, (pointer) &broad_req) != -1 &&
- (broad_req.ifr_flags & IFF_BROADCAST) &&
- (broad_req.ifr_flags & IFF_UP)
- )
- {
- broad_req = *ifr;
- if (ifioctl (fd, SIOCGIFBRDADDR, (pointer) &broad_req) != -1)
- broad_addr = broad_req.ifr_addr;
- else
- continue;
- }
- else
- continue;
- }
-#endif /* SIOCGIFBRDADDR */
- XdmcpRegisterBroadcastAddress ((struct sockaddr_in *) &broad_addr);
- }
-#endif /* XDMCP */
- }
- if (bufptr != buf)
- free(bufptr);
-#else /* HAS_GETIFADDRS */
- if (getifaddrs(&ifap) < 0) {
- ErrorF("Warning: getifaddrs returns %s\n", strerror(errno));
- return;
- }
- for (ifr = ifap; ifr != NULL; ifr = ifr->ifa_next) {
- if (!ifr->ifa_addr)
- continue;
- len = sizeof(*(ifr->ifa_addr));
- family = ConvertAddr((struct sockaddr *) ifr->ifa_addr, &len,
- (pointer *)&addr);
- if (family == -1 || family == FamilyLocal)
- continue;
-#if defined(IPv6) && defined(AF_INET6)
- if (family == FamilyInternet6)
- in6_fillscopeid((struct sockaddr_in6 *)ifr->ifa_addr);
-#endif
-
- for (host = selfhosts;
- host != NULL && !addrEqual(family, addr, len, host);
- host = host->next)
- ;
- if (host != NULL)
- continue;
- MakeHost(host, len);
- if (host != NULL) {
- host->family = family;
- host->len = len;
- acopy(addr, host->addr, len);
- host->next = selfhosts;
- selfhosts = host;
- }
-#ifdef XDMCP
- {
- /*
- * If this isn't an Internet Address, don't register it.
- */
- if (family != FamilyInternet
-#if defined(IPv6) && defined(AF_INET6)
- && family != FamilyInternet6
-#endif
- )
- continue;
-
- /*
- * ignore 'localhost' entries as they're not useful
- * on the other end of the wire
- */
- if (ifr->ifa_flags & IFF_LOOPBACK)
- continue;
-
- if (family == FamilyInternet &&
- addr[0] == 127 && addr[1] == 0 &&
- addr[2] == 0 && addr[3] == 1)
- continue;
-
- /*
- * Ignore '0.0.0.0' entries as they are
- * returned by some OSes for unconfigured NICs but they are
- * not useful on the other end of the wire.
- */
- if (len == 4 &&
- addr[0] == 0 && addr[1] == 0 &&
- addr[2] == 0 && addr[3] == 0)
- continue;
-#if defined(IPv6) && defined(AF_INET6)
- else if (family == FamilyInternet6 &&
- IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr))
- continue;
-#endif
- XdmcpRegisterConnection(family, (char *)addr, len);
-#if defined(IPv6) && defined(AF_INET6)
- if (family == FamilyInternet6)
- /* IPv6 doesn't support broadcasting, so we drop out here */
- continue;
-#endif
- if ((ifr->ifa_flags & IFF_BROADCAST) &&
- (ifr->ifa_flags & IFF_UP) &&
- ifr->ifa_broadaddr)
- XdmcpRegisterBroadcastAddress(
- (struct sockaddr_in *) ifr->ifa_broadaddr);
- else
- continue;
- }
-#endif /* XDMCP */
-
- } /* for */
- freeifaddrs(ifap);
-#endif /* HAS_GETIFADDRS */
-
- /*
- * add something of FamilyLocalHost
- */
- for (host = selfhosts;
- host && !addrEqual(FamilyLocalHost, "", 0, host);
- host = host->next);
- if (!host)
- {
- MakeHost(host, 0);
- if (host)
- {
- host->family = FamilyLocalHost;
- host->len = 0;
- acopy("", host->addr, 0);
- host->next = selfhosts;
- selfhosts = host;
- }
- }
-}
-#endif /* hpux && !HAS_IFREQ */
-
-#ifdef XDMCP
-void
-AugmentSelf(pointer from, int len)
-{
- int family;
- pointer addr;
- register HOST *host;
-
- family = ConvertAddr(from, &len, (pointer *)&addr);
- if (family == -1 || family == FamilyLocal)
- return;
- for (host = selfhosts; host; host = host->next)
- {
- if (addrEqual(family, addr, len, host))
- return;
- }
- MakeHost(host,len)
- if (!host)
- return;
- host->family = family;
- host->len = len;
- acopy(addr, host->addr, len);
- host->next = selfhosts;
- selfhosts = host;
-}
-#endif
-
-void
-AddLocalHosts (void)
-{
- HOST *self;
-
- for (self = selfhosts; self; self = self->next)
- /* Fix for XFree86 bug #156: pass addingLocal = TRUE to
- * NewHost to tell that we are adding the default local
- * host entries and not to flag the entries as being
- * explicitely requested */
- (void) NewHost (self->family, self->addr, self->len, TRUE);
-}
-
-/* Reset access control list to initial hosts */
-void
-ResetHosts (char *display)
-{
- register HOST *host;
- char lhostname[120], ohostname[120];
- char *hostname = ohostname;
- char fname[PATH_MAX + 1];
- int fnamelen;
- FILE *fd;
- char *ptr;
- int i, hostlen;
-#if (defined(TCPCONN) || defined(STREAMSCONN) ) && \
- (!defined(IPv6) || !defined(AF_INET6))
- union {
- struct sockaddr sa;
-#if defined(TCPCONN) || defined(STREAMSCONN)
- struct sockaddr_in in;
-#endif /* TCPCONN || STREAMSCONN */
- } saddr;
-#endif
- int family = 0;
- pointer addr;
- int len;
-
- siTypesInitialize();
- AccessEnabled = defeatAccessControl ? FALSE : DEFAULT_ACCESS_CONTROL;
- LocalHostEnabled = FALSE;
- while ((host = validhosts) != 0)
- {
- validhosts = host->next;
- FreeHost (host);
- }
-
-#if defined WIN32 && defined __MINGW32__
-#define ETC_HOST_PREFIX "X"
-#else
-#define ETC_HOST_PREFIX "/etc/X"
-#endif
-#define ETC_HOST_SUFFIX ".hosts"
- fnamelen = strlen(ETC_HOST_PREFIX) + strlen(ETC_HOST_SUFFIX) +
- strlen(display) + 1;
- if (fnamelen > sizeof(fname))
- FatalError("Display name `%s' is too long\n", display);
- snprintf(fname, sizeof(fname), ETC_HOST_PREFIX "%s" ETC_HOST_SUFFIX,
- display);
-
- if ((fd = fopen (fname, "r")) != 0)
- {
- while (fgets (ohostname, sizeof (ohostname), fd))
- {
- family = FamilyWild;
- if (*ohostname == '#')
- continue;
- if ((ptr = strchr(ohostname, '\n')) != 0)
- *ptr = 0;
- hostlen = strlen(ohostname) + 1;
- for (i = 0; i < hostlen; i++)
- lhostname[i] = tolower(ohostname[i]);
- hostname = ohostname;
- if (!strncmp("local:", lhostname, 6))
- {
- family = FamilyLocalHost;
- NewHost(family, "", 0, FALSE);
- LocalHostRequested = TRUE; /* Fix for XFree86 bug #156 */
- }
-#if defined(TCPCONN) || defined(STREAMSCONN)
- else if (!strncmp("inet:", lhostname, 5))
- {
- family = FamilyInternet;
- hostname = ohostname + 5;
- }
-#if defined(IPv6) && defined(AF_INET6)
- else if (!strncmp("inet6:", lhostname, 6))
- {
- family = FamilyInternet6;
- hostname = ohostname + 6;
- }
-#endif
-#endif
-#ifdef SECURE_RPC
- else if (!strncmp("nis:", lhostname, 4))
- {
- family = FamilyNetname;
- hostname = ohostname + 4;
- }
-#endif
- else if (!strncmp("si:", lhostname, 3))
- {
- family = FamilyServerInterpreted;
- hostname = ohostname + 3;
- hostlen -= 3;
- }
-
-
- if (family == FamilyServerInterpreted)
- {
- len = siCheckAddr(hostname, hostlen);
- if (len >= 0) {
- NewHost(family, hostname, len, FALSE);
- }
- }
- else
-#ifdef SECURE_RPC
- if ((family == FamilyNetname) || (strchr(hostname, '@')))
- {
- SecureRPCInit ();
- (void) NewHost (FamilyNetname, hostname, strlen (hostname), FALSE);
- }
- else
-#endif /* SECURE_RPC */
-#if defined(TCPCONN) || defined(STREAMSCONN)
- {
-#if defined(IPv6) && defined(AF_INET6)
- if ( (family == FamilyInternet) || (family == FamilyInternet6) ||
- (family == FamilyWild) )
- {
- struct addrinfo *addresses;
- struct addrinfo *a;
- int f;
-
- if (getaddrinfo(hostname, NULL, NULL, &addresses) == 0) {
- for (a = addresses ; a != NULL ; a = a->ai_next) {
- len = a->ai_addrlen;
- f = ConvertAddr(a->ai_addr,&len,(pointer *)&addr);
- if ( (family == f) ||
- ((family == FamilyWild) && (f != -1)) ) {
- NewHost(f, addr, len, FALSE);
- }
- }
- freeaddrinfo(addresses);
- }
- }
-#else
-#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
- _Xgethostbynameparams hparams;
-#endif
- register struct hostent *hp;
-
- /* host name */
- if ((family == FamilyInternet &&
- ((hp = _XGethostbyname(hostname, hparams)) != 0)) ||
- ((hp = _XGethostbyname(hostname, hparams)) != 0))
- {
- saddr.sa.sa_family = hp->h_addrtype;
- len = sizeof(saddr.sa);
- if ((family = ConvertAddr (&saddr.sa, &len, (pointer *)&addr)) != -1)
- {
-#ifdef h_addr /* new 4.3bsd version of gethostent */
- char **list;
-
- /* iterate over the addresses */
- for (list = hp->h_addr_list; *list; list++)
- (void) NewHost (family, (pointer)*list, len, FALSE);
-#else
- (void) NewHost (family, (pointer)hp->h_addr, len, FALSE);
-#endif
- }
- }
-#endif /* IPv6 */
- }
-#endif /* TCPCONN || STREAMSCONN */
- family = FamilyWild;
- }
- fclose (fd);
- }
-}
-
-/* Is client on the local host */
-Bool LocalClient(ClientPtr client)
-{
- int alen, family, notused;
- Xtransaddr *from = NULL;
- pointer addr;
- register HOST *host;
-
- if (!client->osPrivate)
- return FALSE;
- if (!((OsCommPtr)client->osPrivate)->trans_conn)
- return FALSE;
-
- if (!_XSERVTransGetPeerAddr (((OsCommPtr)client->osPrivate)->trans_conn,
- &notused, &alen, &from))
- {
- family = ConvertAddr ((struct sockaddr *) from,
- &alen, (pointer *)&addr);
- if (family == -1)
- {
- free(from);
- return FALSE;
- }
- if (family == FamilyLocal)
- {
- free(from);
- return TRUE;
- }
- for (host = selfhosts; host; host = host->next)
- {
- if (addrEqual (family, addr, alen, host))
- return TRUE;
- }
- free(from);
- }
- return FALSE;
-}
-
-/*
- * Return the uid and gid of a connected local client
- *
- * Used by XShm to test access rights to shared memory segments
- */
-int
-LocalClientCred(ClientPtr client, int *pUid, int *pGid)
-{
- LocalClientCredRec *lcc;
- int ret = GetLocalClientCreds(client, &lcc);
-
- if (ret == 0) {
-#ifdef HAVE_GETZONEID /* only local if in the same zone */
- if ((lcc->fieldsSet & LCC_ZID_SET) && (lcc->zoneid != getzoneid())) {
- FreeLocalClientCreds(lcc);
- return -1;
- }
-#endif
- if ((lcc->fieldsSet & LCC_UID_SET) && (pUid != NULL))
- *pUid = lcc->euid;
- if ((lcc->fieldsSet & LCC_GID_SET) && (pGid != NULL))
- *pGid = lcc->egid;
- FreeLocalClientCreds(lcc);
- }
- return ret;
-}
-
-/*
- * Return the uid and all gids of a connected local client
- * Allocates a LocalClientCredRec - caller must call FreeLocalClientCreds
- *
- * Used by localuser & localgroup ServerInterpreted access control forms below
- * Used by AuthAudit to log who local connections came from
- */
-int
-GetLocalClientCreds(ClientPtr client, LocalClientCredRec **lccp)
-{
-#if defined(HAS_GETPEEREID) || defined(HAS_GETPEERUCRED) || defined(SO_PEERCRED)
- int fd;
- XtransConnInfo ci;
- LocalClientCredRec *lcc;
-#ifdef HAS_GETPEEREID
- uid_t uid;
- gid_t gid;
-#elif defined(HAS_GETPEERUCRED)
- ucred_t *peercred = NULL;
- const gid_t *gids;
-#elif defined(SO_PEERCRED)
- struct ucred peercred;
- socklen_t so_len = sizeof(peercred);
-#endif
-
- if (client == NULL)
- return -1;
- ci = ((OsCommPtr)client->osPrivate)->trans_conn;
-#if !(defined(sun) && defined(HAS_GETPEERUCRED))
- /* Most implementations can only determine peer credentials for Unix
- * domain sockets - Solaris getpeerucred can work with a bit more, so
- * we just let it tell us if the connection type is supported or not
- */
- if (!_XSERVTransIsLocal(ci)) {
- return -1;
- }
-#endif
-
- *lccp = calloc(1, sizeof(LocalClientCredRec));
- if (*lccp == NULL)
- return -1;
- lcc = *lccp;
-
- fd = _XSERVTransGetConnectionNumber(ci);
-#ifdef HAS_GETPEEREID
- if (getpeereid(fd, &uid, &gid) == -1) {
- FreeLocalClientCreds(lcc);
- return -1;
- }
- lcc->euid = uid;
- lcc->egid = gid;
- lcc->fieldsSet = LCC_UID_SET | LCC_GID_SET;
- return 0;
-#elif defined(HAS_GETPEERUCRED)
- if (getpeerucred(fd, &peercred) < 0) {
- FreeLocalClientCreds(lcc);
- return -1;
- }
- lcc->euid = ucred_geteuid(peercred);
- if (lcc->euid != -1)
- lcc->fieldsSet |= LCC_UID_SET;
- lcc->egid = ucred_getegid(peercred);
- if (lcc->egid != -1)
- lcc->fieldsSet |= LCC_GID_SET;
- lcc->pid = ucred_getpid(peercred);
- if (lcc->pid != -1)
- lcc->fieldsSet |= LCC_PID_SET;
-#ifdef HAVE_GETZONEID
- lcc->zoneid = ucred_getzoneid(peercred);
- if (lcc->zoneid != -1)
- lcc->fieldsSet |= LCC_ZID_SET;
-#endif
- lcc->nSuppGids = ucred_getgroups(peercred, &gids);
- if (lcc->nSuppGids > 0) {
- lcc->pSuppGids = calloc(lcc->nSuppGids, sizeof(int));
- if (lcc->pSuppGids == NULL) {
- lcc->nSuppGids = 0;
- } else {
- int i;
- for (i = 0 ; i < lcc->nSuppGids; i++) {
- (lcc->pSuppGids)[i] = (int) gids[i];
- }
- }
- } else {
- lcc->nSuppGids = 0;
- }
- ucred_free(peercred);
- return 0;
-#elif defined(SO_PEERCRED)
- if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) == -1) {
- FreeLocalClientCreds(lcc);
- return -1;
- }
- lcc->euid = peercred.uid;
- lcc->egid = peercred.gid;
- lcc->pid = peercred.pid;
- lcc->fieldsSet = LCC_UID_SET | LCC_GID_SET | LCC_PID_SET;
- return 0;
-#endif
-#else
- /* No system call available to get the credentials of the peer */
-#define NO_LOCAL_CLIENT_CRED
- return -1;
-#endif
-}
-
-void
-FreeLocalClientCreds(LocalClientCredRec *lcc)
-{
- if (lcc != NULL) {
- if (lcc->nSuppGids > 0) {
- free(lcc->pSuppGids);
- }
- free(lcc);
- }
-}
-
-static int
-AuthorizedClient(ClientPtr client)
-{
- int rc;
-
- if (!client || defeatAccessControl)
- return Success;
-
- /* untrusted clients can't change host access */
- rc = XaceHook(XACE_SERVER_ACCESS, client, DixManageAccess);
- if (rc != Success)
- return rc;
-
- return LocalClient(client) ? Success : BadAccess;
-}
-
-/* Add a host to the access control list. This is the external interface
- * called from the dispatcher */
-
-int
-AddHost (ClientPtr client,
- int family,
- unsigned length, /* of bytes in pAddr */
- const void * pAddr)
-{
- int rc, len;
-
- rc = AuthorizedClient(client);
- if (rc != Success)
- return rc;
- switch (family) {
- case FamilyLocalHost:
- len = length;
- LocalHostEnabled = TRUE;
- break;
-#ifdef SECURE_RPC
- case FamilyNetname:
- len = length;
- SecureRPCInit ();
- break;
-#endif
- case FamilyInternet:
-#if defined(IPv6) && defined(AF_INET6)
- case FamilyInternet6:
-#endif
- case FamilyDECnet:
- case FamilyChaos:
- case FamilyServerInterpreted:
- if ((len = CheckAddr (family, pAddr, length)) < 0)
- {
- client->errorValue = length;
- return BadValue;
- }
- break;
- case FamilyLocal:
- default:
- client->errorValue = family;
- return BadValue;
- }
- if (NewHost (family, pAddr, len, FALSE))
- return Success;
- return BadAlloc;
-}
-
-Bool
-ForEachHostInFamily (int family,
- Bool (*func)(
- unsigned char * /* addr */,
- short /* len */,
- pointer /* closure */),
- pointer closure)
-{
- HOST *host;
-
- for (host = validhosts; host; host = host->next)
- if (family == host->family && func (host->addr, host->len, closure))
- return TRUE;
- return FALSE;
-}
-
-/* Add a host to the access control list. This is the internal interface
- * called when starting or resetting the server */
-static Bool
-NewHost (int family,
- const void * addr,
- int len,
- int addingLocalHosts)
-{
- register HOST *host;
-
- for (host = validhosts; host; host = host->next)
- {
- if (addrEqual (family, addr, len, host))
- return TRUE;
- }
- if (!addingLocalHosts) { /* Fix for XFree86 bug #156 */
- for (host = selfhosts; host; host = host->next) {
- if (addrEqual (family, addr, len, host)) {
- host->requested = TRUE;
- break;
- }
- }
- }
- MakeHost(host,len)
- if (!host)
- return FALSE;
- host->family = family;
- host->len = len;
- acopy(addr, host->addr, len);
- host->next = validhosts;
- validhosts = host;
- return TRUE;
-}
-
-/* Remove a host from the access control list */
-
-int
-RemoveHost (
- ClientPtr client,
- int family,
- unsigned length, /* of bytes in pAddr */
- pointer pAddr)
-{
- int rc, len;
- register HOST *host, **prev;
-
- rc = AuthorizedClient(client);
- if (rc != Success)
- return rc;
- switch (family) {
- case FamilyLocalHost:
- len = length;
- LocalHostEnabled = FALSE;
- break;
-#ifdef SECURE_RPC
- case FamilyNetname:
- len = length;
- break;
-#endif
- case FamilyInternet:
-#if defined(IPv6) && defined(AF_INET6)
- case FamilyInternet6:
-#endif
- case FamilyDECnet:
- case FamilyChaos:
- case FamilyServerInterpreted:
- if ((len = CheckAddr (family, pAddr, length)) < 0)
- {
- client->errorValue = length;
- return BadValue;
- }
- break;
- case FamilyLocal:
- default:
- client->errorValue = family;
- return BadValue;
- }
- for (prev = &validhosts;
- (host = *prev) && (!addrEqual (family, pAddr, len, host));
- prev = &host->next)
- ;
- if (host)
- {
- *prev = host->next;
- FreeHost (host);
- }
- return Success;
-}
-
-/* Get all hosts in the access control list */
-int
-GetHosts (
- pointer *data,
- int *pnHosts,
- int *pLen,
- BOOL *pEnabled)
-{
- int len;
- register int n = 0;
- register unsigned char *ptr;
- register HOST *host;
- int nHosts = 0;
-
- *pEnabled = AccessEnabled ? EnableAccess : DisableAccess;
- for (host = validhosts; host; host = host->next)
- {
- nHosts++;
- n += pad_to_int32(host->len) + sizeof(xHostEntry);
- }
- if (n)
- {
- *data = ptr = malloc(n);
- if (!ptr)
- {
- return BadAlloc;
- }
- for (host = validhosts; host; host = host->next)
- {
- len = host->len;
- ((xHostEntry *)ptr)->family = host->family;
- ((xHostEntry *)ptr)->length = len;
- ptr += sizeof(xHostEntry);
- acopy (host->addr, ptr, len);
- ptr += pad_to_int32(len);
- }
- } else {
- *data = NULL;
- }
- *pnHosts = nHosts;
- *pLen = n;
- return Success;
-}
-
-/* Check for valid address family and length, and return address length. */
-
-/*ARGSUSED*/
-static int
-CheckAddr (
- int family,
- const void * pAddr,
- unsigned length)
-{
- int len;
-
- switch (family)
- {
-#if defined(TCPCONN) || defined(STREAMSCONN)
- case FamilyInternet:
- if (length == sizeof (struct in_addr))
- len = length;
- else
- len = -1;
- break;
-#if defined(IPv6) && defined(AF_INET6)
- case FamilyInternet6:
- if (length == sizeof (struct in6_addr))
- len = length;
- else
- len = -1;
- break;
-#endif
-#endif
- case FamilyServerInterpreted:
- len = siCheckAddr(pAddr, length);
- break;
- default:
- len = -1;
- }
- return len;
-}
-
-/* Check if a host is not in the access control list.
- * Returns 1 if host is invalid, 0 if we've found it. */
-
-int
-InvalidHost (
- register struct sockaddr *saddr,
- int len,
- ClientPtr client)
-{
- int family;
- pointer addr;
- register HOST *selfhost, *host;
-
- if (!AccessEnabled) /* just let them in */
- return 0;
- family = ConvertAddr (saddr, &len, (pointer *)&addr);
- if (family == -1)
- return 1;
- if (family == FamilyLocal)
- {
- if (!LocalHostEnabled)
- {
- /*
- * check to see if any local address is enabled. This
- * implicitly enables local connections.
- */
- for (selfhost = selfhosts; selfhost; selfhost=selfhost->next)
- {
- for (host = validhosts; host; host=host->next)
- {
- if (addrEqual (selfhost->family, selfhost->addr,
- selfhost->len, host))
- return 0;
- }
- }
- } else
- return 0;
- }
- for (host = validhosts; host; host = host->next)
- {
- if ((host->family == FamilyServerInterpreted)) {
- if (siAddrMatch (family, addr, len, host, client)) {
- return 0;
- }
- } else {
- if (addrEqual (family, addr, len, host))
- return 0;
- }
-
- }
- return 1;
-}
-
-static int
-ConvertAddr (
- register struct sockaddr *saddr,
- int *len,
- pointer *addr)
-{
- if (*len == 0)
- return FamilyLocal;
- switch (saddr->sa_family)
- {
- case AF_UNSPEC:
-#if defined(UNIXCONN) || defined(LOCALCONN)
- case AF_UNIX:
-#endif
- return FamilyLocal;
-#if defined(TCPCONN) || defined(STREAMSCONN)
- case AF_INET:
-#ifdef WIN32
- if (16777343 == *(long*)&((struct sockaddr_in *) saddr)->sin_addr)
- return FamilyLocal;
-#endif
- *len = sizeof (struct in_addr);
- *addr = (pointer) &(((struct sockaddr_in *) saddr)->sin_addr);
- return FamilyInternet;
-#if defined(IPv6) && defined(AF_INET6)
- case AF_INET6:
- {
- struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) saddr;
- if (IN6_IS_ADDR_V4MAPPED(&(saddr6->sin6_addr))) {
- *len = sizeof (struct in_addr);
- *addr = (pointer) &(saddr6->sin6_addr.s6_addr[12]);
- return FamilyInternet;
- } else {
- *len = sizeof (struct in6_addr);
- *addr = (pointer) &(saddr6->sin6_addr);
- return FamilyInternet6;
- }
- }
-#endif
-#endif
- default:
- return -1;
- }
-}
-
-int
-ChangeAccessControl(
- ClientPtr client,
- int fEnabled)
-{
- int rc = AuthorizedClient(client);
- if (rc != Success)
- return rc;
- AccessEnabled = fEnabled;
- return Success;
-}
-
-/* returns FALSE if xhost + in effect, else TRUE */
-int
-GetAccessControl(void)
-{
- return AccessEnabled;
-}
-
-/*****************************************************************************
- * FamilyServerInterpreted host entry implementation
- *
- * Supports an extensible system of host types which the server can interpret
- * See the IPv6 extensions to the X11 protocol spec for the definition.
- *
- * Currently supported schemes:
- *
- * hostname - hostname as defined in IETF RFC 2396
- * ipv6 - IPv6 literal address as defined in IETF RFC's 3513 and <TBD>
- *
- * See xc/doc/specs/SIAddresses for formal definitions of each type.
- */
-
-/* These definitions and the siTypeAdd function could be exported in the
- * future to enable loading additional host types, but that was not done for
- * the initial implementation.
- */
-typedef Bool (*siAddrMatchFunc)(int family, pointer addr, int len,
- const char *siAddr, int siAddrlen, ClientPtr client, void *siTypePriv);
-typedef int (*siCheckAddrFunc)(const char *addrString, int length,
- void *siTypePriv);
-
-struct siType {
- struct siType * next;
- const char * typeName;
- siAddrMatchFunc addrMatch;
- siCheckAddrFunc checkAddr;
- void * typePriv; /* Private data for type routines */
-};
-
-static struct siType *siTypeList;
-
-static int
-siTypeAdd(const char *typeName, siAddrMatchFunc addrMatch,
- siCheckAddrFunc checkAddr, void *typePriv)
-{
- struct siType *s, *p;
-
- if ((typeName == NULL) || (addrMatch == NULL) || (checkAddr == NULL))
- return BadValue;
-
- for (s = siTypeList, p = NULL; s != NULL ; p = s, s = s->next) {
- if (strcmp(typeName, s->typeName) == 0) {
- s->addrMatch = addrMatch;
- s->checkAddr = checkAddr;
- s->typePriv = typePriv;
- return Success;
- }
- }
-
- s = malloc(sizeof(struct siType));
- if (s == NULL)
- return BadAlloc;
-
- if (p == NULL)
- siTypeList = s;
- else
- p->next = s;
-
- s->next = NULL;
- s->typeName = typeName;
- s->addrMatch = addrMatch;
- s->checkAddr = checkAddr;
- s->typePriv = typePriv;
- return Success;
-}
-
-/* Checks to see if a host matches a server-interpreted host entry */
-static Bool
-siAddrMatch(int family, pointer addr, int len, HOST *host, ClientPtr client)
-{
- Bool matches = FALSE;
- struct siType *s;
- const char *valueString;
- int addrlen;
-
- valueString = (const char *) memchr(host->addr, '\0', host->len);
- if (valueString != NULL) {
- for (s = siTypeList; s != NULL ; s = s->next) {
- if (strcmp((char *) host->addr, s->typeName) == 0) {
- addrlen = host->len - (strlen((char *)host->addr) + 1);
- matches = s->addrMatch(family, addr, len,
- valueString + 1, addrlen, client, s->typePriv);
- break;
- }
- }
-#ifdef FAMILY_SI_DEBUG
- ErrorF(
- "Xserver: siAddrMatch(): type = %s, value = %*.*s -- %s\n",
- host->addr, addrlen, addrlen, valueString + 1,
- (matches) ? "accepted" : "rejected");
-#endif
- }
- return matches;
-}
-
-static int
-siCheckAddr(const char *addrString, int length)
-{
- const char *valueString;
- int addrlen, typelen;
- int len = -1;
- struct siType *s;
-
- /* Make sure there is a \0 byte inside the specified length
- to separate the address type from the address value. */
- valueString = (const char *) memchr(addrString, '\0', length);
- if (valueString != NULL) {
- /* Make sure the first string is a recognized address type,
- * and the second string is a valid address of that type.
- */
- typelen = strlen(addrString) + 1;
- addrlen = length - typelen;
-
- for (s = siTypeList; s != NULL ; s = s->next) {
- if (strcmp(addrString, s->typeName) == 0) {
- len = s->checkAddr(valueString + 1, addrlen, s->typePriv);
- if (len >= 0) {
- len += typelen;
- }
- break;
- }
- }
-#ifdef FAMILY_SI_DEBUG
- {
- const char *resultMsg;
-
- if (s == NULL) {
- resultMsg = "type not registered";
- } else {
- if (len == -1)
- resultMsg = "rejected";
- else
- resultMsg = "accepted";
- }
-
- ErrorF("Xserver: siCheckAddr(): type = %s, value = %*.*s, len = %d -- %s\n",
- addrString, addrlen, addrlen, valueString + 1, len, resultMsg);
- }
-#endif
- }
- return len;
-}
-
-
-/***
- * Hostname server-interpreted host type
- *
- * Stored as hostname string, explicitly defined to be resolved ONLY
- * at access check time, to allow for hosts with dynamic addresses
- * but static hostnames, such as found in some DHCP & mobile setups.
- *
- * Hostname must conform to IETF RFC 2396 sec. 3.2.2, which defines it as:
- * hostname = *( domainlabel "." ) toplabel [ "." ]
- * domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
- * toplabel = alpha | alpha *( alphanum | "-" ) alphanum
- */
-
-#ifdef NI_MAXHOST
-# define SI_HOSTNAME_MAXLEN NI_MAXHOST
-#else
-# ifdef MAXHOSTNAMELEN
-# define SI_HOSTNAME_MAXLEN MAXHOSTNAMELEN
-# else
-# define SI_HOSTNAME_MAXLEN 256
-# endif
-#endif
-
-static Bool
-siHostnameAddrMatch(int family, pointer addr, int len,
- const char *siAddr, int siAddrLen, ClientPtr client, void *typePriv)
-{
- Bool res = FALSE;
-
-/* Currently only supports checking against IPv4 & IPv6 connections, but
- * support for other address families, such as DECnet, could be added if
- * desired.
- */
-#if defined(IPv6) && defined(AF_INET6)
- if ((family == FamilyInternet) || (family == FamilyInternet6)) {
- char hostname[SI_HOSTNAME_MAXLEN];
- struct addrinfo *addresses;
- struct addrinfo *a;
- int f, hostaddrlen;
- pointer hostaddr;
-
- if (siAddrLen >= sizeof(hostname))
- return FALSE;
-
- strncpy(hostname, siAddr, siAddrLen);
- hostname[siAddrLen] = '\0';
-
- if (getaddrinfo(hostname, NULL, NULL, &addresses) == 0) {
- for (a = addresses ; a != NULL ; a = a->ai_next) {
- hostaddrlen = a->ai_addrlen;
- f = ConvertAddr(a->ai_addr,&hostaddrlen,&hostaddr);
- if ((f == family) && (len == hostaddrlen) &&
- (acmp (addr, hostaddr, len) == 0) ) {
- res = TRUE;
- break;
- }
- }
- freeaddrinfo(addresses);
- }
- }
-#else /* IPv6 not supported, use gethostbyname instead for IPv4 */
- if (family == FamilyInternet) {
- register struct hostent *hp;
-#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
- _Xgethostbynameparams hparams;
-#endif
- char hostname[SI_HOSTNAME_MAXLEN];
- int f, hostaddrlen;
- pointer hostaddr;
- const char **addrlist;
-
- if (siAddrLen >= sizeof(hostname))
- return FALSE;
-
- strncpy(hostname, siAddr, siAddrLen);
- hostname[siAddrLen] = '\0';
-
- if ((hp = _XGethostbyname(hostname, hparams)) != NULL) {
-#ifdef h_addr /* new 4.3bsd version of gethostent */
- /* iterate over the addresses */
- for (addrlist = hp->h_addr_list; *addrlist; addrlist++)
-#else
- addrlist = &hp->h_addr;
-#endif
- {
- struct sockaddr_in sin;
-
- sin.sin_family = hp->h_addrtype;
- acopy ( *addrlist, &(sin.sin_addr), hp->h_length);
- hostaddrlen = sizeof(sin);
- f = ConvertAddr ((struct sockaddr *)&sin,
- &hostaddrlen, &hostaddr);
- if ((f == family) && (len == hostaddrlen) &&
- (acmp (addr, hostaddr, len) == 0) ) {
- res = TRUE;
- break;
- }
- }
- }
- }
-#endif
- return res;
-}
-
-
-static int
-siHostnameCheckAddr(const char *valueString, int length, void *typePriv)
-{
- /* Check conformance of hostname to RFC 2396 sec. 3.2.2 definition.
- * We do not use ctype functions here to avoid locale-specific
- * character sets. Hostnames must be pure ASCII.
- */
- int len = length;
- int i;
- Bool dotAllowed = FALSE;
- Bool dashAllowed = FALSE;
-
- if ((length <= 0) || (length >= SI_HOSTNAME_MAXLEN)) {
- len = -1;
- } else {
- for (i = 0; i < length; i++) {
- char c = valueString[i];
-
- if (c == 0x2E) { /* '.' */
- if (dotAllowed == FALSE) {
- len = -1;
- break;
- } else {
- dotAllowed = FALSE;
- dashAllowed = FALSE;
- }
- } else if (c == 0x2D) { /* '-' */
- if (dashAllowed == FALSE) {
- len = -1;
- break;
- } else {
- dotAllowed = FALSE;
- }
- } else if (((c >= 0x30) && (c <= 0x3A)) /* 0-9 */ ||
- ((c >= 0x61) && (c <= 0x7A)) /* a-z */ ||
- ((c >= 0x41) && (c <= 0x5A)) /* A-Z */) {
- dotAllowed = TRUE;
- dashAllowed = TRUE;
- } else { /* Invalid character */
- len = -1;
- break;
- }
- }
- }
- return len;
-}
-
-#if defined(IPv6) && defined(AF_INET6)
-/***
- * "ipv6" server interpreted type
- *
- * Currently supports only IPv6 literal address as specified in IETF RFC 3513
- *
- * Once draft-ietf-ipv6-scoping-arch-00.txt becomes an RFC, support will be
- * added for the scoped address format it specifies.
- */
-
-/* Maximum length of an IPv6 address string - increase when adding support
- * for scoped address qualifiers. Includes room for trailing NUL byte.
- */
-#define SI_IPv6_MAXLEN INET6_ADDRSTRLEN
-
-static Bool
-siIPv6AddrMatch(int family, pointer addr, int len,
- const char *siAddr, int siAddrlen, ClientPtr client, void *typePriv)
-{
- struct in6_addr addr6;
- char addrbuf[SI_IPv6_MAXLEN];
-
- if ((family != FamilyInternet6) || (len != sizeof(addr6)))
- return FALSE;
-
- memcpy(addrbuf, siAddr, siAddrlen);
- addrbuf[siAddrlen] = '\0';
-
- if (inet_pton(AF_INET6, addrbuf, &addr6) != 1) {
- perror("inet_pton");
- return FALSE;
- }
-
- if (memcmp(addr, &addr6, len) == 0) {
- return TRUE;
- } else {
- return FALSE;
- }
-}
-
-static int
-siIPv6CheckAddr(const char *addrString, int length, void *typePriv)
-{
- int len;
-
- /* Minimum length is 3 (smallest legal address is "::1") */
- if (length < 3) {
- /* Address is too short! */
- len = -1;
- } else if (length >= SI_IPv6_MAXLEN) {
- /* Address is too long! */
- len = -1;
- } else {
- /* Assume inet_pton is sufficient validation */
- struct in6_addr addr6;
- char addrbuf[SI_IPv6_MAXLEN];
-
- memcpy(addrbuf, addrString, length);
- addrbuf[length] = '\0';
-
- if (inet_pton(AF_INET6, addrbuf, &addr6) != 1) {
- perror("inet_pton");
- len = -1;
- } else {
- len = length;
- }
- }
- return len;
-}
-#endif /* IPv6 */
-
-#if !defined(NO_LOCAL_CLIENT_CRED)
-/***
- * "localuser" & "localgroup" server interpreted types
- *
- * Allows local connections from a given local user or group
- */
-
-#include <pwd.h>
-#include <grp.h>
-
-#define LOCAL_USER 1
-#define LOCAL_GROUP 2
-
-typedef struct {
- int credType;
-} siLocalCredPrivRec, *siLocalCredPrivPtr;
-
-static siLocalCredPrivRec siLocalUserPriv = { LOCAL_USER };
-static siLocalCredPrivRec siLocalGroupPriv = { LOCAL_GROUP };
-
-static Bool
-siLocalCredGetId(const char *addr, int len, siLocalCredPrivPtr lcPriv, int *id)
-{
- Bool parsedOK = FALSE;
- char *addrbuf = malloc(len + 1);
-
- if (addrbuf == NULL) {
- return FALSE;
- }
-
- memcpy(addrbuf, addr, len);
- addrbuf[len] = '\0';
-
- if (addr[0] == '#') { /* numeric id */
- char *cp;
- errno = 0;
- *id = strtol(addrbuf + 1, &cp, 0);
- if ((errno == 0) && (cp != (addrbuf+1))) {
- parsedOK = TRUE;
- }
- } else { /* non-numeric name */
- if (lcPriv->credType == LOCAL_USER) {
- struct passwd *pw = getpwnam(addrbuf);
-
- if (pw != NULL) {
- *id = (int) pw->pw_uid;
- parsedOK = TRUE;
- }
- } else { /* group */
- struct group *gr = getgrnam(addrbuf);
-
- if (gr != NULL) {
- *id = (int) gr->gr_gid;
- parsedOK = TRUE;
- }
- }
- }
-
- free(addrbuf);
- return parsedOK;
-}
-
-static Bool
-siLocalCredAddrMatch(int family, pointer addr, int len,
- const char *siAddr, int siAddrlen, ClientPtr client, void *typePriv)
-{
- int siAddrId;
- LocalClientCredRec *lcc;
- siLocalCredPrivPtr lcPriv = (siLocalCredPrivPtr) typePriv;
-
- if (GetLocalClientCreds(client, &lcc) == -1) {
- return FALSE;
- }
-
-#ifdef HAVE_GETZONEID /* Ensure process is in the same zone */
- if ((lcc->fieldsSet & LCC_ZID_SET) && (lcc->zoneid != getzoneid())) {
- FreeLocalClientCreds(lcc);
- return FALSE;
- }
-#endif
-
- if (siLocalCredGetId(siAddr, siAddrlen, lcPriv, &siAddrId) == FALSE) {
- FreeLocalClientCreds(lcc);
- return FALSE;
- }
-
- if (lcPriv->credType == LOCAL_USER) {
- if ((lcc->fieldsSet & LCC_UID_SET) && (lcc->euid == siAddrId)) {
- FreeLocalClientCreds(lcc);
- return TRUE;
- }
- } else {
- if ((lcc->fieldsSet & LCC_GID_SET) && (lcc->egid == siAddrId)) {
- FreeLocalClientCreds(lcc);
- return TRUE;
- }
- if (lcc->pSuppGids != NULL) {
- int i;
-
- for (i = 0 ; i < lcc->nSuppGids; i++) {
- if (lcc->pSuppGids[i] == siAddrId) {
- FreeLocalClientCreds(lcc);
- return TRUE;
- }
- }
- }
- }
- FreeLocalClientCreds(lcc);
- return FALSE;
-}
-
-static int
-siLocalCredCheckAddr(const char *addrString, int length, void *typePriv)
-{
- int len = length;
- int id;
-
- if (siLocalCredGetId(addrString, length,
- (siLocalCredPrivPtr)typePriv, &id) == FALSE) {
- len = -1;
- }
- return len;
-}
-#endif /* localuser */
-
-static void
-siTypesInitialize(void)
-{
- siTypeAdd("hostname", siHostnameAddrMatch, siHostnameCheckAddr, NULL);
-#if defined(IPv6) && defined(AF_INET6)
- siTypeAdd("ipv6", siIPv6AddrMatch, siIPv6CheckAddr, NULL);
-#endif
-#if !defined(NO_LOCAL_CLIENT_CRED)
- siTypeAdd("localuser", siLocalCredAddrMatch, siLocalCredCheckAddr,
- &siLocalUserPriv);
- siTypeAdd("localgroup", siLocalCredAddrMatch, siLocalCredCheckAddr,
- &siLocalGroupPriv);
-#endif
-}
+/***********************************************************
+
+Copyright 1987, 1998 The Open Group
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
+INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
+FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+X Window System is a trademark of The Open Group.
+
+Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+/*
+ * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifdef WIN32
+#include <X11/Xwinsock.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#define XSERV_t
+#define TRANS_SERVER
+#define TRANS_REOPEN
+#include <X11/Xtrans/Xtrans.h>
+#include <X11/Xauth.h>
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "site.h"
+#include <errno.h>
+#include <sys/types.h>
+#ifndef WIN32
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <ctype.h>
+
+#if defined(TCPCONN) || defined(STREAMSCONN)
+#include <netinet/in.h>
+#endif /* TCPCONN || STREAMSCONN */
+
+#ifdef HAS_GETPEERUCRED
+# include <ucred.h>
+# ifdef sun
+# include <zone.h>
+# endif
+#endif
+
+#if defined(SVR4) || (defined(SYSV) && defined(__i386__)) || defined(__GNU__)
+# include <sys/utsname.h>
+#endif
+#if defined(SYSV) && defined(__i386__)
+# include <sys/stream.h>
+#endif
+#ifdef __GNU__
+#undef SIOCGIFCONF
+#include <netdb.h>
+#else /*!__GNU__*/
+# include <net/if.h>
+#endif /*__GNU__ */
+
+#ifdef SVR4
+#include <sys/sockio.h>
+#include <sys/stropts.h>
+#endif
+
+#include <netdb.h>
+
+#ifdef CSRG_BASED
+#include <sys/param.h>
+#if (BSD >= 199103)
+#define VARIABLE_IFREQ
+#endif
+#endif
+
+#ifdef BSD44SOCKETS
+#ifndef VARIABLE_IFREQ
+#define VARIABLE_IFREQ
+#endif
+#endif
+
+#ifdef HAS_GETIFADDRS
+#include <ifaddrs.h>
+#endif
+
+/* Solaris provides an extended interface SIOCGLIFCONF. Other systems
+ * may have this as well, but the code has only been tested on Solaris
+ * so far, so we only enable it there. Other platforms may be added as
+ * needed.
+ *
+ * Test for Solaris commented out -- TSI @ UQV 2003.06.13
+ */
+#ifdef SIOCGLIFCONF
+/* #if defined(sun) */
+#define USE_SIOCGLIFCONF
+/* #endif */
+#endif
+
+#endif /* WIN32 */
+
+#ifndef PATH_MAX
+#include <sys/param.h>
+#ifndef PATH_MAX
+#ifdef MAXPATHLEN
+#define PATH_MAX MAXPATHLEN
+#else
+#define PATH_MAX 1024
+#endif
+#endif
+#endif
+
+
+#define X_INCLUDE_NETDB_H
+#include <X11/Xos_r.h>
+
+#include "dixstruct.h"
+#include "osdep.h"
+
+#include "xace.h"
+
+#ifndef PATH_MAX
+#ifdef MAXPATHLEN
+#define PATH_MAX MAXPATHLEN
+#else
+#define PATH_MAX 1024
+#endif
+#endif
+
+Bool defeatAccessControl = FALSE;
+
+#define acmp(a1, a2, len) memcmp((char *)(a1), (char *)(a2), len)
+#define acopy(a1, a2, len) memmove((char *)(a2), (char *)(a1), len)
+#define addrEqual(fam, address, length, host) \
+ ((fam) == (host)->family &&\
+ (length) == (host)->len &&\
+ !acmp (address, (host)->addr, length))
+
+static int ConvertAddr(struct sockaddr * /*saddr*/,
+ int * /*len*/,
+ pointer * /*addr*/);
+
+static int CheckAddr(int /*family*/,
+ const void * /*pAddr*/,
+ unsigned /*length*/);
+
+static Bool NewHost(int /*family*/,
+ const void * /*addr*/,
+ int /*len*/,
+ int /* addingLocalHosts */);
+
+/* XFree86 bug #156: To keep track of which hosts were explicitly requested in
+ /etc/X<display>.hosts, we've added a requested field to the HOST struct,
+ and a LocalHostRequested variable. These default to FALSE, but are set
+ to TRUE in ResetHosts when reading in /etc/X<display>.hosts. They are
+ checked in DisableLocalHost(), which is called to disable the default
+ local host entries when stronger authentication is turned on. */
+
+typedef struct _host {
+ short family;
+ short len;
+ unsigned char *addr;
+ struct _host *next;
+ int requested;
+} HOST;
+
+#define MakeHost(h,l) (h)=malloc(sizeof *(h)+(l));\
+ if (h) { \
+ (h)->addr=(unsigned char *) ((h) + 1);\
+ (h)->requested = FALSE; \
+ }
+#define FreeHost(h) free(h)
+static HOST *selfhosts = NULL;
+static HOST *validhosts = NULL;
+static int AccessEnabled = DEFAULT_ACCESS_CONTROL;
+static int LocalHostEnabled = FALSE;
+static int LocalHostRequested = FALSE;
+static int UsingXdmcp = FALSE;
+
+/* FamilyServerInterpreted implementation */
+static Bool siAddrMatch(int family, pointer addr, int len, HOST *host,
+ ClientPtr client);
+static int siCheckAddr(const char *addrString, int length);
+static void siTypesInitialize(void);
+
+/*
+ * called when authorization is not enabled to add the
+ * local host to the access list
+ */
+
+void
+EnableLocalHost (void)
+{
+ if (!UsingXdmcp)
+ {
+ LocalHostEnabled = TRUE;
+ AddLocalHosts ();
+ }
+}
+
+/*
+ * called when authorization is enabled to keep us secure
+ */
+void
+DisableLocalHost (void)
+{
+ HOST *self;
+
+ if (!LocalHostRequested) /* Fix for XFree86 bug #156 */
+ LocalHostEnabled = FALSE;
+ for (self = selfhosts; self; self = self->next) {
+ if (!self->requested) /* Fix for XFree86 bug #156 */
+ (void) RemoveHost ((ClientPtr)NULL, self->family, self->len, (pointer)self->addr);
+ }
+}
+
+/*
+ * called at init time when XDMCP will be used; xdmcp always
+ * adds local hosts manually when needed
+ */
+
+void
+AccessUsingXdmcp (void)
+{
+ UsingXdmcp = TRUE;
+ LocalHostEnabled = FALSE;
+}
+
+
+#if defined(SVR4) && !defined(sun) && defined(SIOCGIFCONF) && !defined(USE_SIOCGLIFCONF)
+
+/* Deal with different SIOCGIFCONF ioctl semantics on these OSs */
+
+static int
+ifioctl (int fd, int cmd, char *arg)
+{
+ struct strioctl ioc;
+ int ret;
+
+ memset((char *) &ioc, 0, sizeof(ioc));
+ ioc.ic_cmd = cmd;
+ ioc.ic_timout = 0;
+ if (cmd == SIOCGIFCONF)
+ {
+ ioc.ic_len = ((struct ifconf *) arg)->ifc_len;
+ ioc.ic_dp = ((struct ifconf *) arg)->ifc_buf;
+ }
+ else
+ {
+ ioc.ic_len = sizeof(struct ifreq);
+ ioc.ic_dp = arg;
+ }
+ ret = ioctl(fd, I_STR, (char *) &ioc);
+ if (ret >= 0 && cmd == SIOCGIFCONF)
+#ifdef SVR4
+ ((struct ifconf *) arg)->ifc_len = ioc.ic_len;
+#endif
+ return ret;
+}
+#else
+#define ifioctl ioctl
+#endif
+
+/*
+ * DefineSelf (fd):
+ *
+ * Define this host for access control. Find all the hosts the OS knows about
+ * for this fd and add them to the selfhosts list.
+ */
+
+#if !defined(SIOCGIFCONF)
+void
+DefineSelf (int fd)
+{
+#if !defined(TCPCONN) && !defined(STREAMSCONN) && !defined(UNIXCONN)
+ return;
+#else
+ register int n;
+ int len;
+ caddr_t addr;
+ int family;
+ register HOST *host;
+
+#ifndef WIN32
+ struct utsname name;
+#else
+ struct {
+ char nodename[512];
+ } name;
+#endif
+
+ register struct hostent *hp;
+
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in in;
+#if defined(IPv6) && defined(AF_INET6)
+ struct sockaddr_in6 in6;
+#endif
+ } saddr;
+
+ struct sockaddr_in *inetaddr;
+ struct sockaddr_in6 *inet6addr;
+ struct sockaddr_in broad_addr;
+#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
+ _Xgethostbynameparams hparams;
+#endif
+
+ /* Why not use gethostname()? Well, at least on my system, I've had to
+ * make an ugly kernel patch to get a name longer than 8 characters, and
+ * uname() lets me access to the whole string (it smashes release, you
+ * see), whereas gethostname() kindly truncates it for me.
+ */
+#ifndef WIN32
+ uname(&name);
+#else
+ gethostname(name.nodename, sizeof(name.nodename));
+#endif
+
+ hp = _XGethostbyname(name.nodename, hparams);
+ if (hp != NULL)
+ {
+ saddr.sa.sa_family = hp->h_addrtype;
+ switch (hp->h_addrtype) {
+ case AF_INET:
+ inetaddr = (struct sockaddr_in *) (&(saddr.sa));
+ acopy ( hp->h_addr, &(inetaddr->sin_addr), hp->h_length);
+ len = sizeof(saddr.sa);
+ break;
+#if defined(IPv6) && defined(AF_INET6)
+ case AF_INET6:
+ inet6addr = (struct sockaddr_in6 *) (&(saddr.sa));
+ acopy ( hp->h_addr, &(inet6addr->sin6_addr), hp->h_length);
+ len = sizeof(saddr.in6);
+ break;
+#endif
+ default:
+ goto DefineLocalHost;
+ }
+ family = ConvertAddr ( &(saddr.sa), &len, (pointer *)&addr);
+ if ( family != -1 && family != FamilyLocal )
+ {
+ for (host = selfhosts;
+ host && !addrEqual (family, addr, len, host);
+ host = host->next) ;
+ if (!host)
+ {
+ /* add this host to the host list. */
+ MakeHost(host,len)
+ if (host)
+ {
+ host->family = family;
+ host->len = len;
+ acopy ( addr, host->addr, len);
+ host->next = selfhosts;
+ selfhosts = host;
+ }
+#ifdef XDMCP
+ /*
+ * If this is an Internet Address, but not the localhost
+ * address (127.0.0.1), nor the bogus address (0.0.0.0),
+ * register it.
+ */
+ if (family == FamilyInternet &&
+ !(len == 4 &&
+ ((addr[0] == 127) ||
+ (addr[0] == 0 && addr[1] == 0 &&
+ addr[2] == 0 && addr[3] == 0)))
+ )
+ {
+ XdmcpRegisterConnection (family, (char *)addr, len);
+ broad_addr = *inetaddr;
+ ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr =
+ htonl (INADDR_BROADCAST);
+ XdmcpRegisterBroadcastAddress ((struct sockaddr_in *)
+ &broad_addr);
+ }
+#if defined(IPv6) && defined(AF_INET6)
+ else if (family == FamilyInternet6 &&
+ !(IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr)))
+ {
+ XdmcpRegisterConnection (family, (char *)addr, len);
+ }
+#endif
+
+#endif /* XDMCP */
+ }
+ }
+ }
+ /*
+ * now add a host of family FamilyLocalHost...
+ */
+DefineLocalHost:
+ for (host = selfhosts;
+ host && !addrEqual(FamilyLocalHost, "", 0, host);
+ host = host->next);
+ if (!host)
+ {
+ MakeHost(host, 0);
+ if (host)
+ {
+ host->family = FamilyLocalHost;
+ host->len = 0;
+ acopy("", host->addr, 0);
+ host->next = selfhosts;
+ selfhosts = host;
+ }
+ }
+#endif /* !TCPCONN && !STREAMSCONN && !UNIXCONN */
+}
+
+#else
+
+#ifdef USE_SIOCGLIFCONF
+#define ifr_type struct lifreq
+#else
+#define ifr_type struct ifreq
+#endif
+
+#ifdef VARIABLE_IFREQ
+#define ifr_size(p) (sizeof (struct ifreq) + \
+ (p->ifr_addr.sa_len > sizeof (p->ifr_addr) ? \
+ p->ifr_addr.sa_len - sizeof (p->ifr_addr) : 0))
+#define ifraddr_size(a) (a.sa_len)
+#else
+#define ifr_size(p) (sizeof (ifr_type))
+#define ifraddr_size(a) (sizeof (a))
+#endif
+
+#if defined(IPv6) && defined(AF_INET6)
+#include <arpa/inet.h>
+#endif
+
+#if defined(IPv6) && defined(AF_INET6)
+static void
+in6_fillscopeid(struct sockaddr_in6 *sin6)
+{
+#if defined(__KAME__)
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
+ sin6->sin6_scope_id =
+ ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]);
+ sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0;
+ }
+#endif
+}
+#endif
+
+void
+DefineSelf (int fd)
+{
+#ifndef HAS_GETIFADDRS
+ char *cp, *cplim;
+# ifdef USE_SIOCGLIFCONF
+ struct sockaddr_storage buf[16];
+ struct lifconf ifc;
+ register struct lifreq *ifr;
+# ifdef SIOCGLIFNUM
+ struct lifnum ifn;
+# endif
+# else /* !USE_SIOCGLIFCONF */
+ char buf[2048];
+ struct ifconf ifc;
+ register struct ifreq *ifr;
+# endif
+ void * bufptr = buf;
+#else /* HAS_GETIFADDRS */
+ struct ifaddrs * ifap, *ifr;
+#endif
+ int len;
+ unsigned char * addr;
+ int family;
+ register HOST *host;
+
+#ifndef HAS_GETIFADDRS
+
+ len = sizeof(buf);
+
+#ifdef USE_SIOCGLIFCONF
+
+#ifdef SIOCGLIFNUM
+ ifn.lifn_family = AF_UNSPEC;
+ ifn.lifn_flags = 0;
+ if (ioctl (fd, SIOCGLIFNUM, (char *) &ifn) < 0)
+ Error ("Getting interface count");
+ if (len < (ifn.lifn_count * sizeof(struct lifreq))) {
+ len = ifn.lifn_count * sizeof(struct lifreq);
+ bufptr = malloc(len);
+ }
+#endif
+
+ ifc.lifc_family = AF_UNSPEC;
+ ifc.lifc_flags = 0;
+ ifc.lifc_len = len;
+ ifc.lifc_buf = bufptr;
+
+#define IFC_IOCTL_REQ SIOCGLIFCONF
+#define IFC_IFC_REQ ifc.lifc_req
+#define IFC_IFC_LEN ifc.lifc_len
+#define IFR_IFR_ADDR ifr->lifr_addr
+#define IFR_IFR_NAME ifr->lifr_name
+
+#else /* Use SIOCGIFCONF */
+ ifc.ifc_len = len;
+ ifc.ifc_buf = bufptr;
+
+#define IFC_IOCTL_REQ SIOCGIFCONF
+#define IFC_IFC_REQ ifc.ifc_req
+#define IFC_IFC_LEN ifc.ifc_len
+#define IFR_IFR_ADDR ifr->ifr_addr
+#define IFR_IFR_NAME ifr->ifr_name
+#endif
+
+ if (ifioctl (fd, IFC_IOCTL_REQ, (pointer) &ifc) < 0)
+ Error ("Getting interface configuration (4)");
+
+ cplim = (char *) IFC_IFC_REQ + IFC_IFC_LEN;
+
+ for (cp = (char *) IFC_IFC_REQ; cp < cplim; cp += ifr_size (ifr))
+ {
+ ifr = (ifr_type *) cp;
+ len = ifraddr_size (IFR_IFR_ADDR);
+ family = ConvertAddr ((struct sockaddr *) &IFR_IFR_ADDR,
+ &len, (pointer *)&addr);
+ if (family == -1 || family == FamilyLocal)
+ continue;
+#if defined(IPv6) && defined(AF_INET6)
+ if (family == FamilyInternet6)
+ in6_fillscopeid((struct sockaddr_in6 *)&IFR_IFR_ADDR);
+#endif
+ for (host = selfhosts;
+ host && !addrEqual (family, addr, len, host);
+ host = host->next)
+ ;
+ if (host)
+ continue;
+ MakeHost(host,len)
+ if (host)
+ {
+ host->family = family;
+ host->len = len;
+ acopy(addr, host->addr, len);
+ host->next = selfhosts;
+ selfhosts = host;
+ }
+#ifdef XDMCP
+ {
+#ifdef USE_SIOCGLIFCONF
+ struct sockaddr_storage broad_addr;
+#else
+ struct sockaddr broad_addr;
+#endif
+
+ /*
+ * If this isn't an Internet Address, don't register it.
+ */
+ if (family != FamilyInternet
+#if defined(IPv6) && defined(AF_INET6)
+ && family != FamilyInternet6
+#endif
+ )
+ continue;
+
+ /*
+ * ignore 'localhost' entries as they're not useful
+ * on the other end of the wire
+ */
+ if (family == FamilyInternet &&
+ addr[0] == 127 && addr[1] == 0 &&
+ addr[2] == 0 && addr[3] == 1)
+ continue;
+#if defined(IPv6) && defined(AF_INET6)
+ else if (family == FamilyInternet6 &&
+ IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr))
+ continue;
+#endif
+
+ /*
+ * Ignore '0.0.0.0' entries as they are
+ * returned by some OSes for unconfigured NICs but they are
+ * not useful on the other end of the wire.
+ */
+ if (len == 4 &&
+ addr[0] == 0 && addr[1] == 0 &&
+ addr[2] == 0 && addr[3] == 0)
+ continue;
+
+ XdmcpRegisterConnection (family, (char *)addr, len);
+
+#if defined(IPv6) && defined(AF_INET6)
+ /* IPv6 doesn't support broadcasting, so we drop out here */
+ if (family == FamilyInternet6)
+ continue;
+#endif
+
+ broad_addr = IFR_IFR_ADDR;
+
+ ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr =
+ htonl (INADDR_BROADCAST);
+#if defined(USE_SIOCGLIFCONF) && defined(SIOCGLIFBRDADDR)
+ {
+ struct lifreq broad_req;
+
+ broad_req = *ifr;
+ if (ioctl (fd, SIOCGLIFFLAGS, (char *) &broad_req) != -1 &&
+ (broad_req.lifr_flags & IFF_BROADCAST) &&
+ (broad_req.lifr_flags & IFF_UP)
+ )
+ {
+ broad_req = *ifr;
+ if (ioctl (fd, SIOCGLIFBRDADDR, &broad_req) != -1)
+ broad_addr = broad_req.lifr_broadaddr;
+ else
+ continue;
+ }
+ else
+ continue;
+ }
+
+#elif defined(SIOCGIFBRDADDR)
+ {
+ struct ifreq broad_req;
+
+ broad_req = *ifr;
+ if (ifioctl (fd, SIOCGIFFLAGS, (pointer) &broad_req) != -1 &&
+ (broad_req.ifr_flags & IFF_BROADCAST) &&
+ (broad_req.ifr_flags & IFF_UP)
+ )
+ {
+ broad_req = *ifr;
+ if (ifioctl (fd, SIOCGIFBRDADDR, (pointer) &broad_req) != -1)
+ broad_addr = broad_req.ifr_addr;
+ else
+ continue;
+ }
+ else
+ continue;
+ }
+#endif /* SIOCGIFBRDADDR */
+ XdmcpRegisterBroadcastAddress ((struct sockaddr_in *) &broad_addr);
+ }
+#endif /* XDMCP */
+ }
+ if (bufptr != buf)
+ free(bufptr);
+#else /* HAS_GETIFADDRS */
+ if (getifaddrs(&ifap) < 0) {
+ ErrorF("Warning: getifaddrs returns %s\n", strerror(errno));
+ return;
+ }
+ for (ifr = ifap; ifr != NULL; ifr = ifr->ifa_next) {
+ if (!ifr->ifa_addr)
+ continue;
+ len = sizeof(*(ifr->ifa_addr));
+ family = ConvertAddr((struct sockaddr *) ifr->ifa_addr, &len,
+ (pointer *)&addr);
+ if (family == -1 || family == FamilyLocal)
+ continue;
+#if defined(IPv6) && defined(AF_INET6)
+ if (family == FamilyInternet6)
+ in6_fillscopeid((struct sockaddr_in6 *)ifr->ifa_addr);
+#endif
+
+ for (host = selfhosts;
+ host != NULL && !addrEqual(family, addr, len, host);
+ host = host->next)
+ ;
+ if (host != NULL)
+ continue;
+ MakeHost(host, len);
+ if (host != NULL) {
+ host->family = family;
+ host->len = len;
+ acopy(addr, host->addr, len);
+ host->next = selfhosts;
+ selfhosts = host;
+ }
+#ifdef XDMCP
+ {
+ /*
+ * If this isn't an Internet Address, don't register it.
+ */
+ if (family != FamilyInternet
+#if defined(IPv6) && defined(AF_INET6)
+ && family != FamilyInternet6
+#endif
+ )
+ continue;
+
+ /*
+ * ignore 'localhost' entries as they're not useful
+ * on the other end of the wire
+ */
+ if (ifr->ifa_flags & IFF_LOOPBACK)
+ continue;
+
+ if (family == FamilyInternet &&
+ addr[0] == 127 && addr[1] == 0 &&
+ addr[2] == 0 && addr[3] == 1)
+ continue;
+
+ /*
+ * Ignore '0.0.0.0' entries as they are
+ * returned by some OSes for unconfigured NICs but they are
+ * not useful on the other end of the wire.
+ */
+ if (len == 4 &&
+ addr[0] == 0 && addr[1] == 0 &&
+ addr[2] == 0 && addr[3] == 0)
+ continue;
+#if defined(IPv6) && defined(AF_INET6)
+ else if (family == FamilyInternet6 &&
+ IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr))
+ continue;
+#endif
+ XdmcpRegisterConnection(family, (char *)addr, len);
+#if defined(IPv6) && defined(AF_INET6)
+ if (family == FamilyInternet6)
+ /* IPv6 doesn't support broadcasting, so we drop out here */
+ continue;
+#endif
+ if ((ifr->ifa_flags & IFF_BROADCAST) &&
+ (ifr->ifa_flags & IFF_UP) &&
+ ifr->ifa_broadaddr)
+ XdmcpRegisterBroadcastAddress(
+ (struct sockaddr_in *) ifr->ifa_broadaddr);
+ else
+ continue;
+ }
+#endif /* XDMCP */
+
+ } /* for */
+ freeifaddrs(ifap);
+#endif /* HAS_GETIFADDRS */
+
+ /*
+ * add something of FamilyLocalHost
+ */
+ for (host = selfhosts;
+ host && !addrEqual(FamilyLocalHost, "", 0, host);
+ host = host->next);
+ if (!host)
+ {
+ MakeHost(host, 0);
+ if (host)
+ {
+ host->family = FamilyLocalHost;
+ host->len = 0;
+ acopy("", host->addr, 0);
+ host->next = selfhosts;
+ selfhosts = host;
+ }
+ }
+}
+#endif /* hpux && !HAS_IFREQ */
+
+#ifdef XDMCP
+void
+AugmentSelf(pointer from, int len)
+{
+ int family;
+ pointer addr;
+ register HOST *host;
+
+ family = ConvertAddr(from, &len, (pointer *)&addr);
+ if (family == -1 || family == FamilyLocal)
+ return;
+ for (host = selfhosts; host; host = host->next)
+ {
+ if (addrEqual(family, addr, len, host))
+ return;
+ }
+ MakeHost(host,len)
+ if (!host)
+ return;
+ host->family = family;
+ host->len = len;
+ acopy(addr, host->addr, len);
+ host->next = selfhosts;
+ selfhosts = host;
+}
+#endif
+
+void
+AddLocalHosts (void)
+{
+ HOST *self;
+
+ for (self = selfhosts; self; self = self->next)
+ /* Fix for XFree86 bug #156: pass addingLocal = TRUE to
+ * NewHost to tell that we are adding the default local
+ * host entries and not to flag the entries as being
+ * explicitely requested */
+ (void) NewHost (self->family, self->addr, self->len, TRUE);
+}
+
+/* Reset access control list to initial hosts */
+void
+ResetHosts (char *display)
+{
+ register HOST *host;
+ char lhostname[120], ohostname[120];
+ char *hostname = ohostname;
+ char fname[PATH_MAX + 1];
+ int fnamelen;
+ FILE *fd;
+ char *ptr;
+ int i, hostlen;
+#if (defined(TCPCONN) || defined(STREAMSCONN) ) && \
+ (!defined(IPv6) || !defined(AF_INET6))
+ union {
+ struct sockaddr sa;
+#if defined(TCPCONN) || defined(STREAMSCONN)
+ struct sockaddr_in in;
+#endif /* TCPCONN || STREAMSCONN */
+ } saddr;
+#endif
+ int family = 0;
+ pointer addr;
+ int len;
+
+ siTypesInitialize();
+ AccessEnabled = defeatAccessControl ? FALSE : DEFAULT_ACCESS_CONTROL;
+ LocalHostEnabled = FALSE;
+ while ((host = validhosts) != 0)
+ {
+ validhosts = host->next;
+ FreeHost (host);
+ }
+
+#if defined WIN32 && defined __MINGW32__
+#define ETC_HOST_PREFIX "X"
+#else
+#define ETC_HOST_PREFIX "/etc/X"
+#endif
+#define ETC_HOST_SUFFIX ".hosts"
+ fnamelen = strlen(ETC_HOST_PREFIX) + strlen(ETC_HOST_SUFFIX) +
+ strlen(display) + 1;
+ if (fnamelen > sizeof(fname))
+ FatalError("Display name `%s' is too long\n", display);
+ snprintf(fname, sizeof(fname), ETC_HOST_PREFIX "%s" ETC_HOST_SUFFIX,
+ display);
+
+ if ((fd = fopen (fname, "r")) != 0)
+ {
+ while (fgets (ohostname, sizeof (ohostname), fd))
+ {
+ family = FamilyWild;
+ if (*ohostname == '#')
+ continue;
+ if ((ptr = strchr(ohostname, '\n')) != 0)
+ *ptr = 0;
+ hostlen = strlen(ohostname) + 1;
+ for (i = 0; i < hostlen; i++)
+ lhostname[i] = tolower(ohostname[i]);
+ hostname = ohostname;
+ if (!strncmp("local:", lhostname, 6))
+ {
+ family = FamilyLocalHost;
+ NewHost(family, "", 0, FALSE);
+ LocalHostRequested = TRUE; /* Fix for XFree86 bug #156 */
+ }
+#if defined(TCPCONN) || defined(STREAMSCONN)
+ else if (!strncmp("inet:", lhostname, 5))
+ {
+ family = FamilyInternet;
+ hostname = ohostname + 5;
+ }
+#if defined(IPv6) && defined(AF_INET6)
+ else if (!strncmp("inet6:", lhostname, 6))
+ {
+ family = FamilyInternet6;
+ hostname = ohostname + 6;
+ }
+#endif
+#endif
+#ifdef SECURE_RPC
+ else if (!strncmp("nis:", lhostname, 4))
+ {
+ family = FamilyNetname;
+ hostname = ohostname + 4;
+ }
+#endif
+ else if (!strncmp("si:", lhostname, 3))
+ {
+ family = FamilyServerInterpreted;
+ hostname = ohostname + 3;
+ hostlen -= 3;
+ }
+
+
+ if (family == FamilyServerInterpreted)
+ {
+ len = siCheckAddr(hostname, hostlen);
+ if (len >= 0) {
+ NewHost(family, hostname, len, FALSE);
+ }
+ }
+ else
+#ifdef SECURE_RPC
+ if ((family == FamilyNetname) || (strchr(hostname, '@')))
+ {
+ SecureRPCInit ();
+ (void) NewHost (FamilyNetname, hostname, strlen (hostname), FALSE);
+ }
+ else
+#endif /* SECURE_RPC */
+#if defined(TCPCONN) || defined(STREAMSCONN)
+ {
+#if defined(IPv6) && defined(AF_INET6)
+ if ( (family == FamilyInternet) || (family == FamilyInternet6) ||
+ (family == FamilyWild) )
+ {
+ struct addrinfo *addresses;
+ struct addrinfo *a;
+ int f;
+
+ if (getaddrinfo(hostname, NULL, NULL, &addresses) == 0) {
+ for (a = addresses ; a != NULL ; a = a->ai_next) {
+ len = a->ai_addrlen;
+ f = ConvertAddr(a->ai_addr,&len,(pointer *)&addr);
+ if ( (family == f) ||
+ ((family == FamilyWild) && (f != -1)) ) {
+ NewHost(f, addr, len, FALSE);
+ }
+ }
+ freeaddrinfo(addresses);
+ }
+ }
+#else
+#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
+ _Xgethostbynameparams hparams;
+#endif
+ register struct hostent *hp;
+
+ /* host name */
+ if ((family == FamilyInternet &&
+ ((hp = _XGethostbyname(hostname, hparams)) != 0)) ||
+ ((hp = _XGethostbyname(hostname, hparams)) != 0))
+ {
+ saddr.sa.sa_family = hp->h_addrtype;
+ len = sizeof(saddr.sa);
+ if ((family = ConvertAddr (&saddr.sa, &len, (pointer *)&addr)) != -1)
+ {
+#ifdef h_addr /* new 4.3bsd version of gethostent */
+ char **list;
+
+ /* iterate over the addresses */
+ for (list = hp->h_addr_list; *list; list++)
+ (void) NewHost (family, (pointer)*list, len, FALSE);
+#else
+ (void) NewHost (family, (pointer)hp->h_addr, len, FALSE);
+#endif
+ }
+ }
+#endif /* IPv6 */
+ }
+#endif /* TCPCONN || STREAMSCONN */
+ family = FamilyWild;
+ }
+ fclose (fd);
+ }
+}
+
+/* Is client on the local host */
+Bool
+ComputeLocalClient(ClientPtr client)
+{
+ int alen, family, notused;
+ Xtransaddr *from = NULL;
+ pointer addr;
+ register HOST *host;
+ OsCommPtr oc = (OsCommPtr) client->osPrivate;
+
+ if (!oc->trans_conn)
+ return FALSE;
+
+ if (!_XSERVTransGetPeerAddr (oc->trans_conn, &notused, &alen, &from))
+ {
+ family = ConvertAddr ((struct sockaddr *) from,
+ &alen, (pointer *)&addr);
+ if (family == -1)
+ {
+ free(from);
+ return FALSE;
+ }
+ if (family == FamilyLocal)
+ {
+ free(from);
+ return TRUE;
+ }
+ for (host = selfhosts; host; host = host->next)
+ {
+ if (addrEqual (family, addr, alen, host)) {
+ free(from);
+ return TRUE;
+ }
+ }
+ free(from);
+ }
+ return FALSE;
+}
+
+Bool LocalClient(ClientPtr client)
+{
+ if (!client->osPrivate)
+ return FALSE;
+ return ((OsCommPtr)client->osPrivate)->local_client;
+}
+
+/*
+ * Return the uid and gid of a connected local client
+ *
+ * Used by XShm to test access rights to shared memory segments
+ */
+int
+LocalClientCred(ClientPtr client, int *pUid, int *pGid)
+{
+ LocalClientCredRec *lcc;
+ int ret = GetLocalClientCreds(client, &lcc);
+
+ if (ret == 0) {
+#ifdef HAVE_GETZONEID /* only local if in the same zone */
+ if ((lcc->fieldsSet & LCC_ZID_SET) && (lcc->zoneid != getzoneid())) {
+ FreeLocalClientCreds(lcc);
+ return -1;
+ }
+#endif
+ if ((lcc->fieldsSet & LCC_UID_SET) && (pUid != NULL))
+ *pUid = lcc->euid;
+ if ((lcc->fieldsSet & LCC_GID_SET) && (pGid != NULL))
+ *pGid = lcc->egid;
+ FreeLocalClientCreds(lcc);
+ }
+ return ret;
+}
+
+/*
+ * Return the uid and all gids of a connected local client
+ * Allocates a LocalClientCredRec - caller must call FreeLocalClientCreds
+ *
+ * Used by localuser & localgroup ServerInterpreted access control forms below
+ * Used by AuthAudit to log who local connections came from
+ */
+int
+GetLocalClientCreds(ClientPtr client, LocalClientCredRec **lccp)
+{
+#if defined(HAS_GETPEEREID) || defined(HAS_GETPEERUCRED) || defined(SO_PEERCRED)
+ int fd;
+ XtransConnInfo ci;
+ LocalClientCredRec *lcc;
+#ifdef HAS_GETPEEREID
+ uid_t uid;
+ gid_t gid;
+#elif defined(HAS_GETPEERUCRED)
+ ucred_t *peercred = NULL;
+ const gid_t *gids;
+#elif defined(SO_PEERCRED)
+ struct ucred peercred;
+ socklen_t so_len = sizeof(peercred);
+#endif
+
+ if (client == NULL)
+ return -1;
+ ci = ((OsCommPtr)client->osPrivate)->trans_conn;
+#if !(defined(sun) && defined(HAS_GETPEERUCRED))
+ /* Most implementations can only determine peer credentials for Unix
+ * domain sockets - Solaris getpeerucred can work with a bit more, so
+ * we just let it tell us if the connection type is supported or not
+ */
+ if (!_XSERVTransIsLocal(ci)) {
+ return -1;
+ }
+#endif
+
+ *lccp = calloc(1, sizeof(LocalClientCredRec));
+ if (*lccp == NULL)
+ return -1;
+ lcc = *lccp;
+
+ fd = _XSERVTransGetConnectionNumber(ci);
+#ifdef HAS_GETPEEREID
+ if (getpeereid(fd, &uid, &gid) == -1) {
+ FreeLocalClientCreds(lcc);
+ return -1;
+ }
+ lcc->euid = uid;
+ lcc->egid = gid;
+ lcc->fieldsSet = LCC_UID_SET | LCC_GID_SET;
+ return 0;
+#elif defined(HAS_GETPEERUCRED)
+ if (getpeerucred(fd, &peercred) < 0) {
+ FreeLocalClientCreds(lcc);
+ return -1;
+ }
+ lcc->euid = ucred_geteuid(peercred);
+ if (lcc->euid != -1)
+ lcc->fieldsSet |= LCC_UID_SET;
+ lcc->egid = ucred_getegid(peercred);
+ if (lcc->egid != -1)
+ lcc->fieldsSet |= LCC_GID_SET;
+ lcc->pid = ucred_getpid(peercred);
+ if (lcc->pid != -1)
+ lcc->fieldsSet |= LCC_PID_SET;
+#ifdef HAVE_GETZONEID
+ lcc->zoneid = ucred_getzoneid(peercred);
+ if (lcc->zoneid != -1)
+ lcc->fieldsSet |= LCC_ZID_SET;
+#endif
+ lcc->nSuppGids = ucred_getgroups(peercred, &gids);
+ if (lcc->nSuppGids > 0) {
+ lcc->pSuppGids = calloc(lcc->nSuppGids, sizeof(int));
+ if (lcc->pSuppGids == NULL) {
+ lcc->nSuppGids = 0;
+ } else {
+ int i;
+ for (i = 0 ; i < lcc->nSuppGids; i++) {
+ (lcc->pSuppGids)[i] = (int) gids[i];
+ }
+ }
+ } else {
+ lcc->nSuppGids = 0;
+ }
+ ucred_free(peercred);
+ return 0;
+#elif defined(SO_PEERCRED)
+ if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) == -1) {
+ FreeLocalClientCreds(lcc);
+ return -1;
+ }
+ lcc->euid = peercred.uid;
+ lcc->egid = peercred.gid;
+ lcc->pid = peercred.pid;
+ lcc->fieldsSet = LCC_UID_SET | LCC_GID_SET | LCC_PID_SET;
+ return 0;
+#endif
+#else
+ /* No system call available to get the credentials of the peer */
+#define NO_LOCAL_CLIENT_CRED
+ return -1;
+#endif
+}
+
+void
+FreeLocalClientCreds(LocalClientCredRec *lcc)
+{
+ if (lcc != NULL) {
+ if (lcc->nSuppGids > 0) {
+ free(lcc->pSuppGids);
+ }
+ free(lcc);
+ }
+}
+
+static int
+AuthorizedClient(ClientPtr client)
+{
+ int rc;
+
+ if (!client || defeatAccessControl)
+ return Success;
+
+ /* untrusted clients can't change host access */
+ rc = XaceHook(XACE_SERVER_ACCESS, client, DixManageAccess);
+ if (rc != Success)
+ return rc;
+
+ return LocalClient(client) ? Success : BadAccess;
+}
+
+/* Add a host to the access control list. This is the external interface
+ * called from the dispatcher */
+
+int
+AddHost (ClientPtr client,
+ int family,
+ unsigned length, /* of bytes in pAddr */
+ const void * pAddr)
+{
+ int rc, len;
+
+ rc = AuthorizedClient(client);
+ if (rc != Success)
+ return rc;
+ switch (family) {
+ case FamilyLocalHost:
+ len = length;
+ LocalHostEnabled = TRUE;
+ break;
+#ifdef SECURE_RPC
+ case FamilyNetname:
+ len = length;
+ SecureRPCInit ();
+ break;
+#endif
+ case FamilyInternet:
+#if defined(IPv6) && defined(AF_INET6)
+ case FamilyInternet6:
+#endif
+ case FamilyDECnet:
+ case FamilyChaos:
+ case FamilyServerInterpreted:
+ if ((len = CheckAddr (family, pAddr, length)) < 0)
+ {
+ client->errorValue = length;
+ return BadValue;
+ }
+ break;
+ case FamilyLocal:
+ default:
+ client->errorValue = family;
+ return BadValue;
+ }
+ if (NewHost (family, pAddr, len, FALSE))
+ return Success;
+ return BadAlloc;
+}
+
+Bool
+ForEachHostInFamily (int family,
+ Bool (*func)(
+ unsigned char * /* addr */,
+ short /* len */,
+ pointer /* closure */),
+ pointer closure)
+{
+ HOST *host;
+
+ for (host = validhosts; host; host = host->next)
+ if (family == host->family && func (host->addr, host->len, closure))
+ return TRUE;
+ return FALSE;
+}
+
+/* Add a host to the access control list. This is the internal interface
+ * called when starting or resetting the server */
+static Bool
+NewHost (int family,
+ const void * addr,
+ int len,
+ int addingLocalHosts)
+{
+ register HOST *host;
+
+ for (host = validhosts; host; host = host->next)
+ {
+ if (addrEqual (family, addr, len, host))
+ return TRUE;
+ }
+ if (!addingLocalHosts) { /* Fix for XFree86 bug #156 */
+ for (host = selfhosts; host; host = host->next) {
+ if (addrEqual (family, addr, len, host)) {
+ host->requested = TRUE;
+ break;
+ }
+ }
+ }
+ MakeHost(host,len)
+ if (!host)
+ return FALSE;
+ host->family = family;
+ host->len = len;
+ acopy(addr, host->addr, len);
+ host->next = validhosts;
+ validhosts = host;
+ return TRUE;
+}
+
+/* Remove a host from the access control list */
+
+int
+RemoveHost (
+ ClientPtr client,
+ int family,
+ unsigned length, /* of bytes in pAddr */
+ pointer pAddr)
+{
+ int rc, len;
+ register HOST *host, **prev;
+
+ rc = AuthorizedClient(client);
+ if (rc != Success)
+ return rc;
+ switch (family) {
+ case FamilyLocalHost:
+ len = length;
+ LocalHostEnabled = FALSE;
+ break;
+#ifdef SECURE_RPC
+ case FamilyNetname:
+ len = length;
+ break;
+#endif
+ case FamilyInternet:
+#if defined(IPv6) && defined(AF_INET6)
+ case FamilyInternet6:
+#endif
+ case FamilyDECnet:
+ case FamilyChaos:
+ case FamilyServerInterpreted:
+ if ((len = CheckAddr (family, pAddr, length)) < 0)
+ {
+ client->errorValue = length;
+ return BadValue;
+ }
+ break;
+ case FamilyLocal:
+ default:
+ client->errorValue = family;
+ return BadValue;
+ }
+ for (prev = &validhosts;
+ (host = *prev) && (!addrEqual (family, pAddr, len, host));
+ prev = &host->next)
+ ;
+ if (host)
+ {
+ *prev = host->next;
+ FreeHost (host);
+ }
+ return Success;
+}
+
+/* Get all hosts in the access control list */
+int
+GetHosts (
+ pointer *data,
+ int *pnHosts,
+ int *pLen,
+ BOOL *pEnabled)
+{
+ int len;
+ register int n = 0;
+ register unsigned char *ptr;
+ register HOST *host;
+ int nHosts = 0;
+
+ *pEnabled = AccessEnabled ? EnableAccess : DisableAccess;
+ for (host = validhosts; host; host = host->next)
+ {
+ nHosts++;
+ n += pad_to_int32(host->len) + sizeof(xHostEntry);
+ }
+ if (n)
+ {
+ *data = ptr = malloc(n);
+ if (!ptr)
+ {
+ return BadAlloc;
+ }
+ for (host = validhosts; host; host = host->next)
+ {
+ len = host->len;
+ ((xHostEntry *)ptr)->family = host->family;
+ ((xHostEntry *)ptr)->length = len;
+ ptr += sizeof(xHostEntry);
+ acopy (host->addr, ptr, len);
+ ptr += pad_to_int32(len);
+ }
+ } else {
+ *data = NULL;
+ }
+ *pnHosts = nHosts;
+ *pLen = n;
+ return Success;
+}
+
+/* Check for valid address family and length, and return address length. */
+
+/*ARGSUSED*/
+static int
+CheckAddr (
+ int family,
+ const void * pAddr,
+ unsigned length)
+{
+ int len;
+
+ switch (family)
+ {
+#if defined(TCPCONN) || defined(STREAMSCONN)
+ case FamilyInternet:
+ if (length == sizeof (struct in_addr))
+ len = length;
+ else
+ len = -1;
+ break;
+#if defined(IPv6) && defined(AF_INET6)
+ case FamilyInternet6:
+ if (length == sizeof (struct in6_addr))
+ len = length;
+ else
+ len = -1;
+ break;
+#endif
+#endif
+ case FamilyServerInterpreted:
+ len = siCheckAddr(pAddr, length);
+ break;
+ default:
+ len = -1;
+ }
+ return len;
+}
+
+/* Check if a host is not in the access control list.
+ * Returns 1 if host is invalid, 0 if we've found it. */
+
+int
+InvalidHost (
+ register struct sockaddr *saddr,
+ int len,
+ ClientPtr client)
+{
+ int family;
+ pointer addr;
+ register HOST *selfhost, *host;
+
+ if (!AccessEnabled) /* just let them in */
+ return 0;
+ family = ConvertAddr (saddr, &len, (pointer *)&addr);
+ if (family == -1)
+ return 1;
+ if (family == FamilyLocal)
+ {
+ if (!LocalHostEnabled)
+ {
+ /*
+ * check to see if any local address is enabled. This
+ * implicitly enables local connections.
+ */
+ for (selfhost = selfhosts; selfhost; selfhost=selfhost->next)
+ {
+ for (host = validhosts; host; host=host->next)
+ {
+ if (addrEqual (selfhost->family, selfhost->addr,
+ selfhost->len, host))
+ return 0;
+ }
+ }
+ } else
+ return 0;
+ }
+ for (host = validhosts; host; host = host->next)
+ {
+ if ((host->family == FamilyServerInterpreted)) {
+ if (siAddrMatch (family, addr, len, host, client)) {
+ return 0;
+ }
+ } else {
+ if (addrEqual (family, addr, len, host))
+ return 0;
+ }
+
+ }
+ return 1;
+}
+
+static int
+ConvertAddr (
+ register struct sockaddr *saddr,
+ int *len,
+ pointer *addr)
+{
+ if (*len == 0)
+ return FamilyLocal;
+ switch (saddr->sa_family)
+ {
+ case AF_UNSPEC:
+#if defined(UNIXCONN) || defined(LOCALCONN)
+ case AF_UNIX:
+#endif
+ return FamilyLocal;
+#if defined(TCPCONN) || defined(STREAMSCONN)
+ case AF_INET:
+#ifdef WIN32
+ if (16777343 == *(long*)&((struct sockaddr_in *) saddr)->sin_addr)
+ return FamilyLocal;
+#endif
+ *len = sizeof (struct in_addr);
+ *addr = (pointer) &(((struct sockaddr_in *) saddr)->sin_addr);
+ return FamilyInternet;
+#if defined(IPv6) && defined(AF_INET6)
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) saddr;
+ if (IN6_IS_ADDR_V4MAPPED(&(saddr6->sin6_addr))) {
+ *len = sizeof (struct in_addr);
+ *addr = (pointer) &(saddr6->sin6_addr.s6_addr[12]);
+ return FamilyInternet;
+ } else {
+ *len = sizeof (struct in6_addr);
+ *addr = (pointer) &(saddr6->sin6_addr);
+ return FamilyInternet6;
+ }
+ }
+#endif
+#endif
+ default:
+ return -1;
+ }
+}
+
+int
+ChangeAccessControl(
+ ClientPtr client,
+ int fEnabled)
+{
+ int rc = AuthorizedClient(client);
+ if (rc != Success)
+ return rc;
+ AccessEnabled = fEnabled;
+ return Success;
+}
+
+/* returns FALSE if xhost + in effect, else TRUE */
+int
+GetAccessControl(void)
+{
+ return AccessEnabled;
+}
+
+/*****************************************************************************
+ * FamilyServerInterpreted host entry implementation
+ *
+ * Supports an extensible system of host types which the server can interpret
+ * See the IPv6 extensions to the X11 protocol spec for the definition.
+ *
+ * Currently supported schemes:
+ *
+ * hostname - hostname as defined in IETF RFC 2396
+ * ipv6 - IPv6 literal address as defined in IETF RFC's 3513 and <TBD>
+ *
+ * See xc/doc/specs/SIAddresses for formal definitions of each type.
+ */
+
+/* These definitions and the siTypeAdd function could be exported in the
+ * future to enable loading additional host types, but that was not done for
+ * the initial implementation.
+ */
+typedef Bool (*siAddrMatchFunc)(int family, pointer addr, int len,
+ const char *siAddr, int siAddrlen, ClientPtr client, void *siTypePriv);
+typedef int (*siCheckAddrFunc)(const char *addrString, int length,
+ void *siTypePriv);
+
+struct siType {
+ struct siType * next;
+ const char * typeName;
+ siAddrMatchFunc addrMatch;
+ siCheckAddrFunc checkAddr;
+ void * typePriv; /* Private data for type routines */
+};
+
+static struct siType *siTypeList;
+
+static int
+siTypeAdd(const char *typeName, siAddrMatchFunc addrMatch,
+ siCheckAddrFunc checkAddr, void *typePriv)
+{
+ struct siType *s, *p;
+
+ if ((typeName == NULL) || (addrMatch == NULL) || (checkAddr == NULL))
+ return BadValue;
+
+ for (s = siTypeList, p = NULL; s != NULL ; p = s, s = s->next) {
+ if (strcmp(typeName, s->typeName) == 0) {
+ s->addrMatch = addrMatch;
+ s->checkAddr = checkAddr;
+ s->typePriv = typePriv;
+ return Success;
+ }
+ }
+
+ s = malloc(sizeof(struct siType));
+ if (s == NULL)
+ return BadAlloc;
+
+ if (p == NULL)
+ siTypeList = s;
+ else
+ p->next = s;
+
+ s->next = NULL;
+ s->typeName = typeName;
+ s->addrMatch = addrMatch;
+ s->checkAddr = checkAddr;
+ s->typePriv = typePriv;
+ return Success;
+}
+
+/* Checks to see if a host matches a server-interpreted host entry */
+static Bool
+siAddrMatch(int family, pointer addr, int len, HOST *host, ClientPtr client)
+{
+ Bool matches = FALSE;
+ struct siType *s;
+ const char *valueString;
+ int addrlen;
+
+ valueString = (const char *) memchr(host->addr, '\0', host->len);
+ if (valueString != NULL) {
+ for (s = siTypeList; s != NULL ; s = s->next) {
+ if (strcmp((char *) host->addr, s->typeName) == 0) {
+ addrlen = host->len - (strlen((char *)host->addr) + 1);
+ matches = s->addrMatch(family, addr, len,
+ valueString + 1, addrlen, client, s->typePriv);
+ break;
+ }
+ }
+#ifdef FAMILY_SI_DEBUG
+ ErrorF(
+ "Xserver: siAddrMatch(): type = %s, value = %*.*s -- %s\n",
+ host->addr, addrlen, addrlen, valueString + 1,
+ (matches) ? "accepted" : "rejected");
+#endif
+ }
+ return matches;
+}
+
+static int
+siCheckAddr(const char *addrString, int length)
+{
+ const char *valueString;
+ int addrlen, typelen;
+ int len = -1;
+ struct siType *s;
+
+ /* Make sure there is a \0 byte inside the specified length
+ to separate the address type from the address value. */
+ valueString = (const char *) memchr(addrString, '\0', length);
+ if (valueString != NULL) {
+ /* Make sure the first string is a recognized address type,
+ * and the second string is a valid address of that type.
+ */
+ typelen = strlen(addrString) + 1;
+ addrlen = length - typelen;
+
+ for (s = siTypeList; s != NULL ; s = s->next) {
+ if (strcmp(addrString, s->typeName) == 0) {
+ len = s->checkAddr(valueString + 1, addrlen, s->typePriv);
+ if (len >= 0) {
+ len += typelen;
+ }
+ break;
+ }
+ }
+#ifdef FAMILY_SI_DEBUG
+ {
+ const char *resultMsg;
+
+ if (s == NULL) {
+ resultMsg = "type not registered";
+ } else {
+ if (len == -1)
+ resultMsg = "rejected";
+ else
+ resultMsg = "accepted";
+ }
+
+ ErrorF("Xserver: siCheckAddr(): type = %s, value = %*.*s, len = %d -- %s\n",
+ addrString, addrlen, addrlen, valueString + 1, len, resultMsg);
+ }
+#endif
+ }
+ return len;
+}
+
+
+/***
+ * Hostname server-interpreted host type
+ *
+ * Stored as hostname string, explicitly defined to be resolved ONLY
+ * at access check time, to allow for hosts with dynamic addresses
+ * but static hostnames, such as found in some DHCP & mobile setups.
+ *
+ * Hostname must conform to IETF RFC 2396 sec. 3.2.2, which defines it as:
+ * hostname = *( domainlabel "." ) toplabel [ "." ]
+ * domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
+ * toplabel = alpha | alpha *( alphanum | "-" ) alphanum
+ */
+
+#ifdef NI_MAXHOST
+# define SI_HOSTNAME_MAXLEN NI_MAXHOST
+#else
+# ifdef MAXHOSTNAMELEN
+# define SI_HOSTNAME_MAXLEN MAXHOSTNAMELEN
+# else
+# define SI_HOSTNAME_MAXLEN 256
+# endif
+#endif
+
+static Bool
+siHostnameAddrMatch(int family, pointer addr, int len,
+ const char *siAddr, int siAddrLen, ClientPtr client, void *typePriv)
+{
+ Bool res = FALSE;
+
+/* Currently only supports checking against IPv4 & IPv6 connections, but
+ * support for other address families, such as DECnet, could be added if
+ * desired.
+ */
+#if defined(IPv6) && defined(AF_INET6)
+ if ((family == FamilyInternet) || (family == FamilyInternet6)) {
+ char hostname[SI_HOSTNAME_MAXLEN];
+ struct addrinfo *addresses;
+ struct addrinfo *a;
+ int f, hostaddrlen;
+ pointer hostaddr;
+
+ if (siAddrLen >= sizeof(hostname))
+ return FALSE;
+
+ strncpy(hostname, siAddr, siAddrLen);
+ hostname[siAddrLen] = '\0';
+
+ if (getaddrinfo(hostname, NULL, NULL, &addresses) == 0) {
+ for (a = addresses ; a != NULL ; a = a->ai_next) {
+ hostaddrlen = a->ai_addrlen;
+ f = ConvertAddr(a->ai_addr,&hostaddrlen,&hostaddr);
+ if ((f == family) && (len == hostaddrlen) &&
+ (acmp (addr, hostaddr, len) == 0) ) {
+ res = TRUE;
+ break;
+ }
+ }
+ freeaddrinfo(addresses);
+ }
+ }
+#else /* IPv6 not supported, use gethostbyname instead for IPv4 */
+ if (family == FamilyInternet) {
+ register struct hostent *hp;
+#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
+ _Xgethostbynameparams hparams;
+#endif
+ char hostname[SI_HOSTNAME_MAXLEN];
+ int f, hostaddrlen;
+ pointer hostaddr;
+ const char **addrlist;
+
+ if (siAddrLen >= sizeof(hostname))
+ return FALSE;
+
+ strncpy(hostname, siAddr, siAddrLen);
+ hostname[siAddrLen] = '\0';
+
+ if ((hp = _XGethostbyname(hostname, hparams)) != NULL) {
+#ifdef h_addr /* new 4.3bsd version of gethostent */
+ /* iterate over the addresses */
+ for (addrlist = hp->h_addr_list; *addrlist; addrlist++)
+#else
+ addrlist = &hp->h_addr;
+#endif
+ {
+ struct sockaddr_in sin;
+
+ sin.sin_family = hp->h_addrtype;
+ acopy ( *addrlist, &(sin.sin_addr), hp->h_length);
+ hostaddrlen = sizeof(sin);
+ f = ConvertAddr ((struct sockaddr *)&sin,
+ &hostaddrlen, &hostaddr);
+ if ((f == family) && (len == hostaddrlen) &&
+ (acmp (addr, hostaddr, len) == 0) ) {
+ res = TRUE;
+ break;
+ }
+ }
+ }
+ }
+#endif
+ return res;
+}
+
+
+static int
+siHostnameCheckAddr(const char *valueString, int length, void *typePriv)
+{
+ /* Check conformance of hostname to RFC 2396 sec. 3.2.2 definition.
+ * We do not use ctype functions here to avoid locale-specific
+ * character sets. Hostnames must be pure ASCII.
+ */
+ int len = length;
+ int i;
+ Bool dotAllowed = FALSE;
+ Bool dashAllowed = FALSE;
+
+ if ((length <= 0) || (length >= SI_HOSTNAME_MAXLEN)) {
+ len = -1;
+ } else {
+ for (i = 0; i < length; i++) {
+ char c = valueString[i];
+
+ if (c == 0x2E) { /* '.' */
+ if (dotAllowed == FALSE) {
+ len = -1;
+ break;
+ } else {
+ dotAllowed = FALSE;
+ dashAllowed = FALSE;
+ }
+ } else if (c == 0x2D) { /* '-' */
+ if (dashAllowed == FALSE) {
+ len = -1;
+ break;
+ } else {
+ dotAllowed = FALSE;
+ }
+ } else if (((c >= 0x30) && (c <= 0x3A)) /* 0-9 */ ||
+ ((c >= 0x61) && (c <= 0x7A)) /* a-z */ ||
+ ((c >= 0x41) && (c <= 0x5A)) /* A-Z */) {
+ dotAllowed = TRUE;
+ dashAllowed = TRUE;
+ } else { /* Invalid character */
+ len = -1;
+ break;
+ }
+ }
+ }
+ return len;
+}
+
+#if defined(IPv6) && defined(AF_INET6)
+/***
+ * "ipv6" server interpreted type
+ *
+ * Currently supports only IPv6 literal address as specified in IETF RFC 3513
+ *
+ * Once draft-ietf-ipv6-scoping-arch-00.txt becomes an RFC, support will be
+ * added for the scoped address format it specifies.
+ */
+
+/* Maximum length of an IPv6 address string - increase when adding support
+ * for scoped address qualifiers. Includes room for trailing NUL byte.
+ */
+#define SI_IPv6_MAXLEN INET6_ADDRSTRLEN
+
+static Bool
+siIPv6AddrMatch(int family, pointer addr, int len,
+ const char *siAddr, int siAddrlen, ClientPtr client, void *typePriv)
+{
+ struct in6_addr addr6;
+ char addrbuf[SI_IPv6_MAXLEN];
+
+ if ((family != FamilyInternet6) || (len != sizeof(addr6)))
+ return FALSE;
+
+ memcpy(addrbuf, siAddr, siAddrlen);
+ addrbuf[siAddrlen] = '\0';
+
+ if (inet_pton(AF_INET6, addrbuf, &addr6) != 1) {
+ perror("inet_pton");
+ return FALSE;
+ }
+
+ if (memcmp(addr, &addr6, len) == 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+static int
+siIPv6CheckAddr(const char *addrString, int length, void *typePriv)
+{
+ int len;
+
+ /* Minimum length is 3 (smallest legal address is "::1") */
+ if (length < 3) {
+ /* Address is too short! */
+ len = -1;
+ } else if (length >= SI_IPv6_MAXLEN) {
+ /* Address is too long! */
+ len = -1;
+ } else {
+ /* Assume inet_pton is sufficient validation */
+ struct in6_addr addr6;
+ char addrbuf[SI_IPv6_MAXLEN];
+
+ memcpy(addrbuf, addrString, length);
+ addrbuf[length] = '\0';
+
+ if (inet_pton(AF_INET6, addrbuf, &addr6) != 1) {
+ perror("inet_pton");
+ len = -1;
+ } else {
+ len = length;
+ }
+ }
+ return len;
+}
+#endif /* IPv6 */
+
+#if !defined(NO_LOCAL_CLIENT_CRED)
+/***
+ * "localuser" & "localgroup" server interpreted types
+ *
+ * Allows local connections from a given local user or group
+ */
+
+#include <pwd.h>
+#include <grp.h>
+
+#define LOCAL_USER 1
+#define LOCAL_GROUP 2
+
+typedef struct {
+ int credType;
+} siLocalCredPrivRec, *siLocalCredPrivPtr;
+
+static siLocalCredPrivRec siLocalUserPriv = { LOCAL_USER };
+static siLocalCredPrivRec siLocalGroupPriv = { LOCAL_GROUP };
+
+static Bool
+siLocalCredGetId(const char *addr, int len, siLocalCredPrivPtr lcPriv, int *id)
+{
+ Bool parsedOK = FALSE;
+ char *addrbuf = malloc(len + 1);
+
+ if (addrbuf == NULL) {
+ return FALSE;
+ }
+
+ memcpy(addrbuf, addr, len);
+ addrbuf[len] = '\0';
+
+ if (addr[0] == '#') { /* numeric id */
+ char *cp;
+ errno = 0;
+ *id = strtol(addrbuf + 1, &cp, 0);
+ if ((errno == 0) && (cp != (addrbuf+1))) {
+ parsedOK = TRUE;
+ }
+ } else { /* non-numeric name */
+ if (lcPriv->credType == LOCAL_USER) {
+ struct passwd *pw = getpwnam(addrbuf);
+
+ if (pw != NULL) {
+ *id = (int) pw->pw_uid;
+ parsedOK = TRUE;
+ }
+ } else { /* group */
+ struct group *gr = getgrnam(addrbuf);
+
+ if (gr != NULL) {
+ *id = (int) gr->gr_gid;
+ parsedOK = TRUE;
+ }
+ }
+ }
+
+ free(addrbuf);
+ return parsedOK;
+}
+
+static Bool
+siLocalCredAddrMatch(int family, pointer addr, int len,
+ const char *siAddr, int siAddrlen, ClientPtr client, void *typePriv)
+{
+ int siAddrId;
+ LocalClientCredRec *lcc;
+ siLocalCredPrivPtr lcPriv = (siLocalCredPrivPtr) typePriv;
+
+ if (GetLocalClientCreds(client, &lcc) == -1) {
+ return FALSE;
+ }
+
+#ifdef HAVE_GETZONEID /* Ensure process is in the same zone */
+ if ((lcc->fieldsSet & LCC_ZID_SET) && (lcc->zoneid != getzoneid())) {
+ FreeLocalClientCreds(lcc);
+ return FALSE;
+ }
+#endif
+
+ if (siLocalCredGetId(siAddr, siAddrlen, lcPriv, &siAddrId) == FALSE) {
+ FreeLocalClientCreds(lcc);
+ return FALSE;
+ }
+
+ if (lcPriv->credType == LOCAL_USER) {
+ if ((lcc->fieldsSet & LCC_UID_SET) && (lcc->euid == siAddrId)) {
+ FreeLocalClientCreds(lcc);
+ return TRUE;
+ }
+ } else {
+ if ((lcc->fieldsSet & LCC_GID_SET) && (lcc->egid == siAddrId)) {
+ FreeLocalClientCreds(lcc);
+ return TRUE;
+ }
+ if (lcc->pSuppGids != NULL) {
+ int i;
+
+ for (i = 0 ; i < lcc->nSuppGids; i++) {
+ if (lcc->pSuppGids[i] == siAddrId) {
+ FreeLocalClientCreds(lcc);
+ return TRUE;
+ }
+ }
+ }
+ }
+ FreeLocalClientCreds(lcc);
+ return FALSE;
+}
+
+static int
+siLocalCredCheckAddr(const char *addrString, int length, void *typePriv)
+{
+ int len = length;
+ int id;
+
+ if (siLocalCredGetId(addrString, length,
+ (siLocalCredPrivPtr)typePriv, &id) == FALSE) {
+ len = -1;
+ }
+ return len;
+}
+#endif /* localuser */
+
+static void
+siTypesInitialize(void)
+{
+ siTypeAdd("hostname", siHostnameAddrMatch, siHostnameCheckAddr, NULL);
+#if defined(IPv6) && defined(AF_INET6)
+ siTypeAdd("ipv6", siIPv6AddrMatch, siIPv6CheckAddr, NULL);
+#endif
+#if !defined(NO_LOCAL_CLIENT_CRED)
+ siTypeAdd("localuser", siLocalCredAddrMatch, siLocalCredCheckAddr,
+ &siLocalUserPriv);
+ siTypeAdd("localgroup", siLocalCredAddrMatch, siLocalCredCheckAddr,
+ &siLocalGroupPriv);
+#endif
+}
diff --git a/xorg-server/os/connection.c b/xorg-server/os/connection.c
index 8026423f7..4eb2c15c7 100644
--- a/xorg-server/os/connection.c
+++ b/xorg-server/os/connection.c
@@ -746,6 +746,7 @@ AllocNewConnection (XtransConnInfo trans_conn, int fd, CARD32 conn_time)
free(oc);
return NullClient;
}
+ oc->local_client = ComputeLocalClient(client);
#if !defined(WIN32)
ConnectionTranslation[fd] = client->index;
#else
diff --git a/xorg-server/os/osdep.h b/xorg-server/os/osdep.h
index 491a746d4..d7756b67a 100644
--- a/xorg-server/os/osdep.h
+++ b/xorg-server/os/osdep.h
@@ -172,6 +172,7 @@ typedef struct _osComm {
XID auth_id; /* authorization id */
CARD32 conn_time; /* timestamp if not established, else 0 */
struct _XtransConnInfo *trans_conn; /* transport connection object */
+ Bool local_client;
} OsCommRec, *OsCommPtr;
extern int FlushClient(
@@ -217,6 +218,9 @@ typedef long int fd_mask;
#define ffs mffs
extern int mffs(fd_mask);
+/* in access.c */
+extern Bool ComputeLocalClient(ClientPtr client);
+
/* in auth.c */
extern void GenerateRandomData (int len, char *buf);
diff --git a/xorg-server/render/animcur.c b/xorg-server/render/animcur.c
index 505c65c18..fddd9f81b 100644
--- a/xorg-server/render/animcur.c
+++ b/xorg-server/render/animcur.c
@@ -95,8 +95,6 @@ AnimCurCloseScreen (int index, ScreenPtr pScreen)
Bool ret;
Unwrap(as, pScreen, CloseScreen);
-
- Unwrap(as, pScreen, BlockHandler);
Unwrap(as, pScreen, CursorLimits);
Unwrap(as, pScreen, DisplayCursor);
@@ -150,6 +148,7 @@ AnimCurScreenBlockHandler (int screenNum,
ScreenPtr pScreen = screenInfo.screens[screenNum];
AnimCurScreenPtr as = GetAnimCurScreen(pScreen);
DeviceIntPtr dev;
+ Bool activeDevice = FALSE;
CARD32 now = 0,
soonest = ~0; /* earliest time to wakeup again */
@@ -157,7 +156,10 @@ AnimCurScreenBlockHandler (int screenNum,
{
if (IsPointerDevice(dev) && pScreen == dev->spriteInfo->anim.pScreen)
{
- if (!now) now = GetTimeInMillis ();
+ if (!activeDevice) {
+ now = GetTimeInMillis ();
+ activeDevice = TRUE;
+ }
if ((INT32) (now - dev->spriteInfo->anim.time) >= 0)
{
@@ -187,12 +189,15 @@ AnimCurScreenBlockHandler (int screenNum,
}
}
- if (now)
+ if (activeDevice)
AdjustWaitForDelay (pTimeout, soonest - now);
Unwrap (as, pScreen, BlockHandler);
(*pScreen->BlockHandler) (screenNum, blockData, pTimeout, pReadmask);
- Wrap (as, pScreen, BlockHandler, AnimCurScreenBlockHandler);
+ if (activeDevice)
+ Wrap (as, pScreen, BlockHandler, AnimCurScreenBlockHandler);
+ else
+ as->BlockHandler = NULL;
}
static Bool
@@ -218,6 +223,9 @@ AnimCurDisplayCursor (DeviceIntPtr pDev,
pDev->spriteInfo->anim.time = GetTimeInMillis () + ac->elts[0].delay;
pDev->spriteInfo->anim.pCursor = pCursor;
pDev->spriteInfo->anim.pScreen = pScreen;
+
+ if (!as->BlockHandler)
+ Wrap(as, pScreen, BlockHandler, AnimCurScreenBlockHandler);
}
}
else
@@ -244,8 +252,12 @@ AnimCurSetCursorPosition (DeviceIntPtr pDev,
Bool ret;
Unwrap (as, pScreen, SetCursorPosition);
- if (pDev->spriteInfo->anim.pCursor)
+ if (pDev->spriteInfo->anim.pCursor) {
pDev->spriteInfo->anim.pScreen = pScreen;
+
+ if (!as->BlockHandler)
+ Wrap(as, pScreen, BlockHandler, AnimCurScreenBlockHandler);
+ }
ret = (*pScreen->SetCursorPosition) (pDev, pScreen, x, y, generateEvent);
Wrap (as, pScreen, SetCursorPosition, AnimCurSetCursorPosition);
return ret;
@@ -330,7 +342,7 @@ AnimCurInit (ScreenPtr pScreen)
return FALSE;
Wrap(as, pScreen, CloseScreen, AnimCurCloseScreen);
- Wrap(as, pScreen, BlockHandler, AnimCurScreenBlockHandler);
+ as->BlockHandler = NULL;
Wrap(as, pScreen, CursorLimits, AnimCurCursorLimits);
Wrap(as, pScreen, DisplayCursor, AnimCurDisplayCursor);
diff --git a/xorg-server/render/mipict.c b/xorg-server/render/mipict.c
index 0f8076243..56d874e25 100644
--- a/xorg-server/render/mipict.c
+++ b/xorg-server/render/mipict.c
@@ -386,7 +386,8 @@ miCompositeSourceValidate (PicturePtr pPicture,
}
x += pPicture->pDrawable->x;
y += pPicture->pDrawable->y;
- (*pScreen->SourceValidate) (pDrawable, x, y, width, height);
+ (*pScreen->SourceValidate) (pDrawable, x, y, width, height,
+ pPicture->subWindowMode);
}
}