MTP on mainline devices with uMTP-Responder

  • This is my :wq (save and quit current task)

    I've managed to get MTP running on the PinePhone with manual steps. These steps could be roughly copied for other mainline devices. However, I'll note why that shouldn't be done in the problems section below.

    How to

    First, required kernel configs:


    Then, install the umtp-responder daemon from the UBports repositories:

    sudo ubports-qa install xenial_-_umtpr
    sudo apt install umtp-responder

    Then put the following Upstart config at /etc/init/umtpr.conf:

    exec /usr/bin/umtprd
    pre-start script
        mkdir -p "$MTPHOME"
        mkdir -p "$MTPEXTERNALSTORAGE"
        for PERMITTEDDIRECTORY in Documents Downloads Music Pictures Videos; do
            mkdir -p "${MTPDIR}"
            mount --bind "/home/phablet/${PERMITTEDDIRECTORY}/" "${MTPDIR}"
        chown phablet:phablet /run/umtpr/
    end script
    post-stop script
        umount /run/umtpr/*/*/ || true
        rmdir /run/umtpr/*/*/
        rmdir /run/umtpr/*/
        rmdir /run/umtpr/
    end script

    Add a working configuration for the A64:

    # uMTP Responder config file
    # Must be copied to /etc/umtprd/umtprd.conf
    loop_on_disconnect 0
    storage "/run/umtpr/phablet" "Internal Storage" "rw"
    storage "/run/umtpr/sd" "SD Card" "rw"
    manufacturer "Pine64"
    product "PinePhone"
    serial "01234567"
    interface "MTP"
    usb_vendor_id  0x1D6B # Linux Foundation
    usb_product_id 0x0100 # PTP Gadget
    usb_class 0x6         # Image
    usb_subclass 0x1      # Still Imaging device
    usb_protocol 0x1      #
    usb_dev_version 0x3008
    # USB gadget device driver path
    usb_functionfs_mode 0x0
    usb_dev_path   "/dev/gadget/musb-hdrc"
    usb_epin_path  "/dev/gadget/ep1in"
    usb_epout_path "/dev/gadget/ep2out"
    usb_epint_path "/dev/gadget/ep2in"
    # Max USB packet size
    usb_max_packet_size 0x200

    Mount gadgetfs where uMTPr expects it:

    modprobe gadgetfs
    mkdir /dev/gadget
    mount -t gadgetfs gadgetfs /dev/gadget/

    Plug your PinePhone in with USB and start uMTPr:

    sudo start umtpr

    The problems

    While uMTPr works okay, there are some remaining questions:

    How do we automatically start it at the right time?

    On Android devices, the MTP connection is not established until USB is plugged in and the device is unlocked. The connection is then maintained until USB is disconnected. After this, both conditions must be met again for the MTP connection to restart.

    Stopping uMTPr is not a problem. When it detects a USB disconnect, it shuts itself down. On the PinePhone, the disconnect occurs on the next reconnection of USB. That's strange, but probably a small bug that could be fixed by using ConfigFS or looking into GadgetFS a bit more in-depth.

    There is a separate discussion whether MTP should be connected whenever the device is unlocked... it'd be better to put another user action between unlocking and USB connecting, like tapping a notification or changing a setting. I don't think we should have that discussion now.

    Is uMTPr the best option?

    Probably. However, there are other options for mainline devices:

    1. Forward-port and maintain the Linaro MTP configfs gadget in newer Linux kernels. Then, modify our MTP server so it does not use Android properties to detect USB plugging and unplugging.
    2. Use Nokia's (now Mer's [Now Sailfish's]) buteo-mtp. This is an MTP responder based on the Sailfish stack. We use buteo-syncfw and msyncd, which buteo-mtp depends on, already. However, buteo-mtp also depends on Sailfish's thumbnailer service, Qt5Sparql, and something called mlite5.
    3. Use Collabora's fork of Tizen's MTP responder, cmtp-responder. I haven't done much research on it. I saw that the project has been relatively silent since June 2019 and passed over.

    I'm not sure what's correct yet. If anyone has experience with any of these, I'd appreciate some help. Otherwise, I'll be coming back to it in due time.

Log in to reply