FreeDATA/freedata_server/list_ports_winreg.py

150 lines
4.3 KiB
Python

#! python
#
# Enumerate serial ports on Windows including a human readable description
# and hardware information using winreg.
#
# Using winreg helps find virtual comports
# Taken from https://github.com/pyserial/pyserial/pull/70 since pyserial isnt getting recent updates
try:
# Python 3.X
import winreg
except ImportError:
# Python 2.7 compatibility
try:
import _winreg as winreg
except ImportError:
winreg = None
from serial.tools import list_ports_common
from serial.tools import list_ports_windows
SERIAL_REGISTRY_PATH = 'HARDWARE\\DEVICEMAP\\SERIALCOMM'
def regval_to_listport(winport):
"""Convert a windows port from registry key to pyserial's ListPortInfo.
Args:
winport (tuple): Windows registry value (description, device, value).
Returns:
listport (ListPortInfo): comport device details.
"""
# Create the ListPortInfo
description, device, _ = winport
listport = list_ports_common.ListPortInfo(device)
# Format the description like other ListPortInfo
description = description.replace('\\Device\\', '')
listport.description = "{} ({})".format(description, device)
return listport
# end regval_to_listport
def winreg_comports():
"""Return windows comports found in the registry.
See Also:
list_ports_winreg.comports(), list_ports_winreg.comports_list(),
list_ports_windows.comports()
Note:
This should include virtual comports, and it is significantly faster
than list_ports_windows.comports(). However, list_ports_windows has far
more information. comports() contains all list_ports_windows.comports()
and winreg_comports() that were not found from list_ports_windows.
Returns:
comports (list): Sorted list of ListPortInfo.
"""
try:
# Get the Serial Coms registry
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, SERIAL_REGISTRY_PATH)
# Get key info - number of values (subkeys, num_vals, last_modified)
num_values = winreg.QueryInfoKey(key)[1]
# Make a generator of comports
for i in range(num_values):
# get registry value for the comport
value = winreg.EnumValue(key, i)
yield regval_to_listport(value)
# Close the registry key
winreg.CloseKey(key)
except (AttributeError, WindowsError, EnvironmentError):
# winreg is None or there was a key error
pass
# end winreg_comports
def comports_list():
"""Return a list of comports found from list_ports_windows and comports
found in the window registry.
See Also:
list_ports_winreg.comports(), list_ports_winreg.winreg_comports(),
list_ports_windows.comports()
Note:
This should include virtual comports. This method contains all
list_ports_windows.comports() and winreg_comports() that were not found
from list_ports_windows.
Returns:
comports (list): List of ListPortInfo comport details.
"""
comports = list(list_ports_windows.comports())
comports[len(comports):] = [li for li in winreg_comports()
if li not in comports]
return comports
# end comports_list
def comports(include_links=False):
"""Generator for comports found from list ports windows and comports found
in the windows registry.
See Also:
list_ports_winreg.comports_list(), list_ports_winreg.winreg_comports(),
list_ports_windows.comports()
Note:
This should include virtual comports. This method contains all
list_ports_windows.comports() and winreg_comports() that were not found
from list_ports_windows.
Yields:
comport (ListPortInfo): Comport details.
Returns:
comports (generator): Generator of ListPortInfo comports.
"""
existing = []
for comport in list_ports_windows.comports():
existing.append(comport)
yield comport
for li in winreg_comports():
if li not in existing:
existing.append(li)
yield li
# end comports
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# test
if __name__ == '__main__':
for port, desc, hwid in sorted(comports()):
print("%s: %s [%s]" % (port, desc, hwid))