Question

The following snippet is from a pyusb tutuorial. It is being used to find all printers connected :

import usb.core
import usb.util
import sys

class find_class(object):
    def __init__(self, class_):
        self._class = class_
    def __call__(self, device):
        # first, let's check the device
        if device.bDeviceClass == self._class:
            return True
        # ok, transverse all devices to find an
        # interface that matches our class
        for cfg in device:
            # find_descriptor: what's it?
            intf = usb.util.find_descriptor(
                                    cfg,
                                    bInterfaceClass=self._class
                                )
            if intf is not None:
                return True

        return False

printers = usb.core.find(find_all=1, custom_match=find_all(7))

This class seems to have multiple points where it returns a boolean value. How many returns are being sent?

Also I couldn't understand how this code searches all printers connected to the system. Things in this code that escape me are:

  • Is device a list/tuple? If yes, how does this code check all the devices by executing if device.bDeviceClass == self._class: just once?

  • what is happening in this line: self._class = class_

  • why is the class find_class never instantiated in printers = usb.core.find(find_all=1, custom_match=find_all(7))

    If you have worked on pyusb/any usb program, please tell me how.

Was it helpful?

Solution

Is device a list/tuple?

device is a usb.core.Device. Iterating over it yields configurations.

If yes, how does this code check all the devices by executing if device.bDeviceClass == self._class: just once?

It doesn't. You missed the part that says "So, to really find all printers connected to the system, we would need to transverse all configurations, and then all interfaces and check if one of the interfaces has its bInterfaceClass field equal to 7.".

what is happening in this line: self._class = class_

Exactly what it says. It's binding the object in that argument to that attribute. For later use.

why is the class find_class never instantiated in printers = usb.core.find(find_all=1, custom_match=find_all(7))

Because someone had a thinko. That last part should be ...=find_class(7).

OTHER TIPS

Why is the class find_class never instantiated in printers = usb.core.find(find_all=1, custom_match=find_all(7))

In the tutorial you link to you’ll see that it’s a typo. The next line in the tutorial uses correctly custom_match=find_class(7).

What is happening in this line: self._class = class_

In the example here it sets self._class = 7. (Coming from the line find_class(7).) The reason not to use self.class = class is that “class” is a reserved word and would provoke a syntax error. Maybe this would be nicer:

class find_class(object):
    def __init__(self, class_nr):
        self.class_nr = class_nr

Also I couldn't understand how this code searches all printers connected to the system.

As mentioned in the tutorial, usb.core.find() returns the first device found, unless you pass a true value to the find_all argument. – It’s not the code you see that searches for all devices, it’s usb.core.find() which does. – It also answers the next question:

Is device a list/tuple?

No.

This class seems to have multiple points where it returns a boolean value. How many returns are being sent?

The __call__() is called for each device usb.core.find() finds. The device is passed in device. __call__() will return only once for each call (obviously). How many times it is called depends on the devices found in the system.

The loop you find in there is for a single device only! The custom search is happy (in this case) if the device is class 7 or any of it’s configurations has an interface with class 7.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top