Skip to content

Instantly share code, notes, and snippets.

@TheBrokenRail
Last active November 17, 2023 07:51
Show Gist options
  • Save TheBrokenRail/d21ffb0a8cfba3a578f3b5394f47329c to your computer and use it in GitHub Desktop.
Save TheBrokenRail/d21ffb0a8cfba3a578f3b5394f47329c to your computer and use it in GitHub Desktop.
Basic MTP on postmarketOS/PinePhone. (This requires a kernel with FunctionFS!)
#!/bin/sh
set -e
# Install Scripts
install -v -m 755 umtprd-*.sh /usr/libexec
# Install Service
install -v -m 755 umtprd /etc/init.d
rc-update add umtprd
#!/sbin/openrc-run
# Start uMTPRD
command='/usr/libexec/umtprd-run.sh'
supervisor='supervise-daemon'
# Handle Stop
stop_post() {
/usr/libexec/umtprd-cleanup.sh
}
#!/bin/sh
set -e
# Variables
GADGET="/sys/kernel/config/usb_gadget/g1"
# Disable USB Gadget
(echo '' > "${GADGET}/UDC" || :) 2> /dev/null
# Remove Old MTP Function
if [ -d /dev/ffs-mtp ]; then
umount /dev/ffs-mtp || :
rm -rf /dev/ffs-mtp
fi
if [ -d "${GADGET}/functions/ffs.mtp" ]; then
rm -f "${GADGET}/configs/c.1/ffs.mtp"
rm -rf "${GADGET}/functions/ffs.mtp"
fi
# Enable USB Gadget
enable_usb_gadget() {
ls /sys/class/udc > "${GADGET}/UDC"
}
if [ ! -z "${MTP_DELAY_GADGET_ENABLE}" ]; then
enable_usb_gadget_delayed() {
sleep 1
enable_usb_gadget
}
enable_usb_gadget_delayed &
else
enable_usb_gadget
fi
#!/bin/sh
set -e
# Stop Old uMTPRD And Remove Old MTP Function If Needed
MTP_DELAY_GADGET_ENABLE=1 # Wait For uMTPR Before Enabling USB Gadget
. /usr/libexec/umtprd-cleanup.sh
# Find Home
USER_UID=10000 # Assume Main User ID
USER_GID="$(getent passwd "${USER_UID}" | cut -d: -f4)"
USER_NAME="$(getent passwd "${USER_UID}" | cut -d: -f1)"
USER_HOME="$(getent passwd "${USER_UID}" | cut -d: -f6)"
if [ -z "${USER_HOME}" ]; then
echo 'Unable to find main user!'
exit 1
fi
# Add MTP Function
mkdir "${GADGET}/functions/ffs.mtp"
ln -s "${GADGET}/functions/ffs.mtp" "${GADGET}/configs/c.1"
# Mount FunctionFS
mkdir /dev/ffs-mtp
mount -t functionfs mtp /dev/ffs-mtp
# Create uMTPRD Config
rm -rf /etc/umtprd
mkdir /etc/umtprd
tee /etc/umtprd/umtprd.conf > /dev/null <<EOF
loop_on_disconnect 1
default_uid ${USER_UID}
default_gid ${USER_GID}
storage "${USER_HOME}" "Internal Storage" "rw,locked"
manufacturer "$(cat "${GADGET}/strings/0x409/manufacturer")"
product "$(cat "${GADGET}/strings/0x409/product")"
serial "$(cat "${GADGET}/strings/0x409/serialnumber")"
interface "MTP"
usb_vendor_id $(cat "${GADGET}/idVendor")
usb_product_id $(cat "${GADGET}/idProduct")
usb_class 0x6
usb_subclass 0x1
usb_protocol 0x1
usb_dev_version 0x3008
usb_functionfs_mode 0x1
usb_dev_path "/dev/ffs-mtp/ep0"
usb_epin_path "/dev/ffs-mtp/ep1"
usb_epout_path "/dev/ffs-mtp/ep2"
usb_epint_path "/dev/ffs-mtp/ep3
usb_max_packet_size 0x200
EOF
# Autostart Lockscreen Watcher
AUTOSTART="${USER_HOME}/.config/autostart"
sudo -u "${USER_NAME}" mkdir -p "${AUTOSTART}"
sudo -u "${USER_NAME}" tee "${AUTOSTART}/umtprd-watch-lockscreen.desktop" > /dev/null <<EOF
[Desktop Entry]
Name=MTP Lockscreen Watcher
Type=Application
Exec=/usr/libexec/umtprd-watch-lockscreen.sh
StartupNotify=false
NoDisplay=true
X-GNOME-Autostart-Phase=Initialization
X-GNOME-AutoRestart=true
X-KDE-autostart-phase=1
X-KDE-AutostartScript=true
EOF
# Check If MTP Should Be Unlocked
check_if_mtp_is_unlocked() {
sleep 1 # Wait For uMTPR
# Check If The Lockscreen Watcher Is Active
if pidof 'umtprd-watch-lockscreen.sh' > /dev/null; then
# Check The Watcher's Current State
if [ -f "${USER_HOME}/.cache/.mtp-is-unlocked" ]; then
# MTP Should Be Unlocked
umtprd -cmd:unlock
fi
fi
}
check_if_mtp_is_unlocked &
# Run uMTPRD
exec umtprd
#!/bin/sh
set -e
# Lock/Unlock
TRACKING_FILE="${HOME}/.cache/.mtp-is-unlocked"
rm -f "${TRACKING_FILE}"
lock_mtp() {
rm -f "${TRACKING_FILE}"
umtprd -cmd:lock
}
unlock_mtp() {
touch "${TRACKING_FILE}"
umtprd -cmd:unlock
}
# Generic Monitoring Function
watch_lockscreen() {
MODE="$1"
# Get Current State
update_mtp_lock() {
LOCK_STATE="$(dbus-send --session --dest="org.${MODE}.ScreenSaver" --print-reply --type=method_call "/org/${MODE}/ScreenSaver" org.${MODE}.ScreenSaver.GetActive)"
if echo "${LOCK_STATE}" | grep 'boolean false' > /dev/null 2>&1; then
# Screen Unlocked
unlock_mtp
elif echo "${LOCK_STATE}" | grep 'boolean true' > /dev/null 2>&1; then
# Screen Locked
lock_mtp
fi
}
update_mtp_lock
# Monitor For Changes
dbus-monitor --session --profile "type='signal',path='/org/${MODE}/ScreenSaver',interface='org.${MODE}.ScreenSaver',member='ActiveChanged'" |
while read -r LINE; do
if echo "${LINE}" | grep 'ActiveChanged' > /dev/null 2>&1; then
update_mtp_lock
fi
done
}
# KDE
watch_lockscreen_kde() {
# https://github.com/KDE/kscreenlocker/blob/master/dbus/org.freedesktop.ScreenSaver.xml
watch_lockscreen 'freedesktop'
}
# GNOME
watch_lockscreen_gnome() {
# https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/data/dbus-interfaces/org.gnome.ScreenSaver.xml
watch_lockscreen 'gnome'
}
# Fallback
watch_lockscreen_fallback() {
echo 'Unable to determine lockscreen status!'
unlock_mtp
}
# Run
case "${XDG_CURRENT_DESKTOP}" in
*GNOME*) watch_lockscreen_gnome;;
*KDE*) watch_lockscreen_kde;;
*) watch_lockscreen_fallback;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment