libinput-list-kernel-devices.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. #!/usr/bin/env python3
  2. # vim: set expandtab shiftwidth=4:
  3. # -*- Mode: python; coding: utf-8; indent-tabs-mode: nil -*- */
  4. #
  5. # Copyright © 2018 Red Hat, Inc.
  6. #
  7. # Permission is hereby granted, free of charge, to any person obtaining a
  8. # copy of this software and associated documentation files (the 'Software'),
  9. # to deal in the Software without restriction, including without limitation
  10. # the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11. # and/or sell copies of the Software, and to permit persons to whom the
  12. # Software is furnished to do so, subject to the following conditions:
  13. #
  14. # The above copyright notice and this permission notice (including the next
  15. # paragraph) shall be included in all copies or substantial portions of the
  16. # Software.
  17. #
  18. # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  21. # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  23. # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  24. # DEALINGS IN THE SOFTWARE.
  25. import argparse
  26. import sys
  27. try:
  28. import pyudev
  29. except ModuleNotFoundError as e:
  30. print(f"Error: {e!s}", file=sys.stderr)
  31. print(
  32. "One or more python modules are missing. Please install those "
  33. "modules and re-run this tool."
  34. )
  35. sys.exit(1)
  36. def list_devices():
  37. devices = {}
  38. context = pyudev.Context()
  39. for device in context.list_devices(subsystem="input"):
  40. if (device.device_node or "").startswith("/dev/input/event"):
  41. parent = device.parent
  42. if parent is not None:
  43. name = parent.properties["NAME"] or ""
  44. # The udev name includes enclosing quotes
  45. devices[device.device_node] = name[1:-1]
  46. def versionsort(key):
  47. return int(key[len("/dev/input/event") :])
  48. for k in sorted(devices, key=versionsort):
  49. print(f"{k}:\t{devices[k]}")
  50. class HidDevice:
  51. def __init__(self, name, driver, vendor, product, devpath):
  52. self.name = name
  53. self.driver = driver
  54. self.vendor = vendor
  55. self.product = product
  56. self.devpath = devpath
  57. self.hidraws = []
  58. self.evdevs = []
  59. def list_hid_devices():
  60. devices = []
  61. context = pyudev.Context()
  62. for device in context.list_devices(subsystem="hid"):
  63. name = device.properties.get("HID_NAME")
  64. driver = device.properties.get("DRIVER")
  65. devpath = device.properties.get("DEVPATH")
  66. id = device.properties.get("HID_ID") or "0:0:0"
  67. _, vendor, product = (int(x, 16) for x in id.split(":"))
  68. devices.append(HidDevice(name, driver, vendor, product, devpath))
  69. for device in context.list_devices(subsystem="hidraw"):
  70. devpath = device.properties["DEVPATH"]
  71. for hid in devices:
  72. if devpath.startswith(hid.devpath):
  73. hid.hidraws.append(f"'{device.device_node}'")
  74. for device in context.list_devices(subsystem="input"):
  75. if (device.device_node or "").startswith("/dev/input/event"):
  76. devpath = device.properties["DEVPATH"]
  77. for hid in devices:
  78. if devpath.startswith(hid.devpath):
  79. hid.evdevs.append(f"'{device.device_node}'")
  80. print("hid:")
  81. for d in devices:
  82. print(f"- name: '{d.name}'")
  83. print(f" id: '{d.vendor:04x}:{d.product:04x}'")
  84. print(f" driver: '{d.driver}'")
  85. print(f" hidraw: [{', '.join(h for h in d.hidraws)}]")
  86. print(f" evdev: [{', '.join(h for h in d.evdevs)}]")
  87. print()
  88. def main():
  89. parser = argparse.ArgumentParser(description="List kernel devices")
  90. parser.add_argument("--hid", action="store_true", default=False)
  91. args = parser.parse_args()
  92. if args.hid:
  93. list_hid_devices()
  94. else:
  95. list_devices()
  96. if __name__ == "__main__":
  97. try:
  98. main()
  99. except KeyboardInterrupt:
  100. print("Exited on user request")