Flicker Flash eGPU Add A Screen Without Leaving X

Lately for whatever reason a Youtube video I made about adding an eGPU and having the screen come on has taken off on Youtube (hello all 190 of you), and people have been asking how I did it. Video in question:

Let me preface this whole thing and let you know I don’t use this anymore, Lenovo is a terrible company who couldn’t care in the slightest about putting out a good quality product or even care that they don’t support Linux (even if they advertise in the bios they do) How Lenovo puts out garbage WWAN adapters that do support USB mode, but don’t provide us any method to enable it, and when we do tape off the the pci pins we get the blacklisted screen. Not to mention that when we put a WWAN card in from a previous generation Thinkpad, we again get the Blacklisted screen. Lenovo you are a terrible company that makes garbage, and you need to be put on notice! Also your thunderbolt bus is slow as hell, which makes the eGPU not work as well as it should. If Apple ever fixes their keyboard I will burn this laptop to the ground.

Ok rant over, let’s get into the nuts and bolts of how this work.

The first thing I needed to know is that when something was plugged in I needed to know that it was plugged in to trigger an action. Enter udev:

/etc/udev/rules.d/99-video-egpu.rules

ACTION=="add", SUBSYSTEM=="pci",ATTRS{vendor}=="0x10de",ATTRS{device}=="0x1b80", RUN+="/bin/sh /usr/bin/addgpu.sh"

Then I needed to actually make the add.sh

#!/bin/bash
#exit
sleep 1
systemctl restart bumblebeed.service
sleep 3
export DISPLAY=:0
export XAUTHORITY=/var/run/lightdm/john/xauthority
su john -c 'optirun intel-virtual-output' 2> /tmp/output

Enter Intel-virtual-output the pig on stilts (The beautiful beautiful pig on stilts).

All good there everything just works.

Now we need a removal script, Linux treats Thunderbolt like a PCI bus, it’s dumb, but that is what it does. so removing an egpu would be like ripping out a PCI video card.. I don’t recommend this. I use Cinnamon. Why? Because I am a gluten for punishment.. So I did write an applet, it’s terrible, but it works most of the time.

applet.js:

const Applet = imports.ui.applet;
const Util = imports.misc.util;


function MyApplet(orientation, panel_height, instance_id) {
    this._init(orientation, panel_height, instance_id);
}

MyApplet.prototype = {
    __proto__: Applet.IconApplet.prototype,

    _init: function(orientation, panel_height, instance_id) {
        Applet.IconApplet.prototype._init.call(this, orientation, panel_height, instance_id);

        this.set_applet_icon_name("desktoptrusted");
        this.set_applet_tooltip(_("Click Here To Remove Your EGPU!"));
    },

    on_applet_clicked: function() {
        Util.spawn(['sudo','/usr/bin/remove.sh']);
    }
    
};

function main(metadata, orientation, panel_height, instance_id) {
    return new MyApplet(orientation, panel_height, instance_id);
}

manifest.json:

{
    "uuid": "remove-egpu@getanp.com",
    "name": "Remove The EGPU",
    "description": "Quickly and easily remove the GPU from your system",
    "icon": "desktoptrusted"
}


Removal bash script (I counted on you to not use 10 or more monitors):

echo "Unplug eGPU script started."
if [ "$(id -u)" != "0" ]; then
    #echo "Please run using sudo. Exiting."
    notify-send-all --icon=desktoptrusted "Remove GPU" "Please Run as Root with sudo" -t 5000
    exit 1
fi
PID=`pidof intel-virtual-output`
kill -9 $PID
sleep 2
#export DISPLAY=:0
#export XAUTHORITY=/var/run/lightdm/${SUDO_USER}/xauthority
if [ -e $tbt_chain/remove ]
then
    echo 1 > $tbt_chain/remove
    notify-send-all --icon=desktoptrusted "Remove GPU" "You May Now Remove Your EGPU" -t 5000
    echo "Thunderbolt chain removed from PCI tree. Please unplug eGPU now."
    while [ $secs -gt 0 ]; do
        echo -ne "$secs to rescan...\033[0K\r"
        sleep 1
        : $((secs--))
    done
    echo 1 > /sys/bus/pci/rescan
    xrandr --output VIRTUAL1 --off
    xrandr --output VIRTUAL2 --off
    xrandr --output VIRTUAL3 --off
    xrandr --output VIRTUAL4 --off
    xrandr --output VIRTUAL5 --off
    xrandr --output VIRTUAL6 --off
    xrandr --output VIRTUAL7 --off
    xrandr --output VIRTUAL8 --off
    xrandr --output VIRTUAL9 --off
    sleep 12
    if [ ! -d $tbt_chain ]; then
        notify-send-all --icon=desktoptrusted "Remove GPU" "You Have Safely Removed Your EGPU" -t 5000
    else
        notify-send-all --icon=desktoptrusted "Remove GPU" "You Have NOT Safely Removed Your EGPU" -t 5000

    fi 
    echo "Rescanned the PCI bus. Completed."
    exit 0
else
    exit 1
fi

/etc/sudoers.d/remove

%sudo  ALL=NOPASSWD: /usr/bin/remove.sh

Here is my bumblebee.conf, No I won’t help you setup your nvidia proprietary drivers.

# Configuration file for Bumblebee. Values should **not** be put between quotes

## Server options. Any change made in this section will need a server restart
# to take effect.
[bumblebeed]
# The secondary Xorg server DISPLAY number
VirtualDisplay=:8
# Should the unused Xorg server be kept running? Set this to true if waiting
# for X to be ready is too long and don't need power management at all.
KeepUnusedXServer=false
# The name of the Bumbleblee server group name (GID name)
ServerGroup=bumblebee
# Card power state at exit. Set to false if the card shoud be ON when Bumblebee
# server exits.
TurnCardOffAtExit=false
# The default behavior of '-f' option on optirun. If set to "true", '-f' will
# be ignored.
NoEcoModeOverride=false
# The Driver used by Bumblebee server. If this value is not set (or empty),
# auto-detection is performed. The available drivers are nvidia and nouveau
# (See also the driver-specific sections below)
Driver=nvidia
# Directory with a dummy config file to pass as a -configdir to secondary X
XorgConfDir=/etc/bumblebee/xorg.conf.d
# Xorg binary to run
XorgBinary=/usr/lib/xorg/Xorg

## Client options. Will take effect on the next optirun executed.
[optirun]
# Acceleration/ rendering bridge, possible values are auto, virtualgl and
# primus.
Bridge=auto
#Bridge=primus
# The method used for VirtualGL to transport frames between X servers.
# Possible values are proxy, jpeg, rgb, xv and yuv.
VGLTransport=yuv
# List of paths which are searched for the primus libGL.so.1 when using
# the primus bridge
PrimusLibraryPath=/usr/lib/x86_64-linux-gnu/primus:/usr/lib/i386-linux-gnu/primus
# Should the program run under optirun even if Bumblebee server or nvidia card
# is not available?
AllowFallbackToIGC=false


# Driver-specific settings are grouped under [driver-NAME]. The sections are
# parsed if the Driver setting in [bumblebeed] is set to NAME (or if auto-
# detection resolves to NAME).
# PMMethod: method to use for saving power by disabling the nvidia card, valid
# values are: auto - automatically detect which PM method to use
#         bbswitch - new in BB 3, recommended if available
#       switcheroo - vga_switcheroo method, use at your own risk
#             none - disable PM completely
# https://github.com/Bumblebee-Project/Bumblebee/wiki/Comparison-of-PM-methods

## Section with nvidia driver specific options, only parsed if Driver=nvidia
[driver-nvidia]
# Module name to load, defaults to Driver if empty or unset
KernelDriver=nvidia
PMMethod=auto
# colon-separated path to the nvidia libraries
LibraryPath=/usr/lib/x86_64-linux-gnu/nvidia/xorg:/usr/lib32/nvidia-current:/usr/lib/x86_64-linux-gnu
# comma-separated path of the directory containing nvidia_drv.so and the
# default Xorg modules path
XorgModulePath=/usr/lib/x86_64-linux-gnu/nvidia/xorg,/usr/lib/xorg/modules
XorgConfFile=/etc/bumblebee/xorg.conf.nvidia

## Section with nouveau driver specific options, only parsed if Driver=nouveau
[driver-nouveau]
KernelDriver=nouveau
PMMethod=auto
XorgConfFile=/etc/bumblebee/xorg.conf.nouveau

That’s it…

John “God help you if you use this” Hass

One other thing to mention.. I love Linux, i have made a career with it. So the views on Linux I expressed early on are jokes.
Except for anything to have to do with Lenovo, they make pieces of shit that masquerade as business class computers, I don’t pull out the big guns all that often, but fuck you Lenovo.
everyone tweet this article @lenvosupport tell them @johnjhass sent you!

Credits:

https://jpamills.wordpress.com/2017/03/18/hotplug-support-for-egpu-on-linux/
https://egpu.io/forums/

And credit for Lenovo being a piece of shit:
https://forums.lenovo.com/t5/Other-Linux-Discussions/Linux-support-for-WWAN-LTE-L850-GL-on-T580-T480/td-p/4067969