1/* 2 * Copyright © 2008 Daniel Stone 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 * 23 * Author: Daniel Stone <daniel@fooishbar.org> 24 */ 25 26#ifdef HAVE_DIX_CONFIG_H 27#include "dix-config.h" 28#endif 29 30#include "exevents.h" 31#include "exglobals.h" 32#include "misc.h" 33#include "input.h" 34#include "inputstr.h" 35#include "xace.h" 36#include "xkbsrv.h" 37#include "xkbstr.h" 38#include "inpututils.h" 39 40/* Check if a button map change is okay with the device. 41 * Returns -1 for BadValue, as it collides with MappingBusy. */ 42static int 43check_butmap_change(DeviceIntPtr dev, CARD8 *map, int len, CARD32 *errval_out, 44 ClientPtr client) 45{ 46 int i, ret; 47 48 if (!dev || !dev->button) 49 { 50 client->errorValue = (dev) ? dev->id : 0; 51 return BadDevice; 52 } 53 54 ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess); 55 if (ret != Success) 56 { 57 client->errorValue = dev->id; 58 return ret; 59 } 60 61 for (i = 0; i < len; i++) { 62 if (dev->button->map[i + 1] != map[i] && dev->button->down[i + 1]) 63 return MappingBusy; 64 } 65 66 return Success; 67} 68 69static void 70do_butmap_change(DeviceIntPtr dev, CARD8 *map, int len, ClientPtr client) 71{ 72 int i; 73 xEvent core_mn; 74 deviceMappingNotify xi_mn; 75 76 /* The map in ButtonClassRec refers to button numbers, whereas the 77 * protocol is zero-indexed. Sigh. */ 78 memcpy(&(dev->button->map[1]), map, len); 79 80 core_mn.u.u.type = MappingNotify; 81 core_mn.u.mappingNotify.request = MappingPointer; 82 83 /* 0 is the server client. */ 84 for (i = 1; i < currentMaxClients; i++) { 85 /* Don't send irrelevant events to naïve clients. */ 86 if (!clients[i] || clients[i]->clientState != ClientStateRunning) 87 continue; 88 89 if (!XIShouldNotify(clients[i], dev)) 90 continue; 91 92 WriteEventsToClient(clients[i], 1, &core_mn); 93 } 94 95 xi_mn.type = DeviceMappingNotify; 96 xi_mn.request = MappingPointer; 97 xi_mn.deviceid = dev->id; 98 xi_mn.time = GetTimeInMillis(); 99 100 SendEventToAllWindows(dev, DeviceMappingNotifyMask, (xEvent *) &xi_mn, 1); 101} 102 103/* 104 * Does what it says on the box, both for core and Xi. 105 * 106 * Faithfully reports any errors encountered while trying to apply the map 107 * to the requested device, faithfully ignores any errors encountered while 108 * trying to apply the map to its master/slaves. 109 */ 110int 111ApplyPointerMapping(DeviceIntPtr dev, CARD8 *map, int len, ClientPtr client) 112{ 113 int ret; 114 115 /* If we can't perform the change on the requested device, bail out. */ 116 ret = check_butmap_change(dev, map, len, &client->errorValue, client); 117 if (ret != Success) 118 return ret; 119 do_butmap_change(dev, map, len, client); 120 121 return Success; 122} 123 124/* Check if a modifier map change is okay with the device. 125 * Returns -1 for BadValue, as it collides with MappingBusy; this particular 126 * caveat can be removed with LegalModifier, as we have no other reason to 127 * set MappingFailed. Sigh. */ 128static int 129check_modmap_change(ClientPtr client, DeviceIntPtr dev, KeyCode *modmap) 130{ 131 int ret, i; 132 XkbDescPtr xkb; 133 134 ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess); 135 if (ret != Success) 136 return ret; 137 138 if (!dev->key) 139 return BadMatch; 140 xkb = dev->key->xkbInfo->desc; 141 142 for (i = 0; i < MAP_LENGTH; i++) { 143 if (!modmap[i]) 144 continue; 145 146 /* Check that all the new modifiers fall within the advertised 147 * keycode range. */ 148 if (i < xkb->min_key_code || i > xkb->max_key_code) { 149 client->errorValue = i; 150 return -1; 151 } 152 153 /* Make sure the mapping is okay with the DDX. */ 154 if (!LegalModifier(i, dev)) { 155 client->errorValue = i; 156 return MappingFailed; 157 } 158 159 /* None of the new modifiers may be down while we change the 160 * map. */ 161 if (key_is_down(dev, i, KEY_POSTED | KEY_PROCESSED)) { 162 client->errorValue = i; 163 return MappingBusy; 164 } 165 } 166 167 /* None of the old modifiers may be down while we change the map, 168 * either. */ 169 for (i = xkb->min_key_code; i < xkb->max_key_code; i++) { 170 if (!xkb->map->modmap[i]) 171 continue; 172 if (key_is_down(dev, i, KEY_POSTED | KEY_PROCESSED)) { 173 client->errorValue = i; 174 return MappingBusy; 175 } 176 } 177 178 return Success; 179} 180 181static int 182check_modmap_change_slave(ClientPtr client, DeviceIntPtr master, 183 DeviceIntPtr slave, CARD8 *modmap) 184{ 185 XkbDescPtr master_xkb, slave_xkb; 186 int i, j; 187 188 if (!slave->key || !master->key) 189 return 0; 190 191 master_xkb = master->key->xkbInfo->desc; 192 slave_xkb = slave->key->xkbInfo->desc; 193 194 /* Ignore devices with a clearly different keymap. */ 195 if (slave_xkb->min_key_code != master_xkb->min_key_code || 196 slave_xkb->max_key_code != master_xkb->max_key_code) 197 return 0; 198 199 for (i = 0; i < MAP_LENGTH; i++) { 200 if (!modmap[i]) 201 continue; 202 203 /* If we have different symbols for any modifier on an 204 * extended keyboard, ignore the whole remap request. */ 205 for (j = 0; 206 j < XkbKeyNumSyms(slave_xkb, i) && 207 j < XkbKeyNumSyms(master_xkb, i); 208 j++) 209 if (XkbKeySymsPtr(slave_xkb, i)[j] != XkbKeySymsPtr(master_xkb, i)[j]) 210 return 0; 211 } 212 213 if (check_modmap_change(client, slave, modmap) != Success) 214 return 0; 215 216 return 1; 217} 218 219/* Actually change the modifier map, and send notifications. Cannot fail. */ 220static void 221do_modmap_change(ClientPtr client, DeviceIntPtr dev, CARD8 *modmap) 222{ 223 XkbApplyMappingChange(dev, NULL, 0, 0, modmap, serverClient); 224} 225 226/* Rebuild modmap (key -> mod) from map (mod -> key). */ 227static int build_modmap_from_modkeymap(CARD8 *modmap, KeyCode *modkeymap, 228 int max_keys_per_mod) 229{ 230 int i, len = max_keys_per_mod * 8; 231 232 memset(modmap, 0, MAP_LENGTH); 233 234 for (i = 0; i < len; i++) { 235 if (!modkeymap[i]) 236 continue; 237 238 if (modkeymap[i] >= MAP_LENGTH) 239 return BadValue; 240 241 if (modmap[modkeymap[i]]) 242 return BadValue; 243 244 modmap[modkeymap[i]] = 1 << (i / max_keys_per_mod); 245 } 246 247 return Success; 248} 249 250int 251change_modmap(ClientPtr client, DeviceIntPtr dev, KeyCode *modkeymap, 252 int max_keys_per_mod) 253{ 254 int ret; 255 CARD8 modmap[MAP_LENGTH]; 256 DeviceIntPtr tmp; 257 258 ret = build_modmap_from_modkeymap(modmap, modkeymap, max_keys_per_mod); 259 if (ret != Success) 260 return ret; 261 262 /* If we can't perform the change on the requested device, bail out. */ 263 ret = check_modmap_change(client, dev, modmap); 264 if (ret != Success) 265 return ret; 266 do_modmap_change(client, dev, modmap); 267 268 /* Change any attached masters/slaves. */ 269 if (IsMaster(dev)) { 270 for (tmp = inputInfo.devices; tmp; tmp = tmp->next) { 271 if (!IsMaster(tmp) && tmp->u.master == dev) 272 if (check_modmap_change_slave(client, dev, tmp, modmap)) 273 do_modmap_change(client, tmp, modmap); 274 } 275 } 276 else if (dev->u.master && dev->u.master->u.lastSlave == dev) { 277 /* If this fails, expect the results to be weird. */ 278 if (check_modmap_change(client, dev->u.master, modmap)) 279 do_modmap_change(client, dev->u.master, modmap); 280 } 281 282 return Success; 283} 284 285int generate_modkeymap(ClientPtr client, DeviceIntPtr dev, 286 KeyCode **modkeymap_out, int *max_keys_per_mod_out) 287{ 288 CARD8 keys_per_mod[8]; 289 int max_keys_per_mod; 290 KeyCode *modkeymap = NULL; 291 int i, j, ret; 292 293 ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGetAttrAccess); 294 if (ret != Success) 295 return ret; 296 297 if (!dev->key) 298 return BadMatch; 299 300 /* Count the number of keys per modifier to determine how wide we 301 * should make the map. */ 302 max_keys_per_mod = 0; 303 for (i = 0; i < 8; i++) 304 keys_per_mod[i] = 0; 305 for (i = 8; i < MAP_LENGTH; i++) { 306 for (j = 0; j < 8; j++) { 307 if (dev->key->xkbInfo->desc->map->modmap[i] & (1 << j)) { 308 if (++keys_per_mod[j] > max_keys_per_mod) 309 max_keys_per_mod = keys_per_mod[j]; 310 } 311 } 312 } 313 314 if (max_keys_per_mod != 0) { 315 modkeymap = calloc(max_keys_per_mod * 8, sizeof(KeyCode)); 316 if (!modkeymap) 317 return BadAlloc; 318 319 for (i = 0; i < 8; i++) 320 keys_per_mod[i] = 0; 321 322 for (i = 8; i < MAP_LENGTH; i++) { 323 for (j = 0; j < 8; j++) { 324 if (dev->key->xkbInfo->desc->map->modmap[i] & (1 << j)) { 325 modkeymap[(j * max_keys_per_mod) + keys_per_mod[j]] = i; 326 keys_per_mod[j]++; 327 } 328 } 329 } 330 } 331 332 *max_keys_per_mod_out = max_keys_per_mod; 333 *modkeymap_out = modkeymap; 334 335 return Success; 336} 337 338/** 339 * Duplicate the InputAttributes in the most obvious way. 340 * No special memory handling is used to give drivers the maximum 341 * flexibility with the data. Drivers should be able to call realloc on the 342 * product string if needed and perform similar operations. 343 */ 344InputAttributes* 345DuplicateInputAttributes(InputAttributes *attrs) 346{ 347 InputAttributes *new_attr; 348 int ntags = 0; 349 char **tags, **new_tags; 350 351 if (!attrs) 352 return NULL; 353 354 if (!(new_attr = calloc(1, sizeof(InputAttributes)))) 355 goto unwind; 356 357 if (attrs->product && !(new_attr->product = strdup(attrs->product))) 358 goto unwind; 359 if (attrs->vendor && !(new_attr->vendor = strdup(attrs->vendor))) 360 goto unwind; 361 if (attrs->device && !(new_attr->device = strdup(attrs->device))) 362 goto unwind; 363 if (attrs->pnp_id && !(new_attr->pnp_id = strdup(attrs->pnp_id))) 364 goto unwind; 365 if (attrs->usb_id && !(new_attr->usb_id = strdup(attrs->usb_id))) 366 goto unwind; 367 368 new_attr->flags = attrs->flags; 369 370 if ((tags = attrs->tags)) 371 { 372 while(*tags++) 373 ntags++; 374 375 new_attr->tags = calloc(ntags + 1, sizeof(char*)); 376 if (!new_attr->tags) 377 goto unwind; 378 379 tags = attrs->tags; 380 new_tags = new_attr->tags; 381 382 while(*tags) 383 { 384 *new_tags = strdup(*tags); 385 if (!*new_tags) 386 goto unwind; 387 388 tags++; 389 new_tags++; 390 } 391 } 392 393 return new_attr; 394 395unwind: 396 FreeInputAttributes(new_attr); 397 return NULL; 398} 399 400void 401FreeInputAttributes(InputAttributes *attrs) 402{ 403 char **tags; 404 405 if (!attrs) 406 return; 407 408 free(attrs->product); 409 free(attrs->vendor); 410 free(attrs->device); 411 free(attrs->pnp_id); 412 free(attrs->usb_id); 413 414 if ((tags = attrs->tags)) 415 while(*tags) 416 free(*tags++); 417 418 free(attrs->tags); 419 free(attrs); 420} 421 422/** 423 * Alloc a valuator mask large enough for num_valuators. 424 */ 425ValuatorMask* 426valuator_mask_new(int num_valuators) 427{ 428 /* alloc a fixed size mask for now and ignore num_valuators. in the 429 * flying-car future, when we can dynamically alloc the masks and are 430 * not constrained by signals, we can start using num_valuators */ 431 ValuatorMask *mask = calloc(1, sizeof(ValuatorMask)); 432 mask->last_bit = -1; 433 return mask; 434} 435 436void 437valuator_mask_free(ValuatorMask **mask) 438{ 439 free(*mask); 440 *mask = NULL; 441} 442 443 444/** 445 * Sets a range of valuators between first_valuator and num_valuators with 446 * the data in the valuators array. All other values are set to 0. 447 */ 448void 449valuator_mask_set_range(ValuatorMask *mask, int first_valuator, int num_valuators, 450 const int* valuators) 451{ 452 int i; 453 454 valuator_mask_zero(mask); 455 456 for (i = first_valuator; i < min(first_valuator + num_valuators, MAX_VALUATORS); i++) 457 valuator_mask_set(mask, i, valuators[i - first_valuator]); 458} 459 460/** 461 * Reset mask to zero. 462 */ 463void 464valuator_mask_zero(ValuatorMask *mask) 465{ 466 memset(mask, 0, sizeof(*mask)); 467 mask->last_bit = -1; 468} 469 470/** 471 * Returns the current size of the mask (i.e. the highest number of 472 * valuators currently set + 1). 473 */ 474int 475valuator_mask_size(const ValuatorMask *mask) 476{ 477 return mask->last_bit + 1; 478} 479 480/** 481 * Returns the number of valuators set in the given mask. 482 */ 483int 484valuator_mask_num_valuators(const ValuatorMask *mask) 485{ 486 return CountBits(mask->mask, min(mask->last_bit + 1, MAX_VALUATORS)); 487} 488 489/** 490 * Return true if the valuator is set in the mask, or false otherwise. 491 */ 492int 493valuator_mask_isset(const ValuatorMask *mask, int valuator) 494{ 495 return mask->last_bit >= valuator && BitIsOn(mask->mask, valuator); 496} 497 498/** 499 * Set the valuator to the given data. 500 */ 501void 502valuator_mask_set(ValuatorMask *mask, int valuator, int data) 503{ 504 mask->last_bit = max(valuator, mask->last_bit); 505 SetBit(mask->mask, valuator); 506 mask->valuators[valuator] = data; 507} 508 509/** 510 * Return the requested valuator value. If the mask bit is not set for the 511 * given valuator, the returned value is undefined. 512 */ 513int 514valuator_mask_get(const ValuatorMask *mask, int valuator) 515{ 516 return mask->valuators[valuator]; 517} 518 519/** 520 * Remove the valuator from the mask. 521 */ 522void 523valuator_mask_unset(ValuatorMask *mask, int valuator) 524{ 525 if (mask->last_bit >= valuator) { 526 int i, lastbit = -1; 527 528 ClearBit(mask->mask, valuator); 529 mask->valuators[valuator] = 0; 530 531 for (i = 0; i <= mask->last_bit; i++) 532 if (valuator_mask_isset(mask, i)) 533 lastbit = max(lastbit, i); 534 mask->last_bit = lastbit; 535 } 536} 537 538void 539valuator_mask_copy(ValuatorMask *dest, const ValuatorMask *src) 540{ 541 if (src) 542 memcpy(dest, src, sizeof(*dest)); 543 else 544 valuator_mask_zero(dest); 545} 546 547int 548CountBits(const uint8_t *mask, int len) 549{ 550 int i; 551 int ret = 0; 552 553 for (i = 0; i < len; i++) 554 if (BitIsOn(mask, i)) 555 ret++; 556 557 return ret; 558} 559