libinput-record.c 67 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857
  1. /*
  2. * Copyright © 2018 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. #include "config.h"
  24. #include <dirent.h>
  25. #include <errno.h>
  26. #include <fcntl.h>
  27. #include <getopt.h>
  28. #include <inttypes.h>
  29. #include <libevdev/libevdev.h>
  30. #include <libudev.h>
  31. #include <linux/input.h>
  32. #include <poll.h>
  33. #include <signal.h>
  34. #include <stdbool.h>
  35. #include <string.h>
  36. #include <sys/epoll.h>
  37. #include <sys/signalfd.h>
  38. #include <sys/stat.h>
  39. #include <sys/utsname.h>
  40. #include <time.h>
  41. #include <unistd.h>
  42. #include "util-bits.h"
  43. #include "util-files.h"
  44. #include "util-input-event.h"
  45. #include "util-list.h"
  46. #include "util-macros.h"
  47. #include "util-mem.h"
  48. #include "util-strings.h"
  49. #include "util-time.h"
  50. #include "util-udev.h"
  51. #include "builddir.h"
  52. #include "libinput-git-version.h"
  53. #include "libinput-util.h"
  54. #include "libinput-version.h"
  55. #include "libinput-versionsort.h"
  56. #include "shared.h"
  57. static const int FILE_VERSION_NUMBER = 1;
  58. /* Indentation levels for the various data nodes */
  59. enum indent {
  60. I_NONE = 0,
  61. I_TOPLEVEL = 0,
  62. I_LIBINPUT = 2, /* nodes inside libinput: */
  63. I_SYSTEM = 2, /* nodes inside system: */
  64. I_DEVICE = 2, /* nodes inside devices: */
  65. I_EVDEV = 4, /* nodes inside evdev: */
  66. I_EVDEV_DATA = 6, /* nodes below evdev: */
  67. I_UDEV = 4, /* nodes inside udev: */
  68. I_UDEV_DATA = 6, /* nodes below udev: */
  69. I_QUIRKS = 4, /* nodes inside quirks: */
  70. I_LIBINPUTDEV = 4, /* nodes inside libinput: (the
  71. device description */
  72. I_EVENTTYPE = 4, /* event type (evdev:, libinput:,
  73. hidraw:) */
  74. I_EVENT = 6, /* event data */
  75. };
  76. struct record_device {
  77. struct record_context *ctx;
  78. struct list link;
  79. char *devnode; /* device node of the source device */
  80. struct libevdev *evdev;
  81. struct libevdev *evdev_prev; /* previous value, used for EV_ABS
  82. deltas */
  83. struct libinput_device *device;
  84. struct list hidraw_devices;
  85. struct {
  86. bool is_touch_device;
  87. uint16_t slot_state;
  88. uint16_t last_slot_state;
  89. } touch;
  90. FILE *fp;
  91. };
  92. struct hidraw {
  93. struct list link;
  94. struct record_device *device;
  95. int fd;
  96. char *name;
  97. };
  98. struct record_context {
  99. usec_t timeout;
  100. bool show_keycodes;
  101. usec_t offset;
  102. /* The first device to be added */
  103. struct record_device *first_device;
  104. struct list devices;
  105. int ndevices;
  106. struct {
  107. char *name; /* file name given on cmdline */
  108. char *name_with_suffix; /* full file name with suffix */
  109. } output_file;
  110. struct libinput *libinput;
  111. int epoll_fd;
  112. struct list sources;
  113. struct {
  114. usec_t last_wall_time;
  115. } timestamps;
  116. bool had_events;
  117. bool stop;
  118. bool no_events;
  119. };
  120. #define resize(array_, sz_) \
  121. { \
  122. size_t new_size = (sz_) + 1000; \
  123. void *tmp = realloc((array_), new_size * sizeof(*(array_))); \
  124. assert(tmp); \
  125. (array_) = tmp; \
  126. (sz_) = new_size; \
  127. }
  128. typedef void (*source_dispatch_t)(struct record_context *ctx, int fd, void *user_data);
  129. struct source {
  130. source_dispatch_t dispatch;
  131. void *user_data;
  132. int fd;
  133. struct list link;
  134. };
  135. static bool
  136. obfuscate_keycode(struct input_event *ev)
  137. {
  138. switch (ev->type) {
  139. case EV_KEY:
  140. switch (ev->code) {
  141. case KEY_ESC:
  142. case KEY_TAB:
  143. case KEY_ENTER:
  144. case KEY_LEFTCTRL:
  145. break;
  146. default:
  147. if ((ev->code > KEY_ESC && ev->code < KEY_CAPSLOCK) ||
  148. (ev->code >= KEY_KP7 && ev->code <= KEY_KPDOT)) {
  149. ev->code = KEY_A;
  150. return true;
  151. }
  152. }
  153. break;
  154. case EV_MSC:
  155. if (ev->code == MSC_SCAN) {
  156. ev->value = 30; /* KEY_A scancode */
  157. return true;
  158. }
  159. break;
  160. }
  161. return false;
  162. }
  163. /**
  164. * Indented dprintf, indentation is in the context
  165. */
  166. LIBINPUT_ATTRIBUTE_PRINTF(3, 4)
  167. static void
  168. iprintf(FILE *fp, enum indent indent, const char *format, ...)
  169. {
  170. va_list args;
  171. char fmt[1024];
  172. static const char space[] = " ";
  173. static const size_t len = sizeof(space);
  174. int rc;
  175. assert(indent < len);
  176. assert(strlen(format) >= 1);
  177. /* Special case: if we're printing a new list item, we want less
  178. * indentation because the '- ' takes up one level of indentation
  179. *
  180. * This is only needed because I don't want to deal with open/close
  181. * lists statements.
  182. */
  183. if (format[0] == '-' && indent > 0)
  184. indent -= 2;
  185. snprintf(fmt, sizeof(fmt), "%s%s", &space[len - indent - 1], format);
  186. va_start(args, format);
  187. #pragma GCC diagnostic push
  188. #pragma GCC diagnostic ignored "-Wformat-nonliteral"
  189. rc = vfprintf(fp, fmt, args);
  190. #pragma GCC diagnostic pop
  191. va_end(args);
  192. assert(rc != -1 && (unsigned int)rc > indent);
  193. }
  194. static usec_t
  195. time_offset(struct record_context *ctx, usec_t time)
  196. {
  197. return !usec_is_zero(ctx->offset) ? usec_sub(time, ctx->offset)
  198. : usec_from_uint64_t(0);
  199. }
  200. static void
  201. print_evdev_event(struct record_device *dev, struct input_event *ev)
  202. {
  203. const char *tname, *cname;
  204. bool was_modified = false;
  205. char desc[1024];
  206. usec_t time = usec_sub(input_event_time(ev), dev->ctx->offset);
  207. input_event_set_time(ev, time);
  208. /* Don't leak passwords unless the user wants to */
  209. if (!dev->ctx->show_keycodes)
  210. was_modified = obfuscate_keycode(ev);
  211. tname = libevdev_event_type_get_name(ev->type);
  212. cname = libevdev_event_code_get_name(ev->type, ev->code);
  213. if (ev->type == EV_SYN && ev->code == SYN_MT_REPORT) {
  214. snprintf(desc,
  215. sizeof(desc),
  216. "++++++++++++ %s (%d) ++++++++++",
  217. cname,
  218. ev->value);
  219. } else if (ev->type == EV_SYN) {
  220. static usec_t last_time = { 0 };
  221. usec_t time = input_event_time(ev);
  222. usec_t dt = usec_delta(time, last_time);
  223. last_time = time;
  224. snprintf(desc,
  225. sizeof(desc),
  226. "------------ %s (%d) ---------- %+dms",
  227. cname,
  228. ev->value,
  229. usec_to_millis(dt));
  230. } else if (ev->type == EV_ABS) {
  231. int oldval = 0;
  232. enum { DELTA, SLOT_DELTA, NO_DELTA } want = DELTA;
  233. int delta = 0;
  234. /* We want to print deltas for abs axes but there are a few
  235. * that we don't care about for actual deltas because
  236. * they're meaningless.
  237. *
  238. * Also, any slotted axis needs to be printed per slot
  239. */
  240. switch (ev->code) {
  241. case ABS_MT_SLOT:
  242. libevdev_set_event_value(dev->evdev_prev,
  243. ev->type,
  244. ev->code,
  245. ev->value);
  246. want = NO_DELTA;
  247. break;
  248. case ABS_MT_TRACKING_ID:
  249. case ABS_MT_BLOB_ID:
  250. want = NO_DELTA;
  251. break;
  252. case ABS_MT_TOUCH_MAJOR ... ABS_MT_POSITION_Y:
  253. case ABS_MT_PRESSURE ... ABS_MT_TOOL_Y:
  254. if (libevdev_get_num_slots(dev->evdev_prev) > 0)
  255. want = SLOT_DELTA;
  256. break;
  257. default:
  258. break;
  259. }
  260. switch (want) {
  261. case DELTA:
  262. oldval = libevdev_get_event_value(dev->evdev_prev,
  263. ev->type,
  264. ev->code);
  265. libevdev_set_event_value(dev->evdev_prev,
  266. ev->type,
  267. ev->code,
  268. ev->value);
  269. break;
  270. case SLOT_DELTA: {
  271. int slot = libevdev_get_current_slot(dev->evdev_prev);
  272. oldval = libevdev_get_slot_value(dev->evdev_prev,
  273. slot,
  274. ev->code);
  275. libevdev_set_slot_value(dev->evdev_prev,
  276. slot,
  277. ev->code,
  278. ev->value);
  279. break;
  280. }
  281. case NO_DELTA:
  282. break;
  283. }
  284. delta = ev->value - oldval;
  285. switch (want) {
  286. case DELTA:
  287. case SLOT_DELTA:
  288. snprintf(desc,
  289. sizeof(desc),
  290. "%s / %-20s %6d (%+d)",
  291. tname,
  292. cname,
  293. ev->value,
  294. delta);
  295. break;
  296. case NO_DELTA:
  297. snprintf(desc,
  298. sizeof(desc),
  299. "%s / %-20s %6d",
  300. tname,
  301. cname,
  302. ev->value);
  303. break;
  304. }
  305. } else {
  306. snprintf(desc,
  307. sizeof(desc),
  308. "%s / %-20s %6d%s",
  309. tname,
  310. cname,
  311. ev->value,
  312. was_modified ? " (obfuscated)" : "");
  313. }
  314. iprintf(dev->fp,
  315. I_EVENT,
  316. "- [%3lu, %6u, %3d, %3d, %7d] # %s\n",
  317. ev->input_event_sec,
  318. (unsigned int)ev->input_event_usec,
  319. ev->type,
  320. ev->code,
  321. ev->value,
  322. desc);
  323. }
  324. static bool
  325. handle_evdev_frame(struct record_device *d)
  326. {
  327. struct libevdev *evdev = d->evdev;
  328. struct input_event e;
  329. if (libevdev_next_event(evdev, LIBEVDEV_READ_FLAG_NORMAL, &e) !=
  330. LIBEVDEV_READ_STATUS_SUCCESS)
  331. return false;
  332. iprintf(d->fp, I_EVENTTYPE, "- evdev:\n");
  333. do {
  334. if (usec_is_zero(d->ctx->offset)) {
  335. d->ctx->offset = input_event_time(&e);
  336. }
  337. print_evdev_event(d, &e);
  338. if (d->touch.is_touch_device && e.type == EV_ABS &&
  339. e.code == ABS_MT_TRACKING_ID) {
  340. unsigned int slot = libevdev_get_current_slot(evdev);
  341. assert(slot < sizeof(d->touch.slot_state) * 8);
  342. if (e.value != -1)
  343. d->touch.slot_state |= bit(slot);
  344. else
  345. d->touch.slot_state &= ~bit(slot);
  346. }
  347. if (e.type == EV_SYN && e.code == SYN_REPORT)
  348. break;
  349. } while (libevdev_next_event(evdev, LIBEVDEV_READ_FLAG_NORMAL, &e) ==
  350. LIBEVDEV_READ_STATUS_SUCCESS);
  351. if (d->touch.slot_state != d->touch.last_slot_state) {
  352. d->touch.last_slot_state = d->touch.slot_state;
  353. if (d->touch.slot_state == 0) {
  354. iprintf(d->fp,
  355. I_EVENT,
  356. " # Touch device in neutral state\n");
  357. }
  358. }
  359. return true;
  360. }
  361. static void
  362. print_device_notify(struct record_device *dev, struct libinput_event *e)
  363. {
  364. struct libinput_device *d = libinput_event_get_device(e);
  365. struct libinput_seat *seat = libinput_device_get_seat(d);
  366. const char *type = NULL;
  367. switch (libinput_event_get_type(e)) {
  368. case LIBINPUT_EVENT_DEVICE_ADDED:
  369. type = "DEVICE_ADDED";
  370. break;
  371. case LIBINPUT_EVENT_DEVICE_REMOVED:
  372. type = "DEVICE_REMOVED";
  373. break;
  374. default:
  375. abort();
  376. }
  377. iprintf(dev->fp,
  378. I_EVENT,
  379. "- {type: %s, seat: %5s, logical_seat: %7s}\n",
  380. type,
  381. libinput_seat_get_physical_name(seat),
  382. libinput_seat_get_logical_name(seat));
  383. }
  384. static void
  385. print_key_event(struct record_device *dev, struct libinput_event *e)
  386. {
  387. struct libinput_event_keyboard *k = libinput_event_get_keyboard_event(e);
  388. enum libinput_key_state state;
  389. uint32_t key;
  390. usec_t time;
  391. const char *type;
  392. switch (libinput_event_get_type(e)) {
  393. case LIBINPUT_EVENT_KEYBOARD_KEY:
  394. type = "KEYBOARD_KEY";
  395. break;
  396. default:
  397. abort();
  398. }
  399. time = time_offset(
  400. dev->ctx,
  401. usec_from_uint64_t(libinput_event_keyboard_get_time_usec(k)));
  402. state = libinput_event_keyboard_get_key_state(k);
  403. key = libinput_event_keyboard_get_key(k);
  404. if (!dev->ctx->show_keycodes && (key >= KEY_ESC && key < KEY_ZENKAKUHANKAKU))
  405. key = -1;
  406. iprintf(dev->fp,
  407. I_EVENT,
  408. "- {time: %d.%06ld, type: %s, key: %d, state: %s}\n",
  409. usec_to_seconds(time),
  410. (long)(usec_as_uint64_t(time) % (int)1e6),
  411. type,
  412. key,
  413. state == LIBINPUT_KEY_STATE_PRESSED ? "pressed" : "released");
  414. }
  415. static void
  416. print_motion_event(struct record_device *dev, struct libinput_event *e)
  417. {
  418. struct libinput_event_pointer *p = libinput_event_get_pointer_event(e);
  419. double x = libinput_event_pointer_get_dx(p),
  420. y = libinput_event_pointer_get_dy(p);
  421. double uax = libinput_event_pointer_get_dx_unaccelerated(p),
  422. uay = libinput_event_pointer_get_dy_unaccelerated(p);
  423. usec_t time;
  424. const char *type;
  425. switch (libinput_event_get_type(e)) {
  426. case LIBINPUT_EVENT_POINTER_MOTION:
  427. type = "POINTER_MOTION";
  428. break;
  429. default:
  430. abort();
  431. }
  432. time = time_offset(dev->ctx,
  433. usec_from_uint64_t(libinput_event_pointer_get_time_usec(p)));
  434. iprintf(dev->fp,
  435. I_EVENT,
  436. "- {time: %d.%06ld, type: %s, delta: [%6.2f, %6.2f], unaccel: [%6.2f, %6.2f]}\n",
  437. usec_to_seconds(time),
  438. (long)(usec_as_uint64_t(time) % (int)1e6),
  439. type,
  440. x,
  441. y,
  442. uax,
  443. uay);
  444. }
  445. static void
  446. print_absmotion_event(struct record_device *dev, struct libinput_event *e)
  447. {
  448. struct libinput_event_pointer *p = libinput_event_get_pointer_event(e);
  449. double x = libinput_event_pointer_get_absolute_x(p),
  450. y = libinput_event_pointer_get_absolute_y(p);
  451. double tx = libinput_event_pointer_get_absolute_x_transformed(p, 100),
  452. ty = libinput_event_pointer_get_absolute_y_transformed(p, 100);
  453. usec_t time;
  454. const char *type;
  455. switch (libinput_event_get_type(e)) {
  456. case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
  457. type = "POINTER_MOTION_ABSOLUTE";
  458. break;
  459. default:
  460. abort();
  461. }
  462. time = time_offset(dev->ctx,
  463. usec_from_uint64_t(libinput_event_pointer_get_time_usec(p)));
  464. iprintf(dev->fp,
  465. I_EVENT,
  466. "- {time: %d.%06ld, type: %s, point: [%6.2f, %6.2f], transformed: [%6.2f, %6.2f]}\n",
  467. usec_to_seconds(time),
  468. (long)(usec_as_uint64_t(time) % (int)1e6),
  469. type,
  470. x,
  471. y,
  472. tx,
  473. ty);
  474. }
  475. static void
  476. print_pointer_button_event(struct record_device *dev, struct libinput_event *e)
  477. {
  478. struct libinput_event_pointer *p = libinput_event_get_pointer_event(e);
  479. enum libinput_button_state state;
  480. int button;
  481. usec_t time;
  482. const char *type;
  483. switch (libinput_event_get_type(e)) {
  484. case LIBINPUT_EVENT_POINTER_BUTTON:
  485. type = "POINTER_BUTTON";
  486. break;
  487. default:
  488. abort();
  489. }
  490. time = time_offset(dev->ctx,
  491. usec_from_uint64_t(libinput_event_pointer_get_time_usec(p)));
  492. button = libinput_event_pointer_get_button(p);
  493. state = libinput_event_pointer_get_button_state(p);
  494. iprintf(dev->fp,
  495. I_EVENT,
  496. "- {time: %d.%06ld, type: %s, button: %d, state: %s, seat_count: %u}\n",
  497. usec_to_seconds(time),
  498. (long)(usec_as_uint64_t(time) % (int)1e6),
  499. type,
  500. button,
  501. state == LIBINPUT_BUTTON_STATE_PRESSED ? "pressed" : "released",
  502. libinput_event_pointer_get_seat_button_count(p));
  503. }
  504. static void
  505. print_pointer_axis_event(struct record_device *dev, struct libinput_event *e)
  506. {
  507. struct libinput_event_pointer *p = libinput_event_get_pointer_event(e);
  508. usec_t time;
  509. const char *type, *source;
  510. double h = 0, v = 0;
  511. int hd = 0, vd = 0;
  512. switch (libinput_event_get_type(e)) {
  513. case LIBINPUT_EVENT_POINTER_AXIS:
  514. type = "POINTER_AXIS";
  515. break;
  516. default:
  517. abort();
  518. }
  519. time = time_offset(dev->ctx,
  520. usec_from_uint64_t(libinput_event_pointer_get_time_usec(p)));
  521. if (libinput_event_pointer_has_axis(p,
  522. LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) {
  523. h = libinput_event_pointer_get_axis_value(
  524. p,
  525. LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
  526. hd = libinput_event_pointer_get_axis_value_discrete(
  527. p,
  528. LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
  529. }
  530. if (libinput_event_pointer_has_axis(p, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) {
  531. v = libinput_event_pointer_get_axis_value(
  532. p,
  533. LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
  534. vd = libinput_event_pointer_get_axis_value_discrete(
  535. p,
  536. LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
  537. }
  538. switch (libinput_event_pointer_get_axis_source(p)) {
  539. case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL:
  540. source = "wheel";
  541. break;
  542. case LIBINPUT_POINTER_AXIS_SOURCE_FINGER:
  543. source = "finger";
  544. break;
  545. case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS:
  546. source = "continuous";
  547. break;
  548. case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL_TILT:
  549. source = "wheel-tilt";
  550. break;
  551. default:
  552. source = "unknown";
  553. break;
  554. }
  555. iprintf(dev->fp,
  556. I_EVENT,
  557. "- {time: %d.%06ld, type: %s, axes: [%2.2f, %2.2f], discrete: [%d, %d], source: %s}\n",
  558. usec_to_seconds(time),
  559. (long)(usec_as_uint64_t(time) % (int)1e6),
  560. type,
  561. h,
  562. v,
  563. hd,
  564. vd,
  565. source);
  566. }
  567. static void
  568. print_touch_event(struct record_device *dev, struct libinput_event *e)
  569. {
  570. enum libinput_event_type etype = libinput_event_get_type(e);
  571. struct libinput_event_touch *t = libinput_event_get_touch_event(e);
  572. const char *type;
  573. double x, y;
  574. double tx, ty;
  575. usec_t time;
  576. int32_t slot, seat_slot;
  577. switch (etype) {
  578. case LIBINPUT_EVENT_TOUCH_DOWN:
  579. type = "TOUCH_DOWN";
  580. break;
  581. case LIBINPUT_EVENT_TOUCH_UP:
  582. type = "TOUCH_UP";
  583. break;
  584. case LIBINPUT_EVENT_TOUCH_MOTION:
  585. type = "TOUCH_MOTION";
  586. break;
  587. case LIBINPUT_EVENT_TOUCH_CANCEL:
  588. type = "TOUCH_CANCEL";
  589. break;
  590. case LIBINPUT_EVENT_TOUCH_FRAME:
  591. type = "TOUCH_FRAME";
  592. break;
  593. default:
  594. abort();
  595. }
  596. time = time_offset(dev->ctx,
  597. usec_from_uint64_t(libinput_event_touch_get_time_usec(t)));
  598. if (etype != LIBINPUT_EVENT_TOUCH_FRAME) {
  599. slot = libinput_event_touch_get_slot(t);
  600. seat_slot = libinput_event_touch_get_seat_slot(t);
  601. }
  602. switch (etype) {
  603. case LIBINPUT_EVENT_TOUCH_FRAME:
  604. iprintf(dev->fp,
  605. I_EVENT,
  606. "- {time: %ld.%06ld, type: %s}\n",
  607. (long)(usec_as_uint64_t(time) / (int)1e6),
  608. (long)(usec_as_uint64_t(time) % (int)1e6),
  609. type);
  610. break;
  611. case LIBINPUT_EVENT_TOUCH_DOWN:
  612. case LIBINPUT_EVENT_TOUCH_MOTION:
  613. x = libinput_event_touch_get_x(t);
  614. y = libinput_event_touch_get_y(t);
  615. tx = libinput_event_touch_get_x_transformed(t, 100);
  616. ty = libinput_event_touch_get_y_transformed(t, 100);
  617. iprintf(dev->fp,
  618. I_EVENT,
  619. "- {time: %d.%06ld, type: %s, slot: %d, seat_slot: %d, "
  620. "point: [%6.2f, %6.2f], transformed: [%6.2f, %6.2f]}\n",
  621. usec_to_seconds(time),
  622. (long)(usec_as_uint64_t(time) % (int)1e6),
  623. type,
  624. slot,
  625. seat_slot,
  626. x,
  627. y,
  628. tx,
  629. ty);
  630. break;
  631. case LIBINPUT_EVENT_TOUCH_UP:
  632. case LIBINPUT_EVENT_TOUCH_CANCEL:
  633. iprintf(dev->fp,
  634. I_EVENT,
  635. "- {time: %d.%06ld, type: %s, slot: %d, seat_slot: %d}\n",
  636. usec_to_seconds(time),
  637. (long)(usec_as_uint64_t(time) % (int)1e6),
  638. type,
  639. slot,
  640. seat_slot);
  641. break;
  642. default:
  643. abort();
  644. }
  645. }
  646. static void
  647. print_gesture_event(struct record_device *dev, struct libinput_event *e)
  648. {
  649. enum libinput_event_type etype = libinput_event_get_type(e);
  650. struct libinput_event_gesture *g = libinput_event_get_gesture_event(e);
  651. const char *type;
  652. usec_t time;
  653. switch (etype) {
  654. case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN:
  655. type = "GESTURE_PINCH_BEGIN";
  656. break;
  657. case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE:
  658. type = "GESTURE_PINCH_UPDATE";
  659. break;
  660. case LIBINPUT_EVENT_GESTURE_PINCH_END:
  661. type = "GESTURE_PINCH_END";
  662. break;
  663. case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN:
  664. type = "GESTURE_SWIPE_BEGIN";
  665. break;
  666. case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE:
  667. type = "GESTURE_SWIPE_UPDATE";
  668. break;
  669. case LIBINPUT_EVENT_GESTURE_SWIPE_END:
  670. type = "GESTURE_SWIPE_END";
  671. break;
  672. default:
  673. abort();
  674. }
  675. time = time_offset(dev->ctx,
  676. usec_from_uint64_t(libinput_event_gesture_get_time_usec(g)));
  677. switch (etype) {
  678. case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN:
  679. case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE:
  680. case LIBINPUT_EVENT_GESTURE_PINCH_END:
  681. iprintf(dev->fp,
  682. I_EVENT,
  683. "- {time: %ld.%06ld, type: %s, nfingers: %d, "
  684. "delta: [%6.2f, %6.2f], unaccel: [%6.2f, %6.2f], "
  685. "angle_delta: %6.2f, scale: %6.2f}\n",
  686. (long)(usec_as_uint64_t(time) / (int)1e6),
  687. (long)(usec_as_uint64_t(time) % (int)1e6),
  688. type,
  689. libinput_event_gesture_get_finger_count(g),
  690. libinput_event_gesture_get_dx(g),
  691. libinput_event_gesture_get_dy(g),
  692. libinput_event_gesture_get_dx_unaccelerated(g),
  693. libinput_event_gesture_get_dy_unaccelerated(g),
  694. libinput_event_gesture_get_angle_delta(g),
  695. libinput_event_gesture_get_scale(g));
  696. break;
  697. case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN:
  698. case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE:
  699. case LIBINPUT_EVENT_GESTURE_SWIPE_END:
  700. iprintf(dev->fp,
  701. I_EVENT,
  702. "- {time: %d.%06ld, type: %s, nfingers: %d, "
  703. "delta: [%6.2f, %6.2f], unaccel: [%6.2f, %6.2f]}\n",
  704. usec_to_seconds(time),
  705. (long)(usec_as_uint64_t(time) % (int)1e6),
  706. type,
  707. libinput_event_gesture_get_finger_count(g),
  708. libinput_event_gesture_get_dx(g),
  709. libinput_event_gesture_get_dy(g),
  710. libinput_event_gesture_get_dx_unaccelerated(g),
  711. libinput_event_gesture_get_dy_unaccelerated(g));
  712. break;
  713. default:
  714. abort();
  715. }
  716. }
  717. static char *
  718. buffer_tablet_axes(struct libinput_event_tablet_tool *t)
  719. {
  720. const int MAX_AXES = 10;
  721. struct libinput_tablet_tool *tool;
  722. int idx = 0;
  723. int len;
  724. double x, y;
  725. tool = libinput_event_tablet_tool_get_tool(t);
  726. _autostrvfree_ char **strv = zalloc(MAX_AXES * sizeof *strv);
  727. x = libinput_event_tablet_tool_get_x(t);
  728. y = libinput_event_tablet_tool_get_y(t);
  729. len = xasprintf(&strv[idx++], "point: [%.2f, %.2f]", x, y);
  730. if (len <= 0)
  731. return NULL;
  732. if (libinput_tablet_tool_has_tilt(tool)) {
  733. x = libinput_event_tablet_tool_get_tilt_x(t);
  734. y = libinput_event_tablet_tool_get_tilt_y(t);
  735. len = xasprintf(&strv[idx++], "tilt: [%.2f, %.2f]", x, y);
  736. if (len <= 0)
  737. return NULL;
  738. }
  739. if (libinput_tablet_tool_has_distance(tool) ||
  740. libinput_tablet_tool_has_pressure(tool)) {
  741. double dist, pressure;
  742. dist = libinput_event_tablet_tool_get_distance(t);
  743. pressure = libinput_event_tablet_tool_get_pressure(t);
  744. if (dist)
  745. len = xasprintf(&strv[idx++], "distance: %.2f", dist);
  746. else
  747. len = xasprintf(&strv[idx++], "pressure: %.2f", pressure);
  748. if (len <= 0)
  749. return NULL;
  750. }
  751. if (libinput_tablet_tool_has_rotation(tool)) {
  752. double rotation;
  753. rotation = libinput_event_tablet_tool_get_rotation(t);
  754. len = xasprintf(&strv[idx++], "rotation: %.2f", rotation);
  755. if (len <= 0)
  756. return NULL;
  757. }
  758. if (libinput_tablet_tool_has_slider(tool)) {
  759. double slider;
  760. slider = libinput_event_tablet_tool_get_slider_position(t);
  761. len = xasprintf(&strv[idx++], "slider: %.2f", slider);
  762. if (len <= 0)
  763. return NULL;
  764. }
  765. if (libinput_tablet_tool_has_wheel(tool)) {
  766. double wheel;
  767. int delta;
  768. wheel = libinput_event_tablet_tool_get_wheel_delta(t);
  769. len = xasprintf(&strv[idx++], "wheel: %.2f", wheel);
  770. if (len <= 0)
  771. return NULL;
  772. delta = libinput_event_tablet_tool_get_wheel_delta_discrete(t);
  773. len = xasprintf(&strv[idx++], "wheel-discrete: %d", delta);
  774. if (len <= 0)
  775. return NULL;
  776. }
  777. assert(idx < MAX_AXES);
  778. return strv_join(strv, ", ");
  779. }
  780. static void
  781. print_tablet_tool_proximity_event(struct record_device *dev, struct libinput_event *e)
  782. {
  783. struct libinput_event_tablet_tool *t = libinput_event_get_tablet_tool_event(e);
  784. struct libinput_tablet_tool *tool = libinput_event_tablet_tool_get_tool(t);
  785. usec_t time;
  786. const char *type, *tool_type;
  787. char caps[10] = { 0 };
  788. enum libinput_tablet_tool_proximity_state prox;
  789. size_t idx;
  790. switch (libinput_event_get_type(e)) {
  791. case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY:
  792. type = "TABLET_TOOL_PROXIMITY";
  793. break;
  794. default:
  795. abort();
  796. }
  797. switch (libinput_tablet_tool_get_type(tool)) {
  798. case LIBINPUT_TABLET_TOOL_TYPE_PEN:
  799. tool_type = "pen";
  800. break;
  801. case LIBINPUT_TABLET_TOOL_TYPE_ERASER:
  802. tool_type = "eraser";
  803. break;
  804. case LIBINPUT_TABLET_TOOL_TYPE_BRUSH:
  805. tool_type = "brush";
  806. break;
  807. case LIBINPUT_TABLET_TOOL_TYPE_PENCIL:
  808. tool_type = "pencil";
  809. break;
  810. case LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH:
  811. tool_type = "airbrush";
  812. break;
  813. case LIBINPUT_TABLET_TOOL_TYPE_MOUSE:
  814. tool_type = "mouse";
  815. break;
  816. case LIBINPUT_TABLET_TOOL_TYPE_LENS:
  817. tool_type = "lens";
  818. break;
  819. default:
  820. tool_type = "unknown";
  821. break;
  822. }
  823. prox = libinput_event_tablet_tool_get_proximity_state(t);
  824. time = time_offset(
  825. dev->ctx,
  826. usec_from_uint64_t(libinput_event_tablet_tool_get_time_usec(t)));
  827. _autofree_ char *axes = buffer_tablet_axes(t);
  828. idx = 0;
  829. if (libinput_tablet_tool_has_pressure(tool))
  830. caps[idx++] = 'p';
  831. if (libinput_tablet_tool_has_distance(tool))
  832. caps[idx++] = 'd';
  833. if (libinput_tablet_tool_has_tilt(tool))
  834. caps[idx++] = 't';
  835. if (libinput_tablet_tool_has_rotation(tool))
  836. caps[idx++] = 'r';
  837. if (libinput_tablet_tool_has_slider(tool))
  838. caps[idx++] = 's';
  839. if (libinput_tablet_tool_has_wheel(tool))
  840. caps[idx++] = 'w';
  841. assert(idx <= ARRAY_LENGTH(caps));
  842. iprintf(dev->fp,
  843. I_EVENT,
  844. "- {time: %d.%06ld, type: %s, proximity: %s, tool-type: %s, serial: %" PRIu64
  845. ", axes: %s, %s}\n",
  846. usec_to_seconds(time),
  847. (long)(usec_as_uint64_t(time) % (int)1e6),
  848. type,
  849. prox ? "in" : "out",
  850. tool_type,
  851. libinput_tablet_tool_get_serial(tool),
  852. caps,
  853. axes);
  854. }
  855. static void
  856. print_tablet_tool_button_event(struct record_device *dev, struct libinput_event *e)
  857. {
  858. struct libinput_event_tablet_tool *t = libinput_event_get_tablet_tool_event(e);
  859. usec_t time;
  860. const char *type;
  861. uint32_t button;
  862. enum libinput_button_state state;
  863. switch (libinput_event_get_type(e)) {
  864. case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
  865. type = "TABLET_TOOL_BUTTON";
  866. break;
  867. default:
  868. abort();
  869. }
  870. button = libinput_event_tablet_tool_get_button(t);
  871. state = libinput_event_tablet_tool_get_button_state(t);
  872. time = time_offset(
  873. dev->ctx,
  874. usec_from_uint64_t(libinput_event_tablet_tool_get_time_usec(t)));
  875. iprintf(dev->fp,
  876. I_EVENT,
  877. "- {time: %d.%06ld, type: %s, button: %d, state: %s}\n",
  878. usec_to_seconds(time),
  879. (long)(usec_as_uint64_t(time) % (int)1e6),
  880. type,
  881. button,
  882. state ? "pressed" : "released");
  883. }
  884. static void
  885. print_tablet_tool_event(struct record_device *dev, struct libinput_event *e)
  886. {
  887. struct libinput_event_tablet_tool *t = libinput_event_get_tablet_tool_event(e);
  888. usec_t time;
  889. const char *type;
  890. enum libinput_tablet_tool_tip_state tip;
  891. char btn_buffer[30] = { 0 };
  892. switch (libinput_event_get_type(e)) {
  893. case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
  894. type = "TABLET_TOOL_AXIS";
  895. break;
  896. case LIBINPUT_EVENT_TABLET_TOOL_TIP:
  897. type = "TABLET_TOOL_TIP";
  898. break;
  899. case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
  900. type = "TABLET_TOOL_BUTTON";
  901. break;
  902. default:
  903. abort();
  904. }
  905. if (libinput_event_get_type(e) == LIBINPUT_EVENT_TABLET_TOOL_BUTTON) {
  906. uint32_t button;
  907. enum libinput_button_state state;
  908. button = libinput_event_tablet_tool_get_button(t);
  909. state = libinput_event_tablet_tool_get_button_state(t);
  910. snprintf(btn_buffer,
  911. sizeof(btn_buffer),
  912. ", button: %d, state: %s\n",
  913. button,
  914. state ? "pressed" : "released");
  915. }
  916. tip = libinput_event_tablet_tool_get_tip_state(t);
  917. time = time_offset(
  918. dev->ctx,
  919. usec_from_uint64_t(libinput_event_tablet_tool_get_time_usec(t)));
  920. _autofree_ char *axes = buffer_tablet_axes(t);
  921. iprintf(dev->fp,
  922. I_EVENT,
  923. "- {time: %d.%06ld, type: %s%s, tip: %s, %s}\n",
  924. usec_to_seconds(time),
  925. (long)(usec_as_uint64_t(time) % (int)1e6),
  926. type,
  927. btn_buffer, /* may be empty string */
  928. tip ? "down" : "up",
  929. axes);
  930. }
  931. static void
  932. print_tablet_pad_button_event(struct record_device *dev, struct libinput_event *e)
  933. {
  934. struct libinput_event_tablet_pad *p = libinput_event_get_tablet_pad_event(e);
  935. struct libinput_tablet_pad_mode_group *group;
  936. enum libinput_button_state state;
  937. unsigned int button, mode;
  938. const char *type;
  939. usec_t time;
  940. switch (libinput_event_get_type(e)) {
  941. case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
  942. type = "TABLET_PAD_BUTTON";
  943. break;
  944. default:
  945. abort();
  946. }
  947. time = time_offset(
  948. dev->ctx,
  949. usec_from_uint64_t(libinput_event_tablet_pad_get_time_usec(p)));
  950. button = libinput_event_tablet_pad_get_button_number(p),
  951. state = libinput_event_tablet_pad_get_button_state(p);
  952. mode = libinput_event_tablet_pad_get_mode(p);
  953. group = libinput_event_tablet_pad_get_mode_group(p);
  954. iprintf(dev->fp,
  955. I_EVENT,
  956. "- {time: %d.%06ld, type: %s, button: %d, state: %s, mode: %d, is-toggle: %s}\n",
  957. usec_to_seconds(time),
  958. (long)(usec_as_uint64_t(time) % (int)1e6),
  959. type,
  960. button,
  961. state == LIBINPUT_BUTTON_STATE_PRESSED ? "pressed" : "released",
  962. mode,
  963. truefalse(libinput_tablet_pad_mode_group_button_is_toggle(group,
  964. button)));
  965. }
  966. static void
  967. print_tablet_pad_ringstrip_event(struct record_device *dev, struct libinput_event *e)
  968. {
  969. struct libinput_event_tablet_pad *p = libinput_event_get_tablet_pad_event(e);
  970. const char *source = NULL;
  971. unsigned int mode, number;
  972. const char *type;
  973. usec_t time;
  974. double pos;
  975. switch (libinput_event_get_type(e)) {
  976. case LIBINPUT_EVENT_TABLET_PAD_RING:
  977. type = "TABLET_PAD_RING";
  978. number = libinput_event_tablet_pad_get_ring_number(p);
  979. pos = libinput_event_tablet_pad_get_ring_position(p);
  980. switch (libinput_event_tablet_pad_get_ring_source(p)) {
  981. case LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER:
  982. source = "finger";
  983. break;
  984. case LIBINPUT_TABLET_PAD_RING_SOURCE_UNKNOWN:
  985. source = "unknown";
  986. break;
  987. }
  988. break;
  989. case LIBINPUT_EVENT_TABLET_PAD_STRIP:
  990. type = "TABLET_PAD_STRIP";
  991. number = libinput_event_tablet_pad_get_strip_number(p);
  992. pos = libinput_event_tablet_pad_get_strip_position(p);
  993. switch (libinput_event_tablet_pad_get_strip_source(p)) {
  994. case LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER:
  995. source = "finger";
  996. break;
  997. case LIBINPUT_TABLET_PAD_STRIP_SOURCE_UNKNOWN:
  998. source = "unknown";
  999. break;
  1000. }
  1001. break;
  1002. default:
  1003. abort();
  1004. }
  1005. time = time_offset(
  1006. dev->ctx,
  1007. usec_from_uint64_t(libinput_event_tablet_pad_get_time_usec(p)));
  1008. mode = libinput_event_tablet_pad_get_mode(p);
  1009. iprintf(dev->fp,
  1010. I_EVENT,
  1011. "- {time: %d.%06ld, type: %s, number: %d, position: %.2f, source: %s, mode: %d}\n",
  1012. usec_to_seconds(time),
  1013. (long)(usec_as_uint64_t(time) % (int)1e6),
  1014. type,
  1015. number,
  1016. pos,
  1017. source,
  1018. mode);
  1019. }
  1020. static void
  1021. print_switch_event(struct record_device *dev, struct libinput_event *e)
  1022. {
  1023. struct libinput_event_switch *s = libinput_event_get_switch_event(e);
  1024. enum libinput_switch_state state;
  1025. uint32_t sw;
  1026. const char *type;
  1027. usec_t time;
  1028. switch (libinput_event_get_type(e)) {
  1029. case LIBINPUT_EVENT_SWITCH_TOGGLE:
  1030. type = "SWITCH_TOGGLE";
  1031. break;
  1032. default:
  1033. abort();
  1034. }
  1035. time = time_offset(dev->ctx,
  1036. usec_from_uint64_t(libinput_event_switch_get_time_usec(s)));
  1037. sw = libinput_event_switch_get_switch(s);
  1038. state = libinput_event_switch_get_switch_state(s);
  1039. iprintf(dev->fp,
  1040. I_EVENT,
  1041. "- {time: %d.%06ld, type: %s, switch: %d, state: %s}\n",
  1042. usec_to_seconds(time),
  1043. (long)(usec_as_uint64_t(time) % (int)1e6),
  1044. type,
  1045. sw,
  1046. state == LIBINPUT_SWITCH_STATE_ON ? "on" : "off");
  1047. }
  1048. static void
  1049. print_libinput_event(struct record_device *dev, struct libinput_event *e)
  1050. {
  1051. switch (libinput_event_get_type(e)) {
  1052. case LIBINPUT_EVENT_NONE:
  1053. abort();
  1054. case LIBINPUT_EVENT_DEVICE_ADDED:
  1055. case LIBINPUT_EVENT_DEVICE_REMOVED:
  1056. print_device_notify(dev, e);
  1057. break;
  1058. case LIBINPUT_EVENT_KEYBOARD_KEY:
  1059. print_key_event(dev, e);
  1060. break;
  1061. case LIBINPUT_EVENT_POINTER_MOTION:
  1062. print_motion_event(dev, e);
  1063. break;
  1064. case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
  1065. print_absmotion_event(dev, e);
  1066. break;
  1067. case LIBINPUT_EVENT_POINTER_BUTTON:
  1068. print_pointer_button_event(dev, e);
  1069. break;
  1070. case LIBINPUT_EVENT_POINTER_AXIS:
  1071. print_pointer_axis_event(dev, e);
  1072. break;
  1073. case LIBINPUT_EVENT_TOUCH_DOWN:
  1074. case LIBINPUT_EVENT_TOUCH_UP:
  1075. case LIBINPUT_EVENT_TOUCH_MOTION:
  1076. case LIBINPUT_EVENT_TOUCH_CANCEL:
  1077. case LIBINPUT_EVENT_TOUCH_FRAME:
  1078. print_touch_event(dev, e);
  1079. break;
  1080. case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN:
  1081. case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE:
  1082. case LIBINPUT_EVENT_GESTURE_PINCH_END:
  1083. case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN:
  1084. case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE:
  1085. case LIBINPUT_EVENT_GESTURE_SWIPE_END:
  1086. print_gesture_event(dev, e);
  1087. break;
  1088. case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY:
  1089. print_tablet_tool_proximity_event(dev, e);
  1090. break;
  1091. case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
  1092. case LIBINPUT_EVENT_TABLET_TOOL_TIP:
  1093. print_tablet_tool_event(dev, e);
  1094. break;
  1095. case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
  1096. print_tablet_tool_button_event(dev, e);
  1097. break;
  1098. case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
  1099. print_tablet_pad_button_event(dev, e);
  1100. break;
  1101. case LIBINPUT_EVENT_TABLET_PAD_RING:
  1102. case LIBINPUT_EVENT_TABLET_PAD_STRIP:
  1103. print_tablet_pad_ringstrip_event(dev, e);
  1104. break;
  1105. case LIBINPUT_EVENT_SWITCH_TOGGLE:
  1106. print_switch_event(dev, e);
  1107. break;
  1108. default:
  1109. break;
  1110. }
  1111. }
  1112. static bool
  1113. handle_hidraw(struct hidraw *hidraw)
  1114. {
  1115. struct record_device *d = hidraw->device;
  1116. unsigned char report[4096];
  1117. const char *sep = "";
  1118. struct timespec ts;
  1119. usec_t time;
  1120. int rc = read(hidraw->fd, report, sizeof(report));
  1121. if (rc <= 0)
  1122. return false;
  1123. /* hidraw doesn't give us a timestamps, we have to make them up */
  1124. clock_gettime(CLOCK_MONOTONIC, &ts);
  1125. time = usec_from_timespec(&ts);
  1126. /* The first evdev event is guaranteed to have an event time earlier
  1127. than now, so we don't set the offset here, we rely on the evdev
  1128. events to do so. This potentially leaves us with multiple hidraw
  1129. events at timestap 0 but it's too niche to worry about. */
  1130. if (usec_is_zero(d->ctx->offset))
  1131. time = usec_from_uint64_t(0);
  1132. else
  1133. time = time_offset(d->ctx, time);
  1134. {
  1135. iprintf(d->fp, I_EVENTTYPE, "- hid:\n");
  1136. uint64_t time_sec = usec_to_seconds(time);
  1137. uint64_t time_usec =
  1138. usec_as_uint64_t(time) % usec_as_uint64_t(usec_from_seconds(1));
  1139. iprintf(d->fp,
  1140. I_EVENT,
  1141. "time: [%3" PRIu64 ", %6" PRIu64 "]\n",
  1142. time_sec,
  1143. time_usec);
  1144. }
  1145. iprintf(d->fp, I_EVENT, "%s: [", hidraw->name);
  1146. for (int byte = 0; byte < rc; byte++) {
  1147. if (byte % 16 == 0) {
  1148. iprintf(d->fp, I_NONE, "%s\n", sep);
  1149. iprintf(d->fp, I_EVENT, " ");
  1150. iprintf(d->fp, I_NONE, "0x%02x", report[byte]);
  1151. } else {
  1152. iprintf(d->fp, I_NONE, "%s0x%02x", sep, report[byte]);
  1153. }
  1154. sep = ", ";
  1155. }
  1156. iprintf(d->fp, I_NONE, "\n");
  1157. iprintf(d->fp, I_EVENT, "]\n");
  1158. return true;
  1159. }
  1160. static bool
  1161. handle_libinput_events(struct record_context *ctx,
  1162. struct record_device *d,
  1163. bool start_frame)
  1164. {
  1165. struct libinput_event *e;
  1166. struct record_device *current = d;
  1167. libinput_dispatch(ctx->libinput);
  1168. e = libinput_get_event(ctx->libinput);
  1169. if (!e)
  1170. return false;
  1171. if (start_frame)
  1172. iprintf(d->fp, I_EVENTTYPE, "- libinput:\n");
  1173. else
  1174. iprintf(d->fp, I_EVENTTYPE, "libinput:\n");
  1175. do {
  1176. struct libinput_device *device = libinput_event_get_device(e);
  1177. if (device != current->device) {
  1178. struct record_device *tmp;
  1179. bool found = false;
  1180. list_for_each(tmp, &ctx->devices, link) {
  1181. if (device == tmp->device) {
  1182. current = tmp;
  1183. found = true;
  1184. break;
  1185. }
  1186. }
  1187. assert(found);
  1188. }
  1189. print_libinput_event(current, e);
  1190. libinput_event_destroy(e);
  1191. } while ((e = libinput_get_event(ctx->libinput)) != NULL);
  1192. return true;
  1193. }
  1194. static void
  1195. handle_events(struct record_context *ctx, struct record_device *d)
  1196. {
  1197. bool has_events = true;
  1198. while (has_events) {
  1199. has_events = handle_evdev_frame(d);
  1200. if (ctx->libinput)
  1201. has_events |= handle_libinput_events(ctx, d, !has_events);
  1202. }
  1203. fflush(d->fp);
  1204. }
  1205. static void
  1206. print_libinput_header(FILE *fp, usec_t timeout)
  1207. {
  1208. iprintf(fp, I_TOPLEVEL, "libinput:\n");
  1209. iprintf(fp, I_LIBINPUT, "version: \"%s\"\n", LIBINPUT_VERSION);
  1210. iprintf(fp, I_LIBINPUT, "git: \"%s\"\n", LIBINPUT_GIT_VERSION);
  1211. if (!usec_is_zero(timeout))
  1212. iprintf(fp, I_LIBINPUT, "autorestart: %u\n", usec_to_seconds(timeout));
  1213. }
  1214. static void
  1215. print_system_header(FILE *fp)
  1216. {
  1217. struct utsname u;
  1218. const char *kernel = "unknown";
  1219. iprintf(fp, I_TOPLEVEL, "system:\n");
  1220. /* /etc/os-release version and distribution name */
  1221. _autofclose_ FILE *osrelease = fopen("/etc/os-release", "r");
  1222. if (!osrelease)
  1223. osrelease = fopen("/usr/lib/os-release", "r");
  1224. if (osrelease) {
  1225. _autofree_ char *distro = NULL, *version = NULL;
  1226. char osrstr[256] = "unknown";
  1227. while (fgets(osrstr, sizeof(osrstr), osrelease)) {
  1228. size_t len = strlen(osrstr);
  1229. if (len > 0 && osrstr[len - 1] == '\n')
  1230. osrstr[len - 1] = '\0'; /* linebreak */
  1231. if (!distro && strstartswith(osrstr, "ID="))
  1232. distro = strstrip(&osrstr[3], "\"'");
  1233. else if (!version && strstartswith(osrstr, "VERSION_ID="))
  1234. version = strstrip(&osrstr[11], "\"'");
  1235. if (distro && version)
  1236. break;
  1237. }
  1238. if (distro && version) { // NOLINT: unix.Stream
  1239. iprintf(fp, I_SYSTEM, "os: \"%s:%s\"\n", distro, version);
  1240. }
  1241. }
  1242. /* kernel version */
  1243. if (uname(&u) != -1)
  1244. kernel = u.release;
  1245. iprintf(fp, I_SYSTEM, "kernel: \"%s\"\n", kernel);
  1246. /* dmi modalias */
  1247. _autofclose_ FILE *dmi = fopen("/sys/class/dmi/id/modalias", "r");
  1248. _autofree_ char *dmistr = strdup("unknown"); //
  1249. if (dmi) {
  1250. char buf[2048] = "unknown";
  1251. size_t n = fread(buf, 1, sizeof(buf), dmi); // NOLINT: unix.Stream
  1252. if (n > 0) {
  1253. free(dmistr);
  1254. dmistr = strndup(buf, n - 1);
  1255. }
  1256. }
  1257. iprintf(fp, I_SYSTEM, "dmi: \"%s\"\n", dmistr);
  1258. }
  1259. static void
  1260. print_header(FILE *fp, struct record_context *ctx)
  1261. {
  1262. iprintf(fp, I_TOPLEVEL, "# libinput record\n");
  1263. iprintf(fp, I_TOPLEVEL, "version: %d\n", FILE_VERSION_NUMBER);
  1264. iprintf(fp, I_TOPLEVEL, "ndevices: %d\n", ctx->ndevices);
  1265. print_libinput_header(fp, ctx->timeout);
  1266. print_system_header(fp);
  1267. }
  1268. static void
  1269. print_description_abs(FILE *fp, struct libevdev *dev, unsigned int code)
  1270. {
  1271. const struct input_absinfo *abs;
  1272. abs = libevdev_get_abs_info(dev, code);
  1273. assert(abs);
  1274. iprintf(fp, I_EVDEV, "# Value %6d\n", abs->value);
  1275. iprintf(fp, I_EVDEV, "# Min %6d\n", abs->minimum);
  1276. iprintf(fp, I_EVDEV, "# Max %6d\n", abs->maximum);
  1277. iprintf(fp, I_EVDEV, "# Fuzz %6d\n", abs->fuzz);
  1278. iprintf(fp, I_EVDEV, "# Flat %6d\n", abs->flat);
  1279. iprintf(fp, I_EVDEV, "# Resolution %6d\n", abs->resolution);
  1280. }
  1281. static void
  1282. print_description_state(FILE *fp,
  1283. struct libevdev *dev,
  1284. unsigned int type,
  1285. unsigned int code)
  1286. {
  1287. int state = libevdev_get_event_value(dev, type, code);
  1288. iprintf(fp, I_EVDEV, "# State %d\n", state);
  1289. }
  1290. static void
  1291. print_description_codes(FILE *fp, struct libevdev *dev, unsigned int type)
  1292. {
  1293. int max;
  1294. max = libevdev_event_type_get_max(type);
  1295. if (max == -1)
  1296. return;
  1297. iprintf(fp,
  1298. I_EVDEV,
  1299. "# Event type %d (%s)\n",
  1300. type,
  1301. libevdev_event_type_get_name(type));
  1302. if (type == EV_SYN)
  1303. return;
  1304. for (unsigned int code = 0; code <= (unsigned int)max; code++) {
  1305. if (!libevdev_has_event_code(dev, type, code))
  1306. continue;
  1307. iprintf(fp,
  1308. I_EVDEV,
  1309. "# Event code %d (%s)\n",
  1310. code,
  1311. libevdev_event_code_get_name(type, code));
  1312. switch (type) {
  1313. case EV_ABS:
  1314. print_description_abs(fp, dev, code);
  1315. break;
  1316. case EV_LED:
  1317. case EV_SW:
  1318. print_description_state(fp, dev, type, code);
  1319. break;
  1320. }
  1321. }
  1322. }
  1323. static void
  1324. print_description(FILE *fp, struct libevdev *dev)
  1325. {
  1326. const struct input_absinfo *x, *y;
  1327. int bustype;
  1328. const char *busname;
  1329. bustype = libevdev_get_id_bustype(dev);
  1330. switch (bustype) {
  1331. case BUS_USB:
  1332. busname = " (usb) ";
  1333. break;
  1334. case BUS_BLUETOOTH:
  1335. busname = " (bluetooth) ";
  1336. break;
  1337. case BUS_I2C:
  1338. busname = " (i2c) ";
  1339. break;
  1340. case BUS_SPI:
  1341. busname = " (spi) ";
  1342. break;
  1343. case BUS_RMI:
  1344. busname = " (rmi) ";
  1345. break;
  1346. default:
  1347. busname = " ";
  1348. break;
  1349. }
  1350. _autofree_ char *name = str_sanitize(libevdev_get_name(dev));
  1351. iprintf(fp, I_EVDEV, "# Name: %s\n", name ? name : "");
  1352. iprintf(fp,
  1353. I_EVDEV,
  1354. "# ID: bus 0x%04x%svendor 0x%04x product 0x%04x version 0x%04x\n",
  1355. bustype,
  1356. busname,
  1357. libevdev_get_id_vendor(dev),
  1358. libevdev_get_id_product(dev),
  1359. libevdev_get_id_version(dev));
  1360. x = libevdev_get_abs_info(dev, ABS_X);
  1361. y = libevdev_get_abs_info(dev, ABS_Y);
  1362. if (x && y) {
  1363. if (x->resolution && y->resolution) {
  1364. int w, h;
  1365. w = (x->maximum - x->minimum) / x->resolution;
  1366. h = (y->maximum - y->minimum) / y->resolution;
  1367. iprintf(fp, I_EVDEV, "# Size in mm: %dx%d\n", w, h);
  1368. } else {
  1369. iprintf(fp,
  1370. I_EVDEV,
  1371. "# Size in mm: unknown, missing resolution\n");
  1372. }
  1373. }
  1374. iprintf(fp, I_EVDEV, "# Supported Events:\n");
  1375. for (unsigned int type = 0; type < EV_CNT; type++) {
  1376. if (!libevdev_has_event_type(dev, type))
  1377. continue;
  1378. print_description_codes(fp, dev, type);
  1379. }
  1380. iprintf(fp, I_EVDEV, "# Properties:\n");
  1381. for (unsigned int prop = 0; prop < INPUT_PROP_CNT; prop++) {
  1382. if (libevdev_has_property(dev, prop)) {
  1383. iprintf(fp,
  1384. I_EVDEV,
  1385. "# Property %d (%s)\n",
  1386. prop,
  1387. libevdev_property_get_name(prop));
  1388. }
  1389. }
  1390. }
  1391. static void
  1392. print_bits_info(FILE *fp, struct libevdev *dev)
  1393. {
  1394. _autofree_ char *name = str_sanitize(libevdev_get_name(dev));
  1395. iprintf(fp, I_EVDEV, "name: \"%s\"\n", name ? name : "");
  1396. iprintf(fp,
  1397. I_EVDEV,
  1398. "id: [%d, %d, %d, %d]\n",
  1399. libevdev_get_id_bustype(dev),
  1400. libevdev_get_id_vendor(dev),
  1401. libevdev_get_id_product(dev),
  1402. libevdev_get_id_version(dev));
  1403. }
  1404. static void
  1405. print_bits_absinfo(FILE *fp, struct libevdev *dev)
  1406. {
  1407. const struct input_absinfo *abs;
  1408. if (!libevdev_has_event_type(dev, EV_ABS))
  1409. return;
  1410. iprintf(fp, I_EVDEV, "absinfo:\n");
  1411. for (unsigned int code = 0; code < ABS_CNT; code++) {
  1412. abs = libevdev_get_abs_info(dev, code);
  1413. if (!abs)
  1414. continue;
  1415. iprintf(fp,
  1416. I_EVDEV_DATA,
  1417. "%d: [%d, %d, %d, %d, %d]\n",
  1418. code,
  1419. abs->minimum,
  1420. abs->maximum,
  1421. abs->fuzz,
  1422. abs->flat,
  1423. abs->resolution);
  1424. }
  1425. }
  1426. static void
  1427. print_bits_codes(FILE *fp, struct libevdev *dev, unsigned int type)
  1428. {
  1429. int max;
  1430. const char *sep = "";
  1431. max = libevdev_event_type_get_max(type);
  1432. if (max == -1)
  1433. return;
  1434. iprintf(fp, I_EVDEV_DATA, "%d: [", type);
  1435. for (unsigned int code = 0; code <= (unsigned int)max; code++) {
  1436. if (!libevdev_has_event_code(dev, type, code))
  1437. continue;
  1438. iprintf(fp, I_NONE, "%s%d", sep, code);
  1439. sep = ", ";
  1440. }
  1441. iprintf(fp, I_NONE, "] # %s\n", libevdev_event_type_get_name(type));
  1442. }
  1443. static void
  1444. print_bits_types(FILE *fp, struct libevdev *dev)
  1445. {
  1446. iprintf(fp, I_EVDEV, "codes:\n");
  1447. for (unsigned int type = 0; type < EV_CNT; type++) {
  1448. if (!libevdev_has_event_type(dev, type))
  1449. continue;
  1450. print_bits_codes(fp, dev, type);
  1451. }
  1452. }
  1453. static void
  1454. print_bits_props(FILE *fp, struct libevdev *dev)
  1455. {
  1456. const char *sep = "";
  1457. iprintf(fp, I_EVDEV, "properties: [");
  1458. for (unsigned int prop = 0; prop < INPUT_PROP_CNT; prop++) {
  1459. if (libevdev_has_property(dev, prop)) {
  1460. iprintf(fp, I_NONE, "%s%d", sep, prop);
  1461. sep = ", ";
  1462. }
  1463. }
  1464. iprintf(fp, I_NONE, "]\n"); /* last entry, no comma */
  1465. }
  1466. static void
  1467. print_evdev_description(struct record_device *dev)
  1468. {
  1469. struct libevdev *evdev = dev->evdev;
  1470. iprintf(dev->fp, I_DEVICE, "evdev:\n");
  1471. print_description(dev->fp, evdev);
  1472. print_bits_info(dev->fp, evdev);
  1473. print_bits_types(dev->fp, evdev);
  1474. print_bits_absinfo(dev->fp, evdev);
  1475. print_bits_props(dev->fp, evdev);
  1476. }
  1477. static void
  1478. print_hid_report_descriptor(struct record_device *dev)
  1479. {
  1480. const char *prefix = "/dev/input/event";
  1481. char syspath[PATH_MAX];
  1482. unsigned char buf[1024];
  1483. int len;
  1484. int fd;
  1485. const char *sep = "";
  1486. /* we take the shortcut rather than the proper udev approach, the
  1487. report_descriptor is available in sysfs and two devices up from
  1488. our device.
  1489. This approach won't work for /dev/input/by-id devices. */
  1490. if (!strstartswith(dev->devnode, prefix))
  1491. return;
  1492. len = snprintf(syspath,
  1493. sizeof(syspath),
  1494. "/sys/class/input/%s/device/device/report_descriptor",
  1495. safe_basename(dev->devnode));
  1496. if (len <= 0)
  1497. return;
  1498. fd = open(syspath, O_RDONLY | O_CLOEXEC);
  1499. if (fd == -1)
  1500. return;
  1501. iprintf(dev->fp, I_DEVICE, "hid: [");
  1502. while ((len = read(fd, buf, sizeof(buf))) > 0) {
  1503. for (int i = 0; i < len; i++) {
  1504. /* We can't have a trailing comma, so our line-break
  1505. * handling is awkward.
  1506. * For a linebreak: print the comma, break, indent,
  1507. * then just the hex code.
  1508. * For the other values: print the comma plus the
  1509. * hex code, unindented.
  1510. */
  1511. if (i % 16 == 0) {
  1512. iprintf(dev->fp, I_NONE, "%s\n", sep);
  1513. iprintf(dev->fp, I_DEVICE, " ");
  1514. iprintf(dev->fp, I_NONE, "0x%02x", buf[i]);
  1515. } else {
  1516. iprintf(dev->fp, I_NONE, "%s0x%02x", sep, buf[i]);
  1517. }
  1518. sep = ", ";
  1519. }
  1520. }
  1521. iprintf(dev->fp, I_NONE, "\n");
  1522. iprintf(dev->fp, I_DEVICE, "]\n");
  1523. xclose(&fd);
  1524. }
  1525. static void
  1526. print_udev_properties(struct record_device *dev)
  1527. {
  1528. struct stat st;
  1529. if (stat(dev->devnode, &st) < 0)
  1530. return;
  1531. _unref_(udev) *udev = udev_new();
  1532. if (!udev)
  1533. return;
  1534. _unref_(udev_device) *udev_device =
  1535. udev_device_new_from_devnum(udev, 'c', st.st_rdev);
  1536. if (!udev_device)
  1537. return;
  1538. iprintf(dev->fp, I_DEVICE, "udev:\n");
  1539. iprintf(dev->fp, I_UDEV, "properties:\n");
  1540. struct udev_list_entry *entry =
  1541. udev_device_get_properties_list_entry(udev_device);
  1542. while (entry) {
  1543. const char *key, *value;
  1544. key = udev_list_entry_get_name(entry);
  1545. if (strstartswith(key, "ID_INPUT") || strstartswith(key, "HID_BPF") ||
  1546. strstartswith(key, "LIBINPUT") || strstartswith(key, "EVDEV_ABS") ||
  1547. strstartswith(key, "MOUSE_DPI") ||
  1548. strstartswith(key, "POINTINGSTICK_")) {
  1549. value = udev_list_entry_get_value(entry);
  1550. iprintf(dev->fp, I_UDEV_DATA, "- %s=%s\n", key, value);
  1551. }
  1552. entry = udev_list_entry_get_next(entry);
  1553. }
  1554. for (struct udev_device *parent = udev_device; parent;
  1555. parent = udev_device_get_parent(parent)) {
  1556. const char *driver = udev_device_get_property_value(parent, "DRIVER");
  1557. if (driver) {
  1558. iprintf(dev->fp, I_UDEV_DATA, "- DRIVER=%s\n", driver);
  1559. break;
  1560. }
  1561. }
  1562. iprintf(dev->fp,
  1563. I_UDEV,
  1564. "virtual: %s\n",
  1565. udev_device_is_virtual(udev_device) ? "true" : "false");
  1566. }
  1567. static void
  1568. quirks_log_handler(struct libinput *this_is_null,
  1569. enum libinput_log_priority priority,
  1570. const char *format,
  1571. va_list args)
  1572. {
  1573. }
  1574. static void
  1575. list_print(void *userdata, const char *val)
  1576. {
  1577. FILE *fp = userdata;
  1578. iprintf(fp, I_QUIRKS, "- %s\n", val);
  1579. }
  1580. static void
  1581. print_device_quirks(struct record_device *dev)
  1582. {
  1583. struct stat st;
  1584. const char *data_path = LIBINPUT_QUIRKS_DIR;
  1585. const char *override_file = LIBINPUT_QUIRKS_OVERRIDE_FILE;
  1586. if (stat(dev->devnode, &st) < 0)
  1587. return;
  1588. if (builddir_lookup(NULL)) {
  1589. setenv("LIBINPUT_QUIRKS_DIR", LIBINPUT_QUIRKS_SRCDIR, 0);
  1590. data_path = LIBINPUT_QUIRKS_SRCDIR;
  1591. override_file = NULL;
  1592. }
  1593. _unref_(quirks_context) *quirks =
  1594. quirks_init_subsystem(data_path,
  1595. override_file,
  1596. quirks_log_handler,
  1597. NULL,
  1598. QLOG_CUSTOM_LOG_PRIORITIES);
  1599. if (!quirks) {
  1600. fprintf(stderr,
  1601. "Failed to load the device quirks from %s%s%s. "
  1602. "This will negatively affect device behavior. "
  1603. "See %s/device-quirks.html for details.\n",
  1604. data_path,
  1605. override_file ? " and " : "",
  1606. override_file ? override_file : "",
  1607. HTTP_DOC_LINK);
  1608. return;
  1609. }
  1610. _unref_(udev) *udev = udev_new();
  1611. if (!udev)
  1612. return;
  1613. _unref_(udev_device) *udev_device =
  1614. udev_device_new_from_devnum(udev, 'c', st.st_rdev);
  1615. if (udev_device) {
  1616. iprintf(dev->fp, I_DEVICE, "quirks:\n");
  1617. tools_list_device_quirks(quirks, udev_device, list_print, dev->fp);
  1618. }
  1619. }
  1620. static void
  1621. print_libinput_description(struct record_device *dev)
  1622. {
  1623. struct libinput_device *device = dev->device;
  1624. double w, h;
  1625. struct cap {
  1626. enum libinput_device_capability cap;
  1627. const char *name;
  1628. } caps[] = {
  1629. { LIBINPUT_DEVICE_CAP_KEYBOARD, "keyboard" },
  1630. { LIBINPUT_DEVICE_CAP_POINTER, "pointer" },
  1631. { LIBINPUT_DEVICE_CAP_TOUCH, "touch" },
  1632. { LIBINPUT_DEVICE_CAP_TABLET_TOOL, "tablet" },
  1633. { LIBINPUT_DEVICE_CAP_TABLET_PAD, "pad" },
  1634. { LIBINPUT_DEVICE_CAP_GESTURE, "gesture" },
  1635. { LIBINPUT_DEVICE_CAP_SWITCH, "switch" },
  1636. };
  1637. const char *sep = "";
  1638. if (!device)
  1639. return;
  1640. iprintf(dev->fp, I_DEVICE, "libinput:\n");
  1641. if (libinput_device_get_size(device, &w, &h) == 0)
  1642. iprintf(dev->fp, I_LIBINPUTDEV, "size: [%.f, %.f]\n", w, h);
  1643. iprintf(dev->fp, I_LIBINPUTDEV, "capabilities: [");
  1644. ARRAY_FOR_EACH(caps, cap) {
  1645. if (!libinput_device_has_capability(device, cap->cap))
  1646. continue;
  1647. iprintf(dev->fp, I_NONE, "%s%s", sep, cap->name);
  1648. sep = ", ";
  1649. }
  1650. iprintf(dev->fp, I_NONE, "]\n");
  1651. /* Configuration options should be printed here, but since they
  1652. * don't reflect the user-configured ones their usefulness is
  1653. * questionable. We need the ability to specify the options like in
  1654. * debug-events.
  1655. */
  1656. }
  1657. static void
  1658. print_device_description(struct record_device *dev)
  1659. {
  1660. iprintf(dev->fp, I_DEVICE, "- node: %s\n", dev->devnode);
  1661. print_evdev_description(dev);
  1662. print_hid_report_descriptor(dev);
  1663. print_udev_properties(dev);
  1664. print_device_quirks(dev);
  1665. print_libinput_description(dev);
  1666. }
  1667. static int
  1668. is_event_node(const struct dirent *dir)
  1669. {
  1670. return strstartswith(dir->d_name, "event");
  1671. }
  1672. static char *
  1673. select_device(void)
  1674. {
  1675. _autofree_ struct dirent **namelist;
  1676. int ndev, selected_device;
  1677. int rc;
  1678. char *device_path;
  1679. bool has_eaccess = false;
  1680. int available_devices = 0;
  1681. const char *prefix = "";
  1682. if (!isatty(STDERR_FILENO))
  1683. prefix = "# ";
  1684. ndev = scandir("/dev/input", &namelist, is_event_node, versionsort);
  1685. if (ndev <= 0)
  1686. return NULL;
  1687. fprintf(stderr, "%sAvailable devices:\n", prefix);
  1688. for (int i = 0; i < ndev; i++) {
  1689. _autofree_ struct dirent *entry = namelist[i];
  1690. char path[PATH_MAX];
  1691. snprintf(path, sizeof(path), "/dev/input/%s", entry->d_name);
  1692. _cleanup_(xclose) int fd = open(path, O_RDONLY | O_CLOEXEC);
  1693. if (fd < 0) {
  1694. if (errno == EACCES)
  1695. has_eaccess = true;
  1696. continue;
  1697. }
  1698. struct libevdev *device;
  1699. rc = libevdev_new_from_fd(fd, &device);
  1700. if (rc != 0)
  1701. continue;
  1702. _autofree_ char *name = str_sanitize(libevdev_get_name(device));
  1703. fprintf(stderr, "%s%s: %s\n", prefix, path, name ? name : "");
  1704. libevdev_free(device);
  1705. available_devices++;
  1706. }
  1707. if (available_devices == 0) {
  1708. fprintf(stderr,
  1709. "No devices available.%s\n",
  1710. has_eaccess ? " Please re-run as root." : "");
  1711. return NULL;
  1712. }
  1713. fprintf(stderr, "%sSelect the device event number: ", prefix);
  1714. rc = scanf("%d", &selected_device);
  1715. if (rc != 1 || selected_device < 0)
  1716. return NULL;
  1717. rc = xasprintf(&device_path, "/dev/input/event%d", selected_device);
  1718. if (rc == -1)
  1719. return NULL;
  1720. return device_path;
  1721. }
  1722. static char **
  1723. all_devices(void)
  1724. {
  1725. _autofree_ struct dirent **namelist;
  1726. int ndev;
  1727. _autostrvfree_ char **devices = NULL;
  1728. ndev = scandir("/dev/input", &namelist, is_event_node, versionsort);
  1729. if (ndev <= 0)
  1730. return NULL;
  1731. devices = zalloc((ndev + 1) * sizeof *devices); /* NULL-terminated */
  1732. for (int i = 0; i < ndev; i++) {
  1733. _autofree_ struct dirent *entry = namelist[i];
  1734. char *device_path;
  1735. int rc = xasprintf(&device_path, "/dev/input/%s", entry->d_name);
  1736. if (rc == -1)
  1737. return NULL;
  1738. devices[i] = device_path;
  1739. }
  1740. return steal(&devices);
  1741. }
  1742. static char *
  1743. init_output_file(const char *file, bool is_prefix)
  1744. {
  1745. char name[PATH_MAX];
  1746. assert(file != NULL);
  1747. if (is_prefix) {
  1748. struct tm *tm;
  1749. time_t t;
  1750. char suffix[64];
  1751. t = time(NULL);
  1752. tm = localtime(&t);
  1753. strftime(suffix, sizeof(suffix), "%F-%T", tm);
  1754. snprintf(name, sizeof(name), "%s.%s", file, suffix);
  1755. } else {
  1756. snprintf(name, sizeof(name), "%s", file);
  1757. }
  1758. return safe_strdup(name);
  1759. }
  1760. static bool
  1761. open_output_files(struct record_context *ctx, bool is_prefix)
  1762. {
  1763. FILE *out_file;
  1764. struct record_device *d;
  1765. if (ctx->output_file.name) {
  1766. char *fname = init_output_file(ctx->output_file.name, is_prefix);
  1767. ctx->output_file.name_with_suffix = fname;
  1768. out_file = fopen(fname, "w");
  1769. if (!out_file)
  1770. return false;
  1771. } else {
  1772. ctx->output_file.name_with_suffix = safe_strdup("stdout");
  1773. out_file = stdout;
  1774. }
  1775. ctx->first_device->fp = out_file;
  1776. list_for_each(d, &ctx->devices, link) {
  1777. if (d->fp)
  1778. continue;
  1779. d->fp = tmpfile();
  1780. if (!d->fp)
  1781. return false;
  1782. }
  1783. return true;
  1784. }
  1785. static void
  1786. print_progress_bar(void)
  1787. {
  1788. static uint8_t foo = 0;
  1789. if (!isatty(STDERR_FILENO))
  1790. return;
  1791. if (++foo > 20)
  1792. foo = 1;
  1793. fprintf(stderr, "\rReceiving events: [%*s%*s]", foo, "*", 21 - foo, " ");
  1794. }
  1795. static void
  1796. print_wall_time(struct record_context *ctx)
  1797. {
  1798. time_t t = time(NULL);
  1799. struct tm tm;
  1800. struct record_device *d;
  1801. localtime_r(&t, &tm);
  1802. list_for_each(d, &ctx->devices, link) {
  1803. iprintf(d->fp,
  1804. I_DEVICE,
  1805. "# Current time is %02d:%02d:%02d\n",
  1806. tm.tm_hour,
  1807. tm.tm_min,
  1808. tm.tm_sec);
  1809. fflush(d->fp);
  1810. }
  1811. }
  1812. static struct source *
  1813. add_source(struct record_context *ctx,
  1814. int fd,
  1815. source_dispatch_t dispatch,
  1816. void *user_data)
  1817. {
  1818. assert(fd != -1);
  1819. _autofree_ struct source *source = zalloc(sizeof *source);
  1820. source->dispatch = dispatch;
  1821. source->user_data = user_data;
  1822. source->fd = fd;
  1823. struct epoll_event ep;
  1824. memset(&ep, 0, sizeof ep);
  1825. ep.events = EPOLLIN;
  1826. ep.data.ptr = source;
  1827. if (epoll_ctl(ctx->epoll_fd, EPOLL_CTL_ADD, fd, &ep) < 0) {
  1828. return NULL;
  1829. }
  1830. list_append(&ctx->sources, &source->link);
  1831. return steal(&source);
  1832. }
  1833. static void
  1834. destroy_source(struct record_context *ctx, struct source *source)
  1835. {
  1836. list_remove(&source->link);
  1837. epoll_ctl(ctx->epoll_fd, EPOLL_CTL_DEL, source->fd, NULL);
  1838. xclose(&source->fd);
  1839. free(source);
  1840. }
  1841. static void
  1842. signalfd_dispatch(struct record_context *ctx, int fd, void *data)
  1843. {
  1844. struct signalfd_siginfo fdsi;
  1845. (void)read(fd, &fdsi, sizeof(fdsi));
  1846. ctx->stop = true;
  1847. }
  1848. static void
  1849. evdev_dispatch(struct record_context *ctx, int fd, void *data)
  1850. {
  1851. struct record_device *this_device = data;
  1852. ctx->had_events = true;
  1853. handle_events(ctx, this_device);
  1854. }
  1855. static void
  1856. libinput_ctx_dispatch(struct record_context *ctx, int fd, void *data)
  1857. {
  1858. /* This function should only handle events caused by internal
  1859. * timeouts etc. The real input events caused by the evdev devices
  1860. * are already processed in handle_events */
  1861. libinput_dispatch(ctx->libinput);
  1862. handle_libinput_events(ctx, ctx->first_device, true);
  1863. }
  1864. static void
  1865. hidraw_dispatch(struct record_context *ctx, int fd, void *data)
  1866. {
  1867. struct hidraw *hidraw = data;
  1868. ctx->had_events = true;
  1869. handle_hidraw(hidraw);
  1870. }
  1871. static int
  1872. wait_for_sources(struct record_context *ctx,
  1873. struct epoll_event *ep,
  1874. int max_events,
  1875. int timeout_ms)
  1876. {
  1877. int count = epoll_wait(ctx->epoll_fd, ep, max_events, timeout_ms);
  1878. if (count < 0)
  1879. return -errno;
  1880. return count;
  1881. }
  1882. static void
  1883. dispatch_ready_sources(struct record_context *ctx, struct epoll_event *ep, int count)
  1884. {
  1885. for (int i = 0; i < count; ++i) {
  1886. struct source *source = ep[i].data.ptr;
  1887. if (source->fd == -1)
  1888. continue;
  1889. source->dispatch(ctx, source->fd, source->user_data);
  1890. }
  1891. }
  1892. static int
  1893. dispatch_sources(struct record_context *ctx)
  1894. {
  1895. struct epoll_event ep[64];
  1896. int timeout = usec_to_millis(ctx->timeout);
  1897. int count =
  1898. wait_for_sources(ctx, ep, ARRAY_LENGTH(ep), timeout > 0 ? timeout : -1);
  1899. if (count < 0)
  1900. return count;
  1901. if (count > 0) {
  1902. usec_t now = usec_from_now();
  1903. usec_t dt = usec_delta(now, ctx->timestamps.last_wall_time);
  1904. if (usec_cmp(dt, usec_from_seconds(5)) > 0) {
  1905. ctx->timestamps.last_wall_time = now;
  1906. print_wall_time(ctx);
  1907. }
  1908. }
  1909. dispatch_ready_sources(ctx, ep, count);
  1910. return count;
  1911. }
  1912. static int
  1913. mainloop(struct record_context *ctx)
  1914. {
  1915. bool autorestart = !usec_is_zero(ctx->timeout);
  1916. struct source *source;
  1917. struct record_device *d = NULL;
  1918. sigset_t mask;
  1919. int sigfd;
  1920. assert(!list_empty(&ctx->devices));
  1921. ctx->epoll_fd = epoll_create1(0);
  1922. assert(ctx->epoll_fd >= 0);
  1923. sigemptyset(&mask);
  1924. sigaddset(&mask, SIGINT);
  1925. sigaddset(&mask, SIGQUIT);
  1926. sigprocmask(SIG_BLOCK, &mask, NULL);
  1927. sigfd = signalfd(-1, &mask, SFD_NONBLOCK);
  1928. add_source(ctx, sigfd, signalfd_dispatch, NULL);
  1929. list_for_each(d, &ctx->devices, link) {
  1930. struct hidraw *hidraw;
  1931. add_source(ctx, libevdev_get_fd(d->evdev), evdev_dispatch, d);
  1932. list_for_each(hidraw, &d->hidraw_devices, link) {
  1933. add_source(ctx, hidraw->fd, hidraw_dispatch, hidraw);
  1934. }
  1935. }
  1936. if (ctx->libinput) {
  1937. /* See the note in the dispatch function */
  1938. add_source(ctx,
  1939. libinput_get_fd(ctx->libinput),
  1940. libinput_ctx_dispatch,
  1941. NULL);
  1942. }
  1943. /* If we have more than one device, the time starts at recording
  1944. * start time. Otherwise, the first event starts the recording time.
  1945. */
  1946. if (ctx->ndevices > 1) {
  1947. struct timespec ts;
  1948. clock_gettime(CLOCK_MONOTONIC, &ts);
  1949. ctx->offset = usec_from_timespec(&ts);
  1950. }
  1951. do {
  1952. struct record_device *d;
  1953. struct epoll_event ep[64] = { 0 };
  1954. int count = 0;
  1955. if (autorestart) {
  1956. fprintf(stderr,
  1957. "%sWaiting for events...\n",
  1958. isatty(STDERR_FILENO) ? "" : "# ");
  1959. /* Don't create the output file until we have events */
  1960. count = wait_for_sources(ctx, ep, ARRAY_LENGTH(ep), -1);
  1961. if (count < 0) {
  1962. fprintf(stderr, "Error: %s\n", strerror(-count));
  1963. ctx->stop = true;
  1964. break;
  1965. }
  1966. bool has_event_source = false;
  1967. for (int i = 0; i < count; i++) {
  1968. struct source *s = ep[i].data.ptr;
  1969. if (s->dispatch != signalfd_dispatch)
  1970. has_event_source = true;
  1971. }
  1972. if (!has_event_source) {
  1973. dispatch_ready_sources(ctx, ep, count);
  1974. break;
  1975. }
  1976. }
  1977. if (!open_output_files(ctx, autorestart)) {
  1978. fprintf(stderr,
  1979. "Failed to open '%s'\n",
  1980. ctx->output_file.name_with_suffix);
  1981. break;
  1982. }
  1983. fprintf(stderr,
  1984. "%sRecording to '%s'.\n",
  1985. isatty(STDERR_FILENO) ? "" : "# ",
  1986. ctx->output_file.name_with_suffix);
  1987. ctx->had_events = false;
  1988. print_header(ctx->first_device->fp, ctx);
  1989. if (autorestart)
  1990. iprintf(ctx->first_device->fp,
  1991. I_NONE,
  1992. "# Autorestart timeout: %u\n",
  1993. usec_to_seconds(ctx->timeout));
  1994. iprintf(ctx->first_device->fp, I_TOPLEVEL, "devices:\n");
  1995. list_for_each(d, &ctx->devices, link) {
  1996. print_device_description(d);
  1997. iprintf(d->fp,
  1998. I_DEVICE,
  1999. "events:%s\n",
  2000. ctx->no_events ? " []" : "");
  2001. }
  2002. if (!ctx->no_events) {
  2003. ctx->timestamps.last_wall_time = usec_from_now();
  2004. print_wall_time(ctx);
  2005. if (ctx->libinput) {
  2006. libinput_dispatch(ctx->libinput);
  2007. handle_libinput_events(ctx, ctx->first_device, true);
  2008. }
  2009. if (autorestart) {
  2010. /* Dispatch the events that woke us up from
  2011. * the idle wait */
  2012. dispatch_ready_sources(ctx, ep, count);
  2013. if (ctx->first_device->fp != stdout)
  2014. print_progress_bar();
  2015. }
  2016. while (true) {
  2017. int rc = dispatch_sources(ctx);
  2018. if (rc < 0) { /* error */
  2019. fprintf(stderr, "Error: %s\n", strerror(-rc));
  2020. ctx->stop = true;
  2021. break;
  2022. }
  2023. /* set by the signalfd handler */
  2024. if (ctx->stop)
  2025. break;
  2026. if (rc == 0) {
  2027. fprintf(stderr, " ... timeout\n");
  2028. break;
  2029. }
  2030. if (ctx->first_device->fp != stdout)
  2031. print_progress_bar();
  2032. }
  2033. if (autorestart) {
  2034. list_for_each(d, &ctx->devices, link) {
  2035. iprintf(d->fp,
  2036. I_NONE,
  2037. "# Closing after %us inactivity",
  2038. usec_to_seconds(ctx->timeout));
  2039. }
  2040. }
  2041. }
  2042. /* First device is printed, now append all the data from the
  2043. * other devices, if any */
  2044. list_for_each(d, &ctx->devices, link) {
  2045. char buf[4096];
  2046. size_t n;
  2047. if (d == ctx->first_device)
  2048. continue;
  2049. rewind(d->fp);
  2050. do {
  2051. n = fread(buf, 1, sizeof(buf), d->fp);
  2052. if (n > 0)
  2053. fwrite(buf, 1, n, ctx->first_device->fp);
  2054. } while (n == sizeof(buf));
  2055. fclose(d->fp);
  2056. d->fp = NULL;
  2057. }
  2058. if (!isatty(fileno(ctx->first_device->fp))) {
  2059. list_for_each(d, &ctx->devices, link) {
  2060. if (d->fp && d->fp != stdout) {
  2061. fclose(d->fp);
  2062. d->fp = NULL;
  2063. }
  2064. }
  2065. }
  2066. free_clear(&ctx->output_file.name_with_suffix);
  2067. } while (!ctx->no_events && autorestart && !ctx->stop);
  2068. sigprocmask(SIG_UNBLOCK, &mask, NULL);
  2069. list_for_each_safe(source, &ctx->sources, link) {
  2070. destroy_source(ctx, source);
  2071. }
  2072. xclose(&ctx->epoll_fd);
  2073. return 0;
  2074. }
  2075. static bool
  2076. init_device(struct record_context *ctx, const char *path, bool grab)
  2077. {
  2078. _autofree_ struct record_device *d = zalloc(sizeof(*d));
  2079. d->ctx = ctx;
  2080. d->devnode = safe_strdup(path);
  2081. list_init(&d->hidraw_devices);
  2082. _cleanup_(xclose) int fd = open(d->devnode, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
  2083. if (fd < 0) {
  2084. fprintf(stderr, "Failed to open device %s (%m)\n", d->devnode);
  2085. return false;
  2086. }
  2087. int rc = libevdev_new_from_fd(fd, &d->evdev);
  2088. if (rc == 0)
  2089. rc = libevdev_new_from_fd(fd, &d->evdev_prev);
  2090. if (rc != 0) {
  2091. fprintf(stderr,
  2092. "Failed to create context for %s (%s)\n",
  2093. d->devnode,
  2094. strerror(-rc));
  2095. return false;
  2096. }
  2097. if (grab) {
  2098. rc = libevdev_grab(d->evdev, LIBEVDEV_GRAB);
  2099. if (rc != 0) {
  2100. fprintf(stderr, "Grab failed on %s: %s\n", path, strerror(-rc));
  2101. return false;
  2102. }
  2103. }
  2104. libevdev_set_clock_id(d->evdev, CLOCK_MONOTONIC);
  2105. if (libevdev_get_num_slots(d->evdev) > 0)
  2106. d->touch.is_touch_device = true;
  2107. if (!ctx->first_device)
  2108. ctx->first_device = d;
  2109. list_take_append(&ctx->devices, d, link);
  2110. ctx->ndevices++;
  2111. // Shut up clang-tidy
  2112. steal_fd(&fd);
  2113. return true;
  2114. }
  2115. static int
  2116. open_restricted(const char *path, int flags, void *user_data)
  2117. {
  2118. int fd = open(path, flags);
  2119. return fd == -1 ? -errno : fd;
  2120. }
  2121. static void
  2122. close_restricted(int fd, void *user_data)
  2123. {
  2124. close(fd);
  2125. }
  2126. static const struct libinput_interface interface = {
  2127. .open_restricted = open_restricted,
  2128. .close_restricted = close_restricted,
  2129. };
  2130. static bool
  2131. init_libinput(struct record_context *ctx)
  2132. {
  2133. struct record_device *dev;
  2134. struct libinput *li;
  2135. li = libinput_path_create_context(&interface, NULL);
  2136. if (li == NULL) {
  2137. fprintf(stderr, "Failed to create libinput context\n");
  2138. return false;
  2139. }
  2140. ctx->libinput = li;
  2141. list_for_each(dev, &ctx->devices, link) {
  2142. struct libinput_device *d;
  2143. d = libinput_path_add_device(li, dev->devnode);
  2144. if (!d) {
  2145. fprintf(stderr, "Failed to add device %s\n", dev->devnode);
  2146. continue;
  2147. }
  2148. dev->device = libinput_device_ref(d);
  2149. /* FIXME: this needs to be a commandline option */
  2150. libinput_device_config_tap_set_enabled(d, LIBINPUT_CONFIG_TAP_ENABLED);
  2151. }
  2152. return true;
  2153. }
  2154. static bool
  2155. init_hidraw(struct record_context *ctx)
  2156. {
  2157. struct record_device *dev;
  2158. list_for_each(dev, &ctx->devices, link) {
  2159. char syspath[PATH_MAX];
  2160. DIR *dir;
  2161. struct dirent *entry;
  2162. snprintf(syspath,
  2163. sizeof(syspath),
  2164. "/sys/class/input/%s/device/device/hidraw",
  2165. safe_basename(dev->devnode));
  2166. dir = opendir(syspath);
  2167. if (!dir)
  2168. continue;
  2169. while ((entry = readdir(dir))) {
  2170. char hidraw_node[PATH_MAX];
  2171. int fd;
  2172. struct hidraw *hidraw = NULL;
  2173. if (!strstartswith(entry->d_name, "hidraw"))
  2174. continue;
  2175. snprintf(hidraw_node,
  2176. sizeof(hidraw_node),
  2177. "/dev/%s",
  2178. entry->d_name);
  2179. fd = open(hidraw_node, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
  2180. if (fd == -1)
  2181. continue;
  2182. hidraw = zalloc(sizeof(*hidraw));
  2183. hidraw->fd = fd;
  2184. hidraw->name = safe_strdup(entry->d_name);
  2185. hidraw->device = dev;
  2186. list_insert(&dev->hidraw_devices, &hidraw->link);
  2187. }
  2188. closedir(dir);
  2189. }
  2190. return true;
  2191. }
  2192. static void
  2193. usage(void)
  2194. {
  2195. printf("Usage: %s [--help] [--all] [--autorestart=2] [--output-file filename] [--no-events] [/dev/input/event0] [...]\n"
  2196. "Common use-cases:\n"
  2197. "\n"
  2198. " sudo %s -o recording.yml\n"
  2199. " Then select the device to record and it Ctrl+C to stop.\n"
  2200. " The recorded data is in recording.yml and can be attached to a bug report.\n"
  2201. "\n"
  2202. " sudo %s -o recording.yml --autorestart=2\n"
  2203. " As above, but restarts after 2s of inactivity on the device.\n"
  2204. " Note, the output file is only the prefix.\n"
  2205. "\n"
  2206. " sudo %s -o recording.yml /dev/input/event3 /dev/input/event4\n"
  2207. " Records the two devices into the same recordings file.\n"
  2208. "\n"
  2209. " sudo %s --no-events /dev/input/event3\n"
  2210. " Print the device description only, do not wait for events.\n"
  2211. "\n"
  2212. "For more information, see the %s(1) man page\n",
  2213. program_invocation_short_name,
  2214. program_invocation_short_name,
  2215. program_invocation_short_name,
  2216. program_invocation_short_name,
  2217. program_invocation_short_name,
  2218. program_invocation_short_name);
  2219. }
  2220. enum ftype {
  2221. F_FILE = 8,
  2222. F_DEVICE,
  2223. F_NOEXIST,
  2224. };
  2225. static enum ftype
  2226. is_char_dev(const char *path)
  2227. {
  2228. struct stat st;
  2229. if (strstartswith(path, "/dev"))
  2230. return F_DEVICE;
  2231. if (stat(path, &st) != 0) {
  2232. if (errno == ENOENT)
  2233. return F_NOEXIST;
  2234. return F_FILE;
  2235. }
  2236. return S_ISCHR(st.st_mode) ? F_DEVICE : F_FILE;
  2237. }
  2238. enum fposition {
  2239. ERROR,
  2240. NO_FILE,
  2241. FIRST,
  2242. LAST,
  2243. };
  2244. static enum fposition
  2245. find_output_file(int argc, char *argv[], const char **output_file)
  2246. {
  2247. char *first, *last;
  2248. enum ftype ftype_first, ftype_last;
  2249. first = argv[0];
  2250. ftype_first = is_char_dev(first);
  2251. if (argc == 1) {
  2252. /* arg is *not* a char device, so let's assume it's
  2253. * the output file */
  2254. if (ftype_first != F_DEVICE) {
  2255. *output_file = first;
  2256. return FIRST;
  2257. }
  2258. }
  2259. /* multiple arguments, yay */
  2260. last = argv[argc - 1];
  2261. ftype_last = is_char_dev(last);
  2262. /*
  2263. first is device, last is file -> last
  2264. first is device, last is device -> noop
  2265. first is device, last !exist -> last
  2266. first is file, last is device -> first
  2267. first is file, last is file -> error
  2268. first is file, last !exist -> error
  2269. first !exist, last is device -> first
  2270. first !exist, last is file -> error
  2271. first !exit, last !exist -> error
  2272. */
  2273. #define _m(f, l) (((f) << 8) | (l))
  2274. switch (_m(ftype_first, ftype_last)) {
  2275. case _m(F_FILE, F_DEVICE):
  2276. case _m(F_FILE, F_NOEXIST):
  2277. case _m(F_NOEXIST, F_DEVICE):
  2278. *output_file = first;
  2279. return FIRST;
  2280. case _m(F_DEVICE, F_FILE):
  2281. case _m(F_DEVICE, F_NOEXIST):
  2282. *output_file = last;
  2283. return LAST;
  2284. case _m(F_DEVICE, F_DEVICE):
  2285. break;
  2286. case _m(F_FILE, F_FILE):
  2287. case _m(F_NOEXIST, F_FILE):
  2288. case _m(F_NOEXIST, F_NOEXIST):
  2289. return ERROR;
  2290. }
  2291. #undef _m
  2292. return NO_FILE;
  2293. }
  2294. enum options {
  2295. OPT_AUTORESTART,
  2296. OPT_HELP,
  2297. OPT_OUTFILE,
  2298. OPT_KEYCODES,
  2299. OPT_MULTIPLE,
  2300. OPT_ALL,
  2301. OPT_LIBINPUT,
  2302. OPT_HIDRAW,
  2303. OPT_GRAB,
  2304. OPT_NO_EVENTS,
  2305. };
  2306. int
  2307. main(int argc, char **argv)
  2308. {
  2309. struct record_context ctx = {
  2310. .timeout = usec_from_uint64_t(0),
  2311. .show_keycodes = false,
  2312. .timestamps.last_wall_time = usec_from_uint64_t(0),
  2313. };
  2314. struct option opts[] = {
  2315. { "autorestart", required_argument, 0, OPT_AUTORESTART },
  2316. { "output-file", required_argument, 0, OPT_OUTFILE },
  2317. { "show-keycodes", no_argument, 0, OPT_KEYCODES },
  2318. { "multiple", no_argument, 0, OPT_MULTIPLE },
  2319. { "all", no_argument, 0, OPT_ALL },
  2320. { "help", no_argument, 0, OPT_HELP },
  2321. { "with-libinput", no_argument, 0, OPT_LIBINPUT },
  2322. { "with-hidraw", no_argument, 0, OPT_HIDRAW },
  2323. { "grab", no_argument, 0, OPT_GRAB },
  2324. { "no-events", no_argument, 0, OPT_NO_EVENTS },
  2325. { 0, 0, 0, 0 },
  2326. };
  2327. struct record_device *d;
  2328. const char *output_arg = NULL;
  2329. bool all = false, with_libinput = false, with_hidraw = false, grab = false;
  2330. int ndevices;
  2331. int rc = EXIT_FAILURE;
  2332. _autostrvfree_ char **paths = NULL;
  2333. list_init(&ctx.devices);
  2334. list_init(&ctx.sources);
  2335. while (1) {
  2336. int c;
  2337. int option_index = 0;
  2338. c = getopt_long(argc, argv, "ho:", opts, &option_index);
  2339. if (c == -1)
  2340. break;
  2341. switch (c) {
  2342. case 'h':
  2343. case OPT_HELP:
  2344. usage();
  2345. rc = EXIT_SUCCESS;
  2346. goto out;
  2347. case OPT_AUTORESTART: {
  2348. int timeout;
  2349. if (!safe_atoi(optarg, &timeout) || timeout <= 0) {
  2350. usage();
  2351. rc = EXIT_INVALID_USAGE;
  2352. goto out;
  2353. }
  2354. ctx.timeout = usec_from_seconds(timeout);
  2355. break;
  2356. }
  2357. case 'o':
  2358. case OPT_OUTFILE:
  2359. output_arg = optarg;
  2360. break;
  2361. case OPT_KEYCODES:
  2362. ctx.show_keycodes = true;
  2363. break;
  2364. case OPT_MULTIPLE: /* deprecated */
  2365. break;
  2366. case OPT_ALL:
  2367. all = true;
  2368. break;
  2369. case OPT_LIBINPUT:
  2370. with_libinput = true;
  2371. break;
  2372. case OPT_HIDRAW:
  2373. with_hidraw = true;
  2374. fprintf(stderr,
  2375. "# WARNING: do not type passwords while recording HID reports\n");
  2376. break;
  2377. case OPT_GRAB:
  2378. grab = true;
  2379. break;
  2380. case OPT_NO_EVENTS:
  2381. ctx.no_events = true;
  2382. break;
  2383. default:
  2384. usage();
  2385. rc = EXIT_INVALID_USAGE;
  2386. goto out;
  2387. }
  2388. }
  2389. ndevices = argc - optind;
  2390. /* We allow for multiple arguments after the options, *one* of which
  2391. * may be the output file. That one must be the first or the last to
  2392. * prevent users from running
  2393. * libinput record /dev/input/event0 output.yml /dev/input/event1
  2394. * because this will only backfire anyway.
  2395. */
  2396. if (ndevices >= 1 && output_arg == NULL) {
  2397. enum fposition pos =
  2398. find_output_file(argc - optind, &argv[optind], &output_arg);
  2399. if (pos == ERROR) {
  2400. fprintf(stderr,
  2401. "Ambiguous device vs output file list. "
  2402. "Please use --output-file.\n");
  2403. return EXIT_INVALID_USAGE;
  2404. }
  2405. if (pos == FIRST || pos == LAST)
  2406. ndevices--;
  2407. if (pos == FIRST)
  2408. optind++;
  2409. }
  2410. if (ctx.no_events && !usec_is_zero(ctx.timeout)) {
  2411. fprintf(stderr,
  2412. "Options --no-events and --autorestart are mutually exclusive\n");
  2413. rc = EXIT_INVALID_USAGE;
  2414. goto out;
  2415. }
  2416. if (!usec_is_zero(ctx.timeout) && output_arg == NULL) {
  2417. output_arg = "libinput-recording.yml";
  2418. fprintf(stderr,
  2419. "Option --autorestart requires --output-file, defaulting to libinput-recording.yml\n");
  2420. }
  2421. ctx.output_file.name = safe_strdup(output_arg);
  2422. if (output_arg == NULL && (all || ndevices > 1)) {
  2423. fprintf(stderr, "Recording multiple devices requires an output file\n");
  2424. rc = EXIT_INVALID_USAGE;
  2425. goto out;
  2426. }
  2427. /* Now collect all device paths and init our device struct */
  2428. if (all) {
  2429. paths = all_devices();
  2430. } else if (ndevices >= 1) {
  2431. paths = strv_from_argv(ndevices, &argv[optind]);
  2432. } else {
  2433. _autofree_ char *path = select_device();
  2434. if (path == NULL) {
  2435. goto out;
  2436. }
  2437. paths = strv_from_argv(1, &path);
  2438. }
  2439. for (char **p = paths; *p; p++) {
  2440. if (!init_device(&ctx, *p, grab)) {
  2441. goto out;
  2442. }
  2443. }
  2444. if (with_libinput && !init_libinput(&ctx))
  2445. goto out;
  2446. if (with_hidraw && !init_hidraw(&ctx))
  2447. goto out;
  2448. rc = mainloop(&ctx);
  2449. out:
  2450. list_for_each_safe(d, &ctx.devices, link) {
  2451. struct hidraw *hidraw;
  2452. list_for_each_safe(hidraw, &d->hidraw_devices, link) {
  2453. xclose(&hidraw->fd);
  2454. list_remove(&hidraw->link);
  2455. free(hidraw->name);
  2456. free(hidraw);
  2457. }
  2458. if (d->device)
  2459. libinput_device_unref(d->device);
  2460. free(d->devnode);
  2461. libevdev_free(d->evdev);
  2462. libevdev_free(d->evdev_prev);
  2463. }
  2464. libinput_unref(ctx.libinput);
  2465. return rc;
  2466. }