vmwarectrl.c revision 2e8abef9
16df26cacSmrg/*
26df26cacSmrg * Copyright 2006 by VMware, Inc.
36df26cacSmrg *
46df26cacSmrg * Permission is hereby granted, free of charge, to any person obtaining a
56df26cacSmrg * copy of this software and associated documentation files (the "Software"),
66df26cacSmrg * to deal in the Software without restriction, including without limitation
76df26cacSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
86df26cacSmrg * and/or sell copies of the Software, and to permit persons to whom the
96df26cacSmrg * Software is furnished to do so, subject to the following conditions:
106df26cacSmrg *
116df26cacSmrg * The above copyright notice and this permission notice shall be included in
126df26cacSmrg * all copies or substantial portions of the Software.
136df26cacSmrg *
146df26cacSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
156df26cacSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
166df26cacSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
176df26cacSmrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
186df26cacSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
196df26cacSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
206df26cacSmrg * OTHER DEALINGS IN THE SOFTWARE.
216df26cacSmrg *
226df26cacSmrg * Except as contained in this notice, the name of the copyright holder(s)
236df26cacSmrg * and author(s) shall not be used in advertising or otherwise to promote
246df26cacSmrg * the sale, use or other dealings in this Software without prior written
256df26cacSmrg * authorization from the copyright holder(s) and author(s).
266df26cacSmrg */
276df26cacSmrg
286df26cacSmrg/*
296df26cacSmrg * vmwarectrl.c --
306df26cacSmrg *
316df26cacSmrg *      The implementation of the VMWARE_CTRL protocol extension that
326df26cacSmrg *      allows X clients to communicate with the driver.
336df26cacSmrg */
346df26cacSmrg
356df26cacSmrg
366df26cacSmrg#ifdef HAVE_CONFIG_H
376df26cacSmrg#include "config.h"
386df26cacSmrg#endif
396df26cacSmrg
406df26cacSmrg#define NEED_REPLIES
416df26cacSmrg#define NEED_EVENTS
426df26cacSmrg#include "dixstruct.h"
436df26cacSmrg#include "extnsionst.h"
446df26cacSmrg#include <X11/X.h>
456df26cacSmrg#include <X11/extensions/panoramiXproto.h>
466df26cacSmrg
476df26cacSmrg#include "vmware.h"
486df26cacSmrg#include "vmwarectrlproto.h"
496df26cacSmrg
506df26cacSmrg
516df26cacSmrg/*
526df26cacSmrg *----------------------------------------------------------------------------
536df26cacSmrg *
546df26cacSmrg * VMwareCtrlQueryVersion --
556df26cacSmrg *
566df26cacSmrg *      Implementation of QueryVersion command handler. Initialises and
576df26cacSmrg *      sends a reply.
586df26cacSmrg *
596df26cacSmrg * Results:
606df26cacSmrg *      Standard response codes.
616df26cacSmrg *
626df26cacSmrg * Side effects:
636df26cacSmrg *      Writes reply to client
646df26cacSmrg *
656df26cacSmrg *----------------------------------------------------------------------------
666df26cacSmrg */
676df26cacSmrg
686df26cacSmrgstatic int
696df26cacSmrgVMwareCtrlQueryVersion(ClientPtr client)
706df26cacSmrg{
716df26cacSmrg   xVMwareCtrlQueryVersionReply rep = { 0, };
726df26cacSmrg   register int n;
736df26cacSmrg
746df26cacSmrg   REQUEST_SIZE_MATCH(xVMwareCtrlQueryVersionReq);
756df26cacSmrg
766df26cacSmrg   rep.type = X_Reply;
776df26cacSmrg   rep.length = 0;
786df26cacSmrg   rep.sequenceNumber = client->sequence;
796df26cacSmrg   rep.majorVersion = VMWARE_CTRL_MAJOR_VERSION;
806df26cacSmrg   rep.minorVersion = VMWARE_CTRL_MINOR_VERSION;
816df26cacSmrg   if (client->swapped) {
826df26cacSmrg      swaps(&rep.sequenceNumber, n);
836df26cacSmrg      swapl(&rep.length, n);
846df26cacSmrg      swapl(&rep.majorVersion, n);
856df26cacSmrg      swapl(&rep.minorVersion, n);
866df26cacSmrg   }
876df26cacSmrg   WriteToClient(client, sizeof(xVMwareCtrlQueryVersionReply), (char *)&rep);
886df26cacSmrg
896df26cacSmrg   return client->noClientException;
906df26cacSmrg}
916df26cacSmrg
926df26cacSmrg
936df26cacSmrg/*
946df26cacSmrg *----------------------------------------------------------------------------
956df26cacSmrg *
966df26cacSmrg * VMwareCtrlDoSetRes --
976df26cacSmrg *
986df26cacSmrg *      Set the custom resolution into the mode list.
996df26cacSmrg *
1006df26cacSmrg *      This is done by alternately updating one of two dynamic modes. It is
1016df26cacSmrg *      done this way because the server gets upset if you try to switch
1026df26cacSmrg *      to a new resolution that has the same index as the current one.
1036df26cacSmrg *
1046df26cacSmrg * Results:
1056df26cacSmrg *      TRUE on success, FALSE otherwise.
1066df26cacSmrg *
1076df26cacSmrg * Side effects:
1086df26cacSmrg *      One dynamic mode will be updated if successful.
1096df26cacSmrg *
1106df26cacSmrg *----------------------------------------------------------------------------
1116df26cacSmrg */
1126df26cacSmrg
1136df26cacSmrgstatic Bool
1146df26cacSmrgVMwareCtrlDoSetRes(ScrnInfoPtr pScrn,
1156df26cacSmrg                   CARD32 x,
1166df26cacSmrg                   CARD32 y,
1176df26cacSmrg                   Bool resetXinerama)
1186df26cacSmrg{
11916fd1166Smrg   int modeIndex;
1206df26cacSmrg   DisplayModePtr mode;
1216df26cacSmrg   VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
1226df26cacSmrg
1236df26cacSmrg   if (pScrn && pScrn->modes) {
1246df26cacSmrg      VmwareLog(("DoSetRes: %d %d\n", x, y));
12516fd1166Smrg
1266df26cacSmrg      if (resetXinerama) {
1276df26cacSmrg         xfree(pVMWARE->xineramaNextState);
1286df26cacSmrg         pVMWARE->xineramaNextState = NULL;
1296df26cacSmrg         pVMWARE->xineramaNextNumOutputs = 0;
1306df26cacSmrg      }
1316df26cacSmrg
13216fd1166Smrg      /*
1336df26cacSmrg       * Don't resize larger than possible but don't
1346df26cacSmrg       * return an X Error either.
1356df26cacSmrg       */
1366df26cacSmrg      if (x > pVMWARE->maxWidth ||
1376df26cacSmrg          y > pVMWARE->maxHeight) {
1386df26cacSmrg         return TRUE;
1396df26cacSmrg      }
1406df26cacSmrg
1416df26cacSmrg      /*
14216fd1166Smrg       * Find an dynamic mode which isn't current, and replace it with
14316fd1166Smrg       * the requested mode. Normally this will cause us to alternate
14416fd1166Smrg       * between two dynamic mode slots, but there are some important
14516fd1166Smrg       * corner cases to consider. For example, adding the same mode
14616fd1166Smrg       * multiple times, adding a mode that we never switch to, or
14716fd1166Smrg       * adding a mode which is a duplicate of a built-in mode. The
14816fd1166Smrg       * best way to handle all of these cases is to directly test the
14916fd1166Smrg       * dynamic mode against the current mode pointer for this
15016fd1166Smrg       * screen.
1516df26cacSmrg       */
1526df26cacSmrg
15316fd1166Smrg      for (modeIndex = 0; modeIndex < NUM_DYN_MODES; modeIndex++) {
15416fd1166Smrg         /*
15516fd1166Smrg          * Initialise the dynamic mode if it hasn't been used before.
15616fd1166Smrg          */
15716fd1166Smrg         if (!pVMWARE->dynModes[modeIndex]) {
15816fd1166Smrg            pVMWARE->dynModes[modeIndex] = VMWAREAddDisplayMode(pScrn, "DynMode", 1, 1);
15916fd1166Smrg         }
16016fd1166Smrg
16116fd1166Smrg         mode = pVMWARE->dynModes[modeIndex];
16216fd1166Smrg         if (mode != pScrn->currentMode) {
16316fd1166Smrg            break;
16416fd1166Smrg         }
1656df26cacSmrg      }
1666df26cacSmrg
1676df26cacSmrg      mode->HDisplay = x;
1686df26cacSmrg      mode->VDisplay = y;
1696df26cacSmrg
1706df26cacSmrg      return TRUE;
1716df26cacSmrg   } else {
1726df26cacSmrg      return FALSE;
1736df26cacSmrg   }
1746df26cacSmrg}
1756df26cacSmrg
1766df26cacSmrg
1776df26cacSmrg/*
1786df26cacSmrg *----------------------------------------------------------------------------
1796df26cacSmrg *
1806df26cacSmrg * VMwareCtrlSetRes --
1816df26cacSmrg *
1826df26cacSmrg *      Implementation of SetRes command handler. Initialises and sends a
1836df26cacSmrg *      reply.
1846df26cacSmrg *
1856df26cacSmrg * Results:
1866df26cacSmrg *      Standard response codes.
1876df26cacSmrg *
1886df26cacSmrg * Side effects:
1896df26cacSmrg *      Writes reply to client
1906df26cacSmrg *
1916df26cacSmrg *----------------------------------------------------------------------------
1926df26cacSmrg */
1936df26cacSmrg
1946df26cacSmrgstatic int
1956df26cacSmrgVMwareCtrlSetRes(ClientPtr client)
1966df26cacSmrg{
1976df26cacSmrg   REQUEST(xVMwareCtrlSetResReq);
1986df26cacSmrg   xVMwareCtrlSetResReply rep = { 0, };
1996df26cacSmrg   ScrnInfoPtr pScrn;
2006df26cacSmrg   ExtensionEntry *ext;
2016df26cacSmrg   register int n;
2026df26cacSmrg
2036df26cacSmrg   REQUEST_SIZE_MATCH(xVMwareCtrlSetResReq);
2046df26cacSmrg
2056df26cacSmrg   if (!(ext = CheckExtension(VMWARE_CTRL_PROTOCOL_NAME))) {
2066df26cacSmrg      return BadMatch;
2076df26cacSmrg   }
2086df26cacSmrg
2096df26cacSmrg   pScrn = ext->extPrivate;
2106df26cacSmrg   if (pScrn->scrnIndex != stuff->screen) {
2116df26cacSmrg      return BadMatch;
2126df26cacSmrg   }
2136df26cacSmrg
2146df26cacSmrg   if (!VMwareCtrlDoSetRes(pScrn, stuff->x, stuff->y, TRUE)) {
2156df26cacSmrg      return BadValue;
2166df26cacSmrg   }
2176df26cacSmrg
2186df26cacSmrg   rep.type = X_Reply;
2196df26cacSmrg   rep.length = (sizeof(xVMwareCtrlSetResReply) - sizeof(xGenericReply)) >> 2;
2206df26cacSmrg   rep.sequenceNumber = client->sequence;
2216df26cacSmrg   rep.screen = stuff->screen;
2226df26cacSmrg   rep.x = stuff->x;
2236df26cacSmrg   rep.y = stuff->y;
2246df26cacSmrg   if (client->swapped) {
2256df26cacSmrg      swaps(&rep.sequenceNumber, n);
2266df26cacSmrg      swapl(&rep.length, n);
2276df26cacSmrg      swapl(&rep.screen, n);
2286df26cacSmrg      swapl(&rep.x, n);
2296df26cacSmrg      swapl(&rep.y, n);
2306df26cacSmrg   }
2316df26cacSmrg   WriteToClient(client, sizeof(xVMwareCtrlSetResReply), (char *)&rep);
2326df26cacSmrg
2336df26cacSmrg   return client->noClientException;
2346df26cacSmrg}
2356df26cacSmrg
2366df26cacSmrg
2376df26cacSmrg/*
2386df26cacSmrg *----------------------------------------------------------------------------
2396df26cacSmrg *
2406df26cacSmrg * VMwareCtrlDoSetTopology --
2416df26cacSmrg *
2426df26cacSmrg *      Set the custom topology and set a dynamic mode to the bounding box
2436df26cacSmrg *      of the passed topology. If a topology is already pending, then do
2446df26cacSmrg *      nothing but do not return failure.
2456df26cacSmrg *
2466df26cacSmrg * Results:
2476df26cacSmrg *      TRUE on success, FALSE otherwise.
2486df26cacSmrg *
2496df26cacSmrg * Side effects:
2506df26cacSmrg *      One dynamic mode and the pending xinerama state will be updated if
2516df26cacSmrg *      successful.
2526df26cacSmrg *
2536df26cacSmrg *----------------------------------------------------------------------------
2546df26cacSmrg */
2556df26cacSmrg
2566df26cacSmrgstatic Bool
2576df26cacSmrgVMwareCtrlDoSetTopology(ScrnInfoPtr pScrn,
2586df26cacSmrg                        xXineramaScreenInfo *extents,
2596df26cacSmrg                        unsigned long number)
2606df26cacSmrg{
2616df26cacSmrg   VMWAREPtr pVMWARE = VMWAREPTR(pScrn);
2626df26cacSmrg
2636df26cacSmrg   if (pVMWARE && pVMWARE->xinerama) {
2646df26cacSmrg      VMWAREXineramaPtr xineramaState;
2656df26cacSmrg      short maxX = 0;
2666df26cacSmrg      short maxY = 0;
2676df26cacSmrg      size_t i;
2686df26cacSmrg
2696df26cacSmrg      if (pVMWARE->xineramaNextState) {
2706df26cacSmrg         VmwareLog(("DoSetTopology: Aborting due to existing pending state\n"));
2716df26cacSmrg         return TRUE;
2726df26cacSmrg      }
2736df26cacSmrg
2746df26cacSmrg      for (i = 0; i < number; i++) {
2756df26cacSmrg         maxX = MAX(maxX, extents[i].x_org + extents[i].width);
2766df26cacSmrg         maxY = MAX(maxY, extents[i].y_org + extents[i].height);
2776df26cacSmrg      }
2786df26cacSmrg
2796df26cacSmrg      VmwareLog(("DoSetTopology: %d %d\n", maxX, maxY));
2806df26cacSmrg
2816df26cacSmrg      xineramaState = (VMWAREXineramaPtr)xcalloc(number, sizeof(VMWAREXineramaRec));
2826df26cacSmrg      if (xineramaState) {
2836df26cacSmrg         memcpy(xineramaState, extents, number * sizeof (VMWAREXineramaRec));
2846df26cacSmrg
2852e8abef9Smrg         /*
2862e8abef9Smrg          * Make this the new pending Xinerama state. Normally we'll
2872e8abef9Smrg          * wait until the next mode switch in order to synchronously
2882e8abef9Smrg          * push this state out to X clients and the virtual hardware.
2892e8abef9Smrg          *
2902e8abef9Smrg          * However, if we're already in the right video mode, there
2912e8abef9Smrg          * will be no mode change. In this case, push it out
2922e8abef9Smrg          * immediately.
2932e8abef9Smrg          */
2946df26cacSmrg         xfree(pVMWARE->xineramaNextState);
2956df26cacSmrg         pVMWARE->xineramaNextState = xineramaState;
2966df26cacSmrg         pVMWARE->xineramaNextNumOutputs = number;
2976df26cacSmrg
2982e8abef9Smrg         if (maxX == pVMWARE->ModeReg.svga_reg_width &&
2992e8abef9Smrg             maxY == pVMWARE->ModeReg.svga_reg_height) {
3002e8abef9Smrg
3012e8abef9Smrg            /*
3022e8abef9Smrg             * XXX:
3032e8abef9Smrg             *
3042e8abef9Smrg             * There are problems with trying to set a Xinerama state
3052e8abef9Smrg             * without a mode switch. The biggest one is that
3062e8abef9Smrg             * applications typically won't notice a topology change
3072e8abef9Smrg             * that occurs without a mode switch. If you run "xdpyinfo
3082e8abef9Smrg             * -ext XINERAMA" after one such topology change, it will
3092e8abef9Smrg             * report the new data, but apps (like the GNOME Panel)
3102e8abef9Smrg             * will not notice until the next mode change.
3112e8abef9Smrg             *
3122e8abef9Smrg             * I don't think there's any good solution to this... as
3132e8abef9Smrg             * far as I know, even on a non-virtualized machine
3142e8abef9Smrg             * there's no way for an app to find out if the Xinerama
3152e8abef9Smrg             * opology changes without a resolution change also
3162e8abef9Smrg             * occurring. There might be some cheats we can take, like
3172e8abef9Smrg             * swithcing to a new mode with the same resolution and a
3182e8abef9Smrg             * different (fake) refresh rate, or temporarily switching
3192e8abef9Smrg             * to an intermediate mode. Ick.
3202e8abef9Smrg             *
3212e8abef9Smrg             * The other annoyance here is that when we reprogram the
3222e8abef9Smrg             * SVGA device's monitor topology registers, it may
3232e8abef9Smrg             * rearrange those monitors on the host's screen, but they
3242e8abef9Smrg             * will still have the old contents. This might be
3252e8abef9Smrg             * correct, but it isn't guaranteed to match what's on X's
3262e8abef9Smrg             * framebuffer at the moment. So we'll send a
3272e8abef9Smrg             * full-framebuffer update rect afterwards.
3282e8abef9Smrg             */
3292e8abef9Smrg
3302e8abef9Smrg            vmwareNextXineramaState(pVMWARE);
3312e8abef9Smrg            vmwareSendSVGACmdUpdateFullScreen(pVMWARE);
3322e8abef9Smrg
3332e8abef9Smrg            return TRUE;
3342e8abef9Smrg         } else {
3352e8abef9Smrg            return VMwareCtrlDoSetRes(pScrn, maxX, maxY, FALSE);
3362e8abef9Smrg         }
3372e8abef9Smrg
3386df26cacSmrg      } else {
3396df26cacSmrg         return FALSE;
3406df26cacSmrg      }
3416df26cacSmrg   } else {
3426df26cacSmrg      return FALSE;
3436df26cacSmrg   }
3446df26cacSmrg}
3456df26cacSmrg
3466df26cacSmrg
3476df26cacSmrg/*
3486df26cacSmrg *----------------------------------------------------------------------------
3496df26cacSmrg *
3506df26cacSmrg * VMwareCtrlSetTopology --
3516df26cacSmrg *
3526df26cacSmrg *      Implementation of SetTopology command handler. Initialises and sends a
3536df26cacSmrg *      reply.
3546df26cacSmrg *
3556df26cacSmrg * Results:
3566df26cacSmrg *      Standard response codes.
3576df26cacSmrg *
3586df26cacSmrg * Side effects:
3596df26cacSmrg *      Writes reply to client
3606df26cacSmrg *
3616df26cacSmrg *----------------------------------------------------------------------------
3626df26cacSmrg */
3636df26cacSmrg
3646df26cacSmrgstatic int
3656df26cacSmrgVMwareCtrlSetTopology(ClientPtr client)
3666df26cacSmrg{
3676df26cacSmrg   REQUEST(xVMwareCtrlSetTopologyReq);
3686df26cacSmrg   xVMwareCtrlSetTopologyReply rep = { 0, };
3696df26cacSmrg   ScrnInfoPtr pScrn;
3706df26cacSmrg   ExtensionEntry *ext;
3716df26cacSmrg   register int n;
3726df26cacSmrg   xXineramaScreenInfo *extents;
3736df26cacSmrg
3746df26cacSmrg   REQUEST_AT_LEAST_SIZE(xVMwareCtrlSetTopologyReq);
3756df26cacSmrg
3766df26cacSmrg   if (!(ext = CheckExtension(VMWARE_CTRL_PROTOCOL_NAME))) {
3776df26cacSmrg      return BadMatch;
3786df26cacSmrg   }
3796df26cacSmrg
3806df26cacSmrg   pScrn = ext->extPrivate;
3816df26cacSmrg   if (pScrn->scrnIndex != stuff->screen) {
3826df26cacSmrg      return BadMatch;
3836df26cacSmrg   }
3846df26cacSmrg
3856df26cacSmrg   extents = (xXineramaScreenInfo *)(stuff + 1);
3866df26cacSmrg   if (!VMwareCtrlDoSetTopology(pScrn, extents, stuff->number)) {
3876df26cacSmrg      return BadValue;
3886df26cacSmrg   }
3896df26cacSmrg
3906df26cacSmrg   rep.type = X_Reply;
3916df26cacSmrg   rep.length = (sizeof(xVMwareCtrlSetTopologyReply) - sizeof(xGenericReply)) >> 2;
3926df26cacSmrg   rep.sequenceNumber = client->sequence;
3936df26cacSmrg   rep.screen = stuff->screen;
3946df26cacSmrg   if (client->swapped) {
3956df26cacSmrg      swaps(&rep.sequenceNumber, n);
3966df26cacSmrg      swapl(&rep.length, n);
3976df26cacSmrg      swapl(&rep.screen, n);
3986df26cacSmrg   }
3996df26cacSmrg   WriteToClient(client, sizeof(xVMwareCtrlSetTopologyReply), (char *)&rep);
4006df26cacSmrg
4016df26cacSmrg   return client->noClientException;
4026df26cacSmrg}
4036df26cacSmrg
4046df26cacSmrg
4056df26cacSmrg/*
4066df26cacSmrg *----------------------------------------------------------------------------
4076df26cacSmrg *
4086df26cacSmrg * VMwareCtrlDispatch --
4096df26cacSmrg *
4106df26cacSmrg *      Dispatcher for VMWARE_CTRL commands. Calls the correct handler for
4116df26cacSmrg *      each command type.
4126df26cacSmrg *
4136df26cacSmrg * Results:
4146df26cacSmrg *      Standard response codes.
4156df26cacSmrg *
4166df26cacSmrg * Side effects:
4176df26cacSmrg *      Side effects of individual command handlers.
4186df26cacSmrg *
4196df26cacSmrg *----------------------------------------------------------------------------
4206df26cacSmrg */
4216df26cacSmrg
4226df26cacSmrgstatic int
4236df26cacSmrgVMwareCtrlDispatch(ClientPtr client)
4246df26cacSmrg{
4256df26cacSmrg   REQUEST(xReq);
4266df26cacSmrg
4276df26cacSmrg   switch(stuff->data) {
4286df26cacSmrg   case X_VMwareCtrlQueryVersion:
4296df26cacSmrg      return VMwareCtrlQueryVersion(client);
4306df26cacSmrg   case X_VMwareCtrlSetRes:
4316df26cacSmrg      return VMwareCtrlSetRes(client);
4326df26cacSmrg   case X_VMwareCtrlSetTopology:
4336df26cacSmrg      return VMwareCtrlSetTopology(client);
4346df26cacSmrg   }
4356df26cacSmrg   return BadRequest;
4366df26cacSmrg}
4376df26cacSmrg
4386df26cacSmrg
4396df26cacSmrg/*
4406df26cacSmrg *----------------------------------------------------------------------------
4416df26cacSmrg *
4426df26cacSmrg * SVMwareCtrlQueryVersion --
4436df26cacSmrg *
4446df26cacSmrg *      Wrapper for QueryVersion handler that handles input from other-endian
4456df26cacSmrg *      clients.
4466df26cacSmrg *
4476df26cacSmrg * Results:
4486df26cacSmrg *      Standard response codes.
4496df26cacSmrg *
4506df26cacSmrg * Side effects:
4516df26cacSmrg *      Side effects of unswapped implementation.
4526df26cacSmrg *
4536df26cacSmrg *----------------------------------------------------------------------------
4546df26cacSmrg */
4556df26cacSmrg
4566df26cacSmrgstatic int
4576df26cacSmrgSVMwareCtrlQueryVersion(ClientPtr client)
4586df26cacSmrg{
4596df26cacSmrg   register int n;
4606df26cacSmrg
4616df26cacSmrg   REQUEST(xVMwareCtrlQueryVersionReq);
4626df26cacSmrg   REQUEST_SIZE_MATCH(xVMwareCtrlQueryVersionReq);
4636df26cacSmrg
4646df26cacSmrg   swaps(&stuff->length, n);
4656df26cacSmrg
4666df26cacSmrg   return VMwareCtrlQueryVersion(client);
4676df26cacSmrg}
4686df26cacSmrg
4696df26cacSmrg
4706df26cacSmrg/*
4716df26cacSmrg *----------------------------------------------------------------------------
4726df26cacSmrg *
4736df26cacSmrg * SVMwareCtrlSetRes --
4746df26cacSmrg *
4756df26cacSmrg *      Wrapper for SetRes handler that handles input from other-endian
4766df26cacSmrg *      clients.
4776df26cacSmrg *
4786df26cacSmrg * Results:
4796df26cacSmrg *      Standard response codes.
4806df26cacSmrg *
4816df26cacSmrg * Side effects:
4826df26cacSmrg *      Side effects of unswapped implementation.
4836df26cacSmrg *
4846df26cacSmrg *----------------------------------------------------------------------------
4856df26cacSmrg */
4866df26cacSmrg
4876df26cacSmrgstatic int
4886df26cacSmrgSVMwareCtrlSetRes(ClientPtr client)
4896df26cacSmrg{
4906df26cacSmrg   register int n;
4916df26cacSmrg
4926df26cacSmrg   REQUEST(xVMwareCtrlSetResReq);
4936df26cacSmrg   REQUEST_SIZE_MATCH(xVMwareCtrlSetResReq);
4946df26cacSmrg
4956df26cacSmrg   swaps(&stuff->length, n);
4966df26cacSmrg   swapl(&stuff->screen, n);
4976df26cacSmrg   swapl(&stuff->x, n);
4986df26cacSmrg   swapl(&stuff->y, n);
4996df26cacSmrg
5006df26cacSmrg   return VMwareCtrlSetRes(client);
5016df26cacSmrg}
5026df26cacSmrg
5036df26cacSmrg
5046df26cacSmrg/*
5056df26cacSmrg *----------------------------------------------------------------------------
5066df26cacSmrg *
5076df26cacSmrg * SVMwareCtrlSetTopology --
5086df26cacSmrg *
5096df26cacSmrg *      Wrapper for SetTopology handler that handles input from other-endian
5106df26cacSmrg *      clients.
5116df26cacSmrg *
5126df26cacSmrg * Results:
5136df26cacSmrg *      Standard response codes.
5146df26cacSmrg *
5156df26cacSmrg * Side effects:
5166df26cacSmrg *      Side effects of unswapped implementation.
5176df26cacSmrg *
5186df26cacSmrg *----------------------------------------------------------------------------
5196df26cacSmrg */
5206df26cacSmrg
5216df26cacSmrgstatic int
5226df26cacSmrgSVMwareCtrlSetTopology(ClientPtr client)
5236df26cacSmrg{
5246df26cacSmrg   register int n;
5256df26cacSmrg
5266df26cacSmrg   REQUEST(xVMwareCtrlSetTopologyReq);
5276df26cacSmrg   REQUEST_SIZE_MATCH(xVMwareCtrlSetTopologyReq);
5286df26cacSmrg
5296df26cacSmrg   swaps(&stuff->length, n);
5306df26cacSmrg   swapl(&stuff->screen, n);
5316df26cacSmrg   swapl(&stuff->number, n);
5326df26cacSmrg   /* Each extent is a struct of shorts. */
5336df26cacSmrg   SwapRestS(stuff);
5346df26cacSmrg
5356df26cacSmrg   return VMwareCtrlSetTopology(client);
5366df26cacSmrg}
5376df26cacSmrg
5386df26cacSmrg
5396df26cacSmrg/*
5406df26cacSmrg *----------------------------------------------------------------------------
5416df26cacSmrg *
5426df26cacSmrg * SVMwareCtrlDispatch --
5436df26cacSmrg *
5446df26cacSmrg *      Wrapper for dispatcher that handles input from other-endian clients.
5456df26cacSmrg *
5466df26cacSmrg * Results:
5476df26cacSmrg *      Standard response codes.
5486df26cacSmrg *
5496df26cacSmrg * Side effects:
5506df26cacSmrg *      Side effects of individual command handlers.
5516df26cacSmrg *
5526df26cacSmrg *----------------------------------------------------------------------------
5536df26cacSmrg */
5546df26cacSmrg
5556df26cacSmrgstatic int
5566df26cacSmrgSVMwareCtrlDispatch(ClientPtr client)
5576df26cacSmrg{
5586df26cacSmrg   REQUEST(xReq);
5596df26cacSmrg
5606df26cacSmrg   switch(stuff->data) {
5616df26cacSmrg   case X_VMwareCtrlQueryVersion:
5626df26cacSmrg      return SVMwareCtrlQueryVersion(client);
5636df26cacSmrg   case X_VMwareCtrlSetRes:
5646df26cacSmrg      return SVMwareCtrlSetRes(client);
5656df26cacSmrg   case X_VMwareCtrlSetTopology:
5666df26cacSmrg      return SVMwareCtrlSetTopology(client);
5676df26cacSmrg   }
5686df26cacSmrg   return BadRequest;
5696df26cacSmrg}
5706df26cacSmrg
5716df26cacSmrg
5726df26cacSmrg/*
5736df26cacSmrg *----------------------------------------------------------------------------
5746df26cacSmrg *
5756df26cacSmrg * VMwareCtrlResetProc --
5766df26cacSmrg *
5776df26cacSmrg *      Cleanup handler called when the extension is removed.
5786df26cacSmrg *
5796df26cacSmrg * Results:
5806df26cacSmrg *      None
5816df26cacSmrg *
5826df26cacSmrg * Side effects:
5836df26cacSmrg *      None
5846df26cacSmrg *
5856df26cacSmrg *----------------------------------------------------------------------------
5866df26cacSmrg */
5876df26cacSmrg
5886df26cacSmrgstatic void
5896df26cacSmrgVMwareCtrlResetProc(ExtensionEntry* extEntry)
5906df26cacSmrg{
5916df26cacSmrg   /* Currently, no cleanup is necessary. */
5926df26cacSmrg}
5936df26cacSmrg
5946df26cacSmrg
5956df26cacSmrg/*
5966df26cacSmrg *----------------------------------------------------------------------------
5976df26cacSmrg *
5986df26cacSmrg * VMwareCtrl_ExitInit --
5996df26cacSmrg *
6006df26cacSmrg *      Initialiser for the VMWARE_CTRL protocol extension.
6016df26cacSmrg *
6026df26cacSmrg * Results:
6036df26cacSmrg *      None.
6046df26cacSmrg *
6056df26cacSmrg * Side effects:
6066df26cacSmrg *      Protocol extension will be registered if successful.
6076df26cacSmrg *
6086df26cacSmrg *----------------------------------------------------------------------------
6096df26cacSmrg */
6106df26cacSmrg
6116df26cacSmrgvoid
6126df26cacSmrgVMwareCtrl_ExtInit(ScrnInfoPtr pScrn)
6136df26cacSmrg{
6146df26cacSmrg   ExtensionEntry *myext;
6156df26cacSmrg
6166df26cacSmrg   if (!(myext = CheckExtension(VMWARE_CTRL_PROTOCOL_NAME))) {
6176df26cacSmrg      if (!(myext = AddExtension(VMWARE_CTRL_PROTOCOL_NAME, 0, 0,
6186df26cacSmrg                                 VMwareCtrlDispatch,
6196df26cacSmrg                                 SVMwareCtrlDispatch,
6206df26cacSmrg                                 VMwareCtrlResetProc,
6216df26cacSmrg                                 StandardMinorOpcode))) {
6226df26cacSmrg         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
6236df26cacSmrg                    "Failed to add VMWARE_CTRL extension\n");
6246df26cacSmrg	 return;
6256df26cacSmrg      }
6266df26cacSmrg
6276df26cacSmrg      /*
6286df26cacSmrg       * For now, only support one screen as that's all the virtual
6296df26cacSmrg       * hardware supports.
6306df26cacSmrg       */
6316df26cacSmrg      myext->extPrivate = pScrn;
6326df26cacSmrg
6336df26cacSmrg      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
6346df26cacSmrg                 "Initialized VMWARE_CTRL extension version %d.%d\n",
6356df26cacSmrg                 VMWARE_CTRL_MAJOR_VERSION, VMWARE_CTRL_MINOR_VERSION);
6366df26cacSmrg   }
6376df26cacSmrg}
638