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