1/************************************************************ 2 3Copyright 1989, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included in 12all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21Except as contained in this notice, the name of The Open Group shall not be 22used in advertising or otherwise to promote the sale, use or other dealings 23in this Software without prior written authorization from The Open Group. 24 25Copyright 1989 by Hewlett-Packard Company, Palo Alto, California. 26 27 All Rights Reserved 28 29Permission to use, copy, modify, and distribute this software and its 30documentation for any purpose and without fee is hereby granted, 31provided that the above copyright notice appear in all copies and that 32both that copyright notice and this permission notice appear in 33supporting documentation, and that the name of Hewlett-Packard not be 34used in advertising or publicity pertaining to distribution of the 35software without specific, written prior permission. 36 37HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 38ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 39HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 40ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 41WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 42ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 43SOFTWARE. 44 45********************************************************/ 46 47/******************************************************************** 48 * 49 * Change Device control attributes for an extension device. 50 * 51 */ 52 53#ifdef HAVE_DIX_CONFIG_H 54#include <dix-config.h> 55#endif 56 57#include "inputstr.h" /* DeviceIntPtr */ 58#include <X11/extensions/XI.h> 59#include <X11/extensions/XIproto.h> /* control constants */ 60#include "XIstubs.h" 61 62#include "exglobals.h" 63#include "exevents.h" 64 65#include "chgdctl.h" 66 67/*********************************************************************** 68 * 69 * This procedure changes the control attributes for an extension device, 70 * for clients on machines with a different byte ordering than the server. 71 * 72 */ 73 74int 75SProcXChangeDeviceControl(ClientPtr client) 76{ 77 char n; 78 xDeviceCtl *ctl; 79 xDeviceAbsCalibCtl *calib; 80 xDeviceAbsAreaCtl *area; 81 82 REQUEST(xChangeDeviceControlReq); 83 swaps(&stuff->length, n); 84 REQUEST_AT_LEAST_EXTRA_SIZE(xChangeDeviceControlReq, sizeof(xDeviceCtl)); 85 swaps(&stuff->control, n); 86 ctl = (xDeviceCtl*)&stuff[1]; 87 swaps(&ctl->control, n); 88 swaps(&ctl->length, n); 89 switch(stuff->control) { 90 case DEVICE_ABS_CALIB: 91 calib = (xDeviceAbsCalibCtl*)ctl; 92 swaps(&calib->length, n); 93 swapl(&calib->min_x, n); 94 swapl(&calib->max_x, n); 95 swapl(&calib->min_y, n); 96 swapl(&calib->max_y, n); 97 swapl(&calib->flip_x, n); 98 swapl(&calib->flip_y, n); 99 swapl(&calib->rotation, n); 100 swapl(&calib->button_threshold, n); 101 break; 102 case DEVICE_ABS_AREA: 103 area = (xDeviceAbsAreaCtl*)ctl; 104 swapl(&area->offset_x, n); 105 swapl(&area->offset_y, n); 106 swapl(&area->width, n); 107 swapl(&area->height, n); 108 swapl(&area->screen, n); 109 swapl(&area->following, n); 110 break; 111 case DEVICE_CORE: 112 case DEVICE_ENABLE: 113 case DEVICE_RESOLUTION: 114 /* hmm. beer. *drool* */ 115 break; 116 117 } 118 return (ProcXChangeDeviceControl(client)); 119} 120 121/*********************************************************************** 122 * 123 * Change the control attributes. 124 * 125 */ 126 127int 128ProcXChangeDeviceControl(ClientPtr client) 129{ 130 unsigned len; 131 int i, status, ret = BadValue; 132 DeviceIntPtr dev; 133 xDeviceResolutionCtl *r; 134 xChangeDeviceControlReply rep; 135 AxisInfoPtr a; 136 CARD32 *resolution; 137 xDeviceAbsCalibCtl *calib; 138 xDeviceAbsAreaCtl *area; 139 xDeviceEnableCtl *e; 140 devicePresenceNotify dpn; 141 142 REQUEST(xChangeDeviceControlReq); 143 REQUEST_AT_LEAST_EXTRA_SIZE(xChangeDeviceControlReq, sizeof(xDeviceCtl)); 144 145 len = stuff->length - bytes_to_int32(sizeof(xChangeDeviceControlReq)); 146 ret = dixLookupDevice(&dev, stuff->deviceid, client, DixManageAccess); 147 if (ret != Success) 148 goto out; 149 150 rep.repType = X_Reply; 151 rep.RepType = X_ChangeDeviceControl; 152 rep.length = 0; 153 rep.sequenceNumber = client->sequence; 154 155 switch (stuff->control) { 156 case DEVICE_RESOLUTION: 157 r = (xDeviceResolutionCtl *) & stuff[1]; 158 if ((len < bytes_to_int32(sizeof(xDeviceResolutionCtl))) || 159 (len != bytes_to_int32(sizeof(xDeviceResolutionCtl)) + r->num_valuators)) { 160 ret = BadLength; 161 goto out; 162 } 163 if (!dev->valuator) { 164 ret = BadMatch; 165 goto out; 166 } 167 if ((dev->deviceGrab.grab) && !SameClient(dev->deviceGrab.grab, client)) { 168 rep.status = AlreadyGrabbed; 169 ret = Success; 170 goto out; 171 } 172 resolution = (CARD32 *) (r + 1); 173 if (r->first_valuator + r->num_valuators > dev->valuator->numAxes) { 174 ret = BadValue; 175 goto out; 176 } 177 status = ChangeDeviceControl(client, dev, (xDeviceCtl *) r); 178 if (status == Success) { 179 a = &dev->valuator->axes[r->first_valuator]; 180 for (i = 0; i < r->num_valuators; i++) 181 if (*(resolution + i) < (a + i)->min_resolution || 182 *(resolution + i) > (a + i)->max_resolution) 183 return BadValue; 184 for (i = 0; i < r->num_valuators; i++) 185 (a++)->resolution = *resolution++; 186 187 ret = Success; 188 } else if (status == DeviceBusy) { 189 rep.status = DeviceBusy; 190 ret = Success; 191 } else { 192 ret = BadMatch; 193 } 194 break; 195 case DEVICE_ABS_CALIB: 196 calib = (xDeviceAbsCalibCtl *)&stuff[1]; 197 198 if (calib->button_threshold < 0 || calib->button_threshold > 255) { 199 ret = BadValue; 200 goto out; 201 } 202 203 status = ChangeDeviceControl(client, dev, (xDeviceCtl *) calib); 204 205 if (status == Success) { 206 dev->absolute->min_x = calib->min_x; 207 dev->absolute->max_x = calib->max_x; 208 dev->absolute->min_y = calib->min_y; 209 dev->absolute->max_y = calib->max_y; 210 dev->absolute->flip_x = calib->flip_x; 211 dev->absolute->flip_y = calib->flip_y; 212 dev->absolute->rotation = calib->rotation; 213 dev->absolute->button_threshold = calib->button_threshold; 214 ret = Success; 215 } else if (status == DeviceBusy || status == BadValue) { 216 rep.status = status; 217 ret = Success; 218 } else { 219 ret = BadMatch; 220 } 221 222 break; 223 case DEVICE_ABS_AREA: 224 area = (xDeviceAbsAreaCtl *)&stuff[1]; 225 226 status = ChangeDeviceControl(client, dev, (xDeviceCtl *) area); 227 228 if (status == Success) { 229 dev->absolute->offset_x = area->offset_x; 230 dev->absolute->offset_y = area->offset_y; 231 dev->absolute->width = area->width; 232 dev->absolute->height = area->height; 233 dev->absolute->screen = area->screen; 234 dev->absolute->following = area->following; 235 ret = Success; 236 } else if (status == DeviceBusy || status == BadValue) { 237 rep.status = status; 238 ret = Success; 239 } else { 240 ret = Success; 241 } 242 243 break; 244 case DEVICE_CORE: 245 /* Sorry, no device core switching no more. If you want a device to 246 * send core events, attach it to a master device */ 247 ret = BadMatch; 248 break; 249 case DEVICE_ENABLE: 250 e = (xDeviceEnableCtl *)&stuff[1]; 251 if ((len != bytes_to_int32(sizeof(xDeviceEnableCtl)))) { 252 ret = BadLength; 253 goto out; 254 } 255 256 status = ChangeDeviceControl(client, dev, (xDeviceCtl *) e); 257 258 if (status == Success) { 259 if (e->enable) 260 EnableDevice(dev, TRUE); 261 else 262 DisableDevice(dev, TRUE); 263 ret = Success; 264 } else if (status == DeviceBusy) { 265 rep.status = DeviceBusy; 266 ret = Success; 267 } else { 268 ret = BadMatch; 269 } 270 271 break; 272 default: 273 ret = BadValue; 274 } 275 276out: 277 if (ret == Success) { 278 dpn.type = DevicePresenceNotify; 279 dpn.time = currentTime.milliseconds; 280 dpn.devchange = DeviceControlChanged; 281 dpn.deviceid = dev->id; 282 dpn.control = stuff->control; 283 SendEventToAllWindows(dev, DevicePresenceNotifyMask, 284 (xEvent *) &dpn, 1); 285 286 WriteReplyToClient(client, sizeof(xChangeDeviceControlReply), &rep); 287 } 288 289 return ret; 290} 291 292/*********************************************************************** 293 * 294 * This procedure writes the reply for the xChangeDeviceControl function, 295 * if the client and server have a different byte ordering. 296 * 297 */ 298 299void 300SRepXChangeDeviceControl(ClientPtr client, int size, 301 xChangeDeviceControlReply * rep) 302{ 303 char n; 304 305 swaps(&rep->sequenceNumber, n); 306 swapl(&rep->length, n); 307 WriteToClient(client, size, (char *)rep); 308} 309