You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

110 lines
4.4KB

  1. #!/usr/bin/env python
  2. #
  3. # This is a module that gathers a list of serial ports including details on
  4. # GNU/Linux systems.
  5. #
  6. # This file is part of pySerial. https://github.com/pyserial/pyserial
  7. # (C) 2011-2015 Chris Liechti <cliechti@gmx.net>
  8. #
  9. # SPDX-License-Identifier: BSD-3-Clause
  10. from __future__ import absolute_import
  11. import glob
  12. import os
  13. from serial.tools import list_ports_common
  14. class SysFS(list_ports_common.ListPortInfo):
  15. """Wrapper for easy sysfs access and device info"""
  16. def __init__(self, device):
  17. super(SysFS, self).__init__(device)
  18. # special handling for links
  19. if device is not None and os.path.islink(device):
  20. device = os.path.realpath(device)
  21. is_link = True
  22. else:
  23. is_link = False
  24. self.usb_device_path = None
  25. if os.path.exists('/sys/class/tty/{}/device'.format(self.name)):
  26. self.device_path = os.path.realpath('/sys/class/tty/{}/device'.format(self.name))
  27. self.subsystem = os.path.basename(os.path.realpath(os.path.join(self.device_path, 'subsystem')))
  28. else:
  29. self.device_path = None
  30. self.subsystem = None
  31. # check device type
  32. if self.subsystem == 'usb-serial':
  33. self.usb_interface_path = os.path.dirname(self.device_path)
  34. elif self.subsystem == 'usb':
  35. self.usb_interface_path = self.device_path
  36. else:
  37. self.usb_interface_path = None
  38. # fill-in info for USB devices
  39. if self.usb_interface_path is not None:
  40. self.usb_device_path = os.path.dirname(self.usb_interface_path)
  41. try:
  42. num_if = int(self.read_line(self.usb_device_path, 'bNumInterfaces'))
  43. except ValueError:
  44. num_if = 1
  45. self.vid = int(self.read_line(self.usb_device_path, 'idVendor'), 16)
  46. self.pid = int(self.read_line(self.usb_device_path, 'idProduct'), 16)
  47. self.serial_number = self.read_line(self.usb_device_path, 'serial')
  48. if num_if > 1: # multi interface devices like FT4232
  49. self.location = os.path.basename(self.usb_interface_path)
  50. else:
  51. self.location = os.path.basename(self.usb_device_path)
  52. self.manufacturer = self.read_line(self.usb_device_path, 'manufacturer')
  53. self.product = self.read_line(self.usb_device_path, 'product')
  54. self.interface = self.read_line(self.usb_interface_path, 'interface')
  55. if self.subsystem in ('usb', 'usb-serial'):
  56. self.apply_usb_info()
  57. #~ elif self.subsystem in ('pnp', 'amba'): # PCI based devices, raspi
  58. elif self.subsystem == 'pnp': # PCI based devices
  59. self.description = self.name
  60. self.hwid = self.read_line(self.device_path, 'id')
  61. elif self.subsystem == 'amba': # raspi
  62. self.description = self.name
  63. self.hwid = os.path.basename(self.device_path)
  64. if is_link:
  65. self.hwid += ' LINK={}'.format(device)
  66. def read_line(self, *args):
  67. """\
  68. Helper function to read a single line from a file.
  69. One or more parameters are allowed, they are joined with os.path.join.
  70. Returns None on errors..
  71. """
  72. try:
  73. with open(os.path.join(*args)) as f:
  74. line = f.readline().strip()
  75. return line
  76. except IOError:
  77. return None
  78. def comports(include_links=False):
  79. devices = glob.glob('/dev/ttyS*') # built-in serial ports
  80. devices.extend(glob.glob('/dev/ttyUSB*')) # usb-serial with own driver
  81. devices.extend(glob.glob('/dev/ttyXRUSB*')) # xr-usb-serial port exar (DELL Edge 3001)
  82. devices.extend(glob.glob('/dev/ttyACM*')) # usb-serial with CDC-ACM profile
  83. devices.extend(glob.glob('/dev/ttyAMA*')) # ARM internal port (raspi)
  84. devices.extend(glob.glob('/dev/rfcomm*')) # BT serial devices
  85. devices.extend(glob.glob('/dev/ttyAP*')) # Advantech multi-port serial controllers
  86. if include_links:
  87. devices.extend(list_ports_common.list_links(devices))
  88. return [info
  89. for info in [SysFS(d) for d in devices]
  90. if info.subsystem != "platform"] # hide non-present internal serial ports
  91. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  92. # test
  93. if __name__ == '__main__':
  94. for info in sorted(comports()):
  95. print("{0}: {0.subsystem}".format(info))