6 raise ctypes.WinError()
10 from serial.win32
import ULONG_PTR, is_64bit
11 from ctypes.wintypes
import HANDLE
12 from ctypes.wintypes
import BOOL
13 from ctypes.wintypes
import HWND
14 from ctypes.wintypes
import DWORD
15 from ctypes.wintypes
import WORD
16 from ctypes.wintypes
import LONG
17 from ctypes.wintypes
import ULONG
18 from ctypes.wintypes
import LPCSTR
19 from ctypes.wintypes
import HKEY
20 from ctypes.wintypes
import BYTE
23 HDEVINFO = ctypes.c_void_p
24 PCTSTR = ctypes.c_char_p
26 LPDWORD = PDWORD = ctypes.POINTER(DWORD)
28 LPBYTE = PBYTE = ctypes.c_void_p
29 PHKEY = ctypes.POINTER(HKEY)
36 """Get a buffer for a string"""
37 return (BYTE*length)()
43 s.append(chr(c & 0xff))
47 class GUID(ctypes.Structure):
55 return "{%08x-%04x-%04x-%s-%s}" % (
59 ''.join([
"%02x" % d
for d
in self.Data4[:2]]),
60 ''.join([
"%02x" % d
for d
in self.Data4[2:]]),
68 (
'Reserved', ULONG_PTR),
71 return "ClassGuid:%s DevInst:%s" % (self.ClassGuid, self.DevInst)
72 PSP_DEVINFO_DATA = ctypes.POINTER(SP_DEVINFO_DATA)
77 (
'InterfaceClassGuid', GUID),
79 (
'Reserved', ULONG_PTR),
82 return "InterfaceClassGuid:%s Flags:%s" % (self.InterfaceClassGuid, self.Flags)
83 PSP_DEVICE_INTERFACE_DATA = ctypes.POINTER(SP_DEVICE_INTERFACE_DATA)
85 PSP_DEVICE_INTERFACE_DETAIL_DATA = ctypes.c_void_p
87 setupapi = ctypes.windll.LoadLibrary(
"setupapi")
88 SetupDiDestroyDeviceInfoList = setupapi.SetupDiDestroyDeviceInfoList
89 SetupDiDestroyDeviceInfoList.argtypes = [HDEVINFO]
90 SetupDiDestroyDeviceInfoList.restype = BOOL
92 SetupDiGetClassDevs = setupapi.SetupDiGetClassDevsA
93 SetupDiGetClassDevs.argtypes = [ctypes.POINTER(GUID), PCTSTR, HWND, DWORD]
94 SetupDiGetClassDevs.restype = HDEVINFO
95 SetupDiGetClassDevs.errcheck = ValidHandle
97 SetupDiEnumDeviceInterfaces = setupapi.SetupDiEnumDeviceInterfaces
98 SetupDiEnumDeviceInterfaces.argtypes = [HDEVINFO, PSP_DEVINFO_DATA, ctypes.POINTER(GUID), DWORD, PSP_DEVICE_INTERFACE_DATA]
99 SetupDiEnumDeviceInterfaces.restype = BOOL
101 SetupDiGetDeviceInterfaceDetail = setupapi.SetupDiGetDeviceInterfaceDetailA
102 SetupDiGetDeviceInterfaceDetail.argtypes = [HDEVINFO, PSP_DEVICE_INTERFACE_DATA, PSP_DEVICE_INTERFACE_DETAIL_DATA, DWORD, PDWORD, PSP_DEVINFO_DATA]
103 SetupDiGetDeviceInterfaceDetail.restype = BOOL
105 SetupDiGetDeviceRegistryProperty = setupapi.SetupDiGetDeviceRegistryPropertyA
106 SetupDiGetDeviceRegistryProperty.argtypes = [HDEVINFO, PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD]
107 SetupDiGetDeviceRegistryProperty.restype = BOOL
109 SetupDiOpenDevRegKey = setupapi.SetupDiOpenDevRegKey
110 SetupDiOpenDevRegKey.argtypes = [HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM]
111 SetupDiOpenDevRegKey.restype = HKEY
113 advapi32 = ctypes.windll.LoadLibrary(
"Advapi32")
114 RegCloseKey = advapi32.RegCloseKey
115 RegCloseKey.argtypes = [HKEY]
116 RegCloseKey.restype = LONG
118 RegQueryValueEx = advapi32.RegQueryValueExA
119 RegQueryValueEx.argtypes = [HKEY, LPCSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD]
120 RegQueryValueEx.restype = LONG
123 GUID_CLASS_COMPORT =
GUID(0x86e0d1e0L, 0x8089, 0x11d0,
124 (BYTE*8)(0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x73))
127 DIGCF_DEVICEINTERFACE = 16
128 INVALID_HANDLE_VALUE = 0
129 ERROR_INSUFFICIENT_BUFFER = 122
131 SPDRP_FRIENDLYNAME = 12
132 ERROR_NO_MORE_ITEMS = 259
134 DIREG_DEV = 0x00000001
139 PortName = serial.to_bytes([80, 111, 114, 116, 78, 97, 109, 101])
142 """This generator scans the device registry for com ports and yields port, desc, hwid"""
143 g_hdi =
SetupDiGetClassDevs(ctypes.byref(GUID_CLASS_COMPORT),
None, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
145 for dwIndex
in range(256):
147 did.cbSize = ctypes.sizeof(did)
150 if ctypes.GetLastError() != ERROR_NO_MORE_ITEMS:
151 raise ctypes.WinError()
158 if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER:
159 raise ctypes.WinError()
161 class SP_DEVICE_INTERFACE_DETAIL_DATA_A(ctypes.Structure):
164 (
'DevicePath', CHAR*(dwNeeded.value - ctypes.sizeof(DWORD))),
167 return "DevicePath:%s" % (self.DevicePath,)
168 idd = SP_DEVICE_INTERFACE_DETAIL_DATA_A()
174 devinfo.cbSize = ctypes.sizeof(devinfo)
176 raise ctypes.WinError()
180 if not SetupDiGetDeviceRegistryProperty(g_hdi, ctypes.byref(devinfo), SPDRP_HARDWAREID,
None, ctypes.byref(szHardwareID), ctypes.sizeof(szHardwareID) - 1,
None):
182 if GetLastError() != ERROR_INSUFFICIENT_BUFFER:
183 raise ctypes.WinError()
187 if not SetupDiGetDeviceRegistryProperty(g_hdi, ctypes.byref(devinfo), SPDRP_FRIENDLYNAME,
None, ctypes.byref(szFriendlyName), ctypes.sizeof(szFriendlyName) - 1,
None):
189 if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER:
194 hkey =
SetupDiOpenDevRegKey(g_hdi, ctypes.byref(devinfo), DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ)
196 port_name_length = ULONG(ctypes.sizeof(port_name_buffer))
197 RegQueryValueEx(hkey, PortName,
None,
None, ctypes.byref(port_name_buffer), ctypes.byref(port_name_length))
205 if __name__ ==
'__main__':
208 for port, desc, hwid
in sorted(
comports()):
209 print "%s: %s [%s]" % (port, desc, hwid)