On Wed, Nov 7, 2012 at 12:28 AM, Bjørn Mork <bj...@mork.no> wrote: > Linus Walleij <linus.wall...@linaro.org> writes:
>> So all MTP devices manufactured before that spec, and numerous produced >> after that spec came out, and several still being produced don't use the >> class code, i.e. they violate the spec. But we still have to detect them >> somehow. > > Yes, I feared so. But it still seemed likely that the non conforming > ones could be managed as a whitelist, if only most of the new ones were > using the standard class codes. I don't know if most of them do actually. Here is another device I bought just the other day, Philips GoGear Vibe: Bus 002 Device 008: ID 0471:20e5 Philips (or NXP) Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.00 bDeviceClass 0 (Defined at Interface level) bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 64 idVendor 0x0471 Philips (or NXP) idProduct 0x20e5 bcdDevice 0.01 iManufacturer 1 Philips iProduct 2 GoGear ViBE iSerial 5 400400009D0CDC190002DCE4AF289C19 bNumConfigurations 2 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 39 bNumInterfaces 1 bConfigurationValue 1 iConfiguration 3 USB/MSC LCD Player bmAttributes 0x80 (Bus Powered) MaxPower 500mA Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 0 bAlternateSetting 0 bNumEndpoints 3 bInterfaceClass 8 Mass Storage bInterfaceSubClass 6 SCSI bInterfaceProtocol 80 Bulk (Zip) iInterface 4 USB/MSC LCD Player Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x02 EP 2 OUT bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x83 EP 3 IN bmAttributes 3 Transfer Type Interrupt Synch Type None Usage Type Data wMaxPacketSize 0x0040 1x 64 bytes bInterval 16 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 39 bNumInterfaces 1 bConfigurationValue 2 iConfiguration 3 USB/MSC LCD Player bmAttributes 0x80 (Bus Powered) MaxPower 100mA Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 0 bAlternateSetting 0 bNumEndpoints 3 bInterfaceClass 8 Mass Storage bInterfaceSubClass 6 SCSI bInterfaceProtocol 80 Bulk (Zip) iInterface 4 USB/MSC LCD Player Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x02 EP 2 OUT bmAttributes 2 Transfer Type Bulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x83 EP 3 IN bmAttributes 3 Transfer Type Interrupt Synch Type None Usage Type Data wMaxPacketSize 0x0040 1x 64 bytes bInterval 16 Device Qualifier (for other device speed): bLength 10 bDescriptorType 6 bcdUSB 2.00 bDeviceClass 0 (Defined at Interface level) bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 64 bNumConfigurations 2 Device Status: 0x0000 (Bus Powered) So two configurations, each with a USB mass storage interface right? Wrong! One of them is an MTP interface, and will respond to MTP traffic. I think the magic OS handshake make that come into play... So Linux erroneously tries to use MSC on it, and we have to use libusb_detach_kernel_driver() and then use the interface. And then it works. This type of misbehaviour is not uncommon, I just took some device at random, there are literally millions of these. >> Here are some device logs I've been collecting: >> http://libmtp.git.sourceforge.net/git/gitweb.cgi?p=libmtp/libmtp;a=tree;f=logs;hb=HEAD > > Thanks. That looks somewhat useful, except that you only seem to > collect the device codes and not the interface codes. Yeah :-/ I admit to being young and foolish ... > I am wondering if > that is much of the problem here? You seem to only look at the device > when in fact most of the new MTP devices are composite devices (phones)? Yes, I'm perhaps not clever enough with my udev rules. It currently looks like this, first the avoidance of unnecessary or dangerous probes, the sensitive devices react to something in our libusb_open() or subsequent stuff to enumerate configs, interfaces, altsettings etc... ACTION!="add", GOTO="libmtp_rules_end" ENV{MAJOR}!="?*", GOTO="libmtp_rules_end" SUBSYSTEM=="usb", GOTO="libmtp_usb_rules" GOTO="libmtp_rules_end" LABEL="libmtp_usb_rules" # Some sensitive devices we surely don't wanna probe # Color instruments ATTR{idVendor}=="0670", GOTO="libmtp_rules_end" ATTR{idVendor}=="0765", GOTO="libmtp_rules_end" ATTR{idVendor}=="085c", GOTO="libmtp_rules_end" ATTR{idVendor}=="0971", GOTO="libmtp_rules_end" # Canon scanners that look like MTP devices (PID 0x22nn) ATTR{idVendor}=="04a9", ATTR{idProduct}=="22*", GOTO="libmtp_rules_end" # Canon digital camera (EOS 3D) that looks like MTP device (PID 0x3113) ATTR{idVendor}=="04a9", ATTR{idProduct}=="3113", GOTO="libmtp_rules_end" # Sensitive Atheros devices that look like MTP devices ATTR{idVendor}=="0cf3", GOTO="libmtp_rules_end" # Sensitive Atmel JTAG programmers ATTR{idVendor}=="03eb", GOTO="libmtp_rules_end" # Creative ZEN Vision ATTR{idVendor}=="041e", ATTR{idProduct}=="411f", SYMLINK+="libmtp-%k", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1" (...) Then follows a long chunk of whitelisted, known MTP players. (...) # Autoprobe vendor-specific, communication and PTP devices ENV{ID_MTP_DEVICE}!="1", ENV{MTP_NO_PROBE}!="1", ENV{COLOR_MEASUREMENT_DEVICE}!="1", ENV{libsane_matched}!="yes", ATTR{bDeviceClass}=="00|02|06|ef|ff", PROGRAM="mtp-probe /sys$env{DEVPATH} $attr{busnum} $attr{devnum}", RESULT=="1", SYMLINK+="libmtp-%k", ENV{ID_MTP_DEVICE}="1", ENV{ID_MEDIA_PLAYER}="1" LABEL="libmtp_rules_end" So that rather horrible rule avoids probing: - Devices we just detected in the whitelist - Color measurement or scanner devices (these have been prone to errors...) - Then check only the classes we mentioned So I guess you're suggesting another step, checking the interfaces? >> bInterfaceClass 0 (Defined at Interface level) >> bInterfaceSubClass 0 >> bInterfaceProtocol 0 >> iInterface 33 MTP Interface > > > Ouch. Yes, not much else to do there than using vid:pid or probing. That's just one way of misbehaving. The other example is actually more scary I think. > Do you know if these early devices support the typical Microsoft > descriptors? I.e. the 0xee string descriptor with "MSFT100<code>" > and its friends? Almost all devices support this. (There are exceptions even to this.) So this is what we do as a last resort, if we can't figure it out some other way. The problem appear when you ask a device which is not MTP for that descriptor, some of them just die, so I cannot do that. But the blacklisted devices at the top of the udev script does not even survive having libusb open the device to check its descriptors, configs, interfaces etc. > I assume even the most buggy devices will survive asking for a string > descriptor... I don't know actually. We have experiences of devices crashing for everything but maybe I'm over-cautious and a bit superstitious... > Sure you can and should check the interface class. Do a > > grep bInterfaceClass /lib/udev/rules.d/* > > and you will hopefully see a couple of examples. OK this is nice. The first example above will totally violate all such rules though (but it will be cought by the whitelist). > And I still wonder about the libusb_open screwing up devices. It does > not touch the device at all. And you can get the configuration > descriptor without communicating with the device. The OS has already > cached that for you. So how come you think libusb_open screws up > anything? If it did, then the device would already be dead when the > Linux USB core enumerated it. Yeah so I'm not sure that is the case, when you push me on this detail... What we do is found here: http://sourceforge.net/p/libmtp/code/ci/5b9bd248fefe6d6243be9649109718760179d9bd/tree/src/libusb1-glue.c Check functions: probe_device_descriptor() LIBMTP_Check_Specific_Device() The latter is called by the udev script to check if a specific device is MTP or not. >> 02 = comms device class, a lot of phones use this >> 06 = yay! PTP yes among others... >> ef = no idea why this is used, but it is > > I assume that is in combination with subclass 02 and protocol 01, which > specifies "Interface Association Descriptor" and will be common for > phones and modems. See > http://www.usb.org/developers/whitepapers/iadclasscode_r10.pdf > > It's just another "unspecified, check interfaces" really. OK I get it ... that's sort of what I thought. > Those are always going to be a problem. But I was hoping they were only > older devices. The rest of your list of device classes should have > meaningful interface class/subclass/protocol codes. Don't they? See example at top (not an old device) :-P >> To check if a device with class 6 is PTP or MTP the only >> trusted way is to open a PTP session and check for a specific >> descriptor actually. > > Yes, that's what I gathered from the MTP spec. > >> Problem: you cannot open a session to >> an MTP device in say a udev script, then close it and open >> another session later, because many devices crash when >> a session is closed. This is of course yet another spec >> violation, but comes from the fact that Windows never >> close sessions, it keeps the device hogged until it's >> plugged out or the host is shut down. > > Nice. But how are you then going to deal with PTP devices crashing? > Blacklist them by vid:pid? Or is this only a problem with MTP devices? I *think* this is a MTP-only problem. The reason is that pure PTP devices are usually cameras, and as such used by Mac OS geeks, i.e. anyone doing a camera will of course test it with a Mac and scream if it doesn't work. And Mac is more strict with it's PTP. But MTP is only supported by Windows and libmtp implementations... and non-Windows doesn't seem to get much exercise. (I have got some mail from Phone manufacturers recently, SONY are notably helpful.) Yours, Linus Walleij -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html