inpututils.c revision 9ace9065
16747b715Smrg/* 26747b715Smrg * Copyright © 2008 Daniel Stone 36747b715Smrg * 46747b715Smrg * Permission is hereby granted, free of charge, to any person obtaining a 56747b715Smrg * copy of this software and associated documentation files (the "Software"), 66747b715Smrg * to deal in the Software without restriction, including without limitation 76747b715Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 86747b715Smrg * and/or sell copies of the Software, and to permit persons to whom the 96747b715Smrg * Software is furnished to do so, subject to the following conditions: 106747b715Smrg * 116747b715Smrg * The above copyright notice and this permission notice (including the next 126747b715Smrg * paragraph) shall be included in all copies or substantial portions of the 136747b715Smrg * Software. 146747b715Smrg * 156747b715Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 166747b715Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 176747b715Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 186747b715Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 196747b715Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 206747b715Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 216747b715Smrg * DEALINGS IN THE SOFTWARE. 226747b715Smrg * 236747b715Smrg * Author: Daniel Stone <daniel@fooishbar.org> 246747b715Smrg */ 256747b715Smrg 266747b715Smrg#ifdef HAVE_DIX_CONFIG_H 276747b715Smrg#include "dix-config.h" 286747b715Smrg#endif 296747b715Smrg 306747b715Smrg#include "exevents.h" 316747b715Smrg#include "exglobals.h" 326747b715Smrg#include "misc.h" 336747b715Smrg#include "input.h" 346747b715Smrg#include "inputstr.h" 356747b715Smrg#include "xace.h" 366747b715Smrg#include "xkbsrv.h" 376747b715Smrg#include "xkbstr.h" 389ace9065Smrg#include "inpututils.h" 396747b715Smrg 406747b715Smrg/* Check if a button map change is okay with the device. 416747b715Smrg * Returns -1 for BadValue, as it collides with MappingBusy. */ 426747b715Smrgstatic int 436747b715Smrgcheck_butmap_change(DeviceIntPtr dev, CARD8 *map, int len, CARD32 *errval_out, 446747b715Smrg ClientPtr client) 456747b715Smrg{ 466747b715Smrg int i, ret; 476747b715Smrg 486747b715Smrg if (!dev || !dev->button) 496747b715Smrg { 506747b715Smrg client->errorValue = (dev) ? dev->id : 0; 516747b715Smrg return BadDevice; 526747b715Smrg } 536747b715Smrg 546747b715Smrg ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess); 556747b715Smrg if (ret != Success) 566747b715Smrg { 576747b715Smrg client->errorValue = dev->id; 586747b715Smrg return ret; 596747b715Smrg } 606747b715Smrg 616747b715Smrg for (i = 0; i < len; i++) { 626747b715Smrg if (dev->button->map[i + 1] != map[i] && dev->button->down[i + 1]) 636747b715Smrg return MappingBusy; 646747b715Smrg } 656747b715Smrg 666747b715Smrg return Success; 676747b715Smrg} 686747b715Smrg 696747b715Smrgstatic void 706747b715Smrgdo_butmap_change(DeviceIntPtr dev, CARD8 *map, int len, ClientPtr client) 716747b715Smrg{ 726747b715Smrg int i; 736747b715Smrg xEvent core_mn; 746747b715Smrg deviceMappingNotify xi_mn; 756747b715Smrg 766747b715Smrg /* The map in ButtonClassRec refers to button numbers, whereas the 776747b715Smrg * protocol is zero-indexed. Sigh. */ 786747b715Smrg memcpy(&(dev->button->map[1]), map, len); 796747b715Smrg 806747b715Smrg core_mn.u.u.type = MappingNotify; 816747b715Smrg core_mn.u.mappingNotify.request = MappingPointer; 826747b715Smrg 836747b715Smrg /* 0 is the server client. */ 846747b715Smrg for (i = 1; i < currentMaxClients; i++) { 856747b715Smrg /* Don't send irrelevant events to naïve clients. */ 866747b715Smrg if (!clients[i] || clients[i]->clientState != ClientStateRunning) 876747b715Smrg continue; 886747b715Smrg 896747b715Smrg if (!XIShouldNotify(clients[i], dev)) 906747b715Smrg continue; 916747b715Smrg 926747b715Smrg WriteEventsToClient(clients[i], 1, &core_mn); 936747b715Smrg } 946747b715Smrg 956747b715Smrg xi_mn.type = DeviceMappingNotify; 966747b715Smrg xi_mn.request = MappingPointer; 976747b715Smrg xi_mn.deviceid = dev->id; 986747b715Smrg xi_mn.time = GetTimeInMillis(); 996747b715Smrg 1006747b715Smrg SendEventToAllWindows(dev, DeviceMappingNotifyMask, (xEvent *) &xi_mn, 1); 1016747b715Smrg} 1026747b715Smrg 1036747b715Smrg/* 1046747b715Smrg * Does what it says on the box, both for core and Xi. 1056747b715Smrg * 1066747b715Smrg * Faithfully reports any errors encountered while trying to apply the map 1076747b715Smrg * to the requested device, faithfully ignores any errors encountered while 1086747b715Smrg * trying to apply the map to its master/slaves. 1096747b715Smrg */ 1106747b715Smrgint 1116747b715SmrgApplyPointerMapping(DeviceIntPtr dev, CARD8 *map, int len, ClientPtr client) 1126747b715Smrg{ 1136747b715Smrg int ret; 1146747b715Smrg 1156747b715Smrg /* If we can't perform the change on the requested device, bail out. */ 1166747b715Smrg ret = check_butmap_change(dev, map, len, &client->errorValue, client); 1176747b715Smrg if (ret != Success) 1186747b715Smrg return ret; 1196747b715Smrg do_butmap_change(dev, map, len, client); 1206747b715Smrg 1216747b715Smrg return Success; 1226747b715Smrg} 1236747b715Smrg 1246747b715Smrg/* Check if a modifier map change is okay with the device. 1256747b715Smrg * Returns -1 for BadValue, as it collides with MappingBusy; this particular 1266747b715Smrg * caveat can be removed with LegalModifier, as we have no other reason to 1276747b715Smrg * set MappingFailed. Sigh. */ 1286747b715Smrgstatic int 1296747b715Smrgcheck_modmap_change(ClientPtr client, DeviceIntPtr dev, KeyCode *modmap) 1306747b715Smrg{ 1316747b715Smrg int ret, i; 1326747b715Smrg XkbDescPtr xkb; 1336747b715Smrg 1346747b715Smrg ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess); 1356747b715Smrg if (ret != Success) 1366747b715Smrg return ret; 1376747b715Smrg 1386747b715Smrg if (!dev->key) 1396747b715Smrg return BadMatch; 1406747b715Smrg xkb = dev->key->xkbInfo->desc; 1416747b715Smrg 1426747b715Smrg for (i = 0; i < MAP_LENGTH; i++) { 1436747b715Smrg if (!modmap[i]) 1446747b715Smrg continue; 1456747b715Smrg 1466747b715Smrg /* Check that all the new modifiers fall within the advertised 1476747b715Smrg * keycode range. */ 1486747b715Smrg if (i < xkb->min_key_code || i > xkb->max_key_code) { 1496747b715Smrg client->errorValue = i; 1506747b715Smrg return -1; 1516747b715Smrg } 1526747b715Smrg 1536747b715Smrg /* Make sure the mapping is okay with the DDX. */ 1546747b715Smrg if (!LegalModifier(i, dev)) { 1556747b715Smrg client->errorValue = i; 1566747b715Smrg return MappingFailed; 1576747b715Smrg } 1586747b715Smrg 1596747b715Smrg /* None of the new modifiers may be down while we change the 1606747b715Smrg * map. */ 1616747b715Smrg if (key_is_down(dev, i, KEY_POSTED | KEY_PROCESSED)) { 1626747b715Smrg client->errorValue = i; 1636747b715Smrg return MappingBusy; 1646747b715Smrg } 1656747b715Smrg } 1666747b715Smrg 1676747b715Smrg /* None of the old modifiers may be down while we change the map, 1686747b715Smrg * either. */ 1696747b715Smrg for (i = xkb->min_key_code; i < xkb->max_key_code; i++) { 1706747b715Smrg if (!xkb->map->modmap[i]) 1716747b715Smrg continue; 1726747b715Smrg if (key_is_down(dev, i, KEY_POSTED | KEY_PROCESSED)) { 1736747b715Smrg client->errorValue = i; 1746747b715Smrg return MappingBusy; 1756747b715Smrg } 1766747b715Smrg } 1776747b715Smrg 1786747b715Smrg return Success; 1796747b715Smrg} 1806747b715Smrg 1816747b715Smrgstatic int 1826747b715Smrgcheck_modmap_change_slave(ClientPtr client, DeviceIntPtr master, 1836747b715Smrg DeviceIntPtr slave, CARD8 *modmap) 1846747b715Smrg{ 1856747b715Smrg XkbDescPtr master_xkb, slave_xkb; 1866747b715Smrg int i, j; 1876747b715Smrg 1886747b715Smrg if (!slave->key || !master->key) 1896747b715Smrg return 0; 1906747b715Smrg 1916747b715Smrg master_xkb = master->key->xkbInfo->desc; 1926747b715Smrg slave_xkb = slave->key->xkbInfo->desc; 1936747b715Smrg 1946747b715Smrg /* Ignore devices with a clearly different keymap. */ 1956747b715Smrg if (slave_xkb->min_key_code != master_xkb->min_key_code || 1966747b715Smrg slave_xkb->max_key_code != master_xkb->max_key_code) 1976747b715Smrg return 0; 1986747b715Smrg 1996747b715Smrg for (i = 0; i < MAP_LENGTH; i++) { 2006747b715Smrg if (!modmap[i]) 2016747b715Smrg continue; 2026747b715Smrg 2036747b715Smrg /* If we have different symbols for any modifier on an 2046747b715Smrg * extended keyboard, ignore the whole remap request. */ 2056747b715Smrg for (j = 0; 2066747b715Smrg j < XkbKeyNumSyms(slave_xkb, i) && 2076747b715Smrg j < XkbKeyNumSyms(master_xkb, i); 2086747b715Smrg j++) 2096747b715Smrg if (XkbKeySymsPtr(slave_xkb, i)[j] != XkbKeySymsPtr(master_xkb, i)[j]) 2106747b715Smrg return 0; 2116747b715Smrg } 2126747b715Smrg 2136747b715Smrg if (check_modmap_change(client, slave, modmap) != Success) 2146747b715Smrg return 0; 2156747b715Smrg 2166747b715Smrg return 1; 2176747b715Smrg} 2186747b715Smrg 2196747b715Smrg/* Actually change the modifier map, and send notifications. Cannot fail. */ 2206747b715Smrgstatic void 2216747b715Smrgdo_modmap_change(ClientPtr client, DeviceIntPtr dev, CARD8 *modmap) 2226747b715Smrg{ 2236747b715Smrg XkbApplyMappingChange(dev, NULL, 0, 0, modmap, serverClient); 2246747b715Smrg} 2256747b715Smrg 2266747b715Smrg/* Rebuild modmap (key -> mod) from map (mod -> key). */ 2276747b715Smrgstatic int build_modmap_from_modkeymap(CARD8 *modmap, KeyCode *modkeymap, 2286747b715Smrg int max_keys_per_mod) 2296747b715Smrg{ 2306747b715Smrg int i, len = max_keys_per_mod * 8; 2316747b715Smrg 2326747b715Smrg memset(modmap, 0, MAP_LENGTH); 2336747b715Smrg 2346747b715Smrg for (i = 0; i < len; i++) { 2356747b715Smrg if (!modkeymap[i]) 2366747b715Smrg continue; 2376747b715Smrg 2386747b715Smrg if (modkeymap[i] >= MAP_LENGTH) 2396747b715Smrg return BadValue; 2406747b715Smrg 2416747b715Smrg if (modmap[modkeymap[i]]) 2426747b715Smrg return BadValue; 2436747b715Smrg 2446747b715Smrg modmap[modkeymap[i]] = 1 << (i / max_keys_per_mod); 2456747b715Smrg } 2466747b715Smrg 2476747b715Smrg return Success; 2486747b715Smrg} 2496747b715Smrg 2506747b715Smrgint 2516747b715Smrgchange_modmap(ClientPtr client, DeviceIntPtr dev, KeyCode *modkeymap, 2526747b715Smrg int max_keys_per_mod) 2536747b715Smrg{ 2546747b715Smrg int ret; 2556747b715Smrg CARD8 modmap[MAP_LENGTH]; 2566747b715Smrg DeviceIntPtr tmp; 2576747b715Smrg 2586747b715Smrg ret = build_modmap_from_modkeymap(modmap, modkeymap, max_keys_per_mod); 2596747b715Smrg if (ret != Success) 2606747b715Smrg return ret; 2616747b715Smrg 2626747b715Smrg /* If we can't perform the change on the requested device, bail out. */ 2636747b715Smrg ret = check_modmap_change(client, dev, modmap); 2646747b715Smrg if (ret != Success) 2656747b715Smrg return ret; 2666747b715Smrg do_modmap_change(client, dev, modmap); 2676747b715Smrg 2686747b715Smrg /* Change any attached masters/slaves. */ 2696747b715Smrg if (IsMaster(dev)) { 2706747b715Smrg for (tmp = inputInfo.devices; tmp; tmp = tmp->next) { 2716747b715Smrg if (!IsMaster(tmp) && tmp->u.master == dev) 2726747b715Smrg if (check_modmap_change_slave(client, dev, tmp, modmap)) 2736747b715Smrg do_modmap_change(client, tmp, modmap); 2746747b715Smrg } 2756747b715Smrg } 2766747b715Smrg else if (dev->u.master && dev->u.master->u.lastSlave == dev) { 2776747b715Smrg /* If this fails, expect the results to be weird. */ 2786747b715Smrg if (check_modmap_change(client, dev->u.master, modmap)) 2796747b715Smrg do_modmap_change(client, dev->u.master, modmap); 2806747b715Smrg } 2816747b715Smrg 2826747b715Smrg return Success; 2836747b715Smrg} 2846747b715Smrg 2856747b715Smrgint generate_modkeymap(ClientPtr client, DeviceIntPtr dev, 2866747b715Smrg KeyCode **modkeymap_out, int *max_keys_per_mod_out) 2876747b715Smrg{ 2886747b715Smrg CARD8 keys_per_mod[8]; 2896747b715Smrg int max_keys_per_mod; 2908223e2f2Smrg KeyCode *modkeymap = NULL; 2916747b715Smrg int i, j, ret; 2926747b715Smrg 2936747b715Smrg ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGetAttrAccess); 2946747b715Smrg if (ret != Success) 2956747b715Smrg return ret; 2966747b715Smrg 2976747b715Smrg if (!dev->key) 2986747b715Smrg return BadMatch; 2996747b715Smrg 3006747b715Smrg /* Count the number of keys per modifier to determine how wide we 3016747b715Smrg * should make the map. */ 3026747b715Smrg max_keys_per_mod = 0; 3036747b715Smrg for (i = 0; i < 8; i++) 3046747b715Smrg keys_per_mod[i] = 0; 3056747b715Smrg for (i = 8; i < MAP_LENGTH; i++) { 3066747b715Smrg for (j = 0; j < 8; j++) { 3076747b715Smrg if (dev->key->xkbInfo->desc->map->modmap[i] & (1 << j)) { 3086747b715Smrg if (++keys_per_mod[j] > max_keys_per_mod) 3096747b715Smrg max_keys_per_mod = keys_per_mod[j]; 3106747b715Smrg } 3116747b715Smrg } 3126747b715Smrg } 3136747b715Smrg 3148223e2f2Smrg if (max_keys_per_mod != 0) { 3158223e2f2Smrg modkeymap = calloc(max_keys_per_mod * 8, sizeof(KeyCode)); 3168223e2f2Smrg if (!modkeymap) 3178223e2f2Smrg return BadAlloc; 3186747b715Smrg 3198223e2f2Smrg for (i = 0; i < 8; i++) 3208223e2f2Smrg keys_per_mod[i] = 0; 3216747b715Smrg 3228223e2f2Smrg for (i = 8; i < MAP_LENGTH; i++) { 3238223e2f2Smrg for (j = 0; j < 8; j++) { 3248223e2f2Smrg if (dev->key->xkbInfo->desc->map->modmap[i] & (1 << j)) { 3258223e2f2Smrg modkeymap[(j * max_keys_per_mod) + keys_per_mod[j]] = i; 3268223e2f2Smrg keys_per_mod[j]++; 3278223e2f2Smrg } 3286747b715Smrg } 3296747b715Smrg } 3306747b715Smrg } 3316747b715Smrg 3326747b715Smrg *max_keys_per_mod_out = max_keys_per_mod; 3336747b715Smrg *modkeymap_out = modkeymap; 3346747b715Smrg 3356747b715Smrg return Success; 3366747b715Smrg} 3376747b715Smrg 3386747b715Smrg/** 3396747b715Smrg * Duplicate the InputAttributes in the most obvious way. 3406747b715Smrg * No special memory handling is used to give drivers the maximum 3416747b715Smrg * flexibility with the data. Drivers should be able to call realloc on the 3426747b715Smrg * product string if needed and perform similar operations. 3436747b715Smrg */ 3446747b715SmrgInputAttributes* 3456747b715SmrgDuplicateInputAttributes(InputAttributes *attrs) 3466747b715Smrg{ 3476747b715Smrg InputAttributes *new_attr; 3486747b715Smrg int ntags = 0; 3496747b715Smrg char **tags, **new_tags; 3506747b715Smrg 3516747b715Smrg if (!attrs) 3526747b715Smrg return NULL; 3536747b715Smrg 3546747b715Smrg if (!(new_attr = calloc(1, sizeof(InputAttributes)))) 3556747b715Smrg goto unwind; 3566747b715Smrg 3576747b715Smrg if (attrs->product && !(new_attr->product = strdup(attrs->product))) 3586747b715Smrg goto unwind; 3596747b715Smrg if (attrs->vendor && !(new_attr->vendor = strdup(attrs->vendor))) 3606747b715Smrg goto unwind; 3616747b715Smrg if (attrs->device && !(new_attr->device = strdup(attrs->device))) 3626747b715Smrg goto unwind; 3636747b715Smrg if (attrs->pnp_id && !(new_attr->pnp_id = strdup(attrs->pnp_id))) 3646747b715Smrg goto unwind; 3656747b715Smrg if (attrs->usb_id && !(new_attr->usb_id = strdup(attrs->usb_id))) 3666747b715Smrg goto unwind; 3676747b715Smrg 3686747b715Smrg new_attr->flags = attrs->flags; 3696747b715Smrg 3706747b715Smrg if ((tags = attrs->tags)) 3716747b715Smrg { 3726747b715Smrg while(*tags++) 3736747b715Smrg ntags++; 3746747b715Smrg 3756747b715Smrg new_attr->tags = calloc(ntags + 1, sizeof(char*)); 3766747b715Smrg if (!new_attr->tags) 3776747b715Smrg goto unwind; 3786747b715Smrg 3796747b715Smrg tags = attrs->tags; 3806747b715Smrg new_tags = new_attr->tags; 3816747b715Smrg 3826747b715Smrg while(*tags) 3836747b715Smrg { 3846747b715Smrg *new_tags = strdup(*tags); 3856747b715Smrg if (!*new_tags) 3866747b715Smrg goto unwind; 3876747b715Smrg 3886747b715Smrg tags++; 3896747b715Smrg new_tags++; 3906747b715Smrg } 3916747b715Smrg } 3926747b715Smrg 3936747b715Smrg return new_attr; 3946747b715Smrg 3956747b715Smrgunwind: 3966747b715Smrg FreeInputAttributes(new_attr); 3976747b715Smrg return NULL; 3986747b715Smrg} 3996747b715Smrg 4006747b715Smrgvoid 4016747b715SmrgFreeInputAttributes(InputAttributes *attrs) 4026747b715Smrg{ 4036747b715Smrg char **tags; 4046747b715Smrg 4056747b715Smrg if (!attrs) 4066747b715Smrg return; 4076747b715Smrg 4086747b715Smrg free(attrs->product); 4096747b715Smrg free(attrs->vendor); 4106747b715Smrg free(attrs->device); 4116747b715Smrg free(attrs->pnp_id); 4126747b715Smrg free(attrs->usb_id); 4136747b715Smrg 4146747b715Smrg if ((tags = attrs->tags)) 4156747b715Smrg while(*tags) 4166747b715Smrg free(*tags++); 4176747b715Smrg 4186747b715Smrg free(attrs->tags); 4196747b715Smrg free(attrs); 4206747b715Smrg} 4216747b715Smrg 4229ace9065Smrg/** 4239ace9065Smrg * Alloc a valuator mask large enough for num_valuators. 4249ace9065Smrg */ 4259ace9065SmrgValuatorMask* 4269ace9065Smrgvaluator_mask_new(int num_valuators) 4279ace9065Smrg{ 4289ace9065Smrg /* alloc a fixed size mask for now and ignore num_valuators. in the 4299ace9065Smrg * flying-car future, when we can dynamically alloc the masks and are 4309ace9065Smrg * not constrained by signals, we can start using num_valuators */ 4319ace9065Smrg ValuatorMask *mask = calloc(1, sizeof(ValuatorMask)); 4329ace9065Smrg mask->last_bit = -1; 4339ace9065Smrg return mask; 4349ace9065Smrg} 4359ace9065Smrg 4369ace9065Smrgvoid 4379ace9065Smrgvaluator_mask_free(ValuatorMask **mask) 4389ace9065Smrg{ 4399ace9065Smrg free(*mask); 4409ace9065Smrg *mask = NULL; 4419ace9065Smrg} 4429ace9065Smrg 4439ace9065Smrg 4449ace9065Smrg/** 4459ace9065Smrg * Sets a range of valuators between first_valuator and num_valuators with 4469ace9065Smrg * the data in the valuators array. All other values are set to 0. 4479ace9065Smrg */ 4489ace9065Smrgvoid 4499ace9065Smrgvaluator_mask_set_range(ValuatorMask *mask, int first_valuator, int num_valuators, 4509ace9065Smrg const int* valuators) 4519ace9065Smrg{ 4529ace9065Smrg int i; 4539ace9065Smrg 4549ace9065Smrg valuator_mask_zero(mask); 4559ace9065Smrg 4569ace9065Smrg for (i = first_valuator; i < min(first_valuator + num_valuators, MAX_VALUATORS); i++) 4579ace9065Smrg valuator_mask_set(mask, i, valuators[i - first_valuator]); 4589ace9065Smrg} 4599ace9065Smrg 4609ace9065Smrg/** 4619ace9065Smrg * Reset mask to zero. 4629ace9065Smrg */ 4639ace9065Smrgvoid 4649ace9065Smrgvaluator_mask_zero(ValuatorMask *mask) 4659ace9065Smrg{ 4669ace9065Smrg memset(mask, 0, sizeof(*mask)); 4679ace9065Smrg mask->last_bit = -1; 4689ace9065Smrg} 4699ace9065Smrg 4709ace9065Smrg/** 4719ace9065Smrg * Returns the current size of the mask (i.e. the highest number of 4729ace9065Smrg * valuators currently set + 1). 4739ace9065Smrg */ 4749ace9065Smrgint 4759ace9065Smrgvaluator_mask_size(const ValuatorMask *mask) 4769ace9065Smrg{ 4779ace9065Smrg return mask->last_bit + 1; 4789ace9065Smrg} 4799ace9065Smrg 4809ace9065Smrg/** 4819ace9065Smrg * Returns the number of valuators set in the given mask. 4829ace9065Smrg */ 4839ace9065Smrgint 4849ace9065Smrgvaluator_mask_num_valuators(const ValuatorMask *mask) 4859ace9065Smrg{ 4869ace9065Smrg return CountBits(mask->mask, min(mask->last_bit + 1, MAX_VALUATORS)); 4879ace9065Smrg} 4889ace9065Smrg 4899ace9065Smrg/** 4909ace9065Smrg * Return true if the valuator is set in the mask, or false otherwise. 4919ace9065Smrg */ 4929ace9065Smrgint 4939ace9065Smrgvaluator_mask_isset(const ValuatorMask *mask, int valuator) 4949ace9065Smrg{ 4959ace9065Smrg return mask->last_bit >= valuator && BitIsOn(mask->mask, valuator); 4969ace9065Smrg} 4979ace9065Smrg 4989ace9065Smrg/** 4999ace9065Smrg * Set the valuator to the given data. 5009ace9065Smrg */ 5019ace9065Smrgvoid 5029ace9065Smrgvaluator_mask_set(ValuatorMask *mask, int valuator, int data) 5039ace9065Smrg{ 5049ace9065Smrg mask->last_bit = max(valuator, mask->last_bit); 5059ace9065Smrg SetBit(mask->mask, valuator); 5069ace9065Smrg mask->valuators[valuator] = data; 5079ace9065Smrg} 5089ace9065Smrg 5099ace9065Smrg/** 5109ace9065Smrg * Return the requested valuator value. If the mask bit is not set for the 5119ace9065Smrg * given valuator, the returned value is undefined. 5129ace9065Smrg */ 5139ace9065Smrgint 5149ace9065Smrgvaluator_mask_get(const ValuatorMask *mask, int valuator) 5159ace9065Smrg{ 5169ace9065Smrg return mask->valuators[valuator]; 5179ace9065Smrg} 5189ace9065Smrg 5199ace9065Smrg/** 5209ace9065Smrg * Remove the valuator from the mask. 5219ace9065Smrg */ 5229ace9065Smrgvoid 5239ace9065Smrgvaluator_mask_unset(ValuatorMask *mask, int valuator) 5249ace9065Smrg{ 5259ace9065Smrg if (mask->last_bit >= valuator) { 5269ace9065Smrg int i, lastbit = -1; 5279ace9065Smrg 5289ace9065Smrg ClearBit(mask->mask, valuator); 5299ace9065Smrg mask->valuators[valuator] = 0; 5309ace9065Smrg 5319ace9065Smrg for (i = 0; i <= mask->last_bit; i++) 5329ace9065Smrg if (valuator_mask_isset(mask, i)) 5339ace9065Smrg lastbit = max(lastbit, i); 5349ace9065Smrg mask->last_bit = lastbit; 5359ace9065Smrg } 5369ace9065Smrg} 5379ace9065Smrg 5389ace9065Smrgvoid 5399ace9065Smrgvaluator_mask_copy(ValuatorMask *dest, const ValuatorMask *src) 5409ace9065Smrg{ 5419ace9065Smrg if (src) 5429ace9065Smrg memcpy(dest, src, sizeof(*dest)); 5439ace9065Smrg else 5449ace9065Smrg valuator_mask_zero(dest); 5459ace9065Smrg} 5469ace9065Smrg 5479ace9065Smrgint 5489ace9065SmrgCountBits(const uint8_t *mask, int len) 5499ace9065Smrg{ 5509ace9065Smrg int i; 5519ace9065Smrg int ret = 0; 5529ace9065Smrg 5539ace9065Smrg for (i = 0; i < len; i++) 5549ace9065Smrg if (BitIsOn(mask, i)) 5559ace9065Smrg ret++; 5569ace9065Smrg 5579ace9065Smrg return ret; 5589ace9065Smrg} 559