def comports(): """This generator scans the device registry for com ports and yields port, desc, hwid""" g_hdi = SetupDiGetClassDevs(ctypes.byref(GUID_CLASS_COMPORT), None, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); #~ 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() if is_64bit(): idd.cbSize = 8 else: 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 = byte_buffer(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 GetLastError() != ERROR_INSUFFICIENT_BUFFER: raise ctypes.WinError() # friendly name szFriendlyName = byte_buffer(250) if SetupDiGetDeviceRegistryProperty(g_hdi, ctypes.byref(devinfo), SPDRP_FRIENDLYNAME, None, ctypes.byref(szFriendlyName), ctypes.sizeof(szFriendlyName) - 1, None): # the real com port name has to read differently... hkey = SetupDiOpenDevRegKey(g_hdi, ctypes.byref(devinfo), DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ) port_name_buffer = byte_buffer(250) port_name_length = ULONG(ctypes.sizeof(port_name_buffer)) RegQueryValueEx(hkey, PortName, None, None, ctypes.byref(port_name_buffer), ctypes.byref(port_name_length)) RegCloseKey(hkey) yield string(port_name_buffer), string(szFriendlyName), string(szHardwareID) SetupDiDestroyDeviceInfoList(g_hdi)
def comports(): """This generator scans the device registry for com ports and yields port, desc, hwid""" g_hdi = SetupDiGetClassDevs(ctypes.byref(GUID_CLASS_COMPORT), None, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE); #~ 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() if is_64bit(): idd.cbSize = 8 else: 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 = byte_buffer(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 GetLastError() != ERROR_INSUFFICIENT_BUFFER: raise ctypes.WinError() # friendly name szFriendlyName = byte_buffer(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 IOError("failed to get details for %s (%s)" % (devinfo, szHardwareID.value)) port_name = None else: # the real com port name has to read differently... hkey = SetupDiOpenDevRegKey(g_hdi, ctypes.byref(devinfo), DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ) port_name_buffer = byte_buffer(250) port_name_length = ULONG(ctypes.sizeof(port_name_buffer)) RegQueryValueEx(hkey, PortName, None, None, ctypes.byref(port_name_buffer), ctypes.byref(port_name_length)) RegCloseKey(hkey) yield string(port_name_buffer), string(szFriendlyName), string(szHardwareID) SetupDiDestroyDeviceInfoList(g_hdi)
def _yeiComPorts(): """ This generator scans the device registry for com ports and yields port, desc, hw_id """ GUID_list = [GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR, GUID_DEVINTERFACE_COMPORT] ports_yielded = [] bt_device_list = None for device_GUID in GUID_list: g_hdi = SetupDiGetClassDevs(ctypes.byref(device_GUID), None, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE) for dw_index in range(256): friendly_name_string = "" did = SP_DEVICE_INTERFACE_DATA() did.cbSize = ctypes.sizeof(did) if not SetupDiEnumDeviceInterfaces(g_hdi, None, ctypes.byref(device_GUID), dw_index, ctypes.byref(did)): if ctypes.GetLastError() != ERROR_NO_MORE_ITEMS: if '-d' in sys.argv: raise ctypes.WinError() break dw_needed = DWORD() # Get the size if not SetupDiGetDeviceInterfaceDetail(g_hdi, ctypes.byref(did), None, 0, ctypes.byref(dw_needed), None): # Ignore ERROR_INSUFFICIENT_BUFFER if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER: if '-d' in sys.argv: raise ctypes.WinError() # Allocate buffer class SP_DEVICE_INTERFACE_DETAIL_DATA_A(ctypes.Structure): _fields_ = [ ('cbSize', DWORD), ('DevicePath', CHAR * (dw_needed.value - ctypes.sizeof(DWORD))), ] def __str__(self): return "DevicePath: %s" % self.DevicePath idd = SP_DEVICE_INTERFACE_DETAIL_DATA_A() if is_64bit(): idd.cbSize = 8 else: idd.cbSize = 5 dev_info = SP_DEVINFO_DATA() dev_info.cbSize = ctypes.sizeof(dev_info) if not SetupDiGetDeviceInterfaceDetail(g_hdi, ctypes.byref(did), ctypes.byref(idd), dw_needed, None, ctypes.byref(dev_info)): if '-d' in sys.argv: raise ctypes.WinError() # hardware ID sz_hardware_id = _byteBuffer(1024) if not SetupDiGetDeviceRegistryProperty(g_hdi, ctypes.byref(dev_info), SPDRP_HARDWAREID, None, ctypes.byref(sz_hardware_id), ctypes.sizeof(sz_hardware_id) - 1, None): # Ignore ERROR_INSUFFICIENT_BUFFER if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER: if '-d' in sys.argv: raise ctypes.WinError() #Build VID/PID string vid_pid_string = "" hw_string = _string(sz_hardware_id) hw_string = hw_string.upper() vid_idx = hw_string.find("VID_") pid_idx = hw_string.find("PID_") if vid_idx != -1 and pid_idx != -1: vid_end = hw_string.find("&", vid_idx + 1) vid = hw_string[vid_idx:vid_end] pid_end = hw_string.find("&", pid_idx + 1) pid = hw_string[pid_idx:pid_end] vid_pid_string = vid + "&" + pid enum_name_buff = _byteBuffer(1024) if SetupDiGetDeviceRegistryProperty(g_hdi, ctypes.byref(dev_info), SPDRP_ENUMERATOR_NAME, None, ctypes.byref(enum_name_buff), ctypes.sizeof(enum_name_buff) - 1, None): if _string(enum_name_buff).upper() == "BTHENUM": # This is a bluetooth enumerator, we should do further # investigation if bt_device_list is None: bt_device_list = _getBluetoothDevices() device_path_str = idd.DevicePath if type(device_path_str) is bytes: device_path_str = bytes.decode(device_path_str) start_idx = device_path_str.rfind("&") + 1 end_idx = start_idx + 12 bt_addr_string = device_path_str[start_idx:end_idx] bt_address = _stringToBluetoothAddress(bt_addr_string) if bt_address == _stringToBluetoothAddress("0"): continue connected_dev = None for bt_dev in bt_device_list: if bt_dev.Address == bt_address: connected_dev = bt_dev break if connected_dev is not None: if (str(connected_dev.szName).find("YEI_3SpaceBT") != -1): # The device is a 3-Space Sensor! vid_pid_string = "VID_2476&PID_1060" friendly_name_string = "3 Space Bluetooth over Bluetooth link " sz_friendly_name = _byteBuffer(1024) if not SetupDiGetDeviceRegistryProperty(g_hdi, ctypes.byref(dev_info), SPDRP_FRIENDLYNAME, None, ctypes.byref(sz_friendly_name), ctypes.sizeof(sz_friendly_name) - 1, None): # Ignore ERROR_INSUFFICIENT_BUFFER if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER: if '-d' in sys.argv: raise IOError("Failed to get details for %s (%s)" % (dev_info, sz_hardware_id.value)) port_name = None else: # The real com port name has to read differently... h_key = SetupDiOpenDevRegKey(g_hdi, ctypes.byref(dev_info), DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ) port_name_buffer = _byteBuffer(1024) port_name_length = ULONG(ctypes.sizeof(port_name_buffer)) RegQueryValueEx(h_key, PortName, None, None, ctypes.byref(port_name_buffer), ctypes.byref(port_name_length)) RegCloseKey(h_key) # We either use the generated friendly name or our overridden # one, with preference to the overridden one. if friendly_name_string == "": friendly_name_string = _string(sz_friendly_name) else: friendly_name_string += "(" + _string(port_name_buffer) + ")" if _string(port_name_buffer) not in ports_yielded: ports_yielded.append(_string(port_name_buffer)) yield (_string(port_name_buffer), friendly_name_string, _string(sz_hardware_id), vid_pid_string) SetupDiDestroyDeviceInfoList(g_hdi)
def _yeiComPorts(): """ This generator scans the device registry for com ports and yields port, desc, hw_id """ GUID_list = [ GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR, GUID_DEVINTERFACE_COMPORT ] ports_yielded = [] bt_device_list = None for device_GUID in GUID_list: g_hdi = SetupDiGetClassDevs(ctypes.byref(device_GUID), None, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE) for dw_index in range(256): friendly_name_string = "" did = SP_DEVICE_INTERFACE_DATA() did.cbSize = ctypes.sizeof(did) if not SetupDiEnumDeviceInterfaces( g_hdi, None, ctypes.byref(device_GUID), dw_index, ctypes.byref(did)): if ctypes.GetLastError() != ERROR_NO_MORE_ITEMS: if '-d' in sys.argv: raise ctypes.WinError() break dw_needed = DWORD() # Get the size if not SetupDiGetDeviceInterfaceDetail( g_hdi, ctypes.byref(did), None, 0, ctypes.byref(dw_needed), None): # Ignore ERROR_INSUFFICIENT_BUFFER if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER: if '-d' in sys.argv: raise ctypes.WinError() # Allocate buffer class SP_DEVICE_INTERFACE_DETAIL_DATA_A(ctypes.Structure): _fields_ = [ ('cbSize', DWORD), ('DevicePath', CHAR * (dw_needed.value - ctypes.sizeof(DWORD))), ] def __str__(self): return "DevicePath: %s" % self.DevicePath idd = SP_DEVICE_INTERFACE_DETAIL_DATA_A() if is_64bit(): idd.cbSize = 8 else: idd.cbSize = 5 dev_info = SP_DEVINFO_DATA() dev_info.cbSize = ctypes.sizeof(dev_info) if not SetupDiGetDeviceInterfaceDetail( g_hdi, ctypes.byref(did), ctypes.byref(idd), dw_needed, None, ctypes.byref(dev_info)): if '-d' in sys.argv: raise ctypes.WinError() # hardware ID sz_hardware_id = _byteBuffer(1024) if not SetupDiGetDeviceRegistryProperty( g_hdi, ctypes.byref(dev_info), SPDRP_HARDWAREID, None, ctypes.byref(sz_hardware_id), ctypes.sizeof(sz_hardware_id) - 1, None): # Ignore ERROR_INSUFFICIENT_BUFFER if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER: if '-d' in sys.argv: raise ctypes.WinError() #Build VID/PID string vid_pid_string = "" hw_string = _string(sz_hardware_id) hw_string = hw_string.upper() vid_idx = hw_string.find("VID_") pid_idx = hw_string.find("PID_") if vid_idx != -1 and pid_idx != -1: vid_end = hw_string.find("&", vid_idx + 1) vid = hw_string[vid_idx:vid_end] pid_end = hw_string.find("&", pid_idx + 1) pid = hw_string[pid_idx:pid_end] vid_pid_string = vid + "&" + pid enum_name_buff = _byteBuffer(1024) if SetupDiGetDeviceRegistryProperty( g_hdi, ctypes.byref(dev_info), SPDRP_ENUMERATOR_NAME, None, ctypes.byref(enum_name_buff), ctypes.sizeof(enum_name_buff) - 1, None): if _string(enum_name_buff).upper() == "BTHENUM": # This is a bluetooth enumerator, we should do further # investigation if bt_device_list is None: bt_device_list = _getBluetoothDevices() device_path_str = idd.DevicePath if type(device_path_str) is bytes: device_path_str = bytes.decode(device_path_str) start_idx = device_path_str.rfind("&") + 1 end_idx = start_idx + 12 bt_addr_string = device_path_str[start_idx:end_idx] bt_address = _stringToBluetoothAddress(bt_addr_string) if bt_address == _stringToBluetoothAddress("0"): continue connected_dev = None for bt_dev in bt_device_list: if bt_dev.Address == bt_address: connected_dev = bt_dev break if connected_dev is not None: if (str(connected_dev.szName).find("YEI_3SpaceBT") != -1): # The device is a 3-Space Sensor! vid_pid_string = "VID_2476&PID_1060" friendly_name_string = "3 Space Bluetooth over Bluetooth link " sz_friendly_name = _byteBuffer(1024) if not SetupDiGetDeviceRegistryProperty( g_hdi, ctypes.byref(dev_info), SPDRP_FRIENDLYNAME, None, ctypes.byref(sz_friendly_name), ctypes.sizeof(sz_friendly_name) - 1, None): # Ignore ERROR_INSUFFICIENT_BUFFER if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER: if '-d' in sys.argv: raise IOError("Failed to get details for %s (%s)" % (dev_info, sz_hardware_id.value)) port_name = None else: # The real com port name has to read differently... h_key = SetupDiOpenDevRegKey(g_hdi, ctypes.byref(dev_info), DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ) port_name_buffer = _byteBuffer(1024) port_name_length = ULONG(ctypes.sizeof(port_name_buffer)) RegQueryValueEx(h_key, PortName, None, None, ctypes.byref(port_name_buffer), ctypes.byref(port_name_length)) RegCloseKey(h_key) # We either use the generated friendly name or our overridden # one, with preference to the overridden one. if friendly_name_string == "": friendly_name_string = _string(sz_friendly_name) else: friendly_name_string += "(" + _string( port_name_buffer) + ")" if _string(port_name_buffer) not in ports_yielded: ports_yielded.append(_string(port_name_buffer)) yield (_string(port_name_buffer), friendly_name_string, _string(sz_hardware_id), vid_pid_string) SetupDiDestroyDeviceInfoList(g_hdi)