Re: autodetect USB MTP device characteristics without libusb_open()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Linus Walleij <linus.walleij@xxxxxxxxxx> writes:

> Hi,
>
> we had the following problem in libmtp:
>
> - We have to autoprobe every plugged-in device to figure out if it is
>   MTP or not. These devices are numerous and we can no longer
>   count on users reporting each and every VID+PID out there
>
> - Class codes cannot be used

Excuse my lack of knowlegde here, but I have to ask why that is?

I looked briefly at the MTP v1.1 spec from
http://www.usb.org/developers/devclass_docs/MTPv1_1.zip , which I have
to admit is one odd USB class specification, not listing any USB
descriptor requirements at all. But it does point to the PTP class spec,
although the language is... well...  I've never seen anything like it in
any standard of any kind before:

<quote>
 1.5 PTP Compatibility

 This protocol is implemented as an extension of the existing Picture
 Transfer Protocol, as defined by the ISO 15740 specification
 (http://www.iso.org/iso/en/CatalogueDetailPage.CatalogueDetail?CSNUMBER=37445&;
 ICS1=37&ICS2=40&ICS3=99). MTP is intended to co-exist with and not
 overlap PTP functionality, and it is hoped that devices will be
 developed to comply fully with the PTP specification where possible to
 leverage the existing base of PTP-enabled devices and applications.
</quote>


"it is hoped that devices will be" - you gotta love that in a standard
:-)


Anyway, I would believe that the above gives reason to expect devices
(new and unknown ones at least) to conform to the PTP class
specification.  Which is available from
http://www.usb.org/developers/devclass_docs/usb_still_img10.zip

This means that any MTP interfaces should use "Cls=06 Sub=01 Prot=01".
Do they not?  At least the only sample I've got available here does:

T:  Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#=  8 Spd=480  MxCh= 0
D:  Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
P:  Vendor=04e8 ProdID=6860 Rev= 4.00
S:  Manufacturer=SAMSUNG
S:  Product=SAMSUNG_Android
S:  SerialNumber=foo
C:* #Ifs= 4 Cfg#= 1 Atr=c0 MxPwr= 96mA
A:  FirstIf#= 1 IfCount= 2 Cls=02(comm.) Sub=02 Prot=01
I:* If#= 0 Alt= 0 #EPs= 3 Cls=06(still) Sub=01 Prot=01 Driver=(none)
E:  Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=125us
E:  Ad=83(I) Atr=03(Int.) MxPS=  28 Ivl=4ms
I:* If#= 1 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=02 Prot=01 Driver=cdc_acm
E:  Ad=86(I) Atr=03(Int.) MxPS=  10 Ivl=32ms
I:* If#= 2 Alt= 0 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=cdc_acm
E:  Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:* If#= 3 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=(none)
E:  Ad=88(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=07(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms


I realize that you still have to probe to find out whether it supports
MTP or just PTP, but won't it help if this probing could be limited to
only 06/01/01 interfaces?  Possibly with an additional whitelist of
known exceptions based on your current device list.

> - Have to look for devices with interfaces with certain endpoints:
>   - 1 BULK in
>   - 1 BULK out
>   - 1 INTERRUPT in

This seems to be a requirement of the PTP spec.  Verifying it is of
course a good idea, but just looking for this endpoint configuration and
ignoring class codes will give a number of false positives.  Are you
sure that probing all of them really is necessary?

> - Then we do deeper probing.
>
> - However some devices bug out on libusb_open() which is in turn
>   needed to use libusb to figure out if the interface has these
>   BULK and INTERRUPT characteristics

I do not understand how that can happen.  There is absolutely no device
interaction required for libusb_open and configuration descriptor
parsing.  To be absolutely sure, I just tested with this small program
while using usbmon to snoop:

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <libusb.h>
#include <linux/types.h>

int main(int argc, char *argv[])
{
	libusb_device_handle *handle;
	libusb_device *dev;
	struct libusb_config_descriptor *config;
	uint16_t vendor_id = 0, product_id = 0;
	int i, j;

	if ((argc != 2) ||
	    (sscanf(argv[1], " %hx : %hx ", &vendor_id, &product_id) != 2) ||
	    (vendor_id == 0) || (product_id == 0)) {
		fprintf(stderr, "Usage: %s vid:pid\n\n", argv[0]);
		return 0;
	}

	libusb_init(NULL);
	handle = libusb_open_device_with_vid_pid(NULL, vendor_id, product_id);
	dev = libusb_get_device(handle);
	if (!dev) {
		fprintf(stderr, "cannot get device\n");
		goto err;
	}

	if (libusb_get_active_config_descriptor(dev, &config)) {
		fprintf(stderr, "cannot get config descriptor\n");
		goto err;
	}
		

	for (i = 0; i < config->bNumInterfaces; i++) {
		const struct libusb_interface_descriptor *d = config->interface[i].altsetting;

		printf("%02x: endpoints=%u, %02x/%02x/%02x\n",
		       d->bInterfaceNumber, d->bNumEndpoints, d->bInterfaceClass, d->bInterfaceSubClass, d->bInterfaceProtocol);
		for (j = 0; j < d->bNumEndpoints; j++) {
			const struct libusb_endpoint_descriptor *e = &d->endpoint[j];

			printf("  %u: address=%02x, attrs=%02x\n", j, e->bEndpointAddress, e->bmAttributes);
		}			
	}		
	libusb_free_config_descriptor(config);
err:
	libusb_close(handle);
	libusb_exit(NULL);
	return 0;
}


There was no USB traffic whatsoever triggered by this, as expected.


> So since I cannot use libusb_open() I have added code like below
> to libmtp to instead inspect sysfs *before* starting any libusb-based
> business. It is run from udev and udev provides the sysfs node and
> that is passed to check_sysfs().
>
> So:
>
> - Is this a good idea?
>
> - What is the scary business that libusb_open() does that makes
>   a lot of substandard USB devices totally freak out?

This should be debugged further.  There must be something else going on
here.  If this was true, then running lsusb would be enough to freak out
these devices.  I just don't buy that.


Bjørn
--
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


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux