This article uses just about every Unix worst-practice in the book, but there is a reason for all of them. In this article, we pipe downloaded code directly in to bash as root, run Wine as root, and play around with renaming device nodes. None of this broke anything for me, but if you fubar your system, burn your house down, etc… you can’t say I didn’t warn you.
I’m currently using a Ubuntu 18.04 variant, but any distribution with a modern version of Wine will work.
apt install wine-development
dnf install wine
pacman -S wine
zypper install wine
I have only managed to get serial support working when running as the root user. Despite the fact that my user is a member of the dialout group, and the serial port is owned by the dialout group, I am unable to access the serial port through a wine application unless running Wine as root. This is NOT best practice and should be done with care and the upfront knowledge that things could go horribly wrong. I know if I was reading this, I would have my doubts as to the accuracy of this statement. If anyone does manage to get this to work as a regular user, please let me know via the email address on my QRZ page.
Big Fat Warning:
The following command executes the development version of Winetricks directly from the Winetricks github repo. As ROOT. If you aren’t comfortable with this, feel free to install “allfonts” from your distribution’s winetricks package (as root). As of this writing, the version packaged with Ubuntu 18.04 does not work as the Powerpoint Viewer executable it downloads does not match the checksum expected by Winetricks. If you decide not to install these fonts, text in the application will show up as blocks and you will not be able to see what you are doing.
sudo sh -s allfonts <<(wget -qO- https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks)
This takes a while, so grab a snack or some coffee or something.
Download the CPS⌗
Next, go ahead and download the Ailunce CPS from here. Grab the latest version for your particular radio variant (GPS or non-GPS). I happen to have the non-GPS variant so I have only tested with that.
Install the CPS⌗
First, unzip the installer. Your filename may be different once there is a newer version released.
Start the installer (as root) from the command line. Again, your filename may have a different version number.
sudo wine /path/to/extracted/file/'HD1 v1.93.exe'
The installer should start and run with no issues. Click through everything, but when it finishes, uncheck the box to start the application. If you forget and the application starts, it’s no big deal, just close it.
Configure the serial port⌗
This is where things get interesting. Plug in the USB cable that came with the radio. Once it is connected, run:
You should see something that looks like this.
[1926698.114821] pl2303 1-1.3:1.0: pl2303 converter detected [1926698.116372] usb 1-1.3: pl2303 converter now attached to ttyUSB0
As you can see, on my computer, the serial port is ttyUSB0. Depending on whether or not you have other USB to serial adapters, your device name may end with a different number (ttyUSB1, ttyUSB2, etc…)
Older versions of Wine required a symlink to be manually created in order to map a COM port for the Windows application to see to the serial interface in Linux. Newer versions of Wine “helpfully” do this automatically. The problem is, on any modern distribution, 32 or so /dev/ttyS devices are created automatically on boot up. This would be useful if your computer had 32 physical serial ports, but in 2018 you are lucky if you have one, and most people have none. This means that when Wine starts, it enumerates your serial ports and helpfully creates COM1-COM32 for use in your Windows application in Wine. If your USB programming cable is connected, it will be assigned to COM33. This is all well and good, but the Ailunce CPS apparently can’t handle serial ports with that high of a number. It errors out and says it’s an invalid COM port.
From here on out you are better off working as root. I’m sure you know the dangers, so double check what you are typing.
Now that you have a root shell, let’s take a look at the COM devices currently available to Wine.
ls -l /root/.wine/dosdevices
Here is my output:
total 0 lrwxrwxrwx 1 root root 10 Jul 12 16:42 c: -> ../drive_c lrwxrwxrwx 1 root root 10 Jul 12 16:42 com1 -> /dev/ttyS0 lrwxrwxrwx 1 root root 10 Jul 12 16:42 com10 -> /dev/ttyS9 lrwxrwxrwx 1 root root 11 Jul 12 16:42 com11 -> /dev/ttyS10 lrwxrwxrwx 1 root root 11 Jul 12 16:42 com12 -> /dev/ttyS11 lrwxrwxrwx 1 root root 11 Jul 12 16:42 com13 -> /dev/ttyS12 lrwxrwxrwx 1 root root 11 Jul 12 16:42 com14 -> /dev/ttyS13 lrwxrwxrwx 1 root root 11 Jul 12 16:42 com15 -> /dev/ttyS14 lrwxrwxrwx 1 root root 11 Jul 12 16:42 com16 -> /dev/ttyS15 lrwxrwxrwx 1 root root 11 Jul 12 16:42 com17 -> /dev/ttyS16 lrwxrwxrwx 1 root root 11 Jul 12 16:42 com18 -> /dev/ttyS17 lrwxrwxrwx 1 root root 11 Jul 12 16:42 com19 -> /dev/ttyS18 lrwxrwxrwx 1 root root 10 Jul 12 16:42 com2 -> /dev/ttyS1 lrwxrwxrwx 1 root root 11 Jul 12 16:42 com20 -> /dev/ttyS19 lrwxrwxrwx 1 root root 11 Jul 12 16:42 com21 -> /dev/ttyS20 lrwxrwxrwx 1 root root 11 Jul 12 16:42 com22 -> /dev/ttyS21 lrwxrwxrwx 1 root root 11 Jul 12 16:42 com23 -> /dev/ttyS22 lrwxrwxrwx 1 root root 11 Jul 12 16:42 com24 -> /dev/ttyS23 lrwxrwxrwx 1 root root 11 Jul 12 16:42 com25 -> /dev/ttyS24 lrwxrwxrwx 1 root root 11 Jul 12 16:42 com26 -> /dev/ttyS25 lrwxrwxrwx 1 root root 11 Jul 12 16:42 com27 -> /dev/ttyS26 lrwxrwxrwx 1 root root 11 Jul 12 16:42 com28 -> /dev/ttyS27 lrwxrwxrwx 1 root root 11 Jul 12 16:42 com29 -> /dev/ttyS28 lrwxrwxrwx 1 root root 10 Jul 12 16:42 com3 -> /dev/ttyS2 lrwxrwxrwx 1 root root 11 Jul 12 16:42 com30 -> /dev/ttyS29 lrwxrwxrwx 1 root root 11 Jul 12 16:42 com31 -> /dev/ttyS30 lrwxrwxrwx 1 root root 11 Jul 12 16:42 com32 -> /dev/ttyS31 lrwxrwxrwx 1 root root 12 Jul 12 16:42 com33 -> /dev/ttyUSB0 lrwxrwxrwx 1 root root 10 Jul 12 16:42 com4 -> /dev/ttyS3 lrwxrwxrwx 1 root root 10 Jul 12 16:42 com5 -> /dev/ttyS4 lrwxrwxrwx 1 root root 10 Jul 12 16:42 com6 -> /dev/ttyS5 lrwxrwxrwx 1 root root 10 Jul 12 16:42 com7 -> /dev/ttyS6 lrwxrwxrwx 1 root root 10 Jul 12 16:42 com8 -> /dev/ttyS7 lrwxrwxrwx 1 root root 10 Jul 12 16:42 com9 -> /dev/ttyS8 lrwxrwxrwx 1 root root 8 Jul 12 16:42 d:: -> /dev/sr0 lrwxrwxrwx 1 root root 8 Jul 12 16:42 e:: -> /dev/sdc lrwxrwxrwx 1 root root 8 Jul 12 16:42 f: -> /storage lrwxrwxrwx 1 root root 9 Jul 12 16:42 f:: -> /dev/sdc1 lrwxrwxrwx 1 root root 1 Jul 12 16:42 z: -> /
Take note of the number of serial devices here. We can use grep to filter for only USB serial devices.
ls -l /root/.wine/dosdevices | grep ttyUSB
As expected, /dev/ttyUSB0 was assigned to COM33
lrwxrwxrwx 1 root root 12 Jul 12 16:42 com33 -> /dev/ttyUSB0
There is a quick, but very dirty fix for this. My first thought was to manually symlink /dev/ttyUSB0 to /root/.wine/dosdevices/COM1. I did this, but when I fired up Wine, it reset itself and /dev/ttyUSB0 was assigned to COM33 again. Not good. The next thing I tried is where things get a little dirty.
mv /dev/ttyS0 /dev/oldserialport
BUT WAIT, didn’t you just mess with a device node? Isn’t that going to bork your system later?
First, I have no physical serial ports, so renaming the device node will not affect MY system. If you do, great. You can always move it back, or if you forget the device node will be recreated by udev next time your computer reboots. This means you have to do this step each time you want to run the CPS if you reboot in between. If you do have a physical serial port, you can always move it back and everything will be back to normal.
Now that /dev/ttyS0 is gone, let’s run wineboot so that it can re-enumerate the serial devices.
Wine has now re-created all the serial devices. Take a look at the dosdevices directory to see what happened.
ls -l /root/.wine/dosdevices
Now mine looks like this:
lrwxrwxrwx 1 root root 10 Jul 12 16:42 c: -> ../drive_c lrwxrwxrwx 1 root root 12 Jul 12 17:02 com1 -> /dev/ttyUSB0 lrwxrwxrwx 1 root root 8 Jul 12 16:42 d:: -> /dev/sr0 lrwxrwxrwx 1 root root 8 Jul 12 16:42 e:: -> /dev/sdc lrwxrwxrwx 1 root root 8 Jul 12 17:02 f: -> /storage lrwxrwxrwx 1 root root 9 Jul 12 16:42 f:: -> /dev/sdc1 lrwxrwxrwx 1 root root 1 Jul 12 16:42 z: -> /
Wait, I see that com1 is now /dev/ttyUSB0, but what happened to the rest of the COM devices?
Beats me, but they are still in /dev. It looks like this works around Wine’s device detection nicely.
root@localhost:~/.wine/dosdevices# ls /dev/ttyS* /dev/ttyS1 /dev/ttyS13 /dev/ttyS17 /dev/ttyS20 /dev/ttyS24 /dev/ttyS28 /dev/ttyS31 /dev/ttyS7 /dev/ttyS10 /dev/ttyS14 /dev/ttyS18 /dev/ttyS21 /dev/ttyS25 /dev/ttyS29 /dev/ttyS4 /dev/ttyS8 /dev/ttyS11 /dev/ttyS15 /dev/ttyS19 /dev/ttyS22 /dev/ttyS26 /dev/ttyS3 /dev/ttyS5 /dev/ttyS9 /dev/ttyS12 /dev/ttyS16 /dev/ttyS2 /dev/ttyS23 /dev/ttyS27 /dev/ttyS30 /dev/ttyS6
Now that we have a usable serial port, it’s time to start working on codeplugs.
Running the CPS⌗
Browse to the HD1 program files directory in your Wine virtual C: drive. If you aren’t using a root shell, now would be a good time to run sudo -s again.
cd /root/.wine/drive_c/Program\ Files\ \(x86\)/HD1/
And run the HD1 executable. Remember to use the correct executable name if you are using a different version.
wine HD1\ v1.93.exe
You are now up and running with the CPS. Remember to configure it to use COM1 and enjoy.
Making Things Easy⌗
So, you can run and use the CPS, but it sucks to have to mess around with the serial port stuff after every reboot. Here’s a nice script you can use to automate everything. Run
sudo nano -w /usr/bin/hd1-cps.sh
Paste in the following script (using Ctrl+Shift+V or right-click, paste). Save with Ctrl+O. Exit with Ctrl+x.
#!/bin/bash ##### #HD1 CPS Launcher Script #July 13, 2018 #Ben Kuhn - KU0HN #Version 1.0 ####### # Make sure this is being run as root if [[ $EUID -ne 0 ]]; then echo "This script must be run as root" exit 1 fi # Hide the physical serial port to work around Wine's COM port numbering mv /dev/ttyS0 /dev/oldserial # Regenerate the devices in ~/.wine/dosdevices wineboot #If using a different Wine HD1 Program Files Path, adjust below hd1_path="/root/.wine/drive_c/Program Files (x86)/HD1" #Find the current verision of the installed HD1 CPS hd1_exe=`ls -1 "$hd1_path" | grep HD1` cd "$hd1_path" #Run the CPS sudo wine "$hd1_exe" #Restore the serial port device node mv /dev/oldserial /dev/ttyS0
Now, make the script executable.
chmod +x /usr/bin/hd1-cps.sh
Now, you can run the CPS simply with the following command.
Add a GUI Launcher for the CPS⌗
If you primarily use the GUI, you may want a menu entry to launch the CPS. Create the .desktop file below to launch the CPS from a gui.
sudo nano /usr/share/applications/HD1.desktop
Paste in the text below, save and exit.
[Desktop Entry] Version=0.0 Name=HD1 Comment=Ailunce HD1 CPS Exec=sudo /usr/bin/hd1-cps.sh Icon=smartphone Terminal=true Type=Application Categories=HamRadio
A terminal window will open and you will be prompted for your sudo password. You could replace sudo in the Exec string above with gksu or something else, and set Terminal to false for a more “GUI” experience, but these aren’t installed on everyone’s systems by default anymore so, for the sake of being as generic as possible, I am defaulting to running as a terminal application.
Good luck, and happy codeplug editing!