Hello,
This script is a workaround for saving the USB Passthrough configuration which gets over-riden on XCP-ng updates (known issue).
The script was earlier removed as per request of stormi in the interest of not overburdening our lovely devs at Vates, but I added it back seeing many people are affected; for helping a greater set of the community.
Disclaimer:
This script is made as a workaround to prevent usb-policy.conf from getting overridden by new patches/restarts.
WARNING: Please note that issues caused by this script (if any) shall not be covered by the XCP-NG Support team.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Testing Status:
- XCP-ng version 8.3 - Tested & Working.
- XCP-ng version 8.2 - Untested. (Should Work)
- Other versions - Completely Untested. Do not use unless you know what you are doing !
Instructions for Install :
- Please Copy and Save this script as install_usb_passthrough.sh
- You can either add your settings by editing this file or change it later.
- Run
chmod +x install_usb_passthrough.sh
- Run
./install_usb_passthrough.sh
Instructions for Usage :
- Change /opt/usb_passthrough_conf/usb-policy.conf as per your configuration.
- Run the included
.sh script (placed in the above directory) or Re-boot for effect.
- You configuration will survive on every re-boot/update.
Instructions for Un-Installation/Removal :
- Run the originally saved
install_usb_passthrough.sh with --remove as parameter to completely uninstall the program. (It leaves no 'residue')
Script version - v2.1
Changelog:
- Saves existing configuration instead of starting from scratch
#!/bin/bash
## This script installs/uninstalls /etc/xensource/usb-policy.conf to be overwritten on every boot
#Variables
DIR=/opt/usb_passthrough_conf
SCRIPT="${DIR}/usb-passthrough-config.sh"
USB_SCAN_LOG="${DIR}/usb-scan.log"
# Declare variables for Cron
cron_remarks="# USB Passthrough Override"
cron_job="@reboot /usr/bin/bash $SCRIPT > /dev/null"
# Get current UUID required for scanning USB devices
CURRENT_UUID=$(grep -i installation_uuid /etc/xensource-inventory | cut -d'=' -f2- | tr -d "'\"")
# Install
if [ "$1" != "--remove" ]; then
# region Install
# Create Directory
echo "Creating Directory ${DIR}"
mkdir -p "$DIR"
# Create Config File
# ^@Edit Config File (only contents, not file-name)
echo "Creating Config File (from existing setup)"
if [ -f /etc/xensource/usb-policy.conf ]; then
cp /etc/xensource/usb-policy.conf "${DIR}/usb-policy.conf"
echo "USB policy created successfully from original setup"
else
cat <<-EOF > "${DIR}/usb-policy.conf"
# When you change this file, run 'xe pusb-scan' to confirm
# the file can be parsed correctly.
# You can also run '/opt/xensource/libexec/usb_scan.py -d' to see
# debug output from the script parsing this configuration file.
#
# Syntax is an ordered list of case insensitive rules where # is line comment
# and each rule is (ALLOW | DENY) : ( match )*
# and each match is (class|subclass|prot|vid|pid|rel) = hex-number
# Maximum hex value for class/subclass/prot is FF, and for vid/pid/rel is FFFF
#
# Rules are ordered so that the first matching rule will override
# any other rules for the device below it
#
# USB Hubs (class 09) are always denied, independently of the rules in this file
DENY: vid=17e9 # All DisplayLink USB displays
DENY: class=02 # Communications and CDC-Control
ALLOW:vid=056a pid=0315 class=03 # Wacom Intuos tablet
ALLOW:vid=056a pid=0314 class=03 # Wacom Intuos tablet
ALLOW:vid=056a pid=00fb class=03 # Wacom DTU tablet
DENY: class=03 subclass=01 prot=01 # HID Boot keyboards
DENY: class=03 subclass=01 prot=02 # HID Boot mice
DENY: class=0a # CDC-Data
DENY: class=0b # Smartcard
DENY: class=e0 # Wireless controller
DENY: class=ef subclass=04 # Miscellaneous network devices
ALLOW: # Otherwise allow everything else
EOF
fi
# Create Script
echo "Creating USB Passthrough script"
cat <<-EOF > "$SCRIPT"
#!/bin/bash
# Script to overwrite usb passthough policy and scan USB devices
# Enable Backup for current config (set to false to disable)
BACKUP_ORIGINAL="true"
# Check if original differs from our config
if ! cmp -s /etc/xensource/usb-policy.conf "${DIR}/usb-policy.conf"; then
# Get current UUID (required for scanning USB devices)
CURRENT_UUID=\$(grep -i installation_uuid /etc/xensource-inventory | cut -d'=' -f2- | tr -d "'\\"")
# Backup current Config file (if backup is enabled)
if [ "\$BACKUP_ORIGINAL" = "true" ]; then
# Files differ - backup original with incremented suffix
i=1
while [ -e "${DIR}/usb-policy\${i}.conf.backup" ]; do
i=\$((i + 1))
done
cp -f /etc/xensource/usb-policy.conf "${DIR}/usb-policy\${i}.conf.backup"
echo "USB PASSTHROUGH: Backed up original config to ${DIR}/usb-policy\${i}.conf.backup"
fi
# Copy User Config to /etc/xensource/usb-policy.conf
cp -f "${DIR}/usb-policy.conf" /etc/xensource/usb-policy.conf
echo "USB PASSTHROUGH: Copied user config to /etc/xensource/usb-policy.conf"
# Scan USB Devices
/opt/xensource/libexec/usb_scan.py -d > "${USB_SCAN_LOG}"
xe pusb-scan host-uuid=\$CURRENT_UUID
else
echo "USB PASSTHROUGH: Config files are the same, skipping..."
fi
EOF
# Make Script executable
chmod +x "$SCRIPT"
# Backup Original File
echo "Backing up original Config"
cp -f /etc/xensource/usb-policy.conf "${DIR}/usb-policy.conf.original"
# Creating Cronjob for running script at every re-start
echo "Installing Cron Job for USB Pass-through"
# Remove existing entries (if any) and re-add to ensure they're consecutive
( crontab -l 2>/dev/null | grep -v -F "$cron_remarks" | grep -v -F "$cron_job"; echo "$cron_remarks"; echo "$cron_job" ) | crontab -
#Create Scan file
touch "$USB_SCAN_LOG"
# Running Script once
echo "Executing USB Passthrough Script"
/usr/bin/bash "$SCRIPT"
# endregion Install
# Uninstall
else
# region Uninstall
# Removing Cron
echo "Removing USB Pass-through cron"
# Remove both entries in one operation
( crontab -l 2>/dev/null | grep -v -F "$cron_remarks" | grep -v -F "$cron_job" ) | crontab -
# Restoring Original File
if [ -e $DIR/usb-policy.conf.original ]; then
cp -f "${DIR}/usb-policy.conf.original" /etc/xensource/usb-policy.conf
echo "Original Config Restored"
else
echo "Original Config not found, skipping..."
fi
# Removing Directory
echo "Removing install directory"
rm -rf "$DIR"
#Restoring Original Scan
/opt/xensource/libexec/usb_scan.py -d > /dev/null
# shellcheck disable=SC2086
xe pusb-scan host-uuid=$CURRENT_UUID
fi
# endregion Uninstall
Script version - v2.0 (tested on XCP-NG 8.3)
Changelog:
- Automatic Change Detection (Only runs when there is a change in configuration.)
- Automatically backs up previous configuration if changed.
- Optimized Code
#!/bin/bash
## This script installs/uninstalls /etc/xensource/usb-policy.conf to be overwritten on every boot
#Variables
DIR=/opt/usb_passthrough_conf
SCRIPT="${DIR}/usb-passthrough-config.sh"
USB_SCAN_LOG="${DIR}/usb-scan.log"
# Declare variables for Cron
cron_remarks="# USB Passthrough Override"
cron_job="@reboot /usr/bin/bash $SCRIPT > /dev/null"
# Get current UUID required for scanning USB devices
CURRENT_UUID=$(grep -i installation_uuid /etc/xensource-inventory | cut -d'=' -f2- | tr -d "'\"")
# Install
if [ "$1" != "--remove" ]; then
# region Install
# Create Directory
echo "Creating Directory ${DIR}"
mkdir -p $DIR
# Create Config File
# ^@Edit Config File (only contents, not file-name)
echo "Creating Config File"
cat <<-EOF > "${DIR}/usb-policy.conf"
# When you change this file, run 'xe pusb-scan' to confirm
# the file can be parsed correctly.
# You can also run '/opt/xensource/libexec/usb_scan.py -d' to see
# debug output from the script parsing this configuration file.
#
# Syntax is an ordered list of case insensitive rules where # is line comment
# and each rule is (ALLOW | DENY) : ( match )*
# and each match is (class|subclass|prot|vid|pid|rel) = hex-number
# Maximum hex value for class/subclass/prot is FF, and for vid/pid/rel is FFFF
#
# Rules are ordered so that the first matching rule will override
# any other rules for the device below it
#
# USB Hubs (class 09) are always denied, independently of the rules in this file
DENY: vid=17e9 # All DisplayLink USB displays
DENY: class=02 # Communications and CDC-Control
ALLOW:vid=056a pid=0315 class=03 # Wacom Intuos tablet
ALLOW:vid=056a pid=0314 class=03 # Wacom Intuos tablet
ALLOW:vid=056a pid=00fb class=03 # Wacom DTU tablet
DENY: class=03 subclass=01 prot=01 # HID Boot keyboards
DENY: class=03 subclass=01 prot=02 # HID Boot mice
DENY: class=0a # CDC-Data
DENY: class=0b # Smartcard
DENY: class=e0 # Wireless controller
DENY: class=ef subclass=04 # Miscellaneous network devices
ALLOW: # Otherwise allow everything else
EOF
# Create Script
echo "Creating USB Passthrough script"
cat <<-EOF > "$SCRIPT"
#!/bin/bash
# Script to overwrite usb passthough policy and scan USB devices
# Enable Backup for current config (set to false to disable)
BACKUP_ORIGINAL="true"
# Check if original differs from our config
if ! cmp -s /etc/xensource/usb-policy.conf "${DIR}/usb-policy.conf"; then
# Get current UUID (required for scanning USB devices)
CURRENT_UUID=\$(grep -i installation_uuid /etc/xensource-inventory | cut -d'=' -f2- | tr -d "'\\"")
# Backup current Config file (if backup is enabled)
if [ "\$BACKUP_ORIGINAL" = "true" ]; then
# Files differ - backup original with incremented suffix
i=1
while [ -e "${DIR}/usb-policy\${i}.conf.backup" ]; do
i=\$((i + 1))
done
cp -f /etc/xensource/usb-policy.conf "${DIR}/usb-policy\${i}.conf.backup"
echo "USB PASSTHROUGH: Backed up original config to ${DIR}/usb-policy\${i}.conf.backup"
fi
# Copy User Config to /etc/xensource/usb-policy.conf
cp -f "${DIR}/usb-policy.conf" /etc/xensource/usb-policy.conf
echo "USB PASSTHROUGH: Copied user config to /etc/xensource/usb-policy.conf"
# Scan USB Devices
/opt/xensource/libexec/usb_scan.py -d > "${USB_SCAN_LOG}"
xe pusb-scan host-uuid=\$CURRENT_UUID
else
echo "USB PASSTHROUGH: Config files are the same, skipping..."
fi
EOF
# Make Script executable
chmod +x "$SCRIPT"
# Backup Original File
echo "Backing up original Config"
cp -f /etc/xensource/usb-policy.conf "${DIR}/usb-policy.conf.original"
# Creating Cronjob for running script at every re-start
echo "Installing Cron Job for USB Pass-through"
# Remove existing entries (if any) and re-add to ensure they're consecutive
( crontab -l 2>/dev/null | grep -v -F "$cron_remarks" | grep -v -F "$cron_job"; echo "$cron_remarks"; echo "$cron_job" ) | crontab -
#Create Scan file
touch "$USB_SCAN_LOG"
# Running Script once
echo "Executing USB Passthrough Script"
/usr/bin/bash "$SCRIPT"
# endregion Install
# Uninstall
else
# region Uninstall
# Removing Cron
echo "Removing USB Pass-through cron"
# Remove both entries in one operation
( crontab -l 2>/dev/null | grep -v -F "$cron_remarks" | grep -v -F "$cron_job" ) | crontab -
# Restoring Original File
if [ -e $DIR/usb-policy.conf.original ]; then
cp -f "${DIR}/usb-policy.conf.original" /etc/xensource/usb-policy.conf
echo "Original Config Restored"
else
echo "Original Config not found, skipping..."
fi
# Removing Directory
echo "Removing install directory"
rm -rf $DIR
#Restoring Original Scan
/opt/xensource/libexec/usb_scan.py -d > /dev/null
# shellcheck disable=SC2086
xe pusb-scan host-uuid=$CURRENT_UUID
fi
# endregion Uninstall