Sample Header Ad - 728x90

Mount MTP devices using systemd

1 vote
1 answer
1443 views
- **Linux**: build based on the Thinstation 6.2 project (on systemd) - **Task**: automatic mounting of MTP devices (namely Android phones) when connected to a thin client - **Problem**: error loading the distribution when the device is connected or incorrect mounting of the device. - **Software used when mounting**: simple-mtpfs , android-file-transfer-linux , android-udev-rules ## The first attempt In rules 51-android.rules , I added the execution of the program in case I connect my phone to a thin client:
...
# Skip other vendor tests
LABEL="android_usb_rule_match"
RUN+="/etc/udev/scripts/mtp.sh"
...
My script /etc/udev/scripts/mtp.sh that performed device mounting when connected:
#!/bin/sh

. /etc/thinstation.env
. $TS_GLOBAL

if [[ $ACTION == "add" ]]; then
    echo "********************* START MOUNT *******************" | systemd-cat -p info -t "mtp"
    /bin/aft-mtp-mount /phone
    grep -oe "/phone" /proc/mounts | systemd-cat -p err -t "mtp"
    ls "/phone/Внутренний общий накопитель" | systemd-cat -p err -t "mtp"
    echo "********************** END MOUNT ********************" | systemd-cat -p info -t "mtp"
elif [[ $ACTION == "remove" ]]; then
    echo "******************** START UNMOUNT ******************" | systemd-cat -p info -t "mtp"
    umount /phone
    echo "********************* END UNMOUNT *******************" | systemd-cat -p info -t "mtp"
fi
*P.S. I use the construction of recording logs as echo ..., since the logger from BusyBox does not write to the log on TS.* I used a logging script to see why my device was NOT mounted. Or rather, it was mounted and after some time fell off, while it was not visible in the system as a mounted device. Googling on the internet, I found information that systemd by default runs systemd-udevd.service with a separate "mount namespace". ## The second attempt I rewrote the rules in 51-android.rules as follows:
...
# Skip other vendor tests
LABEL="android_usb_rule_match"
ACTION=="add", PROGRAM="/bin/aft-mtp-mount -p --template=mtp@.service $env{ID_MODEL}_$env{ID_VENDOR}", ENV{SYSTEMD_WANTS}+="%c"
...
and in /etc/systemd/system/mtp@.service placed the following:
[Service]
Type=oneshot
ExecStart=/etc/udev/scripts/mtp.sh
Accordingly, I rewrote the script /etc/udev/scripts/mtp.sh that would respond only to the add event:
#!/bin/sh

. /etc/thinstation.env
. $TS_GLOBAL

/bin/aft-mtp-mount /phone
It is logical to assume that during testing I unmounted the directory myself, without a script. As a result, the phone was not always connected the first time. It feels like he had some kind of timeout for the connection limit of a few minutes. In the end, I never figured out what the problem was. ## The third attempt My whole process of solving this problem is similar to something similar that is already available on stackoverflow . I tried to reproduce the solution from this post. Corrected the 51-android.rules script in this way:
...
# Skip other vendor tests
LABEL="android_usb_rule_match"
ACTION=="add", RUN+="/bin/systemctl start mtp@$env{ID_VENDOR}_$env{ID_MODEL}_$env{ID_REVISION}.service"
ACTION=="remove", RUN+="/bin/systemctl stop mtp@$env{ID_VENDOR}_$env{ID_MODEL}_$env{ID_REVISION}.service"
...
and in /etc/systemd/system/mtp@.service placed the following:
[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/etc/udev/scripts/mtp.sh add %I
ExecStop=/etc/udev/scripts/mtp.sh remove %I
And the mount execution script /etc/udev/scripts/mtp.sh:
#! /bin/sh

. /etc/thinstation.env
. $TS_GLOBAL

ACTION=$1
DEVICE_NAME=$2
MOUNT=/bin/aft-mtp-mount

CURRENT_DEVICE_MOUNT_PATH=$BASE_MOUNT_PATH/$USB_MOUNT_DIR/$DEVICE_NAME

_logger() {
    echo "$2" | systemd-cat -p $1 -t "mtp"
}

_mounted() {
    if [ -n "$(grep -oe "$1" /proc/mounts)" ]; then
        return 0
    else
        return 1
    fi
}

_mount() {
    _logger info "mount $DEVICE_NAME"
    if [ -d $CURRENT_DEVICE_MOUNT_PATH ] && _mounted $CURRENT_DEVICE_MOUNT_PATH; then
        _logger warning "$DEVICE_NAME already mounted"
        exit 1
    fi
    if [ ! -d $CURRENT_DEVICE_MOUNT_PATH ]; then
        mkdir $CURRENT_DEVICE_MOUNT_PATH
        if is_enabled "$USB_STORAGE_SYNC" && [ ! -n "$(echo $USB_MOUNT_OPTIONS | grep -e sync)" ]; then
            USB_MOUNT_OPTIONS=$USB_MOUNT_OPTIONS,sync
        fi
        $MOUNT -o $USB_MOUNT_OPTIONS $CURRENT_DEVICE_MOUNT_PATH
        if _mounted $CURRENT_DEVICE_MOUNT_PATH && [ "$(ls -A $CURRENT_DEVICE_MOUNT_PATH)" ]; then
            _logger info "mounted $DEVICE_NAME in $CURRENT_DEVICE_MOUNT_PATH"
        else
            _logger warning "$DEVICE_NAME failed to mount"
            _umount
            exit 2
        fi
    else
        _logger warning "$CURRENT_DEVICE_MOUNT_PATH already exists"
        exit 3
    fi
}

_umount() {
    _logger info "unmount $DEVICE_NAME"
    if [[ -d $CURRENT_DEVICE_MOUNT_PATH ]]; then
        while _mounted $CURRENT_DEVICE_MOUNT_PATH; do
            umount $CURRENT_DEVICE_MOUNT_PATH
        done
        _logger info "unmounted $DEVICE_NAME in $CURRENT_DEVICE_MOUNT_PATH"
        rm -r $CURRENT_DEVICE_MOUNT_PATH
    else
        _logger warning "$DEVICE_NAME was not mounted"
    fi
}

if [ $ACTION == "add" ]; then
    _mount
elif [ $ACTION == "remove" ]; then
    _umount
fi

exit 0
Now everything works as it was intended! But there is a nuance. If the phone is initially attached to a thin client during its boot process, the system refuses to turn on. If the phone is disconnected during the boot process, then the thin client loads without problems and mounting also works after connection. It seems that in the process of downloading a thin client, systemd-udevd tries to read the 51-android.rules rules and call the phone mount script, which creates a further problem with loading. I tried to pull out the download data and this is what I saw: Systemd services loading schedule Kernel log I don't understand, maybe I implemented everything incorrectly, or there are some pitfalls. It seems that I tried to try different options. It would be possible to try to mount the device via systemd-mount, but it does not support the MTP protocol to mount it. Or i can somehow implement it by other means? I have not found any additional information on this topic. I ask for help from those who know, since I have reached a dead end on the Arch forum. I have created themes on GitHub , but so far there is no progress either.
Asked by alexanderzhirov (130 rep)
Jan 29, 2023, 03:51 PM
Last activity: Jan 30, 2023, 08:53 AM