So, after a heartbreaking month of having a Surface Pro 3 that was utterly unstable and unusable, I now seem (emphasis on seem) to have it completely stable and successfully running an instance of Linux Mint 18.2.

Required Equipment

Here's all the things I did, probably in the order I did them. First: buy some stuff: A powered hub with at least four ports, a USB-to-Ethernet connection, and two 16GB USB memory sticks. If you want to preserve the installed Windows instance, you'll need a second 32GB USB memory stick. (You'll have to go on-line to find instructions on how to back up your Windows instance.)

I assume you have a USB-capable keyboard and mouse. Download the latest version of Linux Mint. For Ubuntu-based distributions, you must also go and get more up-to-date kernels. As of this writing, I used the Linux Kernel 4.12.8, amd64 versions. There are five files in that collection; the three you want are the headers, the generic headers, and the image; skip the ones label "lowlatency".

With another Linux computer, use unetbootin to install the Linux Mint ISO on one of the 16GB sticks. Do not reformat the drive to a Linux format; let unetbootin install the contents of the ISO into the FAT32-formatted stick.

The other 16GB stick can be any format Linux recognizes, and Linux recognizes FAT32. Copy the linux kernel files you downloaded onto it. You will also want to copy the latest versions of the MRVL firmware onto the stick to update the Surface Pro's wifi firmware.

Installation of Linux Mint 18.2

Plug the hub into your Surface Pro. Into the HUB plug: the ethernet cable, hooked to a live network; a keyboard; a mouse; the 16GB stick with the bootable ISO on it.

Turn on the Surface Pro while holding down the "volume up" button; this will give you access to the BIOS. Disable "Secure Boot" and "Trusted Platform," and changed the boot order to USB → SSD. Exit and let the boot process proceed. If you've done it right, you'll get the "Welcome to Linux Mint!" page. Do your thing: Install Linux Mint. I just blew away my Windows install; I didn't care to keep it. That's not the purpose of this exercise anyway.

When I tried to reboot, nothing worked. It kept insisting that there was no bootable medium! I found this solution, but I had to change hd2 to hd1 as I am not dual-booting. Once I was in to my instance of Linux, I was able to see via efibootmgr that the master boot record was corrupted; I installed and ran YannUbuntu's boot-repair, and to my pleasure it actually fixed the problem the first time.

I rebooted back into the BIOS and switched back to "Secure Mode" for boot, and continued, and it worked fine. Yay!

Upgrade to the latest kernel

My hopes were dashed, though, when the network proved to be just as flaky as it had been earlier. But I had bigger problems: the keyboard and touchpad didn't work. To fix that, put in the memory stick with the linux kernel image on it and type:

<code>dpkg -i linux-*.deb</code>

(If you downloaded more than one kernel, you'll have to find a way to distinguish them.) Now reboot. If you have a kernel past 4.11, your keyboard, touchpad, and touchscreen should now all work. Yay!

Hibernate and Wifi

I did get the wireless working, too.

  1. I updated the firmware to the latest versions by copying the files in that directory to /lib/firmware/mrvl

  2. I added to /etc/NetworkManager/NetworkManager.conf:

[device] wifi.scan-rand-mac-address=no

  1. I edited /etc/NetworkManager/conf.d/default-wifi-powersave-on.conf and changed "wifi.powersave=3" to "wifi.powersave=2".

The one thing I did not do, which I did last time, was blindly drop my old .config directory onto the new machine. The last time I tried this, I built the box, then restored from backup my personal account from my old Lenovo Yoga. This included all the keys, passwords, configuration details and some cached data (because idiots keep using .config as a cache directory; I'm looking at you, Google Chrome!) from the old NetworkManager, and it appears that some of those changes were what broke the old one.

The next step is to disable "sleep mode"; the Surface Pro doesn't have a sleep mode! Instead, it's either "off," "on," or "connected," the last of which is much like your phone when the screen is off: still processing network events and handling notifications. The Linux kernel isn't up-to-date on this state, and almost no applications understand connected mode, so it's useless. The best we can do is hibernate. This isn't that bad because the Surface Pro has an SSD; booting to a hibernated screen is about 15 seconds, not terribly shabby. Not the ~3 seconds of my Yoga, but livable.

On Linux Mint 18.2, these commands were:

<code>cd /lib/systemd/system
sudo mv suspend.target suspend.target.orig
sudo ln -s hibernate.target suspend.target</code>

This links the systemd (gag) suspend target to hibernate, so that commands to suspend trigger hibernation instead. It's actually pretty functional. Unfortunately, the mwifiex driver is still flaky, so you'll have to handle it by hand. The following script goes into /lib/systemd/system-sleep/mwifiex, and has to be chown root mwifiex; chmod 755 mwifiex in order to run correctly.

<code>#!/bin/sh
set -e

if [ "$2" = "hibernate" ]; then
    case "$1" in
        pre) modprobe -r mwifiex_pcie mwifiex ;;
        post) modprobe mwifiex_pcie ;;
    esac</code>

Now, theoretically, you have everything. Hibernate works and recovers; wifi comes back.

Bluetooth

Bluetooth works out of the box with the 4.13.0 kernel, but the LE features only work with the very latest version of bluez, and even then you have to modify /lib/systemd/system/bluetooth.service, changing the Exec line to this:

<code>ExecStart=/usr/libexec/bluetooth/bluetoothd --experimental</code>

Adding the "experimental" line will let things like Bose products work with bluetooth.

Also, if you're a pulseaudio user (and if you're on Ubuntu or Mint, you are), add this line to the end of /etc/pulse/default.pa, and when your headphones connect Pulseaudio will automatically re-route the audio, rather than your having to do it manually.

<code>load-module module-switch-on-connect</code>

Cameras

The cameras worked out of the box. I played with Cheese and it liked both cameras.

Autorotate

The best autorotate script I've found yet is Ayko Poel's SurfacePro3 Scripts. It does automapping of the pen for you, which is really nice.

Touchegg

I really like Touchegg. I use QComicbook to read hentai comics, and by configuring both autorotate and touchegg's configuration, I get an easy, pagable interface that I can use to flip through the pages as fast as I can.

Gimp and Krita

Both worked out of the box. Pen pressure worked out of the box, but getting the eraser and the button required a little configuration. Now that they're working, though, I have a pretty good casual art pad as well as a decent writing machine and even a competent coding machine.

Next steps

I'd like to get autobrightness working. The bluetooth configuration is still a little flaky, but better than it used to be. One thing I'd really like to get is to map the accelerometer and/or the gyroscope devices to a joystick device, so that you could use the tilt of the surface pro as a kind of joystick. I once wrote a lightsaber toy that used the old Thinkpad HDAPS sensor as a joystick, and porting that to the Surface Pro (and maybe to Rust) would be a pretty good exercise.