I finally decided to go with Mac for Amateur Radio stuff. Time Machine and Spotlight make life so much more comfortable. Not to mention good sleep/wake performance, terminal with bash command line etc. Of course, there will always be some tools that are Windows only, so I use Parallels for this. Download your Windows tool on Mac with Safari, organise stuff in iCloud and then just double click the installer program from Mac. Parallels will start Windows (from pause, no booting involved) and run the installer. When it’s time to use it, launch the tool with Spotlight from Mac. IMHO this will work best with small productivity tools, and better use Mac native programs for the real work. (otherwise just buy a PC and save some frustration..)

Back to Icom: in order to use IC-7300 and IC-9700 on Mojave, you first have to install the serial port drivers from SiLabs. After a reboot, three new serial ports (one for IC-7300, two for IC-9700) are created in /dev and can be used in WSJT-X for example. The USB audio devices don’t require any drivers and are visible in Audio/Midi tool. All good? Unfortunately not….

After the first transceiver power cycle, the 2nd and 3rd  SiLabs serial port magically gets renamed and you end up with this after some time:

crw-rw-rw-  1 root  wheel   18,  30 Jan 15 06:48 /dev/cu.SLAB_USBtoUART
crw-rw-rw-  1 root  wheel   18,  32 Jan 15 06:48 /dev/cu.SLAB_USBtoUART16
crw-rw-rw-  1 root  wheel   18,  34 Jan 15 06:48 /dev/cu.SLAB_USBtoUART17
and after the next power cycle:
crw-rw-rw-  1 root  wheel   18,  36 Jan 15 06:50 /dev/cu.SLAB_USBtoUART
crw-rw-rw-  1 root  wheel   18,  38 Jan 15 06:50 /dev/cu.SLAB_USBtoUART19
crw-rw-rw-  1 root  wheel   18,  40 Jan 15 06:50 /dev/cu.SLAB_USBtoUART20

A know problem according to SiLabs: https://www.silabs.com/community/interface/forum.topic.html/cp2102_device_namec-Tq3r

The solution lies in the use of a symlink that has an unique and never changing name and points to the changing device file. For example:

lrwxr-xr-x  1 Frank  wheel  25 Jan 16 15:35 /tmp/IC-7300_03003333 -> /dev/cu.SLAB_USBtoUART19

Good thing is that WSJT-X supports the use of filenames in the serial port drop down box.

There are several command line tools on Mac that you can use to show all the USB port properties. I used “ioreg” as follows:

ioreg -r -c IOUSBHostDevice -l -a

I wrote a small Perl script to parse the output by filtering on IC-9700 or IC-7300 in the serialname (USB property) and for each to determine the corresponding device name. With this information, the script (re-)creates the symlink files with updated info.

After a transceiver power cycle and before using a Mac program that uses the serial port, I run the small script. And if I forget and start WSJT-X first? Well then WSJT-X will complain about transceiver communication with a cancel, retry etc. window. Then run the script and then hit retry in WSJT-X and all is good.

Below you will find the Perl code. Best use Automator to create an application with windowed output from the script. Therefor all exits are zero, and dies are fatal…

use 5.010;
use strict;
use warnings;
use XML::LibXML;

my $linkdir = "/private/tmp";
my $device = "";
my %map = ();

my $xml_data = `ioreg -r -c IOUSBHostDevice -l -a`;
if ($?) {
  die "Fatal: ioreg command failed!\n";
}

# load ioreg output in XML object 'dom'
my $dom = XML::LibXML->load_xml(string => $xml_data);

# search 'dom' for Icom UARTs and store results in 'map' hash
foreach my $title ($dom->findnodes('/plist//string')) {
  if ( $title =~ /cu.SLAB_USBtoUART/ ) {
    $device = $title->to_literal();
  }
  if ( $title =~ /IC-7300|IC-9700|IC-7610/ ) {
    $map{$device} = $title->to_literal();
  }
}

unless (keys %map) {
  print "No Icom SLAB devices detected\n";
  exit 0;
}

my $ser;
my $target = "";

# create the symlinks in a 'sorted' way
foreach my $d (sort { $map{$a} cmp $map{$b} } keys %map) {
  unless (-e $d) {
    die "Fatal: device $d does not exist!\n";
  }

  $ser = $map{$d};
  $ser =~ s/ /_/g;

  # readlink follows symlink and tests dest file
  $target = readlink("$linkdir/$ser");

  # update symlink if needed
  if (!$target || $target ne $d) {
    unlink("$linkdir/$ser");
    symlink("$d", "$linkdir/$ser");
    print "$ser updated\n";
  }
  else {
    print "$ser not changed\n";
  }
}

exit 0;

Leave a Reply

Your email address will not be published. Required fields are marked *

7 + 1 =