121e67964Smrg/************************************************************
221e67964Smrg
321e67964SmrgCopyright 2008 Peter Hutterer
421e67964Smrg
521e67964SmrgPermission to use, copy, modify, distribute, and sell this software and its
621e67964Smrgdocumentation for any purpose is hereby granted without fee, provided that
721e67964Smrgthe above copyright notice appear in all copies and that both that
821e67964Smrgcopyright notice and this permission notice appear in supporting
921e67964Smrgdocumentation.
1021e67964Smrg
1121e67964SmrgThe above copyright notice and this permission notice shall be included in
1221e67964Smrgall copies or substantial portions of the Software.
1321e67964Smrg
1421e67964SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1521e67964SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1621e67964SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
1721e67964SmrgAUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1821e67964SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1921e67964SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2021e67964Smrg
2121e67964SmrgExcept as contained in this notice, the name of the author shall not be
2221e67964Smrgused in advertising or otherwise to promote the sale, use or other dealings
2321e67964Smrgin this Software without prior written authorization from the author.
2421e67964Smrg
2521e67964Smrg*/
2621e67964Smrg
2721e67964Smrg/***********************************************************************
2821e67964Smrg * XGetDeviceProperties - get an input device's properties.
2921e67964Smrg */
3021e67964Smrg
3121e67964Smrg#ifdef HAVE_CONFIG_H
3221e67964Smrg#include <config.h>
3321e67964Smrg#endif
3421e67964Smrg
3521e67964Smrg#include <X11/Xlibint.h>
3621e67964Smrg#include <X11/extensions/XI.h>
3721e67964Smrg#include <X11/extensions/XIproto.h>
3821e67964Smrg#include <X11/extensions/XInput.h>
3921e67964Smrg#include <X11/extensions/extutil.h>
4021e67964Smrg#include "XIint.h"
41190694daSmrg#include <limits.h>
4221e67964Smrg
4321e67964Smrgint
4421e67964SmrgXGetDeviceProperty(Display* dpy, XDevice* dev,
4521e67964Smrg			 Atom property, long offset, long length, Bool delete,
4621e67964Smrg                         Atom req_type, Atom *actual_type, int *actual_format,
4721e67964Smrg                         unsigned long *nitems, unsigned long *bytes_after,
4821e67964Smrg                         unsigned char **prop)
4921e67964Smrg{
5021e67964Smrg    xGetDevicePropertyReq   *req;
5121e67964Smrg    xGetDevicePropertyReply rep;
52190694daSmrg    unsigned long           nbytes, rbytes;
53190694daSmrg    int                     ret = Success;
5421e67964Smrg
5521e67964Smrg    XExtDisplayInfo *info = XInput_find_display(dpy);
5621e67964Smrg
5721e67964Smrg    LockDisplay(dpy);
5821e67964Smrg    if (_XiCheckExtInit(dpy, XInput_Initial_Release, info) == -1)
5921e67964Smrg	return 1;
6021e67964Smrg
6121e67964Smrg    GetReq(GetDeviceProperty, req);
6221e67964Smrg    req->reqType    = info->codes->major_opcode;
6321e67964Smrg    req->ReqType    = X_GetDeviceProperty;
6421e67964Smrg    req->deviceid   = dev->device_id;
6521e67964Smrg    req->property   = property;
6621e67964Smrg    req->type       = req_type;
6721e67964Smrg    req->longOffset = offset;
6821e67964Smrg    req->longLength = length;
6921e67964Smrg    req->delete     = delete;
7021e67964Smrg
7121e67964Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
7221e67964Smrg    {
7321e67964Smrg	UnlockDisplay (dpy);
7421e67964Smrg	SyncHandle ();
7521e67964Smrg	return 1;
7621e67964Smrg    }
7721e67964Smrg
7821e67964Smrg    *prop = (unsigned char *) NULL;
7921e67964Smrg
8021e67964Smrg    if (rep.propertyType != None) {
8121e67964Smrg	/*
8221e67964Smrg	 * One extra byte is malloced than is needed to contain the property
8321e67964Smrg	 * data, but this last byte is null terminated and convenient for
8421e67964Smrg	 * returning string properties, so the client doesn't then have to
8521e67964Smrg	 * recopy the string to make it null terminated.
86190694daSmrg	 *
87190694daSmrg	 * Maximum item limits are set to both prevent integer overflow when
88190694daSmrg	 * calculating the amount of memory to malloc, and to limit how much
89190694daSmrg	 * memory will be used if a server provides an insanely high count.
9021e67964Smrg	 */
9121e67964Smrg	switch (rep.format) {
9221e67964Smrg	case 8:
93190694daSmrg	    if (rep.nItems < INT_MAX) {
94190694daSmrg		nbytes = rep.nItems;
95190694daSmrg		rbytes = rep.nItems + 1;
96190694daSmrg		if ((*prop = Xmalloc (rbytes)))
97190694daSmrg		    _XReadPad (dpy, (char *) *prop, nbytes);
98190694daSmrg		else
99190694daSmrg		    ret = BadAlloc;
100190694daSmrg	    }
10121e67964Smrg	    break;
10221e67964Smrg
10321e67964Smrg	case 16:
104190694daSmrg	    if (rep.nItems < (INT_MAX / sizeof (short))) {
105190694daSmrg		nbytes = rep.nItems << 1;
106190694daSmrg		rbytes = rep.nItems * sizeof (short) + 1;
107190694daSmrg		if ((*prop = Xmalloc (rbytes)))
108190694daSmrg		    _XRead16Pad (dpy, (short *) *prop, nbytes);
109190694daSmrg		else
110190694daSmrg		    ret = BadAlloc;
111190694daSmrg	    }
11221e67964Smrg	    break;
11321e67964Smrg
11421e67964Smrg	case 32:
115190694daSmrg	    if (rep.nItems < (INT_MAX / sizeof (long))) {
116190694daSmrg		nbytes = rep.nItems << 2;
117190694daSmrg		rbytes = rep.nItems * sizeof (long) + 1;
118190694daSmrg		if ((*prop = Xmalloc (rbytes)))
119190694daSmrg		    _XRead32 (dpy, (long *) *prop, nbytes);
120190694daSmrg		else
121190694daSmrg		    ret = BadAlloc;
122190694daSmrg	    }
12321e67964Smrg	    break;
12421e67964Smrg
12521e67964Smrg	default:
12621e67964Smrg	    /*
12721e67964Smrg	     * This part of the code should never be reached.  If it is,
12821e67964Smrg	     * the server sent back a property with an invalid format.
12921e67964Smrg	     */
130190694daSmrg	    ret = BadImplementation;
13121e67964Smrg	}
13221e67964Smrg	if (! *prop) {
13310baa824Smrg	    _XEatDataWords(dpy, rep.length);
134190694daSmrg	    if (ret == Success)
135190694daSmrg		ret = BadAlloc;
136190694daSmrg	    goto out;
13721e67964Smrg	}
13821e67964Smrg	(*prop)[rbytes - 1] = '\0';
13921e67964Smrg    }
14021e67964Smrg
14121e67964Smrg    *actual_type = rep.propertyType;
14221e67964Smrg    *actual_format = rep.format;
14321e67964Smrg    *nitems = rep.nItems;
14421e67964Smrg    *bytes_after = rep.bytesAfter;
145190694daSmrg  out:
14621e67964Smrg    UnlockDisplay (dpy);
14721e67964Smrg    SyncHandle ();
14821e67964Smrg
149190694daSmrg    return ret;
15021e67964Smrg}
15121e67964Smrg
152