| Index: tools/telemetry/third_party/pyserial/serial/tools/list_ports_osx.py
|
| diff --git a/tools/telemetry/third_party/pyserial/serial/tools/list_ports_osx.py b/tools/telemetry/third_party/pyserial/serial/tools/list_ports_osx.py
|
| new file mode 100755
|
| index 0000000000000000000000000000000000000000..c9ed6150f37fcc6aec8ed8d03e4978879466c147
|
| --- /dev/null
|
| +++ b/tools/telemetry/third_party/pyserial/serial/tools/list_ports_osx.py
|
| @@ -0,0 +1,208 @@
|
| +#!/usr/bin/env python
|
| +
|
| +# portable serial port access with python
|
| +#
|
| +# This is a module that gathers a list of serial ports including details on OSX
|
| +#
|
| +# code originally from https://github.com/makerbot/pyserial/tree/master/serial/tools
|
| +# with contributions from cibomahto, dgs3, FarMcKon, tedbrandston
|
| +# and modifications by cliechti
|
| +#
|
| +# this is distributed under a free software license, see license.txt
|
| +
|
| +
|
| +
|
| +# List all of the callout devices in OS/X by querying IOKit.
|
| +
|
| +# See the following for a reference of how to do this:
|
| +# http://developer.apple.com/library/mac/#documentation/DeviceDrivers/Conceptual/WorkingWSerial/WWSerial_SerialDevs/SerialDevices.html#//apple_ref/doc/uid/TP30000384-CIHGEAFD
|
| +
|
| +# More help from darwin_hid.py
|
| +
|
| +# Also see the 'IORegistryExplorer' for an idea of what we are actually searching
|
| +
|
| +import ctypes
|
| +from ctypes import util
|
| +import re
|
| +
|
| +iokit = ctypes.cdll.LoadLibrary(ctypes.util.find_library('IOKit'))
|
| +cf = ctypes.cdll.LoadLibrary(ctypes.util.find_library('CoreFoundation'))
|
| +
|
| +kIOMasterPortDefault = ctypes.c_void_p.in_dll(iokit, "kIOMasterPortDefault")
|
| +kCFAllocatorDefault = ctypes.c_void_p.in_dll(cf, "kCFAllocatorDefault")
|
| +
|
| +kCFStringEncodingMacRoman = 0
|
| +
|
| +iokit.IOServiceMatching.restype = ctypes.c_void_p
|
| +
|
| +iokit.IOServiceGetMatchingServices.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
|
| +iokit.IOServiceGetMatchingServices.restype = ctypes.c_void_p
|
| +
|
| +iokit.IORegistryEntryGetParentEntry.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
|
| +
|
| +iokit.IORegistryEntryCreateCFProperty.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_uint32]
|
| +iokit.IORegistryEntryCreateCFProperty.restype = ctypes.c_void_p
|
| +
|
| +iokit.IORegistryEntryGetPath.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
|
| +iokit.IORegistryEntryGetPath.restype = ctypes.c_void_p
|
| +
|
| +iokit.IORegistryEntryGetName.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
|
| +iokit.IORegistryEntryGetName.restype = ctypes.c_void_p
|
| +
|
| +iokit.IOObjectGetClass.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
|
| +iokit.IOObjectGetClass.restype = ctypes.c_void_p
|
| +
|
| +iokit.IOObjectRelease.argtypes = [ctypes.c_void_p]
|
| +
|
| +
|
| +cf.CFStringCreateWithCString.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int32]
|
| +cf.CFStringCreateWithCString.restype = ctypes.c_void_p
|
| +
|
| +cf.CFStringGetCStringPtr.argtypes = [ctypes.c_void_p, ctypes.c_uint32]
|
| +cf.CFStringGetCStringPtr.restype = ctypes.c_char_p
|
| +
|
| +cf.CFNumberGetValue.argtypes = [ctypes.c_void_p, ctypes.c_uint32, ctypes.c_void_p]
|
| +cf.CFNumberGetValue.restype = ctypes.c_void_p
|
| +
|
| +def get_string_property(device_t, property):
|
| + """ Search the given device for the specified string property
|
| +
|
| + @param device_t Device to search
|
| + @param property String to search for.
|
| + @return Python string containing the value, or None if not found.
|
| + """
|
| + key = cf.CFStringCreateWithCString(
|
| + kCFAllocatorDefault,
|
| + property.encode("mac_roman"),
|
| + kCFStringEncodingMacRoman
|
| + )
|
| +
|
| + CFContainer = iokit.IORegistryEntryCreateCFProperty(
|
| + device_t,
|
| + key,
|
| + kCFAllocatorDefault,
|
| + 0
|
| + );
|
| +
|
| + output = None
|
| +
|
| + if CFContainer:
|
| + output = cf.CFStringGetCStringPtr(CFContainer, 0)
|
| +
|
| + return output
|
| +
|
| +def get_int_property(device_t, property):
|
| + """ Search the given device for the specified string property
|
| +
|
| + @param device_t Device to search
|
| + @param property String to search for.
|
| + @return Python string containing the value, or None if not found.
|
| + """
|
| + key = cf.CFStringCreateWithCString(
|
| + kCFAllocatorDefault,
|
| + property.encode("mac_roman"),
|
| + kCFStringEncodingMacRoman
|
| + )
|
| +
|
| + CFContainer = iokit.IORegistryEntryCreateCFProperty(
|
| + device_t,
|
| + key,
|
| + kCFAllocatorDefault,
|
| + 0
|
| + );
|
| +
|
| + number = ctypes.c_uint16()
|
| +
|
| + if CFContainer:
|
| + output = cf.CFNumberGetValue(CFContainer, 2, ctypes.byref(number))
|
| +
|
| + return number.value
|
| +
|
| +def IORegistryEntryGetName(device):
|
| + pathname = ctypes.create_string_buffer(100) # TODO: Is this ok?
|
| + iokit.IOObjectGetClass(
|
| + device,
|
| + ctypes.byref(pathname)
|
| + )
|
| +
|
| + return pathname.value
|
| +
|
| +def GetParentDeviceByType(device, parent_type):
|
| + """ Find the first parent of a device that implements the parent_type
|
| + @param IOService Service to inspect
|
| + @return Pointer to the parent type, or None if it was not found.
|
| + """
|
| + # First, try to walk up the IOService tree to find a parent of this device that is a IOUSBDevice.
|
| + while IORegistryEntryGetName(device) != parent_type:
|
| + parent = ctypes.c_void_p()
|
| + response = iokit.IORegistryEntryGetParentEntry(
|
| + device,
|
| + "IOService".encode("mac_roman"),
|
| + ctypes.byref(parent)
|
| + )
|
| +
|
| + # If we weren't able to find a parent for the device, we're done.
|
| + if response != 0:
|
| + return None
|
| +
|
| + device = parent
|
| +
|
| + return device
|
| +
|
| +def GetIOServicesByType(service_type):
|
| + """
|
| + """
|
| + serial_port_iterator = ctypes.c_void_p()
|
| +
|
| + response = iokit.IOServiceGetMatchingServices(
|
| + kIOMasterPortDefault,
|
| + iokit.IOServiceMatching(service_type),
|
| + ctypes.byref(serial_port_iterator)
|
| + )
|
| +
|
| + services = []
|
| + while iokit.IOIteratorIsValid(serial_port_iterator):
|
| + service = iokit.IOIteratorNext(serial_port_iterator)
|
| + if not service:
|
| + break
|
| + services.append(service)
|
| +
|
| + iokit.IOObjectRelease(serial_port_iterator)
|
| +
|
| + return services
|
| +
|
| +def comports():
|
| + # Scan for all iokit serial ports
|
| + services = GetIOServicesByType('IOSerialBSDClient')
|
| +
|
| + ports = []
|
| + for service in services:
|
| + info = []
|
| +
|
| + # First, add the callout device file.
|
| + info.append(get_string_property(service, "IOCalloutDevice"))
|
| +
|
| + # If the serial port is implemented by a
|
| + usb_device = GetParentDeviceByType(service, "IOUSBDevice")
|
| + if usb_device != None:
|
| + info.append(get_string_property(usb_device, "USB Product Name"))
|
| +
|
| + info.append(
|
| + "USB VID:PID=%x:%x SNR=%s"%(
|
| + get_int_property(usb_device, "idVendor"),
|
| + get_int_property(usb_device, "idProduct"),
|
| + get_string_property(usb_device, "USB Serial Number"))
|
| + )
|
| + else:
|
| + info.append('n/a')
|
| + info.append('n/a')
|
| +
|
| + ports.append(info)
|
| +
|
| + return ports
|
| +
|
| +# test
|
| +if __name__ == '__main__':
|
| + for port, desc, hwid in sorted(comports()):
|
| + print "%s: %s [%s]" % (port, desc, hwid)
|
| +
|
|
|