On Wed, Nov 7, 2012 at 12:28 AM, Bjørn Mork <[email protected]> wrote:
> Linus Walleij <[email protected]> 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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html