1 #include "usb_os_platform.h"
2 
3 #include "usb_list.h"
4 #include "usb_gen_dev_mod.h"
5 #include "usb_host_common.h"
6 
7 
8 
9 
10 /**
11  * usb_match_id - find first usb_device_id matching device or interface
12  * @interface: the interface of interest
13  * @id: array of usb_device_id structures, terminated by zero entry
14  *
15  * usb_match_id searches an array of usb_device_id's and returns
16  * the first one matching the device or interface, or null.
17  * This is used when binding (or rebinding) a driver to an interface.
18  * Most USB device drivers will use this indirectly, through the usb core,
19  * but some layered driver frameworks use it directly.
20  * These device tables are exported with MODULE_DEVICE_TABLE, through
21  * modutils and "modules.usbmap", to support the driver loading
22  * functionality of USB hotplugging.
23  *
24  * What Matches:
25  *
26  * The "match_flags" element in a usb_device_id controls which
27  * members are used.  If the corresponding bit is set, the
28  * value in the device_id must match its corresponding member
29  * in the device or interface descriptor, or else the device_id
30  * does not match.
31  *
32  * "driver_info" is normally used only by device drivers,
33  * but you can create a wildcard "matches anything" usb_device_id
34  * as a driver's "modules.usbmap" entry if you provide an id with
35  * only a nonzero "driver_info" field.  If you do this, the USB device
36  * driver's probe() routine should use additional intelligence to
37  * decide whether to bind to the specified interface.
38  *
39  * What Makes Good usb_device_id Tables:
40  *
41  * The match algorithm is very simple, so that intelligence in
42  * driver selection must come from smart driver id records.
43  * Unless you have good reasons to use another selection policy,
44  * provide match elements only in related groups, and order match
45  * specifiers from specific to general.  Use the macros provided
46  * for that purpose if you can.
47  *
48  * The most specific match specifiers use device descriptor
49  * data.  These are commonly used with product-specific matches;
50  * the USB_DEVICE macro lets you provide vendor and product IDs,
51  * and you can also match against ranges of product revisions.
52  * These are widely used for devices with application or vendor
53  * specific bDeviceClass values.
54  *
55  * Matches based on device class/subclass/protocol specifications
56  * are slightly more general; use the USB_DEVICE_INFO macro, or
57  * its siblings.  These are used with single-function devices
58  * where bDeviceClass doesn't specify that each interface has
59  * its own class.
60  *
61  * Matches based on interface class/subclass/protocol are the
62  * most general; they let drivers bind to any interface on a
63  * multiple-function device.  Use the USB_INTERFACE_INFO
64  * macro, or its siblings, to match class-per-interface style
65  * devices (as recorded in bDeviceClass).
66  *
67  * Within those groups, remember that not all combinations are
68  * meaningful.  For example, don't give a product version range
69  * without vendor and product IDs; or specify a protocol without
70  * its associated class and subclass.
71  */
usb_match_id(struct usb_interface * intf,const struct usb_drv_dev_match_table * id)72 const struct usb_drv_dev_match_table *usb_match_id(struct usb_interface *intf,
73         const struct usb_drv_dev_match_table *id)
74 {
75     struct usb_host_virt_interface *virt_intf = NULL;
76     struct usb_host_virt_dev  *dev = NULL;
77 
78     /* proc_connectinfo in devio.c may call us with id == NULL. */
79     if (id == NULL)
80     {
81         hal_log_err("ERR: usb_match_id: input error");
82         return NULL;
83     }
84 
85     virt_intf = intf->cur_altsetting;
86 
87     if (virt_intf == NULL)
88     {
89         hal_log_err("ERR: usb_match_id: virt_intf == NULL");
90         return NULL;
91     }
92 
93     dev = usb_mod_interface_to_usbdev(intf);
94 
95     if (dev == NULL)
96     {
97         hal_log_err("ERR: usb_match_id: dev == NULL");
98         return NULL;
99     }
100 
101     /* It is important to check that id->driver_info is nonzero,
102        since an entry that is all zeroes except for a nonzero
103        id->driver_info is the way to create an entry that
104        indicates that the driver want to examine every
105        device and interface. */
106     for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass ||
107          id->driver_info; id++)
108     {
109         /*
110                 hal_log_info("usb match id, match_flags = %x, bInterfaceClass= (%x, %x)",
111                            id->match_flags, id->bInterfaceClass,
112                            virt_intf->desc.bInterfaceClass);
113         */
114         if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
115             id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
116         {
117             continue;
118         }
119 
120         if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
121             id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
122         {
123             continue;
124         }
125 
126         /* No need to test id->bcdDevice_lo != 0, since 0 is never
127            greater than any unsigned number. */
128         if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
129             (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
130         {
131             continue;
132         }
133 
134         if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
135             (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
136         {
137             continue;
138         }
139 
140         if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
141             (id->bDeviceClass != dev->descriptor.bDeviceClass))
142         {
143             continue;
144         }
145 
146         if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
147             (id->bDeviceSubClass != dev->descriptor.bDeviceSubClass))
148         {
149             continue;
150         }
151 
152         if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
153             (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
154         {
155             continue;
156         }
157 
158         if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&
159             (id->bInterfaceClass != virt_intf->desc.bInterfaceClass))
160         {
161             continue;
162         }
163 
164         if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) &&
165             (id->bInterfaceSubClass != virt_intf->desc.bInterfaceSubClass))
166         {
167             continue;
168         }
169 
170         if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) &&
171             (id->bInterfaceProtocol != virt_intf->desc.bInterfaceProtocol))
172         {
173             continue;
174         }
175 
176         hal_log_info("usb match id suceessfull");
177         return id;
178     }
179 
180     hal_log_info("usb match id failed, bDeviceClass = %x, bInterfaceClass = %x",
181               dev->descriptor.bDeviceClass, virt_intf->desc.bInterfaceClass);
182     return NULL;
183 }
184 
185 
186