summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcliechti <cliechti@f19166aa-fa4f-0410-85c2-fa1106f25c8a>2006-11-12 23:50:45 +0000
committercliechti <cliechti@f19166aa-fa4f-0410-85c2-fa1106f25c8a>2006-11-12 23:50:45 +0000
commit3d4bfb28d3cd5893ac947c22c107ee4898332fee (patch)
tree16a4b528f8d1363f4c28751a50c13b947aaccf89
parentb2f5fc8e5566f8309480567b1c9c7ca3445ccd53 (diff)
downloadpyserial-git-3d4bfb28d3cd5893ac947c22c107ee4898332fee.tar.gz
*** empty log message ***
-rw-r--r--pyserial/examples/scanwin32.py192
1 files changed, 192 insertions, 0 deletions
diff --git a/pyserial/examples/scanwin32.py b/pyserial/examples/scanwin32.py
new file mode 100644
index 0000000..9e9a06d
--- /dev/null
+++ b/pyserial/examples/scanwin32.py
@@ -0,0 +1,192 @@
+import ctypes
+import re
+
+def ValidHandle(value):
+ if value == 0:
+ raise ctypes.WinError()
+ return value
+
+NULL = 0
+HDEVINFO = ctypes.c_int
+BOOL = ctypes.c_int
+CHAR = ctypes.c_char
+PCTSTR = ctypes.c_char_p
+HWND = ctypes.c_uint
+DWORD = ctypes.c_ulong
+PDWORD = ctypes.POINTER(DWORD)
+ULONG = ctypes.c_ulong
+ULONG_PTR = ctypes.POINTER(ULONG)
+#~ PBYTE = ctypes.c_char_p
+PBYTE = ctypes.c_void_p
+
+class GUID(ctypes.Structure):
+ _fields_ = [
+ ('Data1', ctypes.c_ulong),
+ ('Data2', ctypes.c_ushort),
+ ('Data3', ctypes.c_ushort),
+ ('Data4', ctypes.c_ubyte*8),
+ ]
+ def __str__(self):
+ return "{%08x-%04x-%04x-%s-%s}" % (
+ self.Data1,
+ self.Data2,
+ self.Data3,
+ ''.join(["%02x" % d for d in self.Data4[:2]]),
+ ''.join(["%02x" % d for d in self.Data4[2:]]),
+ )
+
+class SP_DEVINFO_DATA(ctypes.Structure):
+ _fields_ = [
+ ('cbSize', DWORD),
+ ('ClassGuid', GUID),
+ ('DevInst', DWORD),
+ ('Reserved', ULONG_PTR),
+ ]
+ def __str__(self):
+ return "ClassGuid:%s DevInst:%s" % (self.ClassGuid, self.DevInst)
+PSP_DEVINFO_DATA = ctypes.POINTER(SP_DEVINFO_DATA)
+
+class SP_DEVICE_INTERFACE_DATA(ctypes.Structure):
+ _fields_ = [
+ ('cbSize', DWORD),
+ ('InterfaceClassGuid', GUID),
+ ('Flags', DWORD),
+ ('Reserved', ULONG_PTR),
+ ]
+ def __str__(self):
+ return "InterfaceClassGuid:%s Flags:%s" % (self.InterfaceClassGuid, self.Flags)
+PSP_DEVICE_INTERFACE_DATA = ctypes.POINTER(SP_DEVICE_INTERFACE_DATA)
+
+PSP_DEVICE_INTERFACE_DETAIL_DATA = ctypes.c_void_p
+
+SetupDiDestroyDeviceInfoList = ctypes.windll.setupapi.SetupDiDestroyDeviceInfoList
+SetupDiDestroyDeviceInfoList.argtypes = [HDEVINFO]
+SetupDiDestroyDeviceInfoList.restype = BOOL
+
+SetupDiGetClassDevs = ctypes.windll.setupapi.SetupDiGetClassDevsA
+SetupDiGetClassDevs.argtypes = [ctypes.POINTER(GUID), PCTSTR, HWND, DWORD]
+SetupDiGetClassDevs.restype = ValidHandle #HDEVINFO
+
+SetupDiEnumDeviceInterfaces = ctypes.windll.setupapi.SetupDiEnumDeviceInterfaces
+SetupDiEnumDeviceInterfaces.argtypes = [HDEVINFO, PSP_DEVINFO_DATA, ctypes.POINTER(GUID), DWORD, PSP_DEVICE_INTERFACE_DATA]
+SetupDiEnumDeviceInterfaces.restype = BOOL
+
+SetupDiGetDeviceInterfaceDetail = ctypes.windll.setupapi.SetupDiGetDeviceInterfaceDetailA
+SetupDiGetDeviceInterfaceDetail.argtypes = [HDEVINFO, PSP_DEVICE_INTERFACE_DATA, PSP_DEVICE_INTERFACE_DETAIL_DATA, DWORD, PDWORD, PSP_DEVINFO_DATA]
+SetupDiGetDeviceInterfaceDetail.restype = BOOL
+
+SetupDiGetDeviceRegistryProperty = ctypes.windll.setupapi.SetupDiGetDeviceRegistryPropertyA
+SetupDiGetDeviceRegistryProperty.argtypes = [HDEVINFO, PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD]
+SetupDiGetDeviceRegistryProperty.restype = BOOL
+
+
+GUID_CLASS_COMPORT = GUID(0x86e0d1e0L, 0x8089, 0x11d0,
+ (ctypes.c_ubyte*8)(0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x73))
+
+DIGCF_PRESENT = 2
+DIGCF_DEVICEINTERFACE = 16
+INVALID_HANDLE_VALUE = 0
+ERROR_INSUFFICIENT_BUFFER = 122
+SPDRP_HARDWAREID = 1
+SPDRP_FRIENDLYNAME = 12
+ERROR_NO_MORE_ITEMS = 259
+
+def comports(available_only=True):
+ """This generator scans the device registry for com ports and yields port, desc, hwid.
+ If available_only is true only return currently existing ports."""
+ flags = DIGCF_DEVICEINTERFACE
+ if available_only:
+ flags |= DIGCF_PRESENT
+ g_hdi = SetupDiGetClassDevs(ctypes.byref(GUID_CLASS_COMPORT), None, NULL, flags);
+ #~ for i in range(256):
+ for dwIndex in range(256):
+ did = SP_DEVICE_INTERFACE_DATA()
+ did.cbSize = ctypes.sizeof(did)
+
+ if not SetupDiEnumDeviceInterfaces(
+ g_hdi,
+ None,
+ ctypes.byref(GUID_CLASS_COMPORT),
+ dwIndex,
+ ctypes.byref(did)
+ ):
+ if ctypes.GetLastError() != ERROR_NO_MORE_ITEMS:
+ raise ctypes.WinError()
+ break
+
+ dwNeeded = DWORD()
+ # get the size
+ if not SetupDiGetDeviceInterfaceDetail(
+ g_hdi,
+ ctypes.byref(did),
+ None, 0, ctypes.byref(dwNeeded),
+ None
+ ):
+ # Ignore ERROR_INSUFFICIENT_BUFFER
+ if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER:
+ raise ctypes.WinError()
+ # allocate buffer
+ class SP_DEVICE_INTERFACE_DETAIL_DATA_A(ctypes.Structure):
+ _fields_ = [
+ ('cbSize', DWORD),
+ ('DevicePath', CHAR*(dwNeeded.value - ctypes.sizeof(DWORD))),
+ ]
+ def __str__(self):
+ return "DevicePath:%s" % (self.DevicePath,)
+ idd = SP_DEVICE_INTERFACE_DETAIL_DATA_A()
+ idd.cbSize = 5
+ devinfo = SP_DEVINFO_DATA()
+ devinfo.cbSize = ctypes.sizeof(devinfo)
+ if not SetupDiGetDeviceInterfaceDetail(
+ g_hdi,
+ ctypes.byref(did),
+ ctypes.byref(idd), dwNeeded, None,
+ ctypes.byref(devinfo)
+ ):
+ raise ctypes.WinError()
+
+ # hardware ID
+ szHardwareID = ctypes.create_string_buffer('\0' * 250)
+ if not SetupDiGetDeviceRegistryProperty(
+ g_hdi,
+ ctypes.byref(devinfo),
+ SPDRP_HARDWAREID,
+ None,
+ ctypes.byref(szHardwareID), ctypes.sizeof(szHardwareID) - 1,
+ None
+ ):
+ # Ignore ERROR_INSUFFICIENT_BUFFER
+ if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER:
+ raise ctypes.WinError()
+
+ # friendly name
+ szFriendlyName = ctypes.create_string_buffer('\0' * 250)
+ if not SetupDiGetDeviceRegistryProperty(
+ g_hdi,
+ ctypes.byref(devinfo),
+ SPDRP_FRIENDLYNAME,
+ None,
+ ctypes.byref(szFriendlyName), ctypes.sizeof(szFriendlyName) - 1,
+ None
+ ):
+ # Ignore ERROR_INSUFFICIENT_BUFFER
+ if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER:
+ raise ctypes.WinError()
+ port_name = re.search(r"\((.*)\)", szFriendlyName.value).group(1)
+ if len(port_name) > 4:
+ port_name = '\\\\.\\'+port_name
+ yield port_name, szFriendlyName.value, szHardwareID.value
+
+ SetupDiDestroyDeviceInfoList(g_hdi)
+
+
+if __name__ == '__main__':
+ import serial
+ for port, desc, hwid in comports():
+ print "%s: %s (%s)" % (port, desc, hwid)
+ print " "*10, serial.Serial(port) #test open
+
+ # list of all ports the system knows
+ print "-"*60
+ for port, desc, hwid in comports(False):
+ print "%-10s: %s (%s)" % (port, desc, hwid)