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