Mirror of strace – the linux syscall tracer
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

evdev.c 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. /*
  2. * Copyright (c) 2015 Etienne Gemsa <etienne.gemsa@lse.epita.fr>
  3. * Copyright (c) 2015-2016 Dmitry V. Levin <ldv@altlinux.org>
  4. * Copyright (c) 2015-2018 The strace developers.
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. The name of the author may not be used to endorse or promote products
  16. * derived from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  19. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  20. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  21. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  23. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  24. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  25. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  27. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. */
  29. #include "defs.h"
  30. #include "xlat/evdev_abs.h"
  31. #ifdef HAVE_LINUX_INPUT_H
  32. # include <linux/ioctl.h>
  33. # include <linux/input.h>
  34. # include "xlat/evdev_autorepeat.h"
  35. # include "xlat/evdev_ff_status.h"
  36. # include "xlat/evdev_ff_types.h"
  37. # include "xlat/evdev_keycode.h"
  38. # include "xlat/evdev_leds.h"
  39. # include "xlat/evdev_misc.h"
  40. # include "xlat/evdev_mtslots.h"
  41. # include "xlat/evdev_prop.h"
  42. # include "xlat/evdev_relative_axes.h"
  43. # include "xlat/evdev_snd.h"
  44. # include "xlat/evdev_switch.h"
  45. # include "xlat/evdev_sync.h"
  46. # ifndef SYN_MAX
  47. # define SYN_MAX 0xf
  48. # endif
  49. const size_t evdev_abs_size = ARRAY_SIZE(evdev_abs) - 1;
  50. static int
  51. abs_ioctl(struct tcb *const tcp, const kernel_ulong_t arg)
  52. {
  53. tprints(", ");
  54. struct input_absinfo absinfo;
  55. if (!umove_or_printaddr(tcp, arg, &absinfo)) {
  56. tprintf("{value=%u"
  57. ", minimum=%u, ",
  58. absinfo.value,
  59. absinfo.minimum);
  60. if (!abbrev(tcp)) {
  61. tprintf("maximum=%u"
  62. ", fuzz=%u"
  63. ", flat=%u",
  64. absinfo.maximum,
  65. absinfo.fuzz,
  66. absinfo.flat);
  67. # ifdef HAVE_STRUCT_INPUT_ABSINFO_RESOLUTION
  68. tprintf(", resolution=%u",
  69. absinfo.resolution);
  70. # endif
  71. } else {
  72. tprints("...");
  73. }
  74. tprints("}");
  75. }
  76. return RVAL_IOCTL_DECODED;
  77. }
  78. static int
  79. keycode_ioctl(struct tcb *const tcp, const kernel_ulong_t arg)
  80. {
  81. tprints(", ");
  82. unsigned int keycode[2];
  83. if (!umove_or_printaddr(tcp, arg, &keycode)) {
  84. tprintf("[%u, ", keycode[0]);
  85. printxval_index(evdev_keycode, keycode[1], "KEY_???");
  86. tprints("]");
  87. }
  88. return RVAL_IOCTL_DECODED;
  89. }
  90. # ifdef EVIOCGKEYCODE_V2
  91. static int
  92. keycode_V2_ioctl(struct tcb *const tcp, const kernel_ulong_t arg)
  93. {
  94. tprints(", ");
  95. struct input_keymap_entry ike;
  96. if (umove_or_printaddr(tcp, arg, &ike))
  97. return RVAL_IOCTL_DECODED;
  98. tprintf("{flags=%" PRIu8
  99. ", len=%" PRIu8 ", ",
  100. ike.flags,
  101. ike.len);
  102. if (!abbrev(tcp)) {
  103. unsigned int i;
  104. tprintf("index=%" PRIu16 ", keycode=", ike.index);
  105. printxval_index(evdev_keycode, ike.keycode, "KEY_???");
  106. tprints(", scancode=[");
  107. for (i = 0; i < ARRAY_SIZE(ike.scancode); i++) {
  108. if (i > 0)
  109. tprints(", ");
  110. tprintf("%" PRIx8, ike.scancode[i]);
  111. }
  112. tprints("]");
  113. } else {
  114. tprints("...");
  115. }
  116. tprints("}");
  117. return RVAL_IOCTL_DECODED;
  118. }
  119. # endif /* EVIOCGKEYCODE_V2 */
  120. static int
  121. getid_ioctl(struct tcb *const tcp, const kernel_ulong_t arg)
  122. {
  123. tprints(", ");
  124. struct input_id id;
  125. if (!umove_or_printaddr(tcp, arg, &id))
  126. tprintf("{ID_BUS=%" PRIu16
  127. ", ID_VENDOR=%" PRIu16
  128. ", ID_PRODUCT=%" PRIu16
  129. ", ID_VERSION=%" PRIu16 "}",
  130. id.bustype,
  131. id.vendor,
  132. id.product,
  133. id.version);
  134. return RVAL_IOCTL_DECODED;
  135. }
  136. static int
  137. decode_bitset_(struct tcb *const tcp, const kernel_ulong_t arg,
  138. const struct xlat decode_nr[], const unsigned int max_nr,
  139. const char *const dflt, size_t decode_nr_size, enum xlat_type xt)
  140. {
  141. tprints(", ");
  142. unsigned int size;
  143. if ((kernel_ulong_t) tcp->u_rval > max_nr)
  144. size = max_nr;
  145. else
  146. size = tcp->u_rval;
  147. char decoded_arg[size];
  148. if (umove_or_printaddr(tcp, arg, &decoded_arg))
  149. return RVAL_IOCTL_DECODED;
  150. tprints("[");
  151. int bit_displayed = 0;
  152. int i = next_set_bit(decoded_arg, 0, size);
  153. if (i < 0) {
  154. tprints(" 0 ");
  155. } else {
  156. printxval_dispatch(decode_nr, decode_nr_size, i, dflt, xt);
  157. while ((i = next_set_bit(decoded_arg, i + 1, size)) > 0) {
  158. if (abbrev(tcp) && bit_displayed >= 3) {
  159. tprints(", ...");
  160. break;
  161. }
  162. tprints(", ");
  163. printxval_dispatch(decode_nr, decode_nr_size, i, dflt,
  164. xt);
  165. bit_displayed++;
  166. }
  167. }
  168. tprints("]");
  169. return RVAL_IOCTL_DECODED;
  170. }
  171. #define decode_bitset(tcp_, arg_, decode_nr_, max_nr_, dflt_, xt_) \
  172. decode_bitset_((tcp_), (arg_), (decode_nr_), (max_nr_), \
  173. (dflt_), ARRAY_SIZE(decode_nr_), (xt_))
  174. # ifdef EVIOCGMTSLOTS
  175. static int
  176. mtslots_ioctl(struct tcb *const tcp, const unsigned int code,
  177. const kernel_ulong_t arg)
  178. {
  179. tprints(", ");
  180. const size_t size = _IOC_SIZE(code) / sizeof(int);
  181. if (!size) {
  182. printaddr(arg);
  183. return RVAL_IOCTL_DECODED;
  184. }
  185. int buffer[size];
  186. if (umove_or_printaddr(tcp, arg, &buffer))
  187. return RVAL_IOCTL_DECODED;
  188. tprints("{code=");
  189. printxval(evdev_mtslots, buffer[0], "ABS_MT_???");
  190. tprints(", values=[");
  191. unsigned int i;
  192. for (i = 1; i < ARRAY_SIZE(buffer); i++)
  193. tprintf("%s%d", i > 1 ? ", " : "", buffer[i]);
  194. tprints("]}");
  195. return RVAL_IOCTL_DECODED;
  196. }
  197. # endif /* EVIOCGMTSLOTS */
  198. # if defined EVIOCGREP || defined EVIOCSREP
  199. static int
  200. repeat_ioctl(struct tcb *const tcp, const kernel_ulong_t arg)
  201. {
  202. tprints(", ");
  203. printpair_int(tcp, arg, "%u");
  204. return RVAL_IOCTL_DECODED;
  205. }
  206. # endif /* EVIOCGREP || EVIOCSREP */
  207. static int
  208. bit_ioctl(struct tcb *const tcp, const unsigned int ev_nr,
  209. const kernel_ulong_t arg)
  210. {
  211. switch (ev_nr) {
  212. case EV_SYN:
  213. return decode_bitset(tcp, arg, evdev_sync,
  214. SYN_MAX, "SYN_???", XT_INDEXED);
  215. case EV_KEY:
  216. return decode_bitset(tcp, arg, evdev_keycode,
  217. KEY_MAX, "KEY_???", XT_INDEXED);
  218. case EV_REL:
  219. return decode_bitset(tcp, arg, evdev_relative_axes,
  220. REL_MAX, "REL_???", XT_INDEXED);
  221. case EV_ABS:
  222. return decode_bitset(tcp, arg, evdev_abs,
  223. ABS_MAX, "ABS_???", XT_INDEXED);
  224. case EV_MSC:
  225. return decode_bitset(tcp, arg, evdev_misc,
  226. MSC_MAX, "MSC_???", XT_INDEXED);
  227. case EV_SW:
  228. return decode_bitset(tcp, arg, evdev_switch,
  229. SW_MAX, "SW_???", XT_INDEXED);
  230. case EV_LED:
  231. return decode_bitset(tcp, arg, evdev_leds,
  232. LED_MAX, "LED_???", XT_INDEXED);
  233. case EV_SND:
  234. return decode_bitset(tcp, arg, evdev_snd,
  235. SND_MAX, "SND_???", XT_INDEXED);
  236. case EV_REP:
  237. return decode_bitset(tcp, arg, evdev_autorepeat,
  238. REP_MAX, "REP_???", XT_INDEXED);
  239. case EV_FF:
  240. return decode_bitset(tcp, arg, evdev_ff_types,
  241. FF_MAX, "FF_???", XT_SORTED);
  242. case EV_PWR:
  243. tprints(", ");
  244. printnum_int(tcp, arg, "%d");
  245. return RVAL_IOCTL_DECODED;
  246. case EV_FF_STATUS:
  247. return decode_bitset(tcp, arg, evdev_ff_status,
  248. FF_STATUS_MAX, "FF_STATUS_???",
  249. XT_INDEXED);
  250. default:
  251. tprints(", ");
  252. printaddr(arg);
  253. return RVAL_IOCTL_DECODED;
  254. }
  255. }
  256. static int
  257. evdev_read_ioctl(struct tcb *const tcp, const unsigned int code,
  258. const kernel_ulong_t arg)
  259. {
  260. /* fixed-number fixed-length commands */
  261. switch (code) {
  262. case EVIOCGVERSION:
  263. tprints(", ");
  264. printnum_int(tcp, arg, "%#x");
  265. return RVAL_IOCTL_DECODED;
  266. case EVIOCGEFFECTS:
  267. tprints(", ");
  268. printnum_int(tcp, arg, "%u");
  269. return RVAL_IOCTL_DECODED;
  270. case EVIOCGID:
  271. return getid_ioctl(tcp, arg);
  272. # ifdef EVIOCGREP
  273. case EVIOCGREP:
  274. return repeat_ioctl(tcp, arg);
  275. # endif
  276. case EVIOCGKEYCODE:
  277. return keycode_ioctl(tcp, arg);
  278. # ifdef EVIOCGKEYCODE_V2
  279. case EVIOCGKEYCODE_V2:
  280. return keycode_V2_ioctl(tcp, arg);
  281. # endif
  282. }
  283. /* fixed-number variable-length commands */
  284. switch (_IOC_NR(code)) {
  285. # ifdef EVIOCGMTSLOTS
  286. case _IOC_NR(EVIOCGMTSLOTS(0)):
  287. return mtslots_ioctl(tcp, code, arg);
  288. # endif
  289. case _IOC_NR(EVIOCGNAME(0)):
  290. case _IOC_NR(EVIOCGPHYS(0)):
  291. case _IOC_NR(EVIOCGUNIQ(0)):
  292. tprints(", ");
  293. if (syserror(tcp))
  294. printaddr(arg);
  295. else
  296. printstrn(tcp, arg, tcp->u_rval);
  297. return RVAL_IOCTL_DECODED;
  298. # ifdef EVIOCGPROP
  299. case _IOC_NR(EVIOCGPROP(0)):
  300. return decode_bitset(tcp, arg, evdev_prop,
  301. INPUT_PROP_MAX, "PROP_???",
  302. XT_INDEXED);
  303. # endif
  304. case _IOC_NR(EVIOCGSND(0)):
  305. return decode_bitset(tcp, arg, evdev_snd,
  306. SND_MAX, "SND_???", XT_INDEXED);
  307. # ifdef EVIOCGSW
  308. case _IOC_NR(EVIOCGSW(0)):
  309. return decode_bitset(tcp, arg, evdev_switch,
  310. SW_MAX, "SW_???", XT_INDEXED);
  311. # endif
  312. case _IOC_NR(EVIOCGKEY(0)):
  313. return decode_bitset(tcp, arg, evdev_keycode,
  314. KEY_MAX, "KEY_???", XT_INDEXED);
  315. case _IOC_NR(EVIOCGLED(0)):
  316. return decode_bitset(tcp, arg, evdev_leds,
  317. LED_MAX, "LED_???", XT_INDEXED);
  318. }
  319. /* multi-number fixed-length commands */
  320. if ((_IOC_NR(code) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0)))
  321. return abs_ioctl(tcp, arg);
  322. /* multi-number variable-length commands */
  323. if ((_IOC_NR(code) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0)))
  324. return bit_ioctl(tcp, _IOC_NR(code) & EV_MAX, arg);
  325. return 0;
  326. }
  327. static int
  328. evdev_write_ioctl(struct tcb *const tcp, const unsigned int code,
  329. const kernel_ulong_t arg)
  330. {
  331. /* fixed-number fixed-length commands */
  332. switch (code) {
  333. # ifdef EVIOCSREP
  334. case EVIOCSREP:
  335. return repeat_ioctl(tcp, arg);
  336. # endif
  337. case EVIOCSKEYCODE:
  338. return keycode_ioctl(tcp, arg);
  339. # ifdef EVIOCSKEYCODE_V2
  340. case EVIOCSKEYCODE_V2:
  341. return keycode_V2_ioctl(tcp, arg);
  342. # endif
  343. case EVIOCRMFF:
  344. tprintf(", %d", (int) arg);
  345. return RVAL_IOCTL_DECODED;
  346. case EVIOCGRAB:
  347. # ifdef EVIOCREVOKE
  348. case EVIOCREVOKE:
  349. # endif
  350. tprintf(", %" PRI_klu, arg);
  351. return RVAL_IOCTL_DECODED;
  352. # ifdef EVIOCSCLOCKID
  353. case EVIOCSCLOCKID:
  354. tprints(", ");
  355. printnum_int(tcp, arg, "%u");
  356. return RVAL_IOCTL_DECODED;
  357. # endif
  358. default: {
  359. int rc = evdev_write_ioctl_mpers(tcp, code, arg);
  360. if (rc != RVAL_DECODED)
  361. return rc;
  362. }
  363. }
  364. /* multi-number fixed-length commands */
  365. if ((_IOC_NR(code) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0)))
  366. return abs_ioctl(tcp, arg);
  367. return 0;
  368. }
  369. void
  370. print_evdev_ff_type(const kernel_ulong_t val)
  371. {
  372. printxval(evdev_ff_types, val, "FF_???");
  373. }
  374. int
  375. evdev_ioctl(struct tcb *const tcp,
  376. const unsigned int code, const kernel_ulong_t arg)
  377. {
  378. switch (_IOC_DIR(code)) {
  379. case _IOC_READ:
  380. if (entering(tcp))
  381. return 0;
  382. return evdev_read_ioctl(tcp, code, arg);
  383. case _IOC_WRITE:
  384. return evdev_write_ioctl(tcp, code, arg) | RVAL_DECODED;
  385. default:
  386. return RVAL_DECODED;
  387. }
  388. }
  389. #endif /* HAVE_LINUX_INPUT_H */