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