The HD1 CPS running in Wine

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.


Wine Installation

I’m currently using a Ubuntu 18.04 variant, but any distribution with a modern version of Wine will work.

On Ubuntu:

apt install wine-development

On Fedora:

dnf install wine

On Arch:

pacman -S wine

On OpenSUSE:

zypper install wine

Note

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.

Install Fonts

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.

unzip HD1_v1.93.zip

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:

sudo dmesg

You should see something that looks like this.

[1926698.114821] pl2303 1-1.3:1.0: pl2303 converter detected
&#91;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.

sudo -s

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.

wineboot

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.

sudo hd1-cps.sh

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!