in src/main/c/Posix/PosixHelperFunctions.c [1608:1754]
void searchForComPorts(serialPortVector* comPorts)
{
io_object_t serialPort;
io_iterator_t serialPortIterator;
char comPortCu[1024], comPortTty[1024];
char friendlyName[1024], portLocation[1024], serialNumber[128], manufacturer[128];
// Enumerate serial ports on machine
IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching(kIOSerialBSDServiceValue), &serialPortIterator);
while ((serialPort = IOIteratorNext(serialPortIterator)))
{
// Get serial port information
char isUSB = 0;
friendlyName[0] = '\0';
strcpy(serialNumber, "Unknown");
strcpy(manufacturer, "Unknown");
int vendorID = -1, productID = -1;
io_registry_entry_t parent = 0, service = serialPort;
while (service)
{
if (IOObjectConformsTo(service, "IOUSBDevice"))
{
IORegistryEntryGetName(service, friendlyName);
isUSB = 1;
break;
}
if (IORegistryEntryGetParentEntry(service, kIOServicePlane, &parent) != KERN_SUCCESS)
break;
if (service != serialPort)
IOObjectRelease(service);
service = parent;
}
if (service != serialPort)
IOObjectRelease(service);
// Get serial port name and COM value
if (friendlyName[0] == '\0')
{
CFStringRef friendlyNameRef = (CFStringRef)IORegistryEntryCreateCFProperty(serialPort, CFSTR(kIOTTYDeviceKey), kCFAllocatorDefault, 0);
CFStringGetCString(friendlyNameRef, friendlyName, sizeof(friendlyName), kCFStringEncodingUTF8);
CFRelease(friendlyNameRef);
}
CFStringRef comPortRef = (CFStringRef)IORegistryEntryCreateCFProperty(serialPort, CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
CFStringGetCString(comPortRef, comPortCu, sizeof(comPortCu), kCFStringEncodingUTF8);
CFRelease(comPortRef);
comPortRef = (CFStringRef)IORegistryEntryCreateCFProperty(serialPort, CFSTR(kIODialinDeviceKey), kCFAllocatorDefault, 0);
CFStringGetCString(comPortRef, comPortTty, sizeof(comPortTty), kCFStringEncodingUTF8);
CFRelease(comPortRef);
// Get VID, PID, Serial Number, Bus Number, and Port Address
if (isUSB)
{
CFTypeRef propertyRef = IORegistryEntrySearchCFProperty(serialPort, kIOServicePlane, CFSTR("locationID"), kCFAllocatorDefault, kIORegistryIterateRecursively | kIORegistryIterateParents);
if (propertyRef)
{
int locationID = 0;
char multiHub = 0, tempLocation[64];
CFNumberGetValue(propertyRef, kCFNumberIntType, &locationID);
CFRelease(propertyRef);
snprintf(portLocation, sizeof(portLocation), "%d", (locationID >> 24) & 0x000000FF);
strcat(portLocation, "-");
while (locationID & 0x00F00000)
{
if (multiHub)
strcat(portLocation, ".");
snprintf(tempLocation, sizeof(tempLocation), "%d", (locationID >> 20) & 0x0000000F);
strcat(portLocation, tempLocation);
locationID <<= 4;
multiHub = 1;
}
}
propertyRef = IORegistryEntrySearchCFProperty(serialPort, kIOServicePlane, CFSTR("idVendor"), kCFAllocatorDefault, kIORegistryIterateRecursively | kIORegistryIterateParents);
if (propertyRef)
{
CFNumberGetValue(propertyRef, kCFNumberIntType, &vendorID);
CFRelease(propertyRef);
}
propertyRef = IORegistryEntrySearchCFProperty(serialPort, kIOServicePlane, CFSTR("idProduct"), kCFAllocatorDefault, kIORegistryIterateRecursively | kIORegistryIterateParents);
if (propertyRef)
{
CFNumberGetValue(propertyRef, kCFNumberIntType, &productID);
CFRelease(propertyRef);
}
propertyRef = IORegistryEntrySearchCFProperty(serialPort, kIOServicePlane, CFSTR("USB Serial Number"), kCFAllocatorDefault, kIORegistryIterateRecursively | kIORegistryIterateParents);
if (propertyRef)
{
CFStringGetCString(propertyRef, serialNumber, sizeof(serialNumber), kCFStringEncodingUTF8);
CFRelease(propertyRef);
}
propertyRef = IORegistryEntrySearchCFProperty(serialPort, kIOServicePlane, CFSTR("USB Vendor Name"), kCFAllocatorDefault, kIORegistryIterateRecursively | kIORegistryIterateParents);
if (propertyRef)
{
CFStringGetCString(propertyRef, manufacturer, sizeof(manufacturer), kCFStringEncodingUTF8);
CFRelease(propertyRef);
}
}
else
strcpy(portLocation, "0-0");
// Check if callout port is already enumerated
struct serialPort *port = fetchPort(comPorts, comPortCu);
if (port)
{
// See if device has changed locations
port->enumerated = 1;
if (isUSB)
{
int oldLength = strlen(port->portLocation);
int newLength = strlen(portLocation);
if (oldLength != newLength)
{
port->portLocation = (char*)realloc(port->portLocation, newLength + 1);
strcpy(port->portLocation, portLocation);
}
else if (memcmp(port->portLocation, portLocation, newLength))
strcpy(port->portLocation, portLocation);
}
}
else
pushBack(comPorts, comPortCu, friendlyName, friendlyName, portLocation, serialNumber, manufacturer, "Unknown", vendorID, productID, 0);
// Check if dialin port is already enumerated
port = fetchPort(comPorts, comPortTty);
strcat(friendlyName, " (Dial-In)");
if (port)
{
// See if device has changed locations
port->enumerated = 1;
if (isUSB)
{
int oldLength = strlen(port->portLocation);
int newLength = strlen(portLocation);
if (oldLength != newLength)
{
port->portLocation = (char*)realloc(port->portLocation, newLength + 1);
strcpy(port->portLocation, portLocation);
}
else if (memcmp(port->portLocation, portLocation, newLength))
strcpy(port->portLocation, portLocation);
}
}
else
pushBack(comPorts, comPortTty, friendlyName, friendlyName, portLocation, serialNumber, manufacturer, "Unknown", vendorID, productID, 0);
IOObjectRelease(serialPort);
}
IOObjectRelease(serialPortIterator);
}