#!/usr/bin/env perl # Based on listArduinos.pl from https://github.com/todbot/usbSearch (License: MIT) # Original (C) 2012, Tod E. Kurt, http://todbot.com/blog/ # This version by Michael Richters <gedankenexperimenter@gmail.com> use warnings; use strict; # ioreg might be more machine-readable than system_profiler, but I haven't been able to # get it to produce useful output my @output = qx(/usr/sbin/system_profiler SPUSBDataType); my $parse_state = 0; my $device = {}; LINE: foreach my $line (@output) { chomp $line; if ( $parse_state == 0 ) { if ( $line =~ m/Model 01/ ) { $parse_state = 1; next LINE; } } if ( $parse_state == 1 ) { if ( $line =~ m/^\s*$/ ) { $parse_state = 2; next LINE; } } if ( $parse_state == 2 ) { if ( $line =~ m/Serial Number: (.+)$/ ) { $device->{'serial_number'} = $1; next LINE; } if ( $line =~ m/Location ID: (.+)$/ ) { $device->{'location_id'} = $1; next LINE; } if ( $line =~ m/Product ID: (.+)$/ ) { $device->{'product_id'} = $1; next LINE; } if ( $line =~ m/Vendor ID: (.+)$/ ) { $device->{'vendor_id'} = $1; next LINE; } if ( $line =~ m/^\s*$/ ) { last LINE; } } } die "Can't find Model 01" if ( $device == {} ); my $serial_port_name = ""; if ( exists( $device->{'serial_number'} ) ) { $serial_port_name = "/dev/cu.usbmodem" . $device->{'serial_number'}; if ( -e $serial_port_name ) { print $serial_port_name; exit 0; } # High Sierra sometimes has a mismatch between the serial number and the device # filename. I'm not sure why, but system_profiler has a serial number ending in "E", # whereas the device filename ends in "1". In fact, when I change HID.getShortName() # to return "kbio02", the final character is replaced with a "1", so we should do the # same here. $serial_port_name =~ s/.$/1/; if ( -e $serial_port_name ) { print $serial_port_name; exit 0; } } # Here, also, the final character is always a "1", so if macOS ever stops doing that, this # will need an update, as well. if ( exists( $device->{'location_id'} ) ) { my $loc = substr( $device->{'location_id'}, 2, 3 ); $serial_port_name = "/dev/cu.usbmodem" . $loc . 1; if ( -e $serial_port_name ) { print $serial_port_name; exit 0; } } # If none of the above tests succeeds, just list the directory and see if there are any # files that have the device shortname that we expect: foreach my $line (qx(ls /dev/cu.usbmodem*)) { # If this script gets used for the Model 02 (or anything else that won't end it "1"), # the line below should probably drop the final character (see above): if ( $line =~ m/kbio01/ ) { chomp $line; print $line; exit 0; } } die "Can't find Model 01 serial port name";