<s> import ctypes <EOL> import ctypes . util <EOL> from serial . tools import list_ports_common <EOL> iokit = ctypes . cdll . LoadLibrary ( ctypes . util . find_library ( '<STR_LIT>' ) ) <EOL> cf = ctypes . cdll . LoadLibrary ( ctypes . util . find_library ( '<STR_LIT>' ) ) <EOL> kIOMasterPortDefault = ctypes . c_void_p . in_dll ( iokit , "<STR_LIT>" ) <EOL> kCFAllocatorDefault = ctypes . c_void_p . in_dll ( cf , "<STR_LIT>" ) <EOL> kCFStringEncodingMacRoman = <NUM_LIT:0> <EOL> iokit . IOServiceMatching . restype = ctypes . c_void_p <EOL> iokit . IOServiceGetMatchingServices . argtypes = [ ctypes . c_void_p , ctypes . c_void_p , ctypes . c_void_p ] <EOL> iokit . IOServiceGetMatchingServices . restype = ctypes . c_void_p <EOL> iokit . IORegistryEntryGetParentEntry . argtypes = [ ctypes . c_void_p , ctypes . c_void_p , ctypes . c_void_p ] <EOL> iokit . IORegistryEntryCreateCFProperty . argtypes = [ ctypes . c_void_p , ctypes . c_void_p , ctypes . c_void_p , ctypes . c_uint32 ] <EOL> iokit . IORegistryEntryCreateCFProperty . restype = ctypes . c_void_p <EOL> iokit . IORegistryEntryGetPath . argtypes = [ ctypes . c_void_p , ctypes . c_void_p , ctypes . c_void_p ] <EOL> iokit . IORegistryEntryGetPath . restype = ctypes . c_void_p <EOL> iokit . IORegistryEntryGetName . argtypes = [ ctypes . c_void_p , ctypes . c_void_p ] <EOL> iokit . IORegistryEntryGetName . restype = ctypes . c_void_p <EOL> iokit . IOObjectGetClass . argtypes = [ ctypes . c_void_p , ctypes . c_void_p ] <EOL> iokit . IOObjectGetClass . restype = ctypes . c_void_p <EOL> iokit . IOObjectRelease . argtypes = [ ctypes . c_void_p ] <EOL> cf . CFStringCreateWithCString . argtypes = [ ctypes . c_void_p , ctypes . c_char_p , ctypes . c_int32 ] <EOL> cf . CFStringCreateWithCString . restype = ctypes . c_void_p <EOL> cf . CFStringGetCStringPtr . argtypes = [ ctypes . c_void_p , ctypes . c_uint32 ] <EOL> cf . CFStringGetCStringPtr . restype = ctypes . c_char_p <EOL> cf . CFNumberGetValue . argtypes = [ ctypes . c_void_p , ctypes . c_uint32 , ctypes . c_void_p ] <EOL> cf . CFNumberGetValue . restype = ctypes . c_void_p <EOL> cf . CFRelease . argtypes = [ ctypes . c_void_p ] <EOL> cf . CFRelease . restype = None <EOL> kCFNumberSInt8Type = <NUM_LIT:1> <EOL> kCFNumberSInt16Type = <NUM_LIT:2> <EOL> kCFNumberSInt32Type = <NUM_LIT:3> <EOL> kCFNumberSInt64Type = <NUM_LIT:4> <EOL> def get_string_property ( device_type , property ) : <EOL> """<STR_LIT>""" <EOL> key = cf . CFStringCreateWithCString ( <EOL> kCFAllocatorDefault , <EOL> property . encode ( "<STR_LIT>" ) , <EOL> kCFStringEncodingMacRoman ) <EOL> CFContainer = iokit . IORegistryEntryCreateCFProperty ( <EOL> device_type , <EOL> key , <EOL> kCFAllocatorDefault , <EOL> <NUM_LIT:0> ) <EOL> output = None <EOL> if CFContainer : <EOL> output = cf . CFStringGetCStringPtr ( CFContainer , <NUM_LIT:0> ) <EOL> if output is not None : <EOL> output = output . decode ( '<STR_LIT>' ) <EOL> cf . CFRelease ( CFContainer ) <EOL> return output <EOL> def get_int_property ( device_type , property , cf_number_type ) : <EOL> """<STR_LIT>""" <EOL> key = cf . CFStringCreateWithCString ( <EOL> kCFAllocatorDefault , <EOL> property . encode ( "<STR_LIT>" ) , <EOL> kCFStringEncodingMacRoman ) <EOL> CFContainer = iokit . IORegistryEntryCreateCFProperty ( <EOL> device_type , <EOL> key , <EOL> kCFAllocatorDefault , <EOL> <NUM_LIT:0> ) <EOL> if CFContainer : <EOL> if ( cf_number_type == kCFNumberSInt32Type ) : <EOL> number = ctypes . c_uint32 ( ) <EOL> elif ( cf_number_type == kCFNumberSInt16Type ) : <EOL> number = ctypes . c_uint16 ( ) <EOL> cf . CFNumberGetValue ( CFContainer , cf_number_type , ctypes . byref ( number ) ) <EOL> cf . CFRelease ( CFContainer ) <EOL> return number . value <EOL> return None <EOL> def IORegistryEntryGetName ( device ) : <EOL> pathname = ctypes . create_string_buffer ( <NUM_LIT:100> ) <EOL> iokit . IOObjectGetClass ( device , ctypes . byref ( pathname ) ) <EOL> return pathname . value <EOL> def GetParentDeviceByType ( device , parent_type ) : <EOL> """<STR_LIT>""" <EOL> parent_type = parent_type . encode ( '<STR_LIT>' ) <EOL> while IORegistryEntryGetName ( device ) != parent_type : <EOL> parent = ctypes . c_void_p ( ) <EOL> response = iokit . IORegistryEntryGetParentEntry ( <EOL> device , <EOL> "<STR_LIT>" . encode ( "<STR_LIT>" ) , <EOL> ctypes . byref ( parent ) ) <EOL> if response != <NUM_LIT:0> : <EOL> return None <EOL> device = parent <EOL> return device <EOL> def GetIOServicesByType ( service_type ) : <EOL> """<STR_LIT>""" <EOL> serial_port_iterator = ctypes . c_void_p ( ) <EOL> iokit . IOServiceGetMatchingServices ( <EOL> kIOMasterPortDefault , <EOL> iokit . IOServiceMatching ( service_type . encode ( '<STR_LIT>' ) ) , <EOL> ctypes . byref ( serial_port_iterator ) ) <EOL> services = [ ] <EOL> while iokit . IOIteratorIsValid ( serial_port_iterator ) : <EOL> service = iokit . IOIteratorNext ( serial_port_iterator ) <EOL> if not service : <EOL> break <EOL> services . append ( service ) <EOL> iokit . IOObjectRelease ( serial_port_iterator ) <EOL> return services <EOL> def location_to_string ( locationID ) : <EOL> """<STR_LIT>""" <EOL> loc = [ '<STR_LIT>' . format ( locationID >> <NUM_LIT> ) ] <EOL> while locationID & <NUM_LIT> : <EOL> if len ( loc ) > <NUM_LIT:1> : <EOL> loc . append ( '<STR_LIT:.>' ) <EOL> loc . append ( '<STR_LIT:{}>' . format ( ( locationID >> <NUM_LIT:20> ) & <NUM_LIT> ) ) <EOL> locationID <<= <NUM_LIT:4> <EOL> return '<STR_LIT>' . join ( loc ) <EOL> class SuitableSerialInterface ( object ) : <EOL> pass <EOL> def scan_interfaces ( ) : <EOL> """<STR_LIT>""" <EOL> interfaces = [ ] <EOL> for service in GetIOServicesByType ( '<STR_LIT>' ) : <EOL> device = get_string_property ( service , "<STR_LIT>" ) <EOL> if device : <EOL> usb_device = GetParentDeviceByType ( service , "<STR_LIT>" ) <EOL> if usb_device : <EOL> name = get_string_property ( usb_device , "<STR_LIT>" ) or None <EOL> locationID = get_int_property ( usb_device , "<STR_LIT>" , kCFNumberSInt32Type ) or '<STR_LIT>' <EOL> i = SuitableSerialInterface ( ) <EOL> i . id = locationID <EOL> i . name = name <EOL> interfaces . append ( i ) <EOL> return interfaces <EOL> def search_for_locationID_in_interfaces ( serial_interfaces , locationID ) : <EOL> for interface in serial_interfaces : <EOL> if ( interface . id == locationID ) : <EOL> return interface . name <EOL> return None <EOL> def comports ( ) : <EOL> services = GetIOServicesByType ( '<STR_LIT>' ) <EOL> ports = [ ] <EOL> serial_interfaces = scan_interfaces ( ) <EOL> for service in services : <EOL> device = get_string_property ( service , "<STR_LIT>" ) <EOL> if device : <EOL> info = list_ports_common . ListPortInfo ( device ) <EOL> usb_device = GetParentDeviceByType ( service , "<STR_LIT>" ) <EOL> if usb_device : <EOL> info . vid = get_int_property ( usb_device , "<STR_LIT>" , kCFNumberSInt16Type ) <EOL> info . pid = get_int_property ( usb_device , "<STR_LIT>" , kCFNumberSInt16Type ) <EOL> info . serial_number = get_string_property ( usb_device , "<STR_LIT>" ) <EOL> info . product = get_string_property ( usb_device , "<STR_LIT>" ) or '<STR_LIT>' <EOL> info . manufacturer = get_string_property ( usb_device , "<STR_LIT>" ) <EOL> locationID = get_int_property ( usb_device , "<STR_LIT>" , kCFNumberSInt32Type ) <EOL> info . location = location_to_string ( locationID ) <EOL> info . interface = search_for_locationID_in_interfaces ( serial_interfaces , locationID ) <EOL> info . apply_usb_info ( ) <EOL> ports . append ( info ) <EOL> return ports <EOL> if __name__ == '<STR_LIT:__main__>' : <EOL> for port , desc , hwid in sorted ( comports ( ) ) : <EOL> print ( "<STR_LIT>" % ( port , desc , hwid ) ) </s>
