File: | property.c |
Location: | line 389, column 21 |
Description: | Potential leak of memory pointed to by 'data.c' |
1 | /* | |||
2 | * Copyright © 2007 Peter Hutterer | |||
3 | * Copyright © 2009 Red Hat, Inc. | |||
4 | * | |||
5 | * Permission is hereby granted, free of charge, to any person obtaining a | |||
6 | * copy of this software and associated documentation files (the "Software"), | |||
7 | * to deal in the Software without restriction, including without limitation | |||
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
9 | * and/or sell copies of the Software, and to permit persons to whom the | |||
10 | * Software is furnished to do so, subject to the following conditions: | |||
11 | * | |||
12 | * The above copyright notice and this permission notice (including the next | |||
13 | * paragraph) shall be included in all copies or substantial portions of the | |||
14 | * Software. | |||
15 | * | |||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
22 | * DEALINGS IN THE SOFTWARE. | |||
23 | */ | |||
24 | ||||
25 | #include <ctype.h> | |||
26 | #include <string.h> | |||
27 | #include <stdlib.h> | |||
28 | #include <stdint.h> | |||
29 | #include <X11/Xatom.h> | |||
30 | #include <X11/extensions/XIproto.h> | |||
31 | ||||
32 | #include "xinput.h" | |||
33 | ||||
34 | static Atom parse_atom(Display *dpy, char *name) { | |||
35 | Boolint is_atom = True1; | |||
36 | int i; | |||
37 | ||||
38 | for (i = 0; name[i] != '\0'; i++) { | |||
39 | if (!isdigit(name[i])) { | |||
40 | is_atom = False0; | |||
41 | break; | |||
42 | } | |||
43 | } | |||
44 | ||||
45 | if (is_atom) | |||
46 | return atoi(name); | |||
47 | else | |||
48 | return XInternAtom(dpy, name, False0); | |||
49 | } | |||
50 | ||||
51 | static void | |||
52 | print_property(Display *dpy, XDevice* dev, Atom property) | |||
53 | { | |||
54 | Atom act_type; | |||
55 | char *name; | |||
56 | int act_format; | |||
57 | unsigned long nitems, bytes_after; | |||
58 | unsigned char *data, *ptr; | |||
59 | int j, done = False0, size = 0; | |||
60 | ||||
61 | name = XGetAtomName(dpy, property); | |||
62 | printf("\t%s (%ld):\t", name, property); | |||
63 | XFree(name); | |||
64 | ||||
65 | if (XGetDeviceProperty(dpy, dev, property, 0, 1000, False0, | |||
66 | AnyPropertyType0L, &act_type, &act_format, | |||
67 | &nitems, &bytes_after, &data) == Success0) | |||
68 | { | |||
69 | Atom float_atom = XInternAtom(dpy, "FLOAT", True1); | |||
70 | ||||
71 | ptr = data; | |||
72 | ||||
73 | if (nitems == 0) | |||
74 | printf("<no items>"); | |||
75 | ||||
76 | switch(act_format) | |||
77 | { | |||
78 | case 8: size = sizeof(char); break; | |||
79 | case 16: size = sizeof(short); break; | |||
80 | case 32: size = sizeof(long); break; | |||
81 | } | |||
82 | ||||
83 | for (j = 0; j < nitems; j++) | |||
84 | { | |||
85 | switch(act_type) | |||
86 | { | |||
87 | case XA_INTEGER((Atom) 19): | |||
88 | switch(act_format) | |||
89 | { | |||
90 | case 8: | |||
91 | printf("%d", *((char*)ptr)); | |||
92 | break; | |||
93 | case 16: | |||
94 | printf("%d", *((short*)ptr)); | |||
95 | break; | |||
96 | case 32: | |||
97 | printf("%ld", *((long*)ptr)); | |||
98 | break; | |||
99 | } | |||
100 | break; | |||
101 | case XA_CARDINAL((Atom) 6): | |||
102 | switch(act_format) | |||
103 | { | |||
104 | case 8: | |||
105 | printf("%u", *((unsigned char*)ptr)); | |||
106 | break; | |||
107 | case 16: | |||
108 | printf("%u", *((unsigned short*)ptr)); | |||
109 | break; | |||
110 | case 32: | |||
111 | printf("%lu", *((unsigned long*)ptr)); | |||
112 | break; | |||
113 | } | |||
114 | break; | |||
115 | case XA_STRING((Atom) 31): | |||
116 | if (act_format != 8) | |||
117 | { | |||
118 | printf("Unknown string format.\n"); | |||
119 | done = True1; | |||
120 | break; | |||
121 | } | |||
122 | printf("\"%s\"", ptr); | |||
123 | j += strlen((char*)ptr); /* The loop's j++ jumps over the | |||
124 | terminating 0 */ | |||
125 | ptr += strlen((char*)ptr); /* ptr += size below jumps over | |||
126 | the terminating 0 */ | |||
127 | break; | |||
128 | case XA_ATOM((Atom) 4): | |||
129 | { | |||
130 | Atom a = *(Atom*)ptr; | |||
131 | name = (a) ? XGetAtomName(dpy, a) : NULL((void*)0); | |||
132 | printf("\"%s\" (%d)", name ? name : "None", (int)a); | |||
133 | XFree(name); | |||
134 | break; | |||
135 | } | |||
136 | default: | |||
137 | if (float_atom != None0L && act_type == float_atom) | |||
138 | { | |||
139 | printf("%f", *((float*)ptr)); | |||
140 | break; | |||
141 | } | |||
142 | ||||
143 | name = XGetAtomName(dpy, act_type); | |||
144 | printf("\t... of unknown type '%s'\n", name); | |||
145 | XFree(name); | |||
146 | done = True1; | |||
147 | break; | |||
148 | } | |||
149 | ||||
150 | ptr += size; | |||
151 | ||||
152 | if (done == True1) | |||
153 | break; | |||
154 | if (j < nitems - 1) | |||
155 | printf(", "); | |||
156 | } | |||
157 | printf("\n"); | |||
158 | XFree(data); | |||
159 | } else | |||
160 | printf("\tFetch failure\n"); | |||
161 | ||||
162 | } | |||
163 | ||||
164 | static int | |||
165 | list_props_xi1(Display *dpy, int argc, char** argv, char* name, char *desc) | |||
166 | { | |||
167 | XDeviceInfo *info; | |||
168 | XDevice *dev; | |||
169 | int i; | |||
170 | int nprops; | |||
171 | Atom *props; | |||
172 | int rc = EXIT_SUCCESS0; | |||
173 | ||||
174 | if (argc == 0) | |||
175 | { | |||
176 | fprintf(stderr__stderrp, "Usage: xinput %s %s\n", name, desc); | |||
177 | return EXIT_FAILURE1; | |||
178 | } | |||
179 | ||||
180 | for (i = 0; i < argc; i++) | |||
181 | { | |||
182 | info = find_device_info(dpy, argv[i], False0); | |||
183 | if (!info) | |||
184 | { | |||
185 | fprintf(stderr__stderrp, "unable to find device '%s'\n", argv[i]); | |||
186 | rc = EXIT_FAILURE1; | |||
187 | continue; | |||
188 | } | |||
189 | ||||
190 | dev = XOpenDevice(dpy, info->id); | |||
191 | if (!dev) | |||
192 | { | |||
193 | fprintf(stderr__stderrp, "unable to open device '%s'\n", info->name); | |||
194 | rc = EXIT_FAILURE1; | |||
195 | continue; | |||
196 | } | |||
197 | ||||
198 | props = XListDeviceProperties(dpy, dev, &nprops); | |||
199 | if (!nprops) | |||
200 | { | |||
201 | printf("Device '%s' does not report any properties.\n", info->name); | |||
202 | continue; | |||
203 | } | |||
204 | ||||
205 | printf("Device '%s':\n", info->name); | |||
206 | while(nprops--) | |||
207 | { | |||
208 | print_property(dpy, dev, props[nprops]); | |||
209 | } | |||
210 | ||||
211 | XFree(props); | |||
212 | XCloseDevice(dpy, dev); | |||
213 | } | |||
214 | return rc; | |||
215 | } | |||
216 | ||||
217 | ||||
218 | int watch_props(Display *dpy, int argc, char** argv, char* n, char *desc) | |||
219 | { | |||
220 | XDevice *dev; | |||
221 | XDeviceInfo *info; | |||
222 | XEvent ev; | |||
223 | XDevicePropertyNotifyEvent *dpev; | |||
224 | char *name; | |||
225 | int type_prop; | |||
226 | XEventClass cls_prop; | |||
227 | ||||
228 | if (list_props(dpy, argc, argv, n, desc) != EXIT_SUCCESS0) | |||
229 | return EXIT_FAILURE1; | |||
230 | ||||
231 | info = find_device_info(dpy, argv[0], False0); | |||
232 | if (!info) | |||
233 | { | |||
234 | fprintf(stderr__stderrp, "unable to find device '%s'\n", argv[0]); | |||
235 | return EXIT_FAILURE1; | |||
236 | } | |||
237 | ||||
238 | dev = XOpenDevice(dpy, info->id); | |||
239 | if (!dev) | |||
240 | { | |||
241 | fprintf(stderr__stderrp, "unable to open device '%s'\n", info->name); | |||
242 | return EXIT_FAILURE1; | |||
243 | } | |||
244 | ||||
245 | DevicePropertyNotify(dev, type_prop, cls_prop){ int _i; XInputClassInfo *_ip; type_prop = 0; cls_prop = 0; for (_i=0, _ip= ((XDevice *) dev)->classes; _i< ((XDevice * ) dev)->num_classes; _i++, _ip++) if (_ip->input_class == 6) {type_prop = _ip->event_type_base + 6; cls_prop = ((XDevice *) dev)->device_id << 8 | type_prop;}}; | |||
246 | XSelectExtensionEvent(dpy, DefaultRootWindow(dpy)((&((_XPrivDisplay)(dpy))->screens[(((_XPrivDisplay)(dpy ))->default_screen)])->root), &cls_prop, 1); | |||
247 | ||||
248 | while(1) | |||
249 | { | |||
250 | XNextEvent(dpy, &ev); | |||
251 | ||||
252 | dpev = (XDevicePropertyNotifyEvent*)&ev; | |||
253 | if (dpev->type != type_prop) | |||
254 | continue; | |||
255 | ||||
256 | name = XGetAtomName(dpy, dpev->atom); | |||
257 | printf("Property '%s' changed.\n", name); | |||
258 | XFree(name); | |||
259 | print_property(dpy, dev, dpev->atom); | |||
260 | } | |||
261 | ||||
262 | XCloseDevice(dpy, dev); | |||
263 | } | |||
264 | ||||
265 | static int | |||
266 | delete_prop_xi1(Display *dpy, int argc, char** argv, char* n, char *desc) | |||
267 | { | |||
268 | XDevice *dev; | |||
269 | XDeviceInfo *info; | |||
270 | char *name; | |||
271 | Atom prop; | |||
272 | ||||
273 | info = find_device_info(dpy, argv[0], False0); | |||
274 | if (!info) | |||
275 | { | |||
276 | fprintf(stderr__stderrp, "unable to find device '%s'\n", argv[0]); | |||
277 | return EXIT_FAILURE1; | |||
278 | } | |||
279 | ||||
280 | dev = XOpenDevice(dpy, info->id); | |||
281 | if (!dev) | |||
282 | { | |||
283 | fprintf(stderr__stderrp, "unable to open device '%s'\n", info->name); | |||
284 | return EXIT_FAILURE1; | |||
285 | } | |||
286 | ||||
287 | name = argv[1]; | |||
288 | ||||
289 | prop = parse_atom(dpy, name); | |||
290 | ||||
291 | XDeleteDeviceProperty(dpy, dev, prop); | |||
292 | ||||
293 | XCloseDevice(dpy, dev); | |||
294 | return EXIT_SUCCESS0; | |||
295 | } | |||
296 | ||||
297 | static int | |||
298 | do_set_prop_xi1(Display *dpy, Atom type, int format, int argc, char **argv, char *n, char *desc) | |||
299 | { | |||
300 | XDeviceInfo *info; | |||
301 | XDevice *dev; | |||
302 | Atom prop; | |||
303 | Atom old_type; | |||
304 | char *name; | |||
305 | int i; | |||
306 | Atom float_atom; | |||
307 | int old_format, nelements = 0; | |||
308 | unsigned long act_nitems, bytes_after; | |||
309 | char *endptr; | |||
310 | union { | |||
311 | unsigned char *c; | |||
312 | short *s; | |||
313 | long *l; | |||
314 | Atom *a; | |||
315 | } data; | |||
316 | ||||
317 | if (argc < 3) | |||
318 | { | |||
319 | fprintf(stderr__stderrp, "Usage: xinput %s %s\n", n, desc); | |||
320 | return EXIT_FAILURE1; | |||
321 | } | |||
322 | ||||
323 | info = find_device_info(dpy, argv[0], False0); | |||
324 | if (!info) | |||
325 | { | |||
326 | fprintf(stderr__stderrp, "unable to find device '%s'\n", argv[0]); | |||
327 | return EXIT_FAILURE1; | |||
328 | } | |||
329 | ||||
330 | dev = XOpenDevice(dpy, info->id); | |||
331 | if (!dev) | |||
332 | { | |||
333 | fprintf(stderr__stderrp, "unable to open device '%s'\n", argv[0]); | |||
334 | return EXIT_FAILURE1; | |||
335 | } | |||
336 | ||||
337 | name = argv[1]; | |||
338 | ||||
339 | prop = parse_atom(dpy, name); | |||
340 | ||||
341 | if (prop == None0L) { | |||
342 | fprintf(stderr__stderrp, "invalid property '%s'\n", name); | |||
343 | return EXIT_FAILURE1; | |||
344 | } | |||
345 | ||||
346 | float_atom = XInternAtom(dpy, "FLOAT", False0); | |||
347 | ||||
348 | nelements = argc - 2; | |||
349 | if (type == None0L || format == 0) { | |||
350 | if (XGetDeviceProperty(dpy, dev, prop, 0, 0, False0, AnyPropertyType0L, | |||
351 | &old_type, &old_format, &act_nitems, | |||
352 | &bytes_after, &data.c) != Success0) { | |||
353 | fprintf(stderr__stderrp, "failed to get property type and format for '%s'\n", | |||
354 | name); | |||
355 | return EXIT_FAILURE1; | |||
356 | } else { | |||
357 | if (type == None0L) | |||
358 | type = old_type; | |||
359 | if (format == 0) | |||
360 | format = old_format; | |||
361 | } | |||
362 | ||||
363 | XFree(data.c); | |||
364 | } | |||
365 | ||||
366 | if (type == None0L) { | |||
367 | fprintf(stderr__stderrp, "property '%s' doesn't exist, you need to specify " | |||
368 | "its type and format\n", name); | |||
369 | return EXIT_FAILURE1; | |||
370 | } | |||
371 | ||||
372 | data.c = calloc(nelements, sizeof(long)); | |||
373 | ||||
374 | for (i = 0; i < nelements; i++) | |||
375 | { | |||
376 | if (type == XA_INTEGER((Atom) 19) || type == XA_CARDINAL((Atom) 6)) { | |||
377 | switch (format) | |||
378 | { | |||
379 | case 8: | |||
380 | data.c[i] = atoi(argv[2 + i]); | |||
381 | break; | |||
382 | case 16: | |||
383 | data.s[i] = atoi(argv[2 + i]); | |||
384 | break; | |||
385 | case 32: | |||
386 | data.l[i] = atoi(argv[2 + i]); | |||
387 | break; | |||
388 | default: | |||
389 | fprintf(stderr__stderrp, "unexpected size for property '%s'", name); | |||
| ||||
390 | return EXIT_FAILURE1; | |||
391 | } | |||
392 | } else if (type == float_atom) { | |||
393 | if (format != 32) { | |||
394 | fprintf(stderr__stderrp, "unexpected format %d for property '%s'\n", | |||
395 | format, name); | |||
396 | return EXIT_FAILURE1; | |||
397 | } | |||
398 | *(float *)(data.l + i) = strtod(argv[2 + i], &endptr); | |||
399 | if (endptr == argv[2 + i]) { | |||
400 | fprintf(stderr__stderrp, "argument '%s' could not be parsed\n", argv[2 + i]); | |||
401 | return EXIT_FAILURE1; | |||
402 | } | |||
403 | } else if (type == XA_ATOM((Atom) 4)) { | |||
404 | if (format != 32) { | |||
405 | fprintf(stderr__stderrp, "unexpected format %d for property '%s'\n", | |||
406 | format, name); | |||
407 | return EXIT_FAILURE1; | |||
408 | } | |||
409 | data.a[i] = parse_atom(dpy, argv[2 + i]); | |||
410 | } else { | |||
411 | fprintf(stderr__stderrp, "unexpected type for property '%s'\n", name); | |||
412 | return EXIT_FAILURE1; | |||
413 | } | |||
414 | } | |||
415 | ||||
416 | XChangeDeviceProperty(dpy, dev, prop, type, format, PropModeReplace0, | |||
417 | data.c, nelements); | |||
418 | free(data.c); | |||
419 | XCloseDevice(dpy, dev); | |||
420 | return EXIT_SUCCESS0; | |||
421 | } | |||
422 | ||||
423 | #if HAVE_XI21 | |||
424 | static void | |||
425 | print_property_xi2(Display *dpy, int deviceid, Atom property) | |||
426 | { | |||
427 | Atom act_type; | |||
428 | char *name; | |||
429 | int act_format; | |||
430 | unsigned long nitems, bytes_after; | |||
431 | unsigned char *data, *ptr; | |||
432 | int j, done = False0; | |||
433 | ||||
434 | name = XGetAtomName(dpy, property); | |||
435 | printf("\t%s (%ld):\t", name, property); | |||
436 | XFree(name); | |||
437 | ||||
438 | if (XIGetProperty(dpy, deviceid, property, 0, 1000, False0, | |||
439 | AnyPropertyType0L, &act_type, &act_format, | |||
440 | &nitems, &bytes_after, &data) == Success0) | |||
441 | { | |||
442 | Atom float_atom = XInternAtom(dpy, "FLOAT", True1); | |||
443 | ||||
444 | ptr = data; | |||
445 | ||||
446 | if (nitems == 0) | |||
447 | printf("<no items>"); | |||
448 | ||||
449 | for (j = 0; j < nitems; j++) | |||
450 | { | |||
451 | switch(act_type) | |||
452 | { | |||
453 | case XA_INTEGER((Atom) 19): | |||
454 | switch(act_format) | |||
455 | { | |||
456 | case 8: | |||
457 | printf("%d", *((int8_t*)ptr)); | |||
458 | break; | |||
459 | case 16: | |||
460 | printf("%d", *((int16_t*)ptr)); | |||
461 | break; | |||
462 | case 32: | |||
463 | printf("%d", *((int32_t*)ptr)); | |||
464 | break; | |||
465 | } | |||
466 | break; | |||
467 | case XA_CARDINAL((Atom) 6): | |||
468 | switch(act_format) | |||
469 | { | |||
470 | case 8: | |||
471 | printf("%u", *((uint8_t*)ptr)); | |||
472 | break; | |||
473 | case 16: | |||
474 | printf("%u", *((uint16_t*)ptr)); | |||
475 | break; | |||
476 | case 32: | |||
477 | printf("%u", *((uint32_t*)ptr)); | |||
478 | break; | |||
479 | } | |||
480 | break; | |||
481 | case XA_STRING((Atom) 31): | |||
482 | if (act_format != 8) | |||
483 | { | |||
484 | printf("Unknown string format.\n"); | |||
485 | done = True1; | |||
486 | break; | |||
487 | } | |||
488 | printf("\"%s\"", ptr); | |||
489 | j += strlen((char*)ptr); /* The loop's j++ jumps over the | |||
490 | terminating 0 */ | |||
491 | ptr += strlen((char*)ptr); /* ptr += size below jumps over | |||
492 | the terminating 0 */ | |||
493 | break; | |||
494 | case XA_ATOM((Atom) 4): | |||
495 | { | |||
496 | Atom a = *(uint32_t*)ptr; | |||
497 | name = (a) ? XGetAtomName(dpy, a) : NULL((void*)0); | |||
498 | printf("\"%s\" (%ld)", name ? name : "None", a); | |||
499 | XFree(name); | |||
500 | break; | |||
501 | } | |||
502 | break; | |||
503 | default: | |||
504 | if (float_atom != None0L && act_type == float_atom) | |||
505 | { | |||
506 | printf("%f", *((float*)ptr)); | |||
507 | break; | |||
508 | } | |||
509 | ||||
510 | name = XGetAtomName(dpy, act_type); | |||
511 | printf("\t... of unknown type %s\n", name); | |||
512 | XFree(name); | |||
513 | done = True1; | |||
514 | break; | |||
515 | } | |||
516 | ||||
517 | ptr += act_format/8; | |||
518 | ||||
519 | if (done == True1) | |||
520 | break; | |||
521 | if (j < nitems - 1) | |||
522 | printf(", "); | |||
523 | } | |||
524 | printf("\n"); | |||
525 | XFree(data); | |||
526 | } else | |||
527 | printf("\tFetch failure\n"); | |||
528 | ||||
529 | } | |||
530 | ||||
531 | static int | |||
532 | list_props_xi2(Display *dpy, int argc, char** argv, char* name, char *desc) | |||
533 | { | |||
534 | XIDeviceInfo *info; | |||
535 | int i; | |||
536 | int nprops; | |||
537 | Atom *props; | |||
538 | int rc = EXIT_SUCCESS0; | |||
539 | ||||
540 | if (argc == 0) | |||
541 | { | |||
542 | fprintf(stderr__stderrp, "Usage: xinput %s %s\n", name, desc); | |||
543 | return EXIT_FAILURE1; | |||
544 | } | |||
545 | ||||
546 | for (i = 0; i < argc; i++) | |||
547 | { | |||
548 | info = xi2_find_device_info(dpy, argv[i]); | |||
549 | if (!info) | |||
550 | { | |||
551 | fprintf(stderr__stderrp, "unable to find device %s\n", argv[i]); | |||
552 | rc = EXIT_FAILURE1; | |||
553 | continue; | |||
554 | } | |||
555 | ||||
556 | props = XIListProperties(dpy, info->deviceid, &nprops); | |||
557 | if (!nprops) | |||
558 | { | |||
559 | printf("Device '%s' does not report any properties.\n", info->name); | |||
560 | continue; | |||
561 | } | |||
562 | ||||
563 | printf("Device '%s':\n", info->name); | |||
564 | while(nprops--) | |||
565 | { | |||
566 | print_property_xi2(dpy, info->deviceid, props[nprops]); | |||
567 | } | |||
568 | ||||
569 | XFree(props); | |||
570 | } | |||
571 | return rc; | |||
572 | } | |||
573 | ||||
574 | static int | |||
575 | delete_prop_xi2(Display *dpy, int argc, char** argv, char* n, char *desc) | |||
576 | { | |||
577 | XIDeviceInfo *info; | |||
578 | char *name; | |||
579 | Atom prop; | |||
580 | ||||
581 | info = xi2_find_device_info(dpy, argv[0]); | |||
582 | if (!info) | |||
583 | { | |||
584 | fprintf(stderr__stderrp, "unable to find device %s\n", argv[0]); | |||
585 | return EXIT_FAILURE1; | |||
586 | } | |||
587 | ||||
588 | name = argv[1]; | |||
589 | ||||
590 | prop = parse_atom(dpy, name); | |||
591 | ||||
592 | XIDeleteProperty(dpy, info->deviceid, prop); | |||
593 | ||||
594 | return EXIT_SUCCESS0; | |||
595 | } | |||
596 | ||||
597 | static int | |||
598 | do_set_prop_xi2(Display *dpy, Atom type, int format, int argc, char **argv, char *n, char *desc) | |||
599 | { | |||
600 | XIDeviceInfo *info; | |||
601 | Atom prop; | |||
602 | Atom old_type; | |||
603 | char *name; | |||
604 | int i; | |||
605 | Atom float_atom; | |||
606 | int old_format, nelements = 0; | |||
607 | unsigned long act_nitems, bytes_after; | |||
608 | char *endptr; | |||
609 | union { | |||
610 | unsigned char *c; | |||
611 | int16_t *s; | |||
612 | int32_t *l; | |||
613 | } data; | |||
614 | ||||
615 | if (argc < 3) | |||
616 | { | |||
617 | fprintf(stderr__stderrp, "Usage: xinput %s %s\n", n, desc); | |||
618 | return EXIT_FAILURE1; | |||
619 | } | |||
620 | ||||
621 | info = xi2_find_device_info(dpy, argv[0]); | |||
622 | if (!info) | |||
623 | { | |||
624 | fprintf(stderr__stderrp, "unable to find device %s\n", argv[0]); | |||
625 | return EXIT_FAILURE1; | |||
626 | } | |||
627 | ||||
628 | name = argv[1]; | |||
629 | ||||
630 | prop = parse_atom(dpy, name); | |||
631 | ||||
632 | if (prop == None0L) { | |||
633 | fprintf(stderr__stderrp, "invalid property '%s'\n", name); | |||
634 | return EXIT_FAILURE1; | |||
635 | } | |||
636 | ||||
637 | float_atom = XInternAtom(dpy, "FLOAT", False0); | |||
638 | ||||
639 | nelements = argc - 2; | |||
640 | if (type == None0L || format == 0) { | |||
641 | if (XIGetProperty(dpy, info->deviceid, prop, 0, 0, False0, | |||
642 | AnyPropertyType0L, &old_type, &old_format, &act_nitems, | |||
643 | &bytes_after, &data.c) != Success0) { | |||
644 | fprintf(stderr__stderrp, "failed to get property type and format for '%s'\n", | |||
645 | name); | |||
646 | return EXIT_FAILURE1; | |||
647 | } else { | |||
648 | if (type == None0L) | |||
649 | type = old_type; | |||
650 | if (format == 0) | |||
651 | format = old_format; | |||
652 | } | |||
653 | ||||
654 | XFree(data.c); | |||
655 | } | |||
656 | ||||
657 | if (type == None0L) { | |||
658 | fprintf(stderr__stderrp, "property '%s' doesn't exist, you need to specify " | |||
659 | "its type and format\n", name); | |||
660 | return EXIT_FAILURE1; | |||
661 | } | |||
662 | ||||
663 | data.c = calloc(nelements, sizeof(int32_t)); | |||
664 | ||||
665 | for (i = 0; i < nelements; i++) | |||
666 | { | |||
667 | if (type == XA_INTEGER((Atom) 19) || type == XA_CARDINAL((Atom) 6)) { | |||
668 | switch (format) | |||
669 | { | |||
670 | case 8: | |||
671 | data.c[i] = atoi(argv[2 + i]); | |||
672 | break; | |||
673 | case 16: | |||
674 | data.s[i] = atoi(argv[2 + i]); | |||
675 | break; | |||
676 | case 32: | |||
677 | data.l[i] = atoi(argv[2 + i]); | |||
678 | break; | |||
679 | default: | |||
680 | fprintf(stderr__stderrp, "unexpected size for property %s", name); | |||
681 | return EXIT_FAILURE1; | |||
682 | } | |||
683 | } else if (type == float_atom) { | |||
684 | if (format != 32) { | |||
685 | fprintf(stderr__stderrp, "unexpected format %d for property '%s'\n", | |||
686 | format, name); | |||
687 | return EXIT_FAILURE1; | |||
688 | } | |||
689 | *(float *)(data.l + i) = strtod(argv[2 + i], &endptr); | |||
690 | if (endptr == argv[2 + i]) { | |||
691 | fprintf(stderr__stderrp, "argument %s could not be parsed\n", argv[2 + i]); | |||
692 | return EXIT_FAILURE1; | |||
693 | } | |||
694 | } else if (type == XA_ATOM((Atom) 4)) { | |||
695 | if (format != 32) { | |||
696 | fprintf(stderr__stderrp, "unexpected format %d for property '%s'\n", | |||
697 | format, name); | |||
698 | return EXIT_FAILURE1; | |||
699 | } | |||
700 | data.l[i] = parse_atom(dpy, argv[2 + i]); | |||
701 | } else { | |||
702 | fprintf(stderr__stderrp, "unexpected type for property '%s'\n", name); | |||
703 | return EXIT_FAILURE1; | |||
704 | } | |||
705 | } | |||
706 | ||||
707 | XIChangeProperty(dpy, info->deviceid, prop, type, format, PropModeReplace0, | |||
708 | data.c, nelements); | |||
709 | free(data.c); | |||
710 | return EXIT_SUCCESS0; | |||
711 | } | |||
712 | #endif | |||
713 | ||||
714 | int list_props(Display *display, int argc, char *argv[], char *name, | |||
715 | char *desc) | |||
716 | { | |||
717 | #ifdef HAVE_XI21 | |||
718 | if (xinput_version(display) == XI_2_Major2) | |||
719 | return list_props_xi2(display, argc, argv, name, desc); | |||
720 | #endif | |||
721 | return list_props_xi1(display, argc, argv, name, desc); | |||
722 | ||||
723 | } | |||
724 | ||||
725 | int delete_prop(Display *display, int argc, char *argv[], char *name, | |||
726 | char *desc) | |||
727 | { | |||
728 | #ifdef HAVE_XI21 | |||
729 | if (xinput_version(display) == XI_2_Major2) | |||
730 | return delete_prop_xi2(display, argc, argv, name, desc); | |||
731 | #endif | |||
732 | return delete_prop_xi1(display, argc, argv, name, desc); | |||
733 | ||||
734 | } | |||
735 | ||||
736 | static int | |||
737 | do_set_prop(Display *display, Atom type, int format, int argc, char *argv[], char *name, char *desc) | |||
738 | { | |||
739 | #ifdef HAVE_XI21 | |||
740 | if (xinput_version(display) == XI_2_Major2) | |||
741 | return do_set_prop_xi2(display, type, format, argc, argv, name, desc); | |||
742 | #endif | |||
743 | return do_set_prop_xi1(display, type, format, argc, argv, name, desc); | |||
744 | } | |||
745 | ||||
746 | int | |||
747 | set_atom_prop(Display *dpy, int argc, char** argv, char* n, char *desc) | |||
748 | { | |||
749 | return do_set_prop(dpy, XA_ATOM((Atom) 4), 32, argc, argv, n, desc); | |||
750 | } | |||
751 | ||||
752 | int | |||
753 | set_int_prop(Display *dpy, int argc, char** argv, char* n, char *desc) | |||
754 | { | |||
755 | int i; | |||
756 | int format; | |||
757 | ||||
758 | if (argc < 3) | |||
759 | { | |||
760 | fprintf(stderr__stderrp, "Usage: xinput %s %s\n", n, desc); | |||
761 | return EXIT_FAILURE1; | |||
762 | } | |||
763 | ||||
764 | format = atoi(argv[2]); | |||
765 | if (format != 8 && format != 16 && format != 32) | |||
766 | { | |||
767 | fprintf(stderr__stderrp, "Invalid format %d\n", format); | |||
768 | return EXIT_FAILURE1; | |||
769 | } | |||
770 | ||||
771 | for (i = 3; i < argc; i++) | |||
772 | argv[i - 1] = argv[i]; | |||
773 | ||||
774 | return do_set_prop(dpy, XA_INTEGER((Atom) 19), format, argc - 1, argv, n, desc); | |||
775 | } | |||
776 | ||||
777 | int | |||
778 | set_float_prop(Display *dpy, int argc, char** argv, char* n, char *desc) | |||
779 | { | |||
780 | Atom float_atom = XInternAtom(dpy, "FLOAT", False0); | |||
781 | ||||
782 | if (sizeof(float) != 4) | |||
783 | { | |||
784 | fprintf(stderr__stderrp, "sane FP required\n"); | |||
785 | return EXIT_FAILURE1; | |||
786 | } | |||
787 | ||||
788 | return do_set_prop(dpy, float_atom, 32, argc, argv, n, desc); | |||
789 | } | |||
790 | ||||
791 | int set_prop(Display *display, int argc, char *argv[], char *name, | |||
792 | char *desc) | |||
793 | { | |||
794 | Atom type = None0L; | |||
795 | int format = 0; | |||
796 | int i = 0, j; | |||
797 | ||||
798 | while (i < argc) { | |||
799 | char *option = strchr(argv[i], '='); | |||
800 | /* skip non-option arguments */ | |||
801 | if (strncmp(argv[i], "--", 2) || !option) { | |||
802 | i++; | |||
803 | continue; | |||
804 | } | |||
805 | ||||
806 | if (!strncmp(argv[i], "--type=", strlen("--type="))) { | |||
807 | if (!strcmp(option + 1, "int")) { | |||
808 | type = XA_INTEGER((Atom) 19); | |||
809 | } else if (!strcmp(option + 1, "float")) { | |||
810 | type = XInternAtom(display, "FLOAT", False0); | |||
811 | format = 32; | |||
812 | } else if (!strcmp(option + 1, "atom")) { | |||
813 | type = XA_ATOM((Atom) 4); | |||
814 | format = 32; | |||
815 | } else { | |||
816 | fprintf(stderr__stderrp, "unknown property type %s\n", option + 1); | |||
817 | return EXIT_FAILURE1; | |||
818 | } | |||
819 | } else if (!strncmp(argv[i], "--format=", strlen("--format="))) { | |||
820 | format = atoi(option + 1); | |||
821 | if (format != 8 && format != 16 && format != 32) { | |||
822 | fprintf(stderr__stderrp, "invalid property format '%s'\n", option + 1); | |||
823 | return EXIT_FAILURE1; | |||
824 | } | |||
825 | } else { | |||
826 | fprintf(stderr__stderrp, "invalid option '%s'\n", argv[i]); | |||
827 | return EXIT_FAILURE1; | |||
828 | } | |||
829 | ||||
830 | for (j = i; j + 1 < argc; j++) | |||
831 | argv[j] = argv[j + 1]; | |||
832 | argc--; | |||
833 | } | |||
834 | ||||
835 | return do_set_prop(display, type, format, argc, argv, name, desc); | |||
836 | } | |||
837 | ||||
838 | int disable(Display *display, int argc, char *argv[], char *name, char *desc) | |||
839 | { | |||
840 | char *new_argv[3] = { NULL((void*)0), "Device Enabled", "0" }; | |||
841 | ||||
842 | if (argc != 1) { | |||
843 | fprintf(stderr__stderrp, "Usage: xinput %s %s\n", name, desc); | |||
844 | return EXIT_FAILURE1; | |||
845 | } | |||
846 | ||||
847 | new_argv[0] = argv[0]; | |||
848 | ||||
849 | return set_prop(display, 3, new_argv, name, desc); | |||
850 | } | |||
851 | ||||
852 | int enable(Display *display, int argc, char *argv[], char *name, char *desc) | |||
853 | { | |||
854 | char *new_argv[3] = { NULL((void*)0), "Device Enabled", "1" }; | |||
855 | ||||
856 | if (argc != 1) { | |||
| ||||
857 | fprintf(stderr__stderrp, "Usage: xinput %s %s\n", name, desc); | |||
858 | return EXIT_FAILURE1; | |||
859 | } | |||
860 | ||||
861 | new_argv[0] = argv[0]; | |||
862 | ||||
863 | return set_prop(display, 3, new_argv, name, desc); | |||
864 | } |