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 feedback 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 61#include "exglobals.h" 62 63#include "chgfctl.h" 64 65#define DO_ALL (-1) 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 75SProcXChangeFeedbackControl(ClientPtr client) 76{ 77 char n; 78 79 REQUEST(xChangeFeedbackControlReq); 80 swaps(&stuff->length, n); 81 REQUEST_AT_LEAST_SIZE(xChangeFeedbackControlReq); 82 swapl(&stuff->mask, n); 83 return (ProcXChangeFeedbackControl(client)); 84} 85 86/****************************************************************************** 87 * 88 * This procedure changes KbdFeedbackClass data. 89 * 90 */ 91 92static int 93ChangeKbdFeedback(ClientPtr client, DeviceIntPtr dev, long unsigned int mask, 94 KbdFeedbackPtr k, xKbdFeedbackCtl * f) 95{ 96 char n; 97 KeybdCtrl kctrl; 98 int t; 99 int key = DO_ALL; 100 101 if (client->swapped) { 102 swaps(&f->length, n); 103 swaps(&f->pitch, n); 104 swaps(&f->duration, n); 105 swapl(&f->led_mask, n); 106 swapl(&f->led_values, n); 107 } 108 109 kctrl = k->ctrl; 110 if (mask & DvKeyClickPercent) { 111 t = f->click; 112 if (t == -1) 113 t = defaultKeyboardControl.click; 114 else if (t < 0 || t > 100) { 115 client->errorValue = t; 116 return BadValue; 117 } 118 kctrl.click = t; 119 } 120 121 if (mask & DvPercent) { 122 t = f->percent; 123 if (t == -1) 124 t = defaultKeyboardControl.bell; 125 else if (t < 0 || t > 100) { 126 client->errorValue = t; 127 return BadValue; 128 } 129 kctrl.bell = t; 130 } 131 132 if (mask & DvPitch) { 133 t = f->pitch; 134 if (t == -1) 135 t = defaultKeyboardControl.bell_pitch; 136 else if (t < 0) { 137 client->errorValue = t; 138 return BadValue; 139 } 140 kctrl.bell_pitch = t; 141 } 142 143 if (mask & DvDuration) { 144 t = f->duration; 145 if (t == -1) 146 t = defaultKeyboardControl.bell_duration; 147 else if (t < 0) { 148 client->errorValue = t; 149 return BadValue; 150 } 151 kctrl.bell_duration = t; 152 } 153 154 if (mask & DvLed) { 155 kctrl.leds &= ~(f->led_mask); 156 kctrl.leds |= (f->led_mask & f->led_values); 157 } 158 159 if (mask & DvKey) { 160 key = (KeyCode) f->key; 161 if (key < 8 || key > 255) { 162 client->errorValue = key; 163 return BadValue; 164 } 165 if (!(mask & DvAutoRepeatMode)) 166 return BadMatch; 167 } 168 169 if (mask & DvAutoRepeatMode) { 170 int inx = (key >> 3); 171 int kmask = (1 << (key & 7)); 172 173 t = (CARD8) f->auto_repeat_mode; 174 if (t == AutoRepeatModeOff) { 175 if (key == DO_ALL) 176 kctrl.autoRepeat = FALSE; 177 else 178 kctrl.autoRepeats[inx] &= ~kmask; 179 } else if (t == AutoRepeatModeOn) { 180 if (key == DO_ALL) 181 kctrl.autoRepeat = TRUE; 182 else 183 kctrl.autoRepeats[inx] |= kmask; 184 } else if (t == AutoRepeatModeDefault) { 185 if (key == DO_ALL) 186 kctrl.autoRepeat = defaultKeyboardControl.autoRepeat; 187 else 188 kctrl.autoRepeats[inx] &= ~kmask; 189 kctrl.autoRepeats[inx] = 190 (kctrl.autoRepeats[inx] & ~kmask) | 191 (defaultKeyboardControl.autoRepeats[inx] & kmask); 192 } else { 193 client->errorValue = t; 194 return BadValue; 195 } 196 } 197 198 k->ctrl = kctrl; 199 (*k->CtrlProc) (dev, &k->ctrl); 200 return Success; 201} 202 203/****************************************************************************** 204 * 205 * This procedure changes PtrFeedbackClass data. 206 * 207 */ 208 209static int 210ChangePtrFeedback(ClientPtr client, DeviceIntPtr dev, long unsigned int mask, 211 PtrFeedbackPtr p, xPtrFeedbackCtl * f) 212{ 213 char n; 214 PtrCtrl pctrl; /* might get BadValue part way through */ 215 216 if (client->swapped) { 217 swaps(&f->length, n); 218 swaps(&f->num, n); 219 swaps(&f->denom, n); 220 swaps(&f->thresh, n); 221 } 222 223 pctrl = p->ctrl; 224 if (mask & DvAccelNum) { 225 int accelNum; 226 227 accelNum = f->num; 228 if (accelNum == -1) 229 pctrl.num = defaultPointerControl.num; 230 else if (accelNum < 0) { 231 client->errorValue = accelNum; 232 return BadValue; 233 } else 234 pctrl.num = accelNum; 235 } 236 237 if (mask & DvAccelDenom) { 238 int accelDenom; 239 240 accelDenom = f->denom; 241 if (accelDenom == -1) 242 pctrl.den = defaultPointerControl.den; 243 else if (accelDenom <= 0) { 244 client->errorValue = accelDenom; 245 return BadValue; 246 } else 247 pctrl.den = accelDenom; 248 } 249 250 if (mask & DvThreshold) { 251 int threshold; 252 253 threshold = f->thresh; 254 if (threshold == -1) 255 pctrl.threshold = defaultPointerControl.threshold; 256 else if (threshold < 0) { 257 client->errorValue = threshold; 258 return BadValue; 259 } else 260 pctrl.threshold = threshold; 261 } 262 263 p->ctrl = pctrl; 264 (*p->CtrlProc) (dev, &p->ctrl); 265 return Success; 266} 267 268/****************************************************************************** 269 * 270 * This procedure changes IntegerFeedbackClass data. 271 * 272 */ 273 274static int 275ChangeIntegerFeedback(ClientPtr client, DeviceIntPtr dev, 276 long unsigned int mask, IntegerFeedbackPtr i, 277 xIntegerFeedbackCtl * f) 278{ 279 char n; 280 281 if (client->swapped) { 282 swaps(&f->length, n); 283 swapl(&f->int_to_display, n); 284 } 285 286 i->ctrl.integer_displayed = f->int_to_display; 287 (*i->CtrlProc) (dev, &i->ctrl); 288 return Success; 289} 290 291/****************************************************************************** 292 * 293 * This procedure changes StringFeedbackClass data. 294 * 295 */ 296 297static int 298ChangeStringFeedback(ClientPtr client, DeviceIntPtr dev, 299 long unsigned int mask, StringFeedbackPtr s, 300 xStringFeedbackCtl * f) 301{ 302 char n; 303 int i, j; 304 KeySym *syms, *sup_syms; 305 306 syms = (KeySym *) (f + 1); 307 if (client->swapped) { 308 swaps(&f->length, n); /* swapped num_keysyms in calling proc */ 309 SwapLongs((CARD32 *) syms, f->num_keysyms); 310 } 311 312 if (f->num_keysyms > s->ctrl.max_symbols) 313 return BadValue; 314 315 sup_syms = s->ctrl.symbols_supported; 316 for (i = 0; i < f->num_keysyms; i++) { 317 for (j = 0; j < s->ctrl.num_symbols_supported; j++) 318 if (*(syms + i) == *(sup_syms + j)) 319 break; 320 if (j == s->ctrl.num_symbols_supported) 321 return BadMatch; 322 } 323 324 s->ctrl.num_symbols_displayed = f->num_keysyms; 325 for (i = 0; i < f->num_keysyms; i++) 326 *(s->ctrl.symbols_displayed + i) = *(syms + i); 327 (*s->CtrlProc) (dev, &s->ctrl); 328 return Success; 329} 330 331/****************************************************************************** 332 * 333 * This procedure changes BellFeedbackClass data. 334 * 335 */ 336 337static int 338ChangeBellFeedback(ClientPtr client, DeviceIntPtr dev, 339 long unsigned int mask, BellFeedbackPtr b, 340 xBellFeedbackCtl * f) 341{ 342 char n; 343 int t; 344 BellCtrl bctrl; /* might get BadValue part way through */ 345 346 if (client->swapped) { 347 swaps(&f->length, n); 348 swaps(&f->pitch, n); 349 swaps(&f->duration, n); 350 } 351 352 bctrl = b->ctrl; 353 if (mask & DvPercent) { 354 t = f->percent; 355 if (t == -1) 356 t = defaultKeyboardControl.bell; 357 else if (t < 0 || t > 100) { 358 client->errorValue = t; 359 return BadValue; 360 } 361 bctrl.percent = t; 362 } 363 364 if (mask & DvPitch) { 365 t = f->pitch; 366 if (t == -1) 367 t = defaultKeyboardControl.bell_pitch; 368 else if (t < 0) { 369 client->errorValue = t; 370 return BadValue; 371 } 372 bctrl.pitch = t; 373 } 374 375 if (mask & DvDuration) { 376 t = f->duration; 377 if (t == -1) 378 t = defaultKeyboardControl.bell_duration; 379 else if (t < 0) { 380 client->errorValue = t; 381 return BadValue; 382 } 383 bctrl.duration = t; 384 } 385 b->ctrl = bctrl; 386 (*b->CtrlProc) (dev, &b->ctrl); 387 return Success; 388} 389 390/****************************************************************************** 391 * 392 * This procedure changes LedFeedbackClass data. 393 * 394 */ 395 396static int 397ChangeLedFeedback(ClientPtr client, DeviceIntPtr dev, long unsigned int mask, 398 LedFeedbackPtr l, xLedFeedbackCtl * f) 399{ 400 char n; 401 LedCtrl lctrl; /* might get BadValue part way through */ 402 403 if (client->swapped) { 404 swaps(&f->length, n); 405 swapl(&f->led_values, n); 406 swapl(&f->led_mask, n); 407 } 408 409 f->led_mask &= l->ctrl.led_mask; /* set only supported leds */ 410 f->led_values &= l->ctrl.led_mask; /* set only supported leds */ 411 if (mask & DvLed) { 412 lctrl.led_mask = f->led_mask; 413 lctrl.led_values = f->led_values; 414 (*l->CtrlProc) (dev, &lctrl); 415 l->ctrl.led_values &= ~(f->led_mask); /* zero changed leds */ 416 l->ctrl.led_values |= (f->led_mask & f->led_values); /* OR in set leds */ 417 } 418 419 return Success; 420} 421 422/*********************************************************************** 423 * 424 * Change the control attributes. 425 * 426 */ 427 428int 429ProcXChangeFeedbackControl(ClientPtr client) 430{ 431 unsigned len; 432 DeviceIntPtr dev; 433 KbdFeedbackPtr k; 434 PtrFeedbackPtr p; 435 IntegerFeedbackPtr i; 436 StringFeedbackPtr s; 437 BellFeedbackPtr b; 438 LedFeedbackPtr l; 439 int rc; 440 441 REQUEST(xChangeFeedbackControlReq); 442 REQUEST_AT_LEAST_SIZE(xChangeFeedbackControlReq); 443 444 len = stuff->length - bytes_to_int32(sizeof(xChangeFeedbackControlReq)); 445 rc = dixLookupDevice(&dev, stuff->deviceid, client, DixManageAccess); 446 if (rc != Success) 447 return rc; 448 449 switch (stuff->feedbackid) { 450 case KbdFeedbackClass: 451 if (len != bytes_to_int32(sizeof(xKbdFeedbackCtl))) 452 return BadLength; 453 454 for (k = dev->kbdfeed; k; k = k->next) 455 if (k->ctrl.id == ((xKbdFeedbackCtl *) & stuff[1])->id) 456 return ChangeKbdFeedback(client, dev, stuff->mask, k, 457 (xKbdFeedbackCtl *) & stuff[1]); 458 break; 459 case PtrFeedbackClass: 460 if (len != bytes_to_int32(sizeof(xPtrFeedbackCtl))) 461 return BadLength; 462 463 for (p = dev->ptrfeed; p; p = p->next) 464 if (p->ctrl.id == ((xPtrFeedbackCtl *) & stuff[1])->id) 465 return ChangePtrFeedback(client, dev, stuff->mask, p, 466 (xPtrFeedbackCtl *) & stuff[1]); 467 break; 468 case StringFeedbackClass: 469 { 470 char n; 471 xStringFeedbackCtl *f; 472 473 REQUEST_AT_LEAST_EXTRA_SIZE(xChangeFeedbackControlReq, 474 sizeof(xStringFeedbackCtl)); 475 f = ((xStringFeedbackCtl *) &stuff[1]); 476 if (client->swapped) { 477 if (len < bytes_to_int32(sizeof(xStringFeedbackCtl))) 478 return BadLength; 479 swaps(&f->num_keysyms, n); 480 } 481 if (len != (bytes_to_int32(sizeof(xStringFeedbackCtl)) + f->num_keysyms)) 482 return BadLength; 483 484 for (s = dev->stringfeed; s; s = s->next) 485 if (s->ctrl.id == ((xStringFeedbackCtl *) & stuff[1])->id) 486 return ChangeStringFeedback(client, dev, stuff->mask, s, 487 (xStringFeedbackCtl *) & stuff[1]); 488 break; 489 } 490 case IntegerFeedbackClass: 491 if (len != bytes_to_int32(sizeof(xIntegerFeedbackCtl))) 492 return BadLength; 493 494 for (i = dev->intfeed; i; i = i->next) 495 if (i->ctrl.id == ((xIntegerFeedbackCtl *) & stuff[1])->id) 496 return ChangeIntegerFeedback(client, dev, stuff->mask, i, 497 (xIntegerFeedbackCtl *)&stuff[1]); 498 break; 499 case LedFeedbackClass: 500 if (len != bytes_to_int32(sizeof(xLedFeedbackCtl))) 501 return BadLength; 502 503 for (l = dev->leds; l; l = l->next) 504 if (l->ctrl.id == ((xLedFeedbackCtl *) & stuff[1])->id) 505 return ChangeLedFeedback(client, dev, stuff->mask, l, 506 (xLedFeedbackCtl *) & stuff[1]); 507 break; 508 case BellFeedbackClass: 509 if (len != bytes_to_int32(sizeof(xBellFeedbackCtl))) 510 return BadLength; 511 512 for (b = dev->bell; b; b = b->next) 513 if (b->ctrl.id == ((xBellFeedbackCtl *) & stuff[1])->id) 514 return ChangeBellFeedback(client, dev, stuff->mask, b, 515 (xBellFeedbackCtl *) & stuff[1]); 516 break; 517 default: 518 break; 519 } 520 521 return BadMatch; 522} 523 524