usb_quirk.c revision 200887
1/* $FreeBSD: head/sys/dev/usb/quirk/usb_quirk.c 200887 2009-12-23 01:41:52Z thompsa $ */
2/*-
3 * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
4 * Copyright (c) 1998 Lennart Augustsson. All rights reserved.
5 * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <sys/stdint.h>
30#include <sys/stddef.h>
31#include <sys/param.h>
32#include <sys/queue.h>
33#include <sys/types.h>
34#include <sys/systm.h>
35#include <sys/kernel.h>
36#include <sys/bus.h>
37#include <sys/linker_set.h>
38#include <sys/module.h>
39#include <sys/lock.h>
40#include <sys/mutex.h>
41#include <sys/condvar.h>
42#include <sys/sysctl.h>
43#include <sys/sx.h>
44#include <sys/unistd.h>
45#include <sys/callout.h>
46#include <sys/malloc.h>
47#include <sys/priv.h>
48
49#include <dev/usb/usb.h>
50#include <dev/usb/usb_ioctl.h>
51#include <dev/usb/usbdi.h>
52#include "usbdevs.h"
53
54#define	USB_DEBUG_VAR usb_debug
55#include <dev/usb/usb_debug.h>
56#include <dev/usb/usb_dynamic.h>
57
58#include <dev/usb/quirk/usb_quirk.h>
59
60MODULE_DEPEND(usb_quirk, usb, 1, 1, 1);
61MODULE_VERSION(usb_quirk, 1);
62
63#define	USB_DEV_QUIRKS_MAX 256
64#define	USB_SUB_QUIRKS_MAX 8
65
66struct usb_quirk_entry {
67	uint16_t vid;
68	uint16_t pid;
69	uint16_t lo_rev;
70	uint16_t hi_rev;
71	uint16_t quirks[USB_SUB_QUIRKS_MAX];
72};
73
74static struct mtx usb_quirk_mtx;
75
76#define	USB_QUIRK(v,p,l,h,...) \
77  .vid = (v), .pid = (p), .lo_rev = (l), .hi_rev = (h), .quirks = { __VA_ARGS__ }
78static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
79	{USB_QUIRK(USB_VENDOR_ASUS, USB_PRODUCT_ASUS_LCM,
80	    0x0000, 0xFFFF, UQ_HID_IGNORE)},
81	{USB_QUIRK(USB_VENDOR_INSIDEOUT, USB_PRODUCT_INSIDEOUT_EDGEPORT4,
82	    0x094, 0x094, UQ_SWAP_UNICODE)},
83	{USB_QUIRK(USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_J6502,
84	    0x0a2, 0x0a2, UQ_BAD_ADC)},
85	{USB_QUIRK(USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_J6502,
86	    0x0a2, 0x0a2, UQ_AU_NO_XU)},
87	{USB_QUIRK(USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ADA70,
88	    0x103, 0x103, UQ_BAD_ADC)},
89	{USB_QUIRK(USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ASC495,
90	    0x000, 0x000, UQ_BAD_AUDIO)},
91	{USB_QUIRK(USB_VENDOR_QTRONIX, USB_PRODUCT_QTRONIX_980N,
92	    0x110, 0x110, UQ_SPUR_BUT_UP)},
93	{USB_QUIRK(USB_VENDOR_ALCOR2, USB_PRODUCT_ALCOR2_KBD_HUB,
94	    0x001, 0x001, UQ_SPUR_BUT_UP)},
95	{USB_QUIRK(USB_VENDOR_MCT, USB_PRODUCT_MCT_HUB0100,
96	    0x102, 0x102, UQ_BUS_POWERED)},
97	{USB_QUIRK(USB_VENDOR_MCT, USB_PRODUCT_MCT_USB232,
98	    0x102, 0x102, UQ_BUS_POWERED)},
99	{USB_QUIRK(USB_VENDOR_TI, USB_PRODUCT_TI_UTUSB41,
100	    0x110, 0x110, UQ_POWER_CLAIM)},
101	{USB_QUIRK(USB_VENDOR_TELEX, USB_PRODUCT_TELEX_MIC1,
102	    0x009, 0x009, UQ_AU_NO_FRAC)},
103	{USB_QUIRK(USB_VENDOR_SILICONPORTALS,
104	    USB_PRODUCT_SILICONPORTALS_YAPPHONE,
105	    0x100, 0x100, UQ_AU_INP_ASYNC)},
106	{USB_QUIRK(USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_UN53B,
107	    0x0000, 0xFFFF, UQ_NO_STRINGS)},
108	{USB_QUIRK(USB_VENDOR_ELSA, USB_PRODUCT_ELSA_MODEM1,
109	    0x0000, 0xFFFF, UQ_CFG_INDEX_1)},
110
111	/*
112	 * XXX The following quirks should have a more specific revision
113	 * number:
114	 */
115	{USB_QUIRK(USB_VENDOR_HP, USB_PRODUCT_HP_895C,
116	    0x0000, 0xFFFF, UQ_BROKEN_BIDIR)},
117	{USB_QUIRK(USB_VENDOR_HP, USB_PRODUCT_HP_880C,
118	    0x0000, 0xFFFF, UQ_BROKEN_BIDIR)},
119	{USB_QUIRK(USB_VENDOR_HP, USB_PRODUCT_HP_815C,
120	    0x0000, 0xFFFF, UQ_BROKEN_BIDIR)},
121	{USB_QUIRK(USB_VENDOR_HP, USB_PRODUCT_HP_810C,
122	    0x0000, 0xFFFF, UQ_BROKEN_BIDIR)},
123	{USB_QUIRK(USB_VENDOR_HP, USB_PRODUCT_HP_830C,
124	    0x0000, 0xFFFF, UQ_BROKEN_BIDIR)},
125	{USB_QUIRK(USB_VENDOR_HP, USB_PRODUCT_HP_1220C,
126	    0x0000, 0xFFFF, UQ_BROKEN_BIDIR)},
127	{USB_QUIRK(USB_VENDOR_XEROX, USB_PRODUCT_XEROX_WCM15,
128	    0x0000, 0xFFFF, UQ_BROKEN_BIDIR)},
129	/* Devices which should be ignored by uhid */
130	{USB_QUIRK(USB_VENDOR_APC, USB_PRODUCT_APC_UPS,
131	    0x0000, 0xFFFF, UQ_HID_IGNORE)},
132	{USB_QUIRK(USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F6C550AVR,
133	    0x0000, 0xFFFF, UQ_HID_IGNORE)},
134	{USB_QUIRK(USB_VENDOR_CYBERPOWER,
135	    USB_PRODUCT_CYBERPOWER_1500CAVRLCD,
136	    0x0000, 0xFFFF, UQ_HID_IGNORE)},
137	{USB_QUIRK(USB_VENDOR_DELORME, USB_PRODUCT_DELORME_EARTHMATE,
138	    0x0000, 0xFFFF, UQ_HID_IGNORE)},
139	{USB_QUIRK(USB_VENDOR_ITUNERNET, USB_PRODUCT_ITUNERNET_USBLCD2X20,
140	    0x0000, 0xFFFF, UQ_HID_IGNORE)},
141	{USB_QUIRK(USB_VENDOR_ITUNERNET, USB_PRODUCT_ITUNERNET_USBLCD4X20,
142	    0x0000, 0xFFFF, UQ_HID_IGNORE)},
143	{USB_QUIRK(USB_VENDOR_MGE, USB_PRODUCT_MGE_UPS1,
144	    0x0000, 0xFFFF, UQ_HID_IGNORE)},
145	{USB_QUIRK(USB_VENDOR_MGE, USB_PRODUCT_MGE_UPS2,
146	    0x0000, 0xFFFF, UQ_HID_IGNORE)},
147	{USB_QUIRK(USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE,
148	    0x0000, 0xFFFF, UQ_HID_IGNORE)},
149	{USB_QUIRK(USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_3G,
150	    0x0000, 0xFFFF, UQ_HID_IGNORE)},
151	/* Devices which should be ignored by both ukbd and uhid */
152	{USB_QUIRK(USB_VENDOR_CYPRESS, USB_PRODUCT_CYPRESS_WISPY1A,
153	    0x0000, 0xFFFF, UQ_KBD_IGNORE, UQ_HID_IGNORE)},
154	{USB_QUIRK(USB_VENDOR_METAGEEK, USB_PRODUCT_METAGEEK_WISPY1B,
155	    0x0000, 0xFFFF, UQ_KBD_IGNORE, UQ_HID_IGNORE)},
156	{USB_QUIRK(USB_VENDOR_TENX, USB_PRODUCT_TENX_UAUDIO0,
157	    0x0101, 0x0101, UQ_AUDIO_SWAP_LR)},
158	/* MS keyboards do weird things */
159	{USB_QUIRK(USB_VENDOR_MICROSOFT,
160	    USB_PRODUCT_MICROSOFT_WLINTELLIMOUSE,
161	    0x0000, 0xFFFF, UQ_MS_LEADING_BYTE)},
162	{USB_QUIRK(USB_VENDOR_METAGEEK, USB_PRODUCT_METAGEEK_WISPY24X,
163	    0x0000, 0xFFFF, UQ_KBD_IGNORE, UQ_HID_IGNORE)},
164	/* umodem(4) device quirks */
165	{USB_QUIRK(USB_VENDOR_METRICOM, USB_PRODUCT_METRICOM_RICOCHET_GS,
166	    0x100, 0x100, UQ_ASSUME_CM_OVER_DATA)},
167	{USB_QUIRK(USB_VENDOR_SANYO, USB_PRODUCT_SANYO_SCP4900,
168	    0x000, 0x000, UQ_ASSUME_CM_OVER_DATA)},
169	{USB_QUIRK(USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_T720C,
170	    0x001, 0x001, UQ_ASSUME_CM_OVER_DATA)},
171	{USB_QUIRK(USB_VENDOR_EICON, USB_PRODUCT_EICON_DIVA852,
172	    0x100, 0x100, UQ_ASSUME_CM_OVER_DATA)},
173	{USB_QUIRK(USB_VENDOR_SIEMENS2, USB_PRODUCT_SIEMENS2_ES75,
174	    0x000, 0x000, UQ_ASSUME_CM_OVER_DATA)},
175	{USB_QUIRK(USB_VENDOR_QUALCOMM, USB_PRODUCT_QUALCOMM_CDMA_MSM,
176	    0x0000, 0xFFFF, UQ_ASSUME_CM_OVER_DATA)},
177	{USB_QUIRK(USB_VENDOR_QUALCOMM2, USB_PRODUCT_QUALCOMM2_CDMA_MSM,
178	    0x0000, 0xFFFF, UQ_ASSUME_CM_OVER_DATA)},
179	{USB_QUIRK(USB_VENDOR_CURITEL, USB_PRODUCT_CURITEL_UM175,
180	    0x0000, 0xFFFF, UQ_ASSUME_CM_OVER_DATA)},
181
182	/* USB Mass Storage Class Quirks */
183	{USB_QUIRK(USB_VENDOR_ASAHIOPTICAL, 0,
184	    0x0000, 0xFFFF, UQ_MSC_NO_RS_CLEAR_UA, UQ_MATCH_VENDOR_ONLY)},
185	{USB_QUIRK(USB_VENDOR_ADDON, USB_PRODUCT_ADDON_ATTACHE, 0x0000,
186	    0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
187	    UQ_MSC_IGNORE_RESIDUE)},
188	{USB_QUIRK(USB_VENDOR_ADDON, USB_PRODUCT_ADDON_A256MB,
189	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
190	    UQ_MSC_IGNORE_RESIDUE)},
191	{USB_QUIRK(USB_VENDOR_ADDON, USB_PRODUCT_ADDON_DISKPRO512,
192	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
193	    UQ_MSC_IGNORE_RESIDUE)},
194	{USB_QUIRK(USB_VENDOR_ADDONICS2, USB_PRODUCT_ADDONICS2_CABLE_205,
195	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
196	{USB_QUIRK(USB_VENDOR_AIPTEK, USB_PRODUCT_AIPTEK_POCKETCAM3M,
197	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
198	{USB_QUIRK(USB_VENDOR_AIPTEK2, USB_PRODUCT_AIPTEK2_SUNPLUS_TECH,
199	    0x0000, 0xFFFF, UQ_MSC_NO_SYNC_CACHE)},
200	{USB_QUIRK(USB_VENDOR_ALCOR, USB_PRODUCT_ALCOR_SDCR_6335,
201	    0x0000, 0xFFFF, UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_SYNC_CACHE)},
202	{USB_QUIRK(USB_VENDOR_ALCOR, USB_PRODUCT_ALCOR_AU6390,
203	    0x0000, 0xFFFF, UQ_MSC_NO_SYNC_CACHE)},
204	{USB_QUIRK(USB_VENDOR_ALCOR, USB_PRODUCT_ALCOR_UMCR_9361,
205	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
206	    UQ_MSC_NO_GETMAXLUN)},
207	{USB_QUIRK(USB_VENDOR_ALCOR, USB_PRODUCT_ALCOR_TRANSCEND,
208	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
209	    UQ_MSC_NO_GETMAXLUN)},
210	{USB_QUIRK(USB_VENDOR_ASAHIOPTICAL, USB_PRODUCT_ASAHIOPTICAL_OPTIO230,
211	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
212	    UQ_MSC_NO_INQUIRY)},
213	{USB_QUIRK(USB_VENDOR_ASAHIOPTICAL, USB_PRODUCT_ASAHIOPTICAL_OPTIO330,
214	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
215	    UQ_MSC_NO_INQUIRY)},
216	{USB_QUIRK(USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_USB2SCSI,
217	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
218	{USB_QUIRK(USB_VENDOR_CASIO, USB_PRODUCT_CASIO_QV_DIGICAM,
219	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_SCSI,
220	    UQ_MSC_NO_INQUIRY)},
221	{USB_QUIRK(USB_VENDOR_CCYU, USB_PRODUCT_CCYU_ED1064,
222	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
223	{USB_QUIRK(USB_VENDOR_CENTURY, USB_PRODUCT_CENTURY_EX35QUAT,
224	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
225	    UQ_MSC_FORCE_SHORT_INQ, UQ_MSC_NO_START_STOP,
226	    UQ_MSC_IGNORE_RESIDUE)},
227	{USB_QUIRK(USB_VENDOR_CYPRESS, USB_PRODUCT_CYPRESS_XX6830XX,
228	    0x0000, 0xFFFF, UQ_MSC_NO_GETMAXLUN, UQ_MSC_NO_SYNC_CACHE)},
229	{USB_QUIRK(USB_VENDOR_DESKNOTE, USB_PRODUCT_DESKNOTE_UCR_61S2B,
230	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
231	{USB_QUIRK(USB_VENDOR_DMI, USB_PRODUCT_DMI_CFSM_RW,
232	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN)},
233	{USB_QUIRK(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_STYLUS_875DC,
234	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_SCSI,
235	    UQ_MSC_NO_INQUIRY)},
236	{USB_QUIRK(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_STYLUS_895,
237	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
238	    UQ_MSC_NO_GETMAXLUN)},
239	{USB_QUIRK(USB_VENDOR_FEIYA, USB_PRODUCT_FEIYA_5IN1,
240	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
241	{USB_QUIRK(USB_VENDOR_FREECOM, USB_PRODUCT_FREECOM_DVD,
242	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI)},
243	{USB_QUIRK(USB_VENDOR_FUJIPHOTO, USB_PRODUCT_FUJIPHOTO_MASS0100,
244	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI_I, UQ_MSC_FORCE_PROTO_ATAPI,
245	    UQ_MSC_NO_RS_CLEAR_UA)},
246	{USB_QUIRK(USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL641USB2IDE,
247	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
248	    UQ_MSC_FORCE_SHORT_INQ, UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE,
249	    UQ_MSC_NO_SYNC_CACHE)},
250	{USB_QUIRK(USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL641USB2IDE_2,
251	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_ATAPI,
252	    UQ_MSC_FORCE_SHORT_INQ, UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE)},
253	{USB_QUIRK(USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL641USB,
254	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
255	    UQ_MSC_FORCE_SHORT_INQ, UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE)},
256	{USB_QUIRK(USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL641USB_2,
257	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
258	    UQ_MSC_WRONG_CSWSIG)},
259	{USB_QUIRK(USB_VENDOR_HAGIWARA, USB_PRODUCT_HAGIWARA_FG,
260	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
261	{USB_QUIRK(USB_VENDOR_HAGIWARA, USB_PRODUCT_HAGIWARA_FGSM,
262	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
263	{USB_QUIRK(USB_VENDOR_HITACHI, USB_PRODUCT_HITACHI_DVDCAM_DZ_MV100A,
264	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_SCSI,
265	    UQ_MSC_NO_GETMAXLUN)},
266	{USB_QUIRK(USB_VENDOR_HITACHI, USB_PRODUCT_HITACHI_DVDCAM_USB,
267	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI_I, UQ_MSC_FORCE_PROTO_ATAPI,
268	    UQ_MSC_NO_INQUIRY)},
269	{USB_QUIRK(USB_VENDOR_HP, USB_PRODUCT_HP_CDW4E,
270	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_ATAPI)},
271	{USB_QUIRK(USB_VENDOR_HP, USB_PRODUCT_HP_CDW8200,
272	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI_I, UQ_MSC_FORCE_PROTO_ATAPI,
273	    UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_START_STOP)},
274	{USB_QUIRK(USB_VENDOR_IMAGINATION, USB_PRODUCT_IMAGINATION_DBX1,
275	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
276	    UQ_MSC_WRONG_CSWSIG)},
277	{USB_QUIRK(USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_USBCABLE,
278	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_ATAPI,
279	    UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_START_STOP, UQ_MSC_ALT_IFACE_1)},
280	{USB_QUIRK(USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_ATAPI,
281	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_RBC)},
282	{USB_QUIRK(USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_STORAGE_V2,
283	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_RBC)},
284	{USB_QUIRK(USB_VENDOR_IODATA, USB_PRODUCT_IODATA_IU_CD2,
285	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
286	{USB_QUIRK(USB_VENDOR_IODATA, USB_PRODUCT_IODATA_DVR_UEH8,
287	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
288	{USB_QUIRK(USB_VENDOR_IOMEGA, USB_PRODUCT_IOMEGA_ZIP100,
289	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
290	    UQ_MSC_NO_TEST_UNIT_READY)}, /* XXX ZIP drives can also use ATAPI */
291	{USB_QUIRK(USB_VENDOR_KYOCERA, USB_PRODUCT_KYOCERA_FINECAM_L3,
292	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
293	    UQ_MSC_NO_INQUIRY)},
294	{USB_QUIRK(USB_VENDOR_KYOCERA, USB_PRODUCT_KYOCERA_FINECAM_S3X,
295	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_ATAPI,
296	    UQ_MSC_NO_INQUIRY)},
297	{USB_QUIRK(USB_VENDOR_KYOCERA, USB_PRODUCT_KYOCERA_FINECAM_S4,
298	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_ATAPI,
299	    UQ_MSC_NO_INQUIRY)},
300	{USB_QUIRK(USB_VENDOR_KYOCERA, USB_PRODUCT_KYOCERA_FINECAM_S5,
301	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
302	    UQ_MSC_NO_INQUIRY)},
303	{USB_QUIRK(USB_VENDOR_LACIE, USB_PRODUCT_LACIE_HD,
304	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_RBC)},
305	{USB_QUIRK(USB_VENDOR_LEXAR, USB_PRODUCT_LEXAR_CF_READER,
306	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
307	    UQ_MSC_NO_INQUIRY)},
308	{USB_QUIRK(USB_VENDOR_LEXAR, USB_PRODUCT_LEXAR_JUMPSHOT,
309	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI)},
310	{USB_QUIRK(USB_VENDOR_LOGITEC, USB_PRODUCT_LOGITEC_LDR_H443SU2,
311	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI)},
312	{USB_QUIRK(USB_VENDOR_LOGITEC, USB_PRODUCT_LOGITEC_LDR_H443U2,
313	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,)},
314	{USB_QUIRK(USB_VENDOR_MELCO, USB_PRODUCT_MELCO_DUBPXXG,
315	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
316	    UQ_MSC_FORCE_SHORT_INQ, UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE)},
317	{USB_QUIRK(USB_VENDOR_MICROTECH, USB_PRODUCT_MICROTECH_DPCM,
318	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_SCSI,
319	    UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_START_STOP)},
320	{USB_QUIRK(USB_VENDOR_MICROTECH, USB_PRODUCT_MICROTECH_SCSIDB25,
321	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
322	{USB_QUIRK(USB_VENDOR_MICROTECH, USB_PRODUCT_MICROTECH_SCSIHD50,
323	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
324	{USB_QUIRK(USB_VENDOR_MINOLTA, USB_PRODUCT_MINOLTA_E223,
325	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI)},
326	{USB_QUIRK(USB_VENDOR_MINOLTA, USB_PRODUCT_MINOLTA_F300,
327	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
328	{USB_QUIRK(USB_VENDOR_MITSUMI, USB_PRODUCT_MITSUMI_CDRRW,
329	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI | UQ_MSC_FORCE_PROTO_ATAPI)},
330	{USB_QUIRK(USB_VENDOR_MITSUMI, USB_PRODUCT_MITSUMI_FDD,
331	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
332	    UQ_MSC_NO_GETMAXLUN)},
333	{USB_QUIRK(USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_E398,
334	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
335	    UQ_MSC_FORCE_SHORT_INQ, UQ_MSC_NO_INQUIRY_EVPD, UQ_MSC_NO_GETMAXLUN)},
336	{USB_QUIRK(USB_VENDOR_MPMAN, 0,
337	    0x0000, 0xFFFF, UQ_MSC_NO_SYNC_CACHE, UQ_MATCH_VENDOR_ONLY)},
338	{USB_QUIRK(USB_VENDOR_MSYSTEMS, USB_PRODUCT_MSYSTEMS_DISKONKEY,
339	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
340	    UQ_MSC_IGNORE_RESIDUE, UQ_MSC_NO_GETMAXLUN, UQ_MSC_NO_RS_CLEAR_UA)},
341	{USB_QUIRK(USB_VENDOR_MSYSTEMS, USB_PRODUCT_MSYSTEMS_DISKONKEY2,
342	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_ATAPI)},
343	{USB_QUIRK(USB_VENDOR_MYSON, USB_PRODUCT_MYSON_HEDEN,
344	    0x0000, 0xFFFF, UQ_MSC_IGNORE_RESIDUE, UQ_MSC_NO_SYNC_CACHE)},
345	{USB_QUIRK(USB_VENDOR_MYSON, USB_PRODUCT_MYSON_HEDEN_8813,
346	    0x0000, 0xFFFF, UQ_MSC_NO_SYNC_CACHE)},
347	{USB_QUIRK(USB_VENDOR_MYSON, USB_PRODUCT_MYSON_STARREADER,
348	    0x0000, 0xFFFF, UQ_MSC_NO_SYNC_CACHE)},
349	{USB_QUIRK(USB_VENDOR_NEODIO, USB_PRODUCT_NEODIO_ND3260,
350	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
351	    UQ_MSC_FORCE_SHORT_INQ)},
352	{USB_QUIRK(USB_VENDOR_NETAC, USB_PRODUCT_NETAC_CF_CARD,
353	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
354	    UQ_MSC_NO_INQUIRY)},
355	{USB_QUIRK(USB_VENDOR_NETAC, USB_PRODUCT_NETAC_ONLYDISK,
356	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
357	    UQ_MSC_IGNORE_RESIDUE)},
358	{USB_QUIRK(USB_VENDOR_NETCHIP, USB_PRODUCT_NETCHIP_CLIK_40,
359	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_INQUIRY)},
360	{USB_QUIRK(USB_VENDOR_NIKON, USB_PRODUCT_NIKON_D300,
361	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
362	{USB_QUIRK(USB_VENDOR_OLYMPUS, USB_PRODUCT_OLYMPUS_C1,
363	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
364	    UQ_MSC_WRONG_CSWSIG)},
365	{USB_QUIRK(USB_VENDOR_OLYMPUS, USB_PRODUCT_OLYMPUS_C700,
366	    0x0000, 0xFFFF, UQ_MSC_NO_GETMAXLUN)},
367	{USB_QUIRK(USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_SDS_HOTFIND_D,
368	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
369	    UQ_MSC_NO_GETMAXLUN, UQ_MSC_NO_SYNC_CACHE)},
370	{USB_QUIRK(USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_CFMS_RW,
371	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI)},
372	{USB_QUIRK(USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_CFSM_COMBO,
373	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI)},
374	{USB_QUIRK(USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_CFSM_READER,
375	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI)},
376	{USB_QUIRK(USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_CFSM_READER2,
377	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI)},
378	{USB_QUIRK(USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_MDCFE_B_CF_READER,
379	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI)},
380	{USB_QUIRK(USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_MDSM_B_READER,
381	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY)},
382	{USB_QUIRK(USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_READER,
383	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI)},
384	{USB_QUIRK(USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_UCF100,
385	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_ATAPI,
386	    UQ_MSC_NO_INQUIRY | UQ_MSC_NO_GETMAXLUN)},
387	{USB_QUIRK(USB_VENDOR_ONSPEC2, USB_PRODUCT_ONSPEC2_IMAGEMATE_SDDR55,
388	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN)},
389	{USB_QUIRK(USB_VENDOR_PANASONIC, USB_PRODUCT_PANASONIC_KXL840AN,
390	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_ATAPI,
391	    UQ_MSC_NO_GETMAXLUN)},
392	{USB_QUIRK(USB_VENDOR_PANASONIC, USB_PRODUCT_PANASONIC_KXLCB20AN,
393	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
394	{USB_QUIRK(USB_VENDOR_PANASONIC, USB_PRODUCT_PANASONIC_KXLCB35AN,
395	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
396	{USB_QUIRK(USB_VENDOR_PANASONIC, USB_PRODUCT_PANASONIC_LS120CAM,
397	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_UFI)},
398	{USB_QUIRK(USB_VENDOR_PHILIPS, USB_PRODUCT_PHILIPS_SPE3030CC,
399	    0x0000, 0xFFFF, UQ_MSC_NO_SYNC_CACHE)},
400	{USB_QUIRK(USB_VENDOR_PLEXTOR, USB_PRODUCT_PLEXTOR_40_12_40U,
401	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
402	    UQ_MSC_NO_TEST_UNIT_READY)},
403	{USB_QUIRK(USB_VENDOR_PNY, USB_PRODUCT_PNY_ATTACHE2,
404	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
405	    UQ_MSC_IGNORE_RESIDUE, UQ_MSC_NO_START_STOP)},
406	{USB_QUIRK(USB_VENDOR_SAMSUNG_TECHWIN, USB_PRODUCT_SAMSUNG_TECHWIN_DIGIMAX_410,
407	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
408	    UQ_MSC_NO_INQUIRY)},
409	{USB_QUIRK(USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDDR05A,
410	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_SCSI,
411	    UQ_MSC_READ_CAP_OFFBY1, UQ_MSC_NO_GETMAXLUN)},
412	{USB_QUIRK(USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDDR09,
413	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_READ_CAP_OFFBY1,
414	    UQ_MSC_NO_GETMAXLUN)},
415	{USB_QUIRK(USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDDR12,
416	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_SCSI,
417	    UQ_MSC_READ_CAP_OFFBY1, UQ_MSC_NO_GETMAXLUN)},
418	{USB_QUIRK(USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDCZ2_256,
419	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
420	    UQ_MSC_IGNORE_RESIDUE)},
421	{USB_QUIRK(USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDCZ4_128,
422	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
423	    UQ_MSC_IGNORE_RESIDUE)},
424	{USB_QUIRK(USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDCZ4_256,
425	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
426	    UQ_MSC_IGNORE_RESIDUE)},
427	{USB_QUIRK(USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDDR31,
428	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
429	    UQ_MSC_READ_CAP_OFFBY1)},
430	{USB_QUIRK(USB_VENDOR_SCANLOGIC, USB_PRODUCT_SCANLOGIC_SL11R,
431	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_ATAPI,
432	    UQ_MSC_NO_INQUIRY)},
433	{USB_QUIRK(USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSB,
434	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI_I, UQ_MSC_FORCE_PROTO_ATAPI,
435	    UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_START_STOP, UQ_MSC_SHUTTLE_INIT)},
436	{USB_QUIRK(USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_CDRW,
437	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_ATAPI)},
438	{USB_QUIRK(USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_CF,
439	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_ATAPI)},
440	{USB_QUIRK(USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSBATAPI,
441	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_ATAPI)},
442	{USB_QUIRK(USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSBCFSM,
443	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI)},
444	{USB_QUIRK(USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSCSI,
445	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
446	{USB_QUIRK(USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_HIFD,
447	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_SCSI,
448	    UQ_MSC_NO_GETMAXLUN)},
449	{USB_QUIRK(USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_SDDR09,
450	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN)},
451	{USB_QUIRK(USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_ZIOMMC,
452	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_SCSI,
453	    UQ_MSC_NO_GETMAXLUN)},
454	{USB_QUIRK(USB_VENDOR_SIGMATEL, USB_PRODUCT_SIGMATEL_I_BEAD100,
455	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
456	    UQ_MSC_SHUTTLE_INIT)},
457	{USB_QUIRK(USB_VENDOR_SIIG, USB_PRODUCT_SIIG_WINTERREADER,
458	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
459	    UQ_MSC_IGNORE_RESIDUE)},
460	{USB_QUIRK(USB_VENDOR_SKANHEX, USB_PRODUCT_SKANHEX_MD_7425,
461	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
462	    UQ_MSC_NO_INQUIRY)},
463	{USB_QUIRK(USB_VENDOR_SKANHEX, USB_PRODUCT_SKANHEX_SX_520Z,
464	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
465	    UQ_MSC_NO_INQUIRY)},
466	{USB_QUIRK(USB_VENDOR_SONY, USB_PRODUCT_SONY_HANDYCAM,
467	    0x0500, 0x0500, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_RBC,
468	    UQ_MSC_RBC_PAD_TO_12)},
469	{USB_QUIRK(USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_40_MS,
470	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
471	    UQ_MSC_NO_INQUIRY)},
472	{USB_QUIRK(USB_VENDOR_SONY, USB_PRODUCT_SONY_DSC,
473	    0x0500, 0x0500, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_RBC,
474	    UQ_MSC_RBC_PAD_TO_12)},
475	{USB_QUIRK(USB_VENDOR_SONY, USB_PRODUCT_SONY_DSC,
476	    0x0600, 0x0600, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_RBC,
477	    UQ_MSC_RBC_PAD_TO_12)},
478	{USB_QUIRK(USB_VENDOR_SONY, USB_PRODUCT_SONY_DSC,
479	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_RBC)},
480	{USB_QUIRK(USB_VENDOR_SONY, USB_PRODUCT_SONY_HANDYCAM,
481	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_RBC)},
482	{USB_QUIRK(USB_VENDOR_SONY, USB_PRODUCT_SONY_MSC,
483	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_RBC)},
484	{USB_QUIRK(USB_VENDOR_SONY, USB_PRODUCT_SONY_MS_MSC_U03,
485	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_UFI,
486	    UQ_MSC_NO_GETMAXLUN)},
487	{USB_QUIRK(USB_VENDOR_SONY, USB_PRODUCT_SONY_MS_NW_MS7,
488	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
489	    UQ_MSC_NO_GETMAXLUN)},
490	{USB_QUIRK(USB_VENDOR_SONY, USB_PRODUCT_SONY_MS_PEG_N760C,
491	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
492	    UQ_MSC_NO_INQUIRY)},
493	{USB_QUIRK(USB_VENDOR_SONY, USB_PRODUCT_SONY_MSACUS1,
494	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
495	    UQ_MSC_NO_GETMAXLUN)},
496	{USB_QUIRK(USB_VENDOR_SONY, USB_PRODUCT_SONY_PORTABLE_HDD_V2,
497	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
498	{USB_QUIRK(USB_VENDOR_SUPERTOP, USB_PRODUCT_SUPERTOP_IDE,
499	    0x0000, 0xFFFF, UQ_MSC_IGNORE_RESIDUE, UQ_MSC_NO_SYNC_CACHE)},
500	{USB_QUIRK(USB_VENDOR_TAUGA, USB_PRODUCT_TAUGA_CAMERAMATE,
501	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI)},
502	{USB_QUIRK(USB_VENDOR_TEAC, USB_PRODUCT_TEAC_FD05PUB,
503	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_UFI)},
504	{USB_QUIRK(USB_VENDOR_TECLAST, USB_PRODUCT_TECLAST_TLC300,
505	    0x0000, 0xFFFF, UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_SYNC_CACHE)},
506	{USB_QUIRK(USB_VENDOR_TREK, USB_PRODUCT_TREK_MEMKEY,
507	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
508	    UQ_MSC_NO_INQUIRY)},
509	{USB_QUIRK(USB_VENDOR_TREK, USB_PRODUCT_TREK_THUMBDRIVE_8MB,
510	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_ATAPI,
511	    UQ_MSC_IGNORE_RESIDUE)},
512	{USB_QUIRK(USB_VENDOR_TRUMPION, USB_PRODUCT_TRUMPION_C3310,
513	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_UFI)},
514	{USB_QUIRK(USB_VENDOR_TRUMPION, USB_PRODUCT_TRUMPION_MP3,
515	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_RBC)},
516	{USB_QUIRK(USB_VENDOR_TRUMPION, USB_PRODUCT_TRUMPION_T33520,
517	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI)},
518	{USB_QUIRK(USB_VENDOR_TWINMOS, USB_PRODUCT_TWINMOS_MDIV,
519	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
520	{USB_QUIRK(USB_VENDOR_VIA, USB_PRODUCT_VIA_USB2IDEBRIDGE,
521	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
522	    UQ_MSC_NO_SYNC_CACHE)},
523	{USB_QUIRK(USB_VENDOR_VIVITAR, USB_PRODUCT_VIVITAR_35XX,
524	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
525	    UQ_MSC_NO_INQUIRY)},
526	{USB_QUIRK(USB_VENDOR_WESTERN, USB_PRODUCT_WESTERN_COMBO,
527	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
528	    UQ_MSC_FORCE_SHORT_INQ, UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE)},
529	{USB_QUIRK(USB_VENDOR_WESTERN, USB_PRODUCT_WESTERN_EXTHDD,
530	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
531	    UQ_MSC_FORCE_SHORT_INQ, UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE)},
532	{USB_QUIRK(USB_VENDOR_WESTERN, USB_PRODUCT_WESTERN_MYBOOK,
533	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
534	    UQ_MSC_NO_INQUIRY_EVPD)},
535	{USB_QUIRK(USB_VENDOR_WESTERN, USB_PRODUCT_WESTERN_MYPASSWORD,
536	    0x0000, 0xFFFF, UQ_MSC_FORCE_SHORT_INQ)},
537	{USB_QUIRK(USB_VENDOR_WINMAXGROUP, USB_PRODUCT_WINMAXGROUP_FLASH64MC,
538	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
539	    UQ_MSC_NO_INQUIRY)},
540	{USB_QUIRK(USB_VENDOR_YANO, USB_PRODUCT_YANO_FW800HD,
541	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
542	    UQ_MSC_FORCE_SHORT_INQ, UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE)},
543	{USB_QUIRK(USB_VENDOR_YANO, USB_PRODUCT_YANO_U640MO,
544	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI_I, UQ_MSC_FORCE_PROTO_ATAPI,
545	    UQ_MSC_FORCE_SHORT_INQ)},
546	{USB_QUIRK(USB_VENDOR_YEDATA, USB_PRODUCT_YEDATA_FLASHBUSTERU,
547	    0x0000, 0x007F, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_UFI,
548	    UQ_MSC_NO_RS_CLEAR_UA, UQ_MSC_FLOPPY_SPEED,
549	    UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_GETMAXLUN)},
550	{USB_QUIRK(USB_VENDOR_YEDATA, USB_PRODUCT_YEDATA_FLASHBUSTERU,
551	    0x0080, 0x0080, UQ_MSC_FORCE_WIRE_CBI_I, UQ_MSC_FORCE_PROTO_UFI,
552	    UQ_MSC_NO_RS_CLEAR_UA, UQ_MSC_FLOPPY_SPEED,
553	    UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_GETMAXLUN)},
554	{USB_QUIRK(USB_VENDOR_YEDATA, USB_PRODUCT_YEDATA_FLASHBUSTERU,
555	    0x0081, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI_I, UQ_MSC_FORCE_PROTO_UFI,
556	    UQ_MSC_NO_RS_CLEAR_UA, UQ_MSC_FLOPPY_SPEED, UQ_MSC_NO_GETMAXLUN)},
557	{USB_QUIRK(USB_VENDOR_ZORAN, USB_PRODUCT_ZORAN_EX20DSC,
558	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_ATAPI)},
559	{USB_QUIRK(USB_VENDOR_MEIZU, USB_PRODUCT_MEIZU_M6_SL,
560	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
561	    UQ_MSC_NO_INQUIRY, UQ_MSC_NO_SYNC_CACHE)},
562	{USB_QUIRK(USB_VENDOR_ACTIONS, USB_PRODUCT_ACTIONS_MP4,
563	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
564	    UQ_MSC_NO_SYNC_CACHE)},
565	{USB_QUIRK(USB_VENDOR_ASUS, USB_PRODUCT_ASUS_GMSC,
566	    0x0000, 0xFFFF, UQ_MSC_NO_SYNC_CACHE)},
567};
568#undef USB_QUIRK
569
570static const char *usb_quirk_str[USB_QUIRK_MAX] = {
571	[UQ_NONE]		= "UQ_NONE",
572	[UQ_MATCH_VENDOR_ONLY]	= "UQ_MATCH_VENDOR_ONLY",
573	[UQ_AUDIO_SWAP_LR]	= "UQ_AUDIO_SWAP_LR",
574	[UQ_AU_INP_ASYNC]	= "UQ_AU_INP_ASYNC",
575	[UQ_AU_NO_FRAC]		= "UQ_AU_NO_FRAC",
576	[UQ_AU_NO_XU]		= "UQ_AU_NO_XU",
577	[UQ_BAD_ADC]		= "UQ_BAD_ADC",
578	[UQ_BAD_AUDIO]		= "UQ_BAD_AUDIO",
579	[UQ_BROKEN_BIDIR]	= "UQ_BROKEN_BIDIR",
580	[UQ_BUS_POWERED]	= "UQ_BUS_POWERED",
581	[UQ_HID_IGNORE]		= "UQ_HID_IGNORE",
582	[UQ_KBD_IGNORE]		= "UQ_KBD_IGNORE",
583	[UQ_MS_BAD_CLASS]	= "UQ_MS_BAD_CLASS",
584	[UQ_MS_LEADING_BYTE]	= "UQ_MS_LEADING_BYTE",
585	[UQ_MS_REVZ]		= "UQ_MS_REVZ",
586	[UQ_NO_STRINGS]		= "UQ_NO_STRINGS",
587	[UQ_OPEN_CLEARSTALL]	= "UQ_OPEN_CLEARSTALL",
588	[UQ_POWER_CLAIM]	= "UQ_POWER_CLAIM",
589	[UQ_SPUR_BUT_UP]	= "UQ_SPUR_BUT_UP",
590	[UQ_SWAP_UNICODE]	= "UQ_SWAP_UNICODE",
591	[UQ_CFG_INDEX_1]	= "UQ_CFG_INDEX_1",
592	[UQ_CFG_INDEX_2]	= "UQ_CFG_INDEX_2",
593	[UQ_CFG_INDEX_3]	= "UQ_CFG_INDEX_3",
594	[UQ_CFG_INDEX_4]	= "UQ_CFG_INDEX_4",
595	[UQ_CFG_INDEX_0]	= "UQ_CFG_INDEX_0",
596	[UQ_ASSUME_CM_OVER_DATA]	= "UQ_ASSUME_CM_OVER_DATA",
597	[UQ_MSC_NO_TEST_UNIT_READY]	= "UQ_MSC_NO_TEST_UNIT_READY",
598	[UQ_MSC_NO_RS_CLEAR_UA]		= "UQ_MSC_NO_RS_CLEAR_UA",
599	[UQ_MSC_NO_START_STOP]		= "UQ_MSC_NO_START_STOP",
600	[UQ_MSC_NO_GETMAXLUN]		= "UQ_MSC_NO_GETMAXLUN",
601	[UQ_MSC_NO_INQUIRY]		= "UQ_MSC_NO_INQUIRY",
602	[UQ_MSC_NO_INQUIRY_EVPD]	= "UQ_MSC_NO_INQUIRY_EVPD",
603	[UQ_MSC_NO_SYNC_CACHE]		= "UQ_MSC_NO_SYNC_CACHE",
604	[UQ_MSC_SHUTTLE_INIT]		= "UQ_MSC_SHUTTLE_INIT",
605	[UQ_MSC_ALT_IFACE_1]		= "UQ_MSC_ALT_IFACE_1",
606	[UQ_MSC_FLOPPY_SPEED]		= "UQ_MSC_FLOPPY_SPEED",
607	[UQ_MSC_IGNORE_RESIDUE]		= "UQ_MSC_IGNORE_RESIDUE",
608	[UQ_MSC_WRONG_CSWSIG]		= "UQ_MSC_WRONG_CSWSIG",
609	[UQ_MSC_RBC_PAD_TO_12]		= "UQ_MSC_RBC_PAD_TO_12",
610	[UQ_MSC_READ_CAP_OFFBY1]	= "UQ_MSC_READ_CAP_OFFBY1",
611	[UQ_MSC_FORCE_SHORT_INQ]	= "UQ_MSC_FORCE_SHORT_INQ",
612	[UQ_MSC_FORCE_WIRE_BBB]		= "UQ_MSC_FORCE_WIRE_BBB",
613	[UQ_MSC_FORCE_WIRE_CBI]		= "UQ_MSC_FORCE_WIRE_CBI",
614	[UQ_MSC_FORCE_WIRE_CBI_I]	= "UQ_MSC_FORCE_WIRE_CBI_I",
615	[UQ_MSC_FORCE_PROTO_SCSI]	= "UQ_MSC_FORCE_PROTO_SCSI",
616	[UQ_MSC_FORCE_PROTO_ATAPI]	= "UQ_MSC_FORCE_PROTO_ATAPI",
617	[UQ_MSC_FORCE_PROTO_UFI]	= "UQ_MSC_FORCE_PROTO_UFI",
618	[UQ_MSC_FORCE_PROTO_RBC]	= "UQ_MSC_FORCE_PROTO_RBC",
619};
620
621/*------------------------------------------------------------------------*
622 *	usb_quirkstr
623 *
624 * This function converts an USB quirk code into a string.
625 *------------------------------------------------------------------------*/
626static const char *
627usb_quirkstr(uint16_t quirk)
628{
629	return ((quirk < USB_QUIRK_MAX) ?
630	    usb_quirk_str[quirk] : "USB_QUIRK_UNKNOWN");
631}
632
633/*------------------------------------------------------------------------*
634 *	usb_test_quirk_by_info
635 *
636 * Returns:
637 * 0: Quirk not found
638 * Else: Quirk found
639 *------------------------------------------------------------------------*/
640static uint8_t
641usb_test_quirk_by_info(const struct usbd_lookup_info *info, uint16_t quirk)
642{
643	uint16_t x;
644	uint16_t y;
645
646	if (quirk == UQ_NONE) {
647		return (0);
648	}
649	mtx_lock(&usb_quirk_mtx);
650
651	for (x = 0; x != USB_DEV_QUIRKS_MAX; x++) {
652		/* see if quirk information does not match */
653		if ((usb_quirks[x].vid != info->idVendor) ||
654		    (usb_quirks[x].lo_rev > info->bcdDevice) ||
655		    (usb_quirks[x].hi_rev < info->bcdDevice)) {
656			continue;
657		}
658		/* see if quirk only should match vendor ID */
659		if (usb_quirks[x].pid != info->idProduct) {
660			if (usb_quirks[x].pid != 0)
661				continue;
662
663			for (y = 0; y != USB_SUB_QUIRKS_MAX; y++) {
664				if (usb_quirks[x].quirks[y] == UQ_MATCH_VENDOR_ONLY)
665					break;
666			}
667			if (y == USB_SUB_QUIRKS_MAX)
668				continue;
669		}
670		/* lookup quirk */
671		for (y = 0; y != USB_SUB_QUIRKS_MAX; y++) {
672			if (usb_quirks[x].quirks[y] == quirk) {
673				mtx_unlock(&usb_quirk_mtx);
674				DPRINTF("Found quirk '%s'.\n", usb_quirkstr(quirk));
675				return (1);
676			}
677		}
678		/* no quirk found */
679		break;
680	}
681	mtx_unlock(&usb_quirk_mtx);
682	return (0);
683}
684
685static struct usb_quirk_entry *
686usb_quirk_get_entry(uint16_t vid, uint16_t pid,
687    uint16_t lo_rev, uint16_t hi_rev, uint8_t do_alloc)
688{
689	uint16_t x;
690
691	mtx_assert(&usb_quirk_mtx, MA_OWNED);
692
693	if ((vid | pid | lo_rev | hi_rev) == 0) {
694		/* all zero - special case */
695		return (usb_quirks + USB_DEV_QUIRKS_MAX - 1);
696	}
697	/* search for an existing entry */
698	for (x = 0; x != USB_DEV_QUIRKS_MAX; x++) {
699		/* see if quirk information does not match */
700		if ((usb_quirks[x].vid != vid) ||
701		    (usb_quirks[x].pid != pid) ||
702		    (usb_quirks[x].lo_rev != lo_rev) ||
703		    (usb_quirks[x].hi_rev != hi_rev)) {
704			continue;
705		}
706		return (usb_quirks + x);
707	}
708
709	if (do_alloc == 0) {
710		/* no match */
711		return (NULL);
712	}
713	/* search for a free entry */
714	for (x = 0; x != USB_DEV_QUIRKS_MAX; x++) {
715		/* see if quirk information does not match */
716		if ((usb_quirks[x].vid |
717		    usb_quirks[x].pid |
718		    usb_quirks[x].lo_rev |
719		    usb_quirks[x].hi_rev) != 0) {
720			continue;
721		}
722		usb_quirks[x].vid = vid;
723		usb_quirks[x].pid = pid;
724		usb_quirks[x].lo_rev = lo_rev;
725		usb_quirks[x].hi_rev = hi_rev;
726
727		return (usb_quirks + x);
728	}
729
730	/* no entry found */
731	return (NULL);
732}
733
734/*------------------------------------------------------------------------*
735 *	usb_quirk_ioctl - handle quirk IOCTLs
736 *
737 * Returns:
738 * 0: Success
739 * Else: Failure
740 *------------------------------------------------------------------------*/
741static int
742usb_quirk_ioctl(unsigned long cmd, caddr_t data,
743    int fflag, struct thread *td)
744{
745	struct usb_gen_quirk *pgq;
746	struct usb_quirk_entry *pqe;
747	uint32_t x;
748	uint32_t y;
749	int err;
750
751	switch (cmd) {
752	case USB_DEV_QUIRK_GET:
753		pgq = (void *)data;
754		x = pgq->index % USB_SUB_QUIRKS_MAX;
755		y = pgq->index / USB_SUB_QUIRKS_MAX;
756		if (y >= USB_DEV_QUIRKS_MAX) {
757			return (EINVAL);
758		}
759		mtx_lock(&usb_quirk_mtx);
760		/* copy out data */
761		pgq->vid = usb_quirks[y].vid;
762		pgq->pid = usb_quirks[y].pid;
763		pgq->bcdDeviceLow = usb_quirks[y].lo_rev;
764		pgq->bcdDeviceHigh = usb_quirks[y].hi_rev;
765		strlcpy(pgq->quirkname,
766		    usb_quirkstr(usb_quirks[y].quirks[x]),
767		    sizeof(pgq->quirkname));
768		mtx_unlock(&usb_quirk_mtx);
769		return (0);		/* success */
770
771	case USB_QUIRK_NAME_GET:
772		pgq = (void *)data;
773		x = pgq->index;
774		if (x >= USB_QUIRK_MAX) {
775			return (EINVAL);
776		}
777		strlcpy(pgq->quirkname,
778		    usb_quirkstr(x), sizeof(pgq->quirkname));
779		return (0);		/* success */
780
781	case USB_DEV_QUIRK_ADD:
782		pgq = (void *)data;
783
784		/* check privileges */
785		err = priv_check(curthread, PRIV_DRIVER);
786		if (err) {
787			return (err);
788		}
789		/* convert quirk string into numerical */
790		for (y = 0; y != USB_DEV_QUIRKS_MAX; y++) {
791			if (strcmp(pgq->quirkname, usb_quirkstr(y)) == 0) {
792				break;
793			}
794		}
795		if (y == USB_DEV_QUIRKS_MAX) {
796			return (EINVAL);
797		}
798		if (y == UQ_NONE) {
799			return (EINVAL);
800		}
801		mtx_lock(&usb_quirk_mtx);
802		pqe = usb_quirk_get_entry(pgq->vid, pgq->pid,
803		    pgq->bcdDeviceLow, pgq->bcdDeviceHigh, 1);
804		for (x = 0; x != USB_SUB_QUIRKS_MAX; x++) {
805			if (pqe->quirks[x] == UQ_NONE) {
806				pqe->quirks[x] = y;
807				break;
808			}
809		}
810		mtx_unlock(&usb_quirk_mtx);
811		if (x == USB_SUB_QUIRKS_MAX) {
812			return (ENOMEM);
813		}
814		return (0);		/* success */
815
816	case USB_DEV_QUIRK_REMOVE:
817		pgq = (void *)data;
818		/* check privileges */
819		err = priv_check(curthread, PRIV_DRIVER);
820		if (err) {
821			return (err);
822		}
823		/* convert quirk string into numerical */
824		for (y = 0; y != USB_DEV_QUIRKS_MAX; y++) {
825			if (strcmp(pgq->quirkname, usb_quirkstr(y)) == 0) {
826				break;
827			}
828		}
829		if (y == USB_DEV_QUIRKS_MAX) {
830			return (EINVAL);
831		}
832		if (y == UQ_NONE) {
833			return (EINVAL);
834		}
835		mtx_lock(&usb_quirk_mtx);
836		pqe = usb_quirk_get_entry(pgq->vid, pgq->pid,
837		    pgq->bcdDeviceLow, pgq->bcdDeviceHigh, 0);
838		for (x = 0; x != USB_SUB_QUIRKS_MAX; x++) {
839			if (pqe->quirks[x] == y) {
840				pqe->quirks[x] = UQ_NONE;
841				break;
842			}
843		}
844		if (x == USB_SUB_QUIRKS_MAX) {
845			mtx_unlock(&usb_quirk_mtx);
846			return (ENOMEM);
847		}
848		for (x = 0; x != USB_SUB_QUIRKS_MAX; x++) {
849			if (pqe->quirks[x] != UQ_NONE) {
850				break;
851			}
852		}
853		if (x == USB_SUB_QUIRKS_MAX) {
854			/* all quirk entries are unused - release */
855			memset(pqe, 0, sizeof(pqe));
856		}
857		mtx_unlock(&usb_quirk_mtx);
858		return (0);		/* success */
859
860	default:
861		break;
862	}
863	return (ENOIOCTL);
864}
865
866static void
867usb_quirk_init(void *arg)
868{
869	/* initialize mutex */
870	mtx_init(&usb_quirk_mtx, "USB quirk", NULL, MTX_DEF);
871
872	/* register our function */
873	usb_test_quirk_p = &usb_test_quirk_by_info;
874	usb_quirk_ioctl_p = &usb_quirk_ioctl;
875}
876
877static void
878usb_quirk_uninit(void *arg)
879{
880	usb_quirk_unload(arg);
881
882	/* destroy mutex */
883	mtx_destroy(&usb_quirk_mtx);
884}
885
886SYSINIT(usb_quirk_init, SI_SUB_LOCK, SI_ORDER_FIRST, usb_quirk_init, NULL);
887SYSUNINIT(usb_quirk_uninit, SI_SUB_LOCK, SI_ORDER_ANY, usb_quirk_uninit, NULL);
888