Phone support (MTP) on Haiku

Just stating that I’m coding a c++ self contained (only libusb dependant) small code to interact with phones, through the MTP protocol in Haiku which is already in alpha status (improving & cleaning code status).

I know that there are other tools for the protocol (aka the non-working-in-haiku-for-my-phone libmtp), but I’m still working on this personal implementation of the MTP1.1 spec for the client, with a crossplatform environment from Linux (as i check this code for memory leaks and so).

I plan to let it be a CLI exe + library that you can just call from scripts, or whatever need that arises. Later a GUI or Tracker integration may be done by anyone to ease the handling of phone contents.

Here is what’s shown now if I connect my Huawei phone to Haiku (VM) and run the code:

Side note: seems like the MTP storage data doesnt really match Android free storage size tho. Guess it exports what it wants :man_shrugging: .

Ideas, suggestions, comments and critics are very welcome.

15 Likes

Nice!

I wonder if it would be possible to get it to work also with iOS devices. A quick search on Google shows that there is something for Linux called ifuse:

http://manpages.ubuntu.com/manpages/xenial/man1/ifuse.1.html

Not sure if it still works and if it would be easy to port for Haiku.

If the iOS devices support the MTP protocol, which i dont know but seems to be the case, this will work as well (it is supposedly designed as vendor/hardware independant). Meaning there is no need to code drivers per phone.

I dont have a iOS phone/device to check tho.if you have one, and dare to try, you could when i code the mtp usb finder part to scan for devices. I have it harcoded for my huawei right now.

Will improve this and test with my other android phones + windows phone.

Yes, our userlandfs can load Haiku specific filesystem modules, but also FUSE ones. There may be compatibility problems (we dont use this often enough yet), but we can fix the bugs!

3 Likes

ready to help in testing the CLI code with my iPhone :slight_smile:

1 Like

Not sure if they support MTP, but I will be willing to test it and find out.

This may bring some aditinal light over this subject:
https://www.dedoimedo.com/computers/linux-iphone-6.html

1 Like

If you (or @TheClue) can plug a iOS device on Haiku, set it to share files through usb (if the options exists like in android) and run this commands:

listusb

listusb  -v /dev/bus/usb/YOURIPHONEBUSFROMABOVE

And give me the outcome for the second command, i can see if the usb configuration for the iOS devices matches Android one, before you having to test the CLI or any source.

That would be much faster, as I’m already coding the device scanning/filter from the present usb devices on the system.

Also, from past experiences with propietary mobiles (Microsoft Kin Two), MTP specific vendor extensions may be implemented apart from the standard ones, so Apple may use them to do cryptographic handshake before enabling read/write operations on the device files (iTunes would do them when you plug the device).

So interactions with this library would be pretty much limited to say “hi!” and so in that case.

Not really sure about how to enable the selecting device to mount part yet, but fuse + a wrapper to this may do the trick to have Tracker support. May have a extra bit of work, since the protocol doesnt work with files but “objects”, and the file transfer have more phases than a normal FS.

Also, i’m thinking that there may be some “bug” on the libusb interaction with Haiku usb stack for one of the devices in my virtual machine, or some “os error” (take this with a grain of salt), because when listing devices by code, the app gets frozen on haiku, while it works on other OS :thinking: Gotta check where and try to solve it.

Seems like the problem is located when calling libusb_get_string_descriptor_ascii for the product name on VMWare Hub / Usb mouse on Haiku, oops.

I don’t think iOS devices have such thing as a MTP configuration. I will try to do the listusb when I get near the Mac, if no one publishes one here.

So, here it goes list usb for iPhone 7:

05ac:1000 /dev/bus/usb/0/0 "Apple, Inc." "Bluetooth HCI MacBookPro (HID mode)" ver. 1965
0000:0000 /dev/bus/usb/0/hub "HAIKU Inc." "UHCI RootHub" ver. 0110
0000:0000 /dev/bus/usb/1/hub "HAIKU Inc." "UHCI RootHub" ver. 0110
0000:0000 /dev/bus/usb/2/hub "HAIKU Inc." "UHCI RootHub" ver. 0110
0000:0000 /dev/bus/usb/3/hub "HAIKU Inc." "UHCI RootHub" ver. 0110
05ac:8242 /dev/bus/usb/4/0 "Apple, Inc." "Built-in IR Receiver" ver. 0016
05ac:021b /dev/bus/usb/4/1 "Apple, Inc." "Internal Keyboard/Trackpad (ISO)" ver. 0018
0000:0000 /dev/bus/usb/4/hub "HAIKU Inc." "UHCI RootHub" ver. 0110
0000:0000 /dev/bus/usb/5/hub "HAIKU Inc." "EHCI RootHub" ver. 0200
05ac:12a8 /dev/bus/usb/6/0 "Apple, Inc." "iPhone5/5C/5S/6" ver. 0903
05ac:8502 /dev/bus/usb/6/3 "Apple, Inc." "Built-in iSight" ver. 0155
0000:0000 /dev/bus/usb/6/hub "HAIKU Inc." "EHCI RootHub" ver. 0200

And listusb -v for the iPhone line:

[Device /dev/bus/usb/6/0]
    Class .................. 0x00 (Per-interface classes)
    Subclass ............... 0x00
    Protocol ............... 0x00
    Max Endpoint 0 Packet .. 64
    USB Version ............ 2.0
    Vendor ID .............. 0x05ac (Apple, Inc.)
    Product ID ............. 0x12a8 (iPhone5/5C/5S/6)
    Product Version ........ 0x0903
    Manufacturer String .... ""
    Product String ......... ""
    Serial Number .......... ""
    [Configuration 0]
        Configuration String . ""
        [Interface 0]
            [Alternate 0 active]
                Class .............. 0x06 (Image)
                Subclass ........... 0x01
                Protocol ........... 0x01
                Interface String ... ""
                [Endpoint 0]
                    MaxPacketSize .... 512
                    Interval ......... 0
                    Type ............. Bulk
                    Direction ........ Output
                [Endpoint 1]
                    MaxPacketSize .... 512
                    Interval ......... 0
                    Type ............. Bulk
                    Direction ........ Input
                [Endpoint 2]
                    MaxPacketSize .... 64
                    Interval ......... 10
                    Type ............. Interrupt
                    Direction ........ Input
    [Configuration 1]
        Configuration String . ""
        [Interface 0]
            [Alternate 0 active]
                Class .............. 0x01 (Audio)
                Subclass ........... 0x01
                Protocol ........... 0x00
                Interface String ... ""
                [Descriptor 0]
                    Type .............. 0x24
                    Subtype ........... 0x01 (Header)
                    ADC Release ....... 1.0
                    Total Length ...... 30
                    Interfaces ........ 1, 
                [Descriptor 1]
                    Type .............. 0x24
                    Subtype ........... 0x02 (Input Terminal)
                    Terminal ID ....... 1
                    Terminal Type ..... 0x0201 (Microphone)
                    Associated Terminal 2
                    Nr Channels ....... 2
                    Channel Config .... 0x3
                       Front .......... Left Right 
                    Channel Names ..... 0
                    Terminal .......... 0
                [Descriptor 2]
                    Type .............. 0x24
                    Subtype ........... 0x03 (Output Terminal)
                    Terminal ID ....... 2
                    Terminal Type ..... 0x0101 (USB Streaming)
                    Associated Terminal 1
                    Source ID ......... 1
                    Terminal .......... 0
        [Interface 1]
            [Alternate 0 active]
                Class .............. 0x01 (Audio)
                Subclass ........... 0x02
                Protocol ........... 0x00
                Interface String ... ""
            [Alternate 1]
                Class .............. 0x01 (Audio)
                Subclass ........... 0x02
                Protocol ........... 0x00
                Interface String ... ""
                [Endpoint 0]
                    MaxPacketSize .... 192
                    Interval ......... 4
                    Type ............. Isochronous
                    Direction ........ Input
                [Descriptor 0]
                    Subtype ........... 1 (AS_GENERAL)
                    Terminal link ..... 2
                    Delay ............. 1
                    Format tag ........ 1
                [Descriptor 1]
                    Subtype ........... 2 (FORMAT_TYPE)
                    Format Type ....... 1 (FORMAT_TYPE_I)
                    Channels .......... 2
                    Subframe size ..... 2
                    Bit resoultion .... 16
                    Sampling Freq ..... 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 
                [Descriptor 2]
                    Type .............. 0x25 (CS_ENDPOINT)
                    Subtype ........... 0x01 (EP_GENERAL)
                    Attributes ........ 0x01 Sampling Frequency 
                    Lock Delay Units .. 0 (Undefined)
                    Lock Delay ........ 0
        [Interface 2]
            [Alternate 0 active]
                Class .............. 0x03 (HID)
                Subclass ........... 0x00
                Protocol ........... 0x00
                Interface String ... ""
                [Endpoint 0]
                    MaxPacketSize .... 64
                    Interval ......... 1
                    Type ............. Interrupt
                    Direction ........ Input
                [Descriptor 0]
                    Type ............. 0x21
                    Data ............. 11 01 00 01 22 d0 00 
    [Configuration 2]
        Configuration String . ""
        [Interface 0]
            [Alternate 0 active]
                Class .............. 0x06 (Image)
                Subclass ........... 0x01
                Protocol ........... 0x01
                Interface String ... ""
                [Endpoint 0]
                    MaxPacketSize .... 512
                    Interval ......... 0
                    Type ............. Bulk
                    Direction ........ Output
                [Endpoint 1]
                    MaxPacketSize .... 512
                    Interval ......... 0
                    Type ............. Bulk
                    Direction ........ Input
                [Endpoint 2]
                    MaxPacketSize .... 64
                    Interval ......... 10
                    Type ............. Interrupt
                    Direction ........ Input
        [Interface 1]
            [Alternate 0 active]
                Class .............. 0xff (Vendor specific)
                Subclass ........... 0xfe
                Protocol ........... 0x02
                Interface String ... ""
                [Endpoint 0]
                    MaxPacketSize .... 512
                    Interval ......... 0
                    Type ............. Bulk
                    Direction ........ Output
                [Endpoint 1]
                    MaxPacketSize .... 512
                    Interval ......... 0
                    Type ............. Bulk
                    Direction ........ Input
    [Configuration 3]
        Configuration String . ""
        [Interface 0]
            [Alternate 0 active]
                Class .............. 0x06 (Image)
                Subclass ........... 0x01
                Protocol ........... 0x01
                Interface String ... ""
                [Endpoint 0]
                    MaxPacketSize .... 512
                    Interval ......... 0
                    Type ............. Bulk
                    Direction ........ Output
                [Endpoint 1]
                    MaxPacketSize .... 512
                    Interval ......... 0
                    Type ............. Bulk
                    Direction ........ Input
                [Endpoint 2]
                    MaxPacketSize .... 64
                    Interval ......... 10
                    Type ............. Interrupt
                    Direction ........ Input
        [Interface 1]
            [Alternate 0 active]
                Class .............. 0xff (Vendor specific)
                Subclass ........... 0xfe
                Protocol ........... 0x02
                Interface String ... ""
                [Endpoint 0]
                    MaxPacketSize .... 512
                    Interval ......... 0
                    Type ............. Bulk
                    Direction ........ Output
                [Endpoint 1]
                    MaxPacketSize .... 512
                    Interval ......... 0
                    Type ............. Bulk
                    Direction ........ Input
        [Interface 2]
            [Alternate 0 active]
                Class .............. 0xff (Vendor specific)
                Subclass ........... 0xfd
                Protocol ........... 0x01
                Interface String ... ""
            [Alternate 1]
                Class .............. 0xff (Vendor specific)
                Subclass ........... 0xfd
                Protocol ........... 0x01
                Interface String ... ""
                [Endpoint 0]
                    MaxPacketSize .... 512
                    Interval ......... 0
                    Type ............. Bulk
                    Direction ........ Input
                [Endpoint 1]
                    MaxPacketSize .... 512
                    Interval ......... 0
                    Type ............. Bulk
                    Direction ........ Output
            [Alternate 2]
                Class .............. 0xff (Vendor specific)
                Subclass ........... 0xfd
                Protocol ........... 0x01
                Interface String ... ""
                [Endpoint 0]
                    MaxPacketSize .... 512
                    Interval ......... 0
                    Type ............. Bulk
                    Direction ........ Input
                [Endpoint 1]
                    MaxPacketSize .... 512
                    Interval ......... 0
                    Type ............. Bulk
                    Direction ........ Output

1 Like

Thanks so much, that’s just what i needed.

Seems like there is a mtp possible interface, with… 3 configurations. (the ones that have bulk in, bulk out, and interrupt).

If i am able to either solve or skip the current bug i am having with some usb functions in Haiku, you could test it. Right now it hangs when you send a command and it timeouts (im like… Wtf?)

1 Like

At some point we had a filesystem showing Google Search results as query results in Tracker search dialog, so I’m not worried about the flexibility of our filesystem interface. And if it’s not flexible enough we can always extend it.

Yes, there are or at least were some known issues with the libusb port to Haiku. You may have to dig into the libusb code and make some improvements there.

Good to hear. I’ll develop some ideas on this when the basic stuff works. Most problems would be tied to being designed to be a 1 device to 1 device protocol, so all would have to wait and be locked while you do file transfers and so.

Already in the works, stopped because other reasons and the normal season celebration(s), but yes, i have my customized libusb version from haikuports to fix the problems. Solving that bugs would be a benefict for all, not only this “project”.

I’m pretty sure i can replicate the “unexpected” behavior in a small helloworld sample, so it’s just matter of time and send changes to the upstream code.

2 Likes

After digging and tweaking all the libusb code until I understand what happens under the hood, seems like there’s one background thread in Haiku libusb code that hangs, and i cannot solve it.

From [Libusb github], line 85:

if (ioctl(fRawFD, B_USB_RAW_COMMAND_CONTROL_TRANSFER, &command, sizeof(command)) ||

So this thread get stuck in limbo whenever i access a VMware usb device/hub from Haiku libusb (works ok with real devices & haiku usb devices).

Since i wont probably ever need VmWare hardware to do this, i can use the vmware vendor ID and skip those, but i dont know if this kind of libusb behavior has side effects for future uses (other than mines).

Btw, native usb kit seem to work on getting this info OK, when i call “listusb” with verbose output :thinking:

Any ideas?

Hi,

I wonder how you end up running that code on a vmware device. My understanding is that you would first check to identify if the device is indeed MTP compliant (checking device and/or interface class, or at worse, device and vendor ID), and only then start communicating with the device.

However, there should be a timeout for this if the device does not reply. The native USB kit is not doing things much differently, but it seems the subtle details matter. One could compare libusb and native USBkit by running similar test programs through strace, to see what is different in the called ioctls.

Haiku run in a vmware machine, has exported (At least) 2 virtual devices for hubs. I run the same example that’s provided in libusb examples that dumps a list for all the usb devices present in the system, like haiku listusb -v , and it freezes.

That would be the case, but manufactures dont comply to the interface (usb) class. Huawei phone doesnt for example, stating propietary vendor class (0xFF) where it should be… image (0x06) IIRC.
Note that the libusb example doesnt communicate with the device, apart of sending control transfer requests (ioctl in this case).

There is, in the libusb code, on each synchronous operation. For information requests in control transfers is 1000ms. It is the case of the “bug” on the ioctl that i mentioned, which is called when the timeout happens to handle it, pop from the usb transfer from a queue and so on. But as the background thread hangs, the notification to libusb doesnt happen. I suspect there is some unknown behavior on the vmware machine part, which could be checked against libvirt/qemu or virtualbox.

Guess that’s the only complete option to solve it, thanks for the tips and rethinking.

On my part, I did what i mentioned, ignoring vmware vendor devices, and all was ok, even with “stock” libusb from haikudepot :thinking:

I think listusb will not use raw control transfers, but higher level ioctls, letting the kernel side parts do more of the work. At least getting all descriptors should be possible this way, and I don’t think listusb needs to do any more than that.

I had freezes happen also with other devices, so we are likely doing something out of spec and not handling the problems correctly. The ioctl shound not hang this way, it should timeout eventually, at least.

Oh yeah, my bad. I meant usb transfer of Control type (as in control, bulk/interrupt, isochron.). The library is indeed able to get all the descriptors (hence why I can filter out some vendor by VendorID), and the usb endpoints from there.

With the endpoints you can operate ok. I think i found some “corner cases” like reading from a device endpoint without data available, which has the same behaviour, transfer not being handled ok after cancelling by the timeout.

We’ll figure out with new uses of the lib(s).

Improved the alpha a little:

Added a params lib +usage, plus scan feature:

Added file listing as in ls command:

File download by specifying full path to file (veeeeery time consuming if your folder has a lot of files, like Whatsapp, cause mtp has to poll each file to fetch the name):

File download by handle/object ID, which works much faster because it’s like having a direct access to a file pointer:

No file upload yet :thinking:, still in the works.

Still working with my device & hardcoded values, until I find a way to configure another device easily from the scan values and/or probe devices to ease the process.
Need to polish this a little with other of my devices before involving the iPhones :P.

9 Likes

I created a ticket for the USB stall/freeze: https://dev.haiku-os.org/ticket/14835#ticket

Can you confirm you get the same or a similar error in the syslog when it happens?

Not the same output (that error text / code) iirc, but the same behavior. Frozen status after a cancelled transfer (by timeout).

The libusb debug says that the transfer was cancelled, yet you end in a libusb loop with 60sec timeout.

Gonna redo when nearby my Haiku VM host machine to doublecheck the syslog output.