viveris / uMTP-Responder

Lightweight USB Media Transfer Protocol (MTP) responder daemon for GNU/Linux
GNU General Public License v3.0
192 stars 52 forks source link

Does not work with Linux + MacOS #90

Closed knro closed 2 months ago

knro commented 1 year ago

First of all, thank you for this great project! Setting this up was quite easy. I first tried with GadgetFS and that worked right away, I was able to have the identify the device from both Linux + MacOS, but whenever I started copying files, it would simply timeout (using KDE's Dolphin). When I check the device, I see the file transferred already, but on the client side, it shows a timeout. Afterwards, the device cannot be refreshed at all unless I physically unplug the USB cable.

The same issue can be replicated on both Linux & MacOS. On Windows, it behaves better even though sometimes it also take a very long time to copy a small file. On the server side, I don't really see any errors. So it appears the responder works but fails to transfer any files and fails to browse existing files.

FunctionFS is not any better. To get this to work, I had to compile a custom kernel since FunctionFS has been deprecated (Move to legacy) for quite a while in upstream kernel sources.

jfdelnero commented 1 year ago

Which Linux version and CPU/Soc have you on the device ?

Try to enable this in the config file :

 usb_max_rd_buffer_size 0x200      # MAX usb read size. Must be a multiple of 512 and be less than read_buffer_cache_size
 usb_max_wr_buffer_size 0x200      # MAX usb write size. Must be a multiple of 512.
 read_buffer_cache_size 0x4000     # Read file cache buffer. Must be a 2^x value.

If deprecated what replace FunctionFS ?

knro commented 1 year ago

Thank you, there was a discussion on this issue here https://github.com/raspberrypi/linux/issues/5552

Right now, CONFIG_USB_CONFIGFS_F_FS is apparently used. I don't think works with umtp-responder.

knro commented 1 year ago

It's running on Raspberry PI CM4 with Debian Bullseye. The connection is done via the USB OTG. I tried to apply the setting as you suggested, but it did not make much difference. What I noticed is that umtp gets stuck when writing a file to it. Reading appears to be fine, but after a simple file move is made to umtp, then it gets completely stop and no longer responds. After restart the server, I can see that the file was indeed transferred successfully but for some reason umtp stops responding.

The attached log shows the debug after I initiated the file transfer from the host PC to umtp (on cm4)

umtp.log

knro commented 1 year ago

@jfdelnero Any ideas on what to try next? Not sure what to debug further.

superkeka commented 11 months ago

Same bug. This daemon used by DeckMTP does not work with software such as Android File Transfer or OpenMTP.

jfdelnero commented 10 months ago

I just tried Android File Transfer on macOS High Sierra. It appears to have an issue with the inotify feature and this lock all mtp operations. For the moment uncomment the "no_inotify 0x1" line in the config file to disable it.

jfdelnero commented 10 months ago

Although this doesn't make the event/inotify work properly on Android File Transfer (Is it supported by this software ?), i have just commit some modifications to avoid to lock all the mtp endpoints if the event endpoint is stalled for some reasons. I can now copy files to the device without noticing any slow down or transfer failure. @superkeka @knro

knro commented 10 months ago

That's great news! I will give it a go!

mountainstorm commented 9 months ago

Did you ever get this working? I've built it and got it running on a Raspberry Pi Zero 2W, on macOS appears as a device, but nothing appears to be able to talk to it e.g. ImageCapture.app doesn't show a device, openmtp says no device is attached.

I built with DEBUG=1 and have tried all the cfg options listed above but still no luck. I don't even see and log messages when I try talking to the device

on the Raspberry Pi I see this (started via conf/umtprd-ffs.sh)

[uMTPrd - 06:20:18 - Debug] init_usb_mtp_gadget : USB config done
[uMTPrd - 06:20:18 - Debug] uMTP Responder : FunctionFS Mode - entering handle_ffs_ep0
[uMTPrd - 06:20:18 - Debug] handle_ffs_ep0 : Entering...
[uMTPrd - 06:20:19 - Debug] 1 event(s)
[uMTPrd - 06:20:19 - Debug] EP0 FFS BIND
[uMTPrd - 06:20:19 - Debug] Select without timeout

It's running in the background but I never get anymore log messages

on macOS I see this

% system_profiler SPUSBDataType
USB:

    USB 3.1 Bus:

      Host Controller Driver: AppleT6000USBXHCI

    USB 3.1 Bus:

      Host Controller Driver: AppleT6000USBXHCI

        CSTM Product:

          Product ID: 0x0100
          Vendor ID: 0x1d6b  (The Linux Foundation)
          Version: 6.01
          Serial Number: 01234569
          Speed: Up to 480 Mb/s
          Manufacturer: CSTM Technologies
          Location ID: 0x02100000 / 1
          Current Available (mA): 500
          Current Required (mA): 120
          Extra Operating Current (mA): 0

    USB 3.1 Bus:

      Host Controller Driver: AppleT6000USBXHCI
mountainstorm commented 9 months ago

I've figure out the problem, in src/mtp_operations/mtp_op_getdeviceinfos.c there is this check

    if(!ctx->fs_db)
        return MTP_RESPONSE_SESSION_NOT_OPEN;

But GetDeviceInfo's is allowed before a session is opened. Thus commenting out those lines fixes the problem and makes everything work. Thus if I do the following, the device appears (to macOS) in ImageCapture.app and I can see the root directory.

git clone https://github.com/viveris/uMTP-Responder.git
cd uMTP-Responder/
nano src/mtp_operations/mtp_op_getdeviceinfos.c
<comment out the lines above>
make USE_SYSLOG=1 DEBUG=1
sudo cp conf/umtprd.conf /etc/umtprd/umtprd.conf
sudo cp umtprd /usr/bin/
sudo sh conf/umtprd-ffs.sh
jfdelnero commented 9 months ago

Thanks for pointing this. This is indeed a bug. i will fix this.

As reference here are the specifications about the GetDeviceInfo operation :

GetDeviceInfo (0x1001)

This command retrieves the DeviceInfo data set from the portable media player. This data set contains information, such as model and serial number, to identify the portable device and describe the capabilities of the device.

Typically, GetDeviceInfo is the first command issued by an initiator after connecting to a portable device. GetDeviceInfo is the only command that an initiator can send without first opening an MTP session by sending an OpenSession command.

For more information about the DeviceInfo data set, see section 3.5.1 of the MTP specification, 'DeviceInfo Dataset Description.'

jfdelnero commented 9 months ago

Fix on the master branch.

jfdelnero commented 2 months ago

v1.6.8 released - closing this issue.

Please reopen if you still have issues on macOS.