2

I am trying to connect an android device to a (Windows 7 64bit) PC via cable, and then to retrieve some files from android to pc programmatically.

(Note: I need this for a specific device, Moverio BT-200, and I am having drivers issues with that; so please don't suggest to use adb ;-) I know that's the easy and fast way, but it's not feasible)

I have found that my device can be seen as a Windows Portable Device (WPD). I found some really good code examples in C# that enables me to detect WPDs, to enumerate their contents, and to transfer the contents. I also found some code in C++, which does all of the above and much more. All of this examples works like a charm as long as I connect a single sdcard, or a usb key (that is: as long as I have a device which gets recognized by Windows and gets a letter as a proper drive), and I get a full list of the present files, with their absolute paths. However, if I try to connect an android devices, and to list the contents, I get something that I do not understand:

embt2
SD Card
o15F9A
o15F9B
o15F9C
o15F9D
o15F9E
...etc
Internal Storage
o1
o2
o3
o4
o5
o6
oD1F
oD20
oD24
o7
o8
o1E78
o9
...etc

How can that be? Browsing the C# code (second link, above), I found that at some points, the code creates several GUID objects, each with some slightly different parameters:

// Identify the property to retrieve
var property = new _tagpropertykey();
property.fmtid = new Guid(0x26D4979A, 0xE643, 0x4626, 0x9E, 0x2B,
                                      0x73, 0x6D, 0xC0, 0xC9, 0x2F, 0xDC);
property.pid = 12;

[...]

// Get the name of the object
string name;
var property = new _tagpropertykey();
property.fmtid = new Guid(0xEF6B490D, 0x5CD8, 0x437A, 0xAF, 0xFC,
                                  0xDA, 0x8B, 0x60, 0xEE, 0x4A, 0x3C);
property.pid = 4;

[...]

// Get the type of the object
property = new _tagpropertykey();
property.fmtid = new Guid(0xEF6B490D, 0x5CD8, 0x437A, 0xAF, 0xFC,
                                  0xDA, 0x8B, 0x60, 0xEE, 0x4A, 0x3C);
property.pid = 7;

[...]

var folderType = new Guid(0x27E2E392, 0xA111, 0x48E0, 0xAB, 0x0C,
                                  0xE1, 0x77, 0x05, 0xA0, 0x5F, 0x85);
var functionalType = new Guid(0x99ED0160, 0x17FF, 0x4C44, 0x9D, 0x98,
                                      0x1D, 0x7A, 0x6F, 0x94, 0x19, 0x21);

But I couldn't figure out how these exadecimal values work. The documentation online seems scarce. I found my device guid with the Device Manager ({eec5ad98-8080-425f-922a-dabf3de3f69a} ), but everytime I tried to replace one of these guid with my own, I got a COMException.

Am I looking in the right place? Do I need to set some GUID, or something else?

I am tagging this question as C# and C++ because I found some code examples in these two languages, but I am willing to solve the problem in any language (java, python, ... )

ocramot
  • 1,361
  • 28
  • 55
  • I don't think the shown code could compile since it redeclares the name `property`. Anyway it just creates `Guid` objects. Read up on GUIDs in Wikipedia. – Cheers and hth. - Alf May 09 '15 at 09:01
  • @Cheers It is not the exact code: I just copy-pasted together chunks of code coming from different places in the original project. Read the second link for complete explanation. (and yes, it would compile, since this exact piece of code as it is, is just overwriting the same variable). And I really don't think that the Wikipedia page could solve my problem. All the GUID stuff was a guess of mine, I'm not sure my problem is there. – ocramot May 09 '15 at 10:27
  • * it would compile if it wasn't for the multiple "var". My bad. – ocramot May 09 '15 at 10:33

2 Answers2

3

For the record, I ended up using some horrible hack for solving my problem. Since I know the path where are stored the files I'm looking for, I used the function EnumerateContent from Christophe Geer's blog, and modified to check if current folder has the name I'm looking for:

If, for example, the files I'm interested in are in the Sd Card/path/to/directory/, then I adapted the code like this: instead of calling the method EnumerateContents, I call the method EnumerateContentsInTargetDirectory:

private static void EnumerateContentsInTargetDirectory(ref IPortableDeviceContent content, PortableDeviceFolder parent)
{
    // Get the properties of the object
    IPortableDeviceProperties properties;
    content.Properties(out properties);

    // Enumerate the items contained by the current object
    IEnumPortableDeviceObjectIDs objectIds;
    content.EnumObjects(0, parent.Id, null, out objectIds);

    uint fetched = 0;
    do
    {
        string objectId;

        objectIds.Next(1, out objectId, ref fetched);
        if (fetched > 0)
        {
            var currentObject = WrapObject(properties, objectId);

            if (currentObject is PortableDeviceFolder)
            {
                if (currentObject.Name.Equals("SD Card") || currentObject.Name.Equals("path") || currentObject.Name.Equals("to"))
                {
                    parent.Files.Add(currentObject);
                    EnumerateContentsInTargetDirectory(ref content, (PortableDeviceFolder)currentObject);
                }
                else if (currentObject.Name.Equals("directory"))
                {
                    parent.Files.Add(currentObject);
                    // This is the same original method of Christophe Geer.
                    EnumerateContents(ref content, (PortableDeviceFolder)currentObject);
                }
            }
        }
    } while (fetched > 0);

}

ocramot
  • 1,361
  • 28
  • 55
1

What's with all the weird filenames? The first list you posted with a lot of entries which begin with o followed by a hexadecimal number are the PTP/MTP Unique Item Identifiers which allow you to refer to file items on the remote device. Those are normal and a part of the PTP and MTP protocols, they are one of the many pieces of data that go along with the full item enumeration and file transfer systems in the PTP and MTP protocols.

What's the deal with all the GUIDs and slight variations? This is basically how the USB HID (Hardware Identification) protocol works under the covers - specifically how Microsoft implements it. The GUIDs are Microsoft codes which link to HID paths in the USB drivers, which in-turn make calls to the USB device for information (getting or setting information). Every HID command also uses a PID (Product Identifier) to address a specific location of memory within the HID path or command, so passing different PIDs in the HID commands results in getting/setting different pieces of data on the USB device.

What's a little sad and scary is how Microsoft exposed this very low-level interaction up to high-level engineers and programs. And their documentation really didn't provide much useful background information or explanation for what this stuff is and means. If you'd like more solid example code and background, I'd highly recommend checking out Christophe Geer's blogs about using WPD in C#/.Net - they really helped me out a lot. See his follow-up blog on transferring content for more goodies.

One other piece of advice that may be helpful - you can poke around a whole range of PIDs to see what kind of information is there. Just wrap your peeking and poking in try/catch blocks in case they fail. I built an extra little harness around the code from Christophe Geer that peeks into PIDs 0-31 for all of the HID GUIDs in his examples and found a lot of extra and useful information.

tpartee
  • 548
  • 7
  • 20
  • Hi tpartee, thanks! Your answer didn't really helped me solve my problem, but surely contained a lot of interesting information! (except for the two links. As you may have not noticed, I already linked them by myself, in my initial question ;-) ). Thanks for your time. I already solved with some horrible hack. – ocramot May 05 '16 at 21:44
  • 1
    It makes me sad to admit it but this whole system seems like a horrible hack on Microsoft's part. So anything that gets it working is by necessity going to also be a hack. ;) The biggest issue I'm trying to find a workaround for right now is the fact that Windows WPD and WIA only appear to be capable of USB 1.0 speeds - connecting USB 3.0 devices and cables results in no speed improvements. =/ – tpartee May 06 '16 at 00:40