On Tue, Nov 20, 2012 at 7:26 PM, Peter Stuge <peter@xxxxxxxx> wrote: > Windows requests the 0xee string descriptor from *every* device, > unless the same vid and pid has been seen before on the system. I had no clue about that... have you seen this from USB traces? I have seen devices crash when 0xee is requested, but it might be that we're clearing the stall in the wrong way when it's not there. I was certainly under the impression that Windows does not do this for devices it has seen before... >> it turns out that users want MTP devices to "just work" >> just like they "just work" on Windows. > > IMHO there's no other way to accomplish that other than to implement > Microsoft's "extension" to USB; always request the 0xee string > descriptor if the vidpid has not been seen before. So currently we're doing this (using udev and the small program mtp-probe, with the additional restriction that it will only be done on devices that exhibit an interface that can be MTP (1 BULK IN, 1 BULK OUT, 1 INTERRUPT IN). We could do it for all devices but it might be that we're doing something wrong with libusb so that several devices crash when doing this. Currently we do it like this: /* Read the special descriptor */ ret = libusb_get_descriptor(devh, 0x03, 0xee, buf, sizeof(buf)); /* * If something failed we're probably stalled to we need * to clear the stall off the endpoint and say this is not * MTP. */ if (ret < 0) { /* EP0 is the default control endpoint */ libusb_clear_halt (devh, 0); libusb_close(devh); return 0; } // Dump it, if requested if (dumpfile != NULL && ret > 0) { fprintf(dumpfile, "Microsoft device descriptor 0xee:\n"); data_dump_ascii(dumpfile, buf, ret, 16); } /* Check if descriptor length is at least 10 bytes */ if (ret < 10) { libusb_close(devh); return 0; } /* Check if this device has a Microsoft Descriptor */ if (!((buf[2] == 'M') && (buf[4] == 'S') && (buf[6] == 'F') && (buf[8] == 'T'))) { libusb_close(devh); return 0; } /* Check if device responds to control message 1 or if there is an error */ cmd = buf[16]; ret = libusb_control_transfer (devh, LIBUSB_ENDPOINT_IN | LIBUSB_RECIPIENT_DEVICE | LIBUSB_REQUEST_TYPE_VENDOR, cmd, 0, 4, buf, sizeof(buf), USB_TIMEOUT_DEFAULT); // Dump it, if requested if (dumpfile != NULL && ret > 0) { fprintf(dumpfile, "Microsoft device response to control message 1, CMD 0x%02x:\n", cmd); data_dump_ascii(dumpfile, buf, ret, 16); } /* If this is true, the device either isn't MTP or there was an error */ if (ret <= 0x15) { /* TODO: If there was an error, flag it and let the user know somehow */ /* if(ret == -1) {} */ libusb_close(devh); return 0; } /* Check if device is MTP or if it is something like a USB Mass Storage device with Janus DRM support */ if ((buf[0x12] != 'M') || (buf[0x13] != 'T') || (buf[0x14] != 'P')) { libusb_close(devh); return 0; } /* After this point we are probably dealing with an MTP device */ > It would mean that Linux systems must start keeping track of every > device that a system has seen. It's atrocious. > > But I don't think there's another way. Of course, it could be part of > a non-core package, so that only when the MTP software is installed > will there be some database. This is how it works today. The probing comes with libmtp, which also provide the udev rules and thus notify userspace that listen to the udev events. > For most (I'm not sure I dare say all) other devices, it would add no > value on Linux. I fully agree ... well, Microsoft actually intended the device descriptor to be used also for things like WiFi and Bluetooth but it seems they never did that. I have some vague indications that their DRM system for USB mass storage is also using the special 0xee descriptor to identify devices with such capabilities, but I have no clue as to how this actually works. (You can see this from the above code: we need to check that the returned descriptor actually start with "MTP", it *could* say something else...) > When a vidpid is attached which has never been seen on the system, > Windows adds lots of values to the registry saying it has now seen > this device, and then asks for the 0xee string descriptor. > > When a vidpid is attached which *has* been seen on this system > (Windows looks for those values) the string descriptor is not > requested. > > End result: A given device only ever crashes exactly once on a given > Windows system. Yep this is as far as I've understood as well. But now you're contradicting the first paragraph of your mail, so which one is it? >> But they have this concept of an .inf file, so the first time >> you insert an alien device, you are asked for an .inf file >> with some driver information. Then you can bind that >> VID+PID to a specific driver, and then they will not look >> further the next time the same device is plugged in again. >> They will just load the driver given from the .inf file. > > Note that everything in the .inf gets stored in the registry. > Noone looks at the .inf again, once the driver has been installed. OK got it. >> So I could mimic this by starting to cache away any >> successfully initiated MTP devices in some /var/libmtp >> file and just OK them the next time they are plugged in. > > You'll have to cache *every* device, so that you do not make a given > device crash more than once, like Windows. Hm, need to figure out how to do this then... Thanks, Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html