xiquerydevice.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. /*
  2. * Copyright © 2009 Red Hat, Inc.
  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. * Authors: Peter Hutterer
  24. *
  25. */
  26. /**
  27. * @file Protocol handling for the XIQueryDevice request/reply.
  28. */
  29. #ifdef HAVE_DIX_CONFIG_H
  30. #include <dix-config.h>
  31. #endif
  32. #include "inputstr.h"
  33. #include <X11/X.h>
  34. #include <X11/Xatom.h>
  35. #include <X11/extensions/XI2proto.h>
  36. #include "xkbstr.h"
  37. #include "xkbsrv.h"
  38. #include "xserver-properties.h"
  39. #include "exevents.h"
  40. #include "xace.h"
  41. #include "inpututils.h"
  42. #include "xiquerydevice.h"
  43. static Bool ShouldSkipDevice(ClientPtr client, int deviceid, DeviceIntPtr d);
  44. static int
  45. ListDeviceInfo(ClientPtr client, DeviceIntPtr dev, xXIDeviceInfo * info);
  46. static int SizeDeviceInfo(DeviceIntPtr dev);
  47. static void SwapDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo * info);
  48. int
  49. SProcXIQueryDevice(ClientPtr client)
  50. {
  51. REQUEST(xXIQueryDeviceReq);
  52. REQUEST_SIZE_MATCH(xXIQueryDeviceReq);
  53. swaps(&stuff->length);
  54. swaps(&stuff->deviceid);
  55. return ProcXIQueryDevice(client);
  56. }
  57. int
  58. ProcXIQueryDevice(ClientPtr client)
  59. {
  60. xXIQueryDeviceReply rep;
  61. DeviceIntPtr dev = NULL;
  62. int rc = Success;
  63. int i = 0, len = 0;
  64. char *info, *ptr;
  65. Bool *skip = NULL;
  66. REQUEST(xXIQueryDeviceReq);
  67. REQUEST_SIZE_MATCH(xXIQueryDeviceReq);
  68. if (stuff->deviceid != XIAllDevices &&
  69. stuff->deviceid != XIAllMasterDevices) {
  70. rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGetAttrAccess);
  71. if (rc != Success) {
  72. client->errorValue = stuff->deviceid;
  73. return rc;
  74. }
  75. len += SizeDeviceInfo(dev);
  76. }
  77. else {
  78. skip = calloc(sizeof(Bool), inputInfo.numDevices);
  79. if (!skip)
  80. return BadAlloc;
  81. for (dev = inputInfo.devices; dev; dev = dev->next, i++) {
  82. skip[i] = ShouldSkipDevice(client, stuff->deviceid, dev);
  83. if (!skip[i])
  84. len += SizeDeviceInfo(dev);
  85. }
  86. for (dev = inputInfo.off_devices; dev; dev = dev->next, i++) {
  87. skip[i] = ShouldSkipDevice(client, stuff->deviceid, dev);
  88. if (!skip[i])
  89. len += SizeDeviceInfo(dev);
  90. }
  91. }
  92. info = calloc(1, len);
  93. if (!info) {
  94. free(skip);
  95. return BadAlloc;
  96. }
  97. rep = (xXIQueryDeviceReply) {
  98. .repType = X_Reply,
  99. .RepType = X_XIQueryDevice,
  100. .sequenceNumber = client->sequence,
  101. .length = len / 4,
  102. .num_devices = 0
  103. };
  104. ptr = info;
  105. if (dev) {
  106. len = ListDeviceInfo(client, dev, (xXIDeviceInfo *) info);
  107. if (client->swapped)
  108. SwapDeviceInfo(dev, (xXIDeviceInfo *) info);
  109. info += len;
  110. rep.num_devices = 1;
  111. }
  112. else {
  113. i = 0;
  114. for (dev = inputInfo.devices; dev; dev = dev->next, i++) {
  115. if (!skip[i]) {
  116. len = ListDeviceInfo(client, dev, (xXIDeviceInfo *) info);
  117. if (client->swapped)
  118. SwapDeviceInfo(dev, (xXIDeviceInfo *) info);
  119. info += len;
  120. rep.num_devices++;
  121. }
  122. }
  123. for (dev = inputInfo.off_devices; dev; dev = dev->next, i++) {
  124. if (!skip[i]) {
  125. len = ListDeviceInfo(client, dev, (xXIDeviceInfo *) info);
  126. if (client->swapped)
  127. SwapDeviceInfo(dev, (xXIDeviceInfo *) info);
  128. info += len;
  129. rep.num_devices++;
  130. }
  131. }
  132. }
  133. len = rep.length * 4;
  134. WriteReplyToClient(client, sizeof(xXIQueryDeviceReply), &rep);
  135. WriteToClient(client, len, ptr);
  136. free(ptr);
  137. free(skip);
  138. return rc;
  139. }
  140. void
  141. SRepXIQueryDevice(ClientPtr client, int size, xXIQueryDeviceReply * rep)
  142. {
  143. swaps(&rep->sequenceNumber);
  144. swapl(&rep->length);
  145. swaps(&rep->num_devices);
  146. /* Device info is already swapped, see ProcXIQueryDevice */
  147. WriteToClient(client, size, rep);
  148. }
  149. /**
  150. * @return Whether the device should be included in the returned list.
  151. */
  152. static Bool
  153. ShouldSkipDevice(ClientPtr client, int deviceid, DeviceIntPtr dev)
  154. {
  155. /* if all devices are not being queried, only master devices are */
  156. if (deviceid == XIAllDevices || IsMaster(dev)) {
  157. int rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGetAttrAccess);
  158. if (rc == Success)
  159. return FALSE;
  160. }
  161. return TRUE;
  162. }
  163. /**
  164. * @return The number of bytes needed to store this device's xXIDeviceInfo
  165. * (and its classes).
  166. */
  167. static int
  168. SizeDeviceInfo(DeviceIntPtr dev)
  169. {
  170. int len = sizeof(xXIDeviceInfo);
  171. /* 4-padded name */
  172. len += pad_to_int32(strlen(dev->name));
  173. return len + SizeDeviceClasses(dev);
  174. }
  175. /*
  176. * @return The number of bytes needed to store this device's classes.
  177. */
  178. int
  179. SizeDeviceClasses(DeviceIntPtr dev)
  180. {
  181. int len = 0;
  182. if (dev->button) {
  183. len += sizeof(xXIButtonInfo);
  184. len += dev->button->numButtons * sizeof(Atom);
  185. len += pad_to_int32(bits_to_bytes(dev->button->numButtons));
  186. }
  187. if (dev->key) {
  188. XkbDescPtr xkb = dev->key->xkbInfo->desc;
  189. len += sizeof(xXIKeyInfo);
  190. len += (xkb->max_key_code - xkb->min_key_code + 1) * sizeof(uint32_t);
  191. }
  192. if (dev->valuator) {
  193. int i;
  194. len += (sizeof(xXIValuatorInfo)) * dev->valuator->numAxes;
  195. for (i = 0; i < dev->valuator->numAxes; i++) {
  196. if (dev->valuator->axes[i].scroll.type != SCROLL_TYPE_NONE)
  197. len += sizeof(xXIScrollInfo);
  198. }
  199. }
  200. if (dev->touch)
  201. len += sizeof(xXITouchInfo);
  202. return len;
  203. }
  204. /**
  205. * Write button information into info.
  206. * @return Number of bytes written into info.
  207. */
  208. int
  209. ListButtonInfo(DeviceIntPtr dev, xXIButtonInfo * info, Bool reportState)
  210. {
  211. unsigned char *bits;
  212. int mask_len;
  213. int i;
  214. if (!dev || !dev->button)
  215. return 0;
  216. mask_len = bytes_to_int32(bits_to_bytes(dev->button->numButtons));
  217. info->type = ButtonClass;
  218. info->num_buttons = dev->button->numButtons;
  219. info->length = bytes_to_int32(sizeof(xXIButtonInfo)) +
  220. info->num_buttons + mask_len;
  221. info->sourceid = dev->button->sourceid;
  222. bits = (unsigned char *) &info[1];
  223. memset(bits, 0, mask_len * 4);
  224. if (reportState)
  225. for (i = 0; i < dev->button->numButtons; i++)
  226. if (BitIsOn(dev->button->down, i))
  227. SetBit(bits, i);
  228. bits += mask_len * 4;
  229. memcpy(bits, dev->button->labels, dev->button->numButtons * sizeof(Atom));
  230. return info->length * 4;
  231. }
  232. static void
  233. SwapButtonInfo(DeviceIntPtr dev, xXIButtonInfo * info)
  234. {
  235. Atom *btn;
  236. int i;
  237. swaps(&info->type);
  238. swaps(&info->length);
  239. swaps(&info->sourceid);
  240. for (i = 0, btn = (Atom *) &info[1]; i < info->num_buttons; i++, btn++)
  241. swapl(btn);
  242. swaps(&info->num_buttons);
  243. }
  244. /**
  245. * Write key information into info.
  246. * @return Number of bytes written into info.
  247. */
  248. int
  249. ListKeyInfo(DeviceIntPtr dev, xXIKeyInfo * info)
  250. {
  251. int i;
  252. XkbDescPtr xkb = dev->key->xkbInfo->desc;
  253. uint32_t *kc;
  254. info->type = KeyClass;
  255. info->num_keycodes = xkb->max_key_code - xkb->min_key_code + 1;
  256. info->length = sizeof(xXIKeyInfo) / 4 + info->num_keycodes;
  257. info->sourceid = dev->key->sourceid;
  258. kc = (uint32_t *) &info[1];
  259. for (i = xkb->min_key_code; i <= xkb->max_key_code; i++, kc++)
  260. *kc = i;
  261. return info->length * 4;
  262. }
  263. static void
  264. SwapKeyInfo(DeviceIntPtr dev, xXIKeyInfo * info)
  265. {
  266. uint32_t *key;
  267. int i;
  268. swaps(&info->type);
  269. swaps(&info->length);
  270. swaps(&info->sourceid);
  271. for (i = 0, key = (uint32_t *) &info[1]; i < info->num_keycodes;
  272. i++, key++)
  273. swapl(key);
  274. swaps(&info->num_keycodes);
  275. }
  276. /**
  277. * List axis information for the given axis.
  278. *
  279. * @return The number of bytes written into info.
  280. */
  281. int
  282. ListValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo * info, int axisnumber,
  283. Bool reportState)
  284. {
  285. ValuatorClassPtr v = dev->valuator;
  286. info->type = ValuatorClass;
  287. info->length = sizeof(xXIValuatorInfo) / 4;
  288. info->label = v->axes[axisnumber].label;
  289. info->min.integral = v->axes[axisnumber].min_value;
  290. info->min.frac = 0;
  291. info->max.integral = v->axes[axisnumber].max_value;
  292. info->max.frac = 0;
  293. info->value = double_to_fp3232(v->axisVal[axisnumber]);
  294. info->resolution = v->axes[axisnumber].resolution;
  295. info->number = axisnumber;
  296. info->mode = valuator_get_mode(dev, axisnumber);
  297. info->sourceid = v->sourceid;
  298. if (!reportState)
  299. info->value = info->min;
  300. return info->length * 4;
  301. }
  302. static void
  303. SwapValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo * info)
  304. {
  305. swaps(&info->type);
  306. swaps(&info->length);
  307. swapl(&info->label);
  308. swapl(&info->min.integral);
  309. swapl(&info->min.frac);
  310. swapl(&info->max.integral);
  311. swapl(&info->max.frac);
  312. swaps(&info->number);
  313. swaps(&info->sourceid);
  314. }
  315. int
  316. ListScrollInfo(DeviceIntPtr dev, xXIScrollInfo * info, int axisnumber)
  317. {
  318. ValuatorClassPtr v = dev->valuator;
  319. AxisInfoPtr axis = &v->axes[axisnumber];
  320. if (axis->scroll.type == SCROLL_TYPE_NONE)
  321. return 0;
  322. info->type = XIScrollClass;
  323. info->length = sizeof(xXIScrollInfo) / 4;
  324. info->number = axisnumber;
  325. switch (axis->scroll.type) {
  326. case SCROLL_TYPE_VERTICAL:
  327. info->scroll_type = XIScrollTypeVertical;
  328. break;
  329. case SCROLL_TYPE_HORIZONTAL:
  330. info->scroll_type = XIScrollTypeHorizontal;
  331. break;
  332. default:
  333. ErrorF("[Xi] Unknown scroll type %d. This is a bug.\n",
  334. axis->scroll.type);
  335. break;
  336. }
  337. info->increment = double_to_fp3232(axis->scroll.increment);
  338. info->sourceid = v->sourceid;
  339. info->flags = 0;
  340. if (axis->scroll.flags & SCROLL_FLAG_DONT_EMULATE)
  341. info->flags |= XIScrollFlagNoEmulation;
  342. if (axis->scroll.flags & SCROLL_FLAG_PREFERRED)
  343. info->flags |= XIScrollFlagPreferred;
  344. return info->length * 4;
  345. }
  346. static void
  347. SwapScrollInfo(DeviceIntPtr dev, xXIScrollInfo * info)
  348. {
  349. swaps(&info->type);
  350. swaps(&info->length);
  351. swaps(&info->number);
  352. swaps(&info->sourceid);
  353. swaps(&info->scroll_type);
  354. swapl(&info->increment.integral);
  355. swapl(&info->increment.frac);
  356. }
  357. /**
  358. * List multitouch information
  359. *
  360. * @return The number of bytes written into info.
  361. */
  362. int
  363. ListTouchInfo(DeviceIntPtr dev, xXITouchInfo * touch)
  364. {
  365. touch->type = XITouchClass;
  366. touch->length = sizeof(xXITouchInfo) >> 2;
  367. touch->sourceid = dev->touch->sourceid;
  368. touch->mode = dev->touch->mode;
  369. touch->num_touches = dev->touch->num_touches;
  370. return touch->length << 2;
  371. }
  372. static void
  373. SwapTouchInfo(DeviceIntPtr dev, xXITouchInfo * touch)
  374. {
  375. swaps(&touch->type);
  376. swaps(&touch->length);
  377. swaps(&touch->sourceid);
  378. }
  379. int
  380. GetDeviceUse(DeviceIntPtr dev, uint16_t * attachment)
  381. {
  382. DeviceIntPtr master = GetMaster(dev, MASTER_ATTACHED);
  383. int use;
  384. if (IsMaster(dev)) {
  385. DeviceIntPtr paired = GetPairedDevice(dev);
  386. use = IsPointerDevice(dev) ? XIMasterPointer : XIMasterKeyboard;
  387. *attachment = (paired ? paired->id : 0);
  388. }
  389. else if (!IsFloating(dev)) {
  390. use = IsPointerDevice(master) ? XISlavePointer : XISlaveKeyboard;
  391. *attachment = master->id;
  392. }
  393. else
  394. use = XIFloatingSlave;
  395. return use;
  396. }
  397. /**
  398. * Write the info for device dev into the buffer pointed to by info.
  399. *
  400. * @return The number of bytes used.
  401. */
  402. static int
  403. ListDeviceInfo(ClientPtr client, DeviceIntPtr dev, xXIDeviceInfo * info)
  404. {
  405. char *any = (char *) &info[1];
  406. int len = 0, total_len = 0;
  407. info->deviceid = dev->id;
  408. info->use = GetDeviceUse(dev, &info->attachment);
  409. info->num_classes = 0;
  410. info->name_len = strlen(dev->name);
  411. info->enabled = dev->enabled;
  412. total_len = sizeof(xXIDeviceInfo);
  413. len = pad_to_int32(info->name_len);
  414. memset(any, 0, len);
  415. strncpy(any, dev->name, info->name_len);
  416. any += len;
  417. total_len += len;
  418. total_len += ListDeviceClasses(client, dev, any, &info->num_classes);
  419. return total_len;
  420. }
  421. /**
  422. * Write the class info of the device into the memory pointed to by any, set
  423. * nclasses to the number of classes in total and return the number of bytes
  424. * written.
  425. */
  426. int
  427. ListDeviceClasses(ClientPtr client, DeviceIntPtr dev,
  428. char *any, uint16_t * nclasses)
  429. {
  430. int total_len = 0;
  431. int len;
  432. int i;
  433. int rc;
  434. /* Check if the current device state should be suppressed */
  435. rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess);
  436. if (dev->button) {
  437. (*nclasses)++;
  438. len = ListButtonInfo(dev, (xXIButtonInfo *) any, rc == Success);
  439. any += len;
  440. total_len += len;
  441. }
  442. if (dev->key) {
  443. (*nclasses)++;
  444. len = ListKeyInfo(dev, (xXIKeyInfo *) any);
  445. any += len;
  446. total_len += len;
  447. }
  448. for (i = 0; dev->valuator && i < dev->valuator->numAxes; i++) {
  449. (*nclasses)++;
  450. len = ListValuatorInfo(dev, (xXIValuatorInfo *) any, i, rc == Success);
  451. any += len;
  452. total_len += len;
  453. }
  454. for (i = 0; dev->valuator && i < dev->valuator->numAxes; i++) {
  455. len = ListScrollInfo(dev, (xXIScrollInfo *) any, i);
  456. if (len)
  457. (*nclasses)++;
  458. any += len;
  459. total_len += len;
  460. }
  461. if (dev->touch) {
  462. (*nclasses)++;
  463. len = ListTouchInfo(dev, (xXITouchInfo *) any);
  464. any += len;
  465. total_len += len;
  466. }
  467. return total_len;
  468. }
  469. static void
  470. SwapDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo * info)
  471. {
  472. char *any = (char *) &info[1];
  473. int i;
  474. /* Skip over name */
  475. any += pad_to_int32(info->name_len);
  476. for (i = 0; i < info->num_classes; i++) {
  477. int len = ((xXIAnyInfo *) any)->length;
  478. switch (((xXIAnyInfo *) any)->type) {
  479. case XIButtonClass:
  480. SwapButtonInfo(dev, (xXIButtonInfo *) any);
  481. break;
  482. case XIKeyClass:
  483. SwapKeyInfo(dev, (xXIKeyInfo *) any);
  484. break;
  485. case XIValuatorClass:
  486. SwapValuatorInfo(dev, (xXIValuatorInfo *) any);
  487. break;
  488. case XIScrollClass:
  489. SwapScrollInfo(dev, (xXIScrollInfo *) any);
  490. break;
  491. case XITouchClass:
  492. SwapTouchInfo(dev, (xXITouchInfo *) any);
  493. break;
  494. }
  495. any += len * 4;
  496. }
  497. swaps(&info->deviceid);
  498. swaps(&info->use);
  499. swaps(&info->attachment);
  500. swaps(&info->num_classes);
  501. swaps(&info->name_len);
  502. }