usb_quirk.c revision 262732
1179237Sjb/* $FreeBSD: head/sys/dev/usb/quirk/usb_quirk.c 262732 2014-03-04 12:33:18Z hselasky $ */
2179237Sjb/*-
3179237Sjb * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
4179237Sjb * Copyright (c) 1998 Lennart Augustsson. All rights reserved.
5179237Sjb * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
6179237Sjb *
7179237Sjb * Redistribution and use in source and binary forms, with or without
8179237Sjb * modification, are permitted provided that the following conditions
9179237Sjb * are met:
10179237Sjb * 1. Redistributions of source code must retain the above copyright
11179237Sjb *    notice, this list of conditions and the following disclaimer.
12179237Sjb * 2. Redistributions in binary form must reproduce the above copyright
13179237Sjb *    notice, this list of conditions and the following disclaimer in the
14179237Sjb *    documentation and/or other materials provided with the distribution.
15179237Sjb *
16179237Sjb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17179237Sjb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18179237Sjb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19179237Sjb * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20179237Sjb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21179237Sjb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22179237Sjb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23179237Sjb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24179237Sjb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25179237Sjb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26179237Sjb * SUCH DAMAGE.
27179237Sjb */
28179237Sjb
29179237Sjb#include <sys/stdint.h>
30179237Sjb#include <sys/stddef.h>
31179237Sjb#include <sys/param.h>
32179237Sjb#include <sys/queue.h>
33179237Sjb#include <sys/types.h>
34179237Sjb#include <sys/systm.h>
35179237Sjb#include <sys/kernel.h>
36179237Sjb#include <sys/bus.h>
37179237Sjb#include <sys/module.h>
38179237Sjb#include <sys/lock.h>
39179237Sjb#include <sys/mutex.h>
40179237Sjb#include <sys/condvar.h>
41179237Sjb#include <sys/sysctl.h>
42179237Sjb#include <sys/sx.h>
43179237Sjb#include <sys/unistd.h>
44179237Sjb#include <sys/callout.h>
45179237Sjb#include <sys/malloc.h>
46179237Sjb#include <sys/priv.h>
47179237Sjb
48179237Sjb#include <dev/usb/usb.h>
49179237Sjb#include <dev/usb/usb_ioctl.h>
50179237Sjb#include <dev/usb/usbdi.h>
51179237Sjb#include "usbdevs.h"
52179237Sjb
53291855Sandrew#define	USB_DEBUG_VAR usb_debug
54179237Sjb#include <dev/usb/usb_debug.h>
55179237Sjb#include <dev/usb/usb_dynamic.h>
56275576Savg
57179237Sjb#include <dev/usb/quirk/usb_quirk.h>
58179237Sjb
59179237SjbMODULE_DEPEND(usb_quirk, usb, 1, 1, 1);
60179237SjbMODULE_VERSION(usb_quirk, 1);
61179237Sjb
62179237Sjb#define	USB_DEV_QUIRKS_MAX 320
63179237Sjb#define	USB_SUB_QUIRKS_MAX 8
64179237Sjb
65179237Sjbstruct usb_quirk_entry {
66179237Sjb	uint16_t vid;
67179237Sjb	uint16_t pid;
68179237Sjb	uint16_t lo_rev;
69179237Sjb	uint16_t hi_rev;
70179237Sjb	uint16_t quirks[USB_SUB_QUIRKS_MAX];
71179237Sjb};
72179237Sjb
73179237Sjbstatic struct mtx usb_quirk_mtx;
74179237Sjb
75179237Sjb#define	USB_QUIRK_VP(v,p,l,h,...) \
76179237Sjb  { .vid = (v), .pid = (p), .lo_rev = (l), .hi_rev = (h), \
77179237Sjb    .quirks = { __VA_ARGS__ } }
78179237Sjb#define	USB_QUIRK(v,p,l,h,...) \
79179237Sjb  USB_QUIRK_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, l, h, __VA_ARGS__)
80179237Sjb
81179237Sjbstatic struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
82179237Sjb	USB_QUIRK(ASUS, LCM, 0x0000, 0xffff, UQ_HID_IGNORE),
83179237Sjb	USB_QUIRK(INSIDEOUT, EDGEPORT4, 0x094, 0x094, UQ_SWAP_UNICODE),
84179237Sjb	USB_QUIRK(DALLAS, J6502, 0x0a2, 0x0a2, UQ_BAD_ADC),
85179237Sjb	USB_QUIRK(DALLAS, J6502, 0x0a2, 0x0a2, UQ_AU_NO_XU),
86179237Sjb	USB_QUIRK(ALTEC, ADA70, 0x103, 0x103, UQ_BAD_ADC),
87179237Sjb	USB_QUIRK(ALTEC, ASC495, 0x000, 0x000, UQ_BAD_AUDIO),
88179237Sjb	USB_QUIRK(QTRONIX, 980N, 0x110, 0x110, UQ_SPUR_BUT_UP),
89179237Sjb	USB_QUIRK(ALCOR2, KBD_HUB, 0x001, 0x001, UQ_SPUR_BUT_UP),
90179237Sjb	USB_QUIRK(MCT, HUB0100, 0x102, 0x102, UQ_BUS_POWERED),
91179237Sjb	USB_QUIRK(MCT, USB232, 0x102, 0x102, UQ_BUS_POWERED),
92179237Sjb	USB_QUIRK(TI, UTUSB41, 0x110, 0x110, UQ_POWER_CLAIM),
93179237Sjb	USB_QUIRK(TELEX, MIC1, 0x009, 0x009, UQ_AU_NO_FRAC),
94179237Sjb	USB_QUIRK(SILICONPORTALS, YAPPHONE, 0x100, 0x100, UQ_AU_INP_ASYNC),
95179237Sjb	USB_QUIRK(LOGITECH, UN53B, 0x0000, 0xffff, UQ_NO_STRINGS),
96179237Sjb	USB_QUIRK(REALTEK, RTL8196EU, 0x0000, 0xffff, UQ_CFG_INDEX_1),
97179237Sjb	USB_QUIRK(ELSA, MODEM1, 0x0000, 0xffff, UQ_CFG_INDEX_1),
98179237Sjb	USB_QUIRK(PLANEX2, MZKUE150N, 0x0000, 0xffff, UQ_CFG_INDEX_1),
99179237Sjb	/* Quirks for printer devices */
100179237Sjb	USB_QUIRK(HP, 895C, 0x0000, 0xffff, UQ_BROKEN_BIDIR),
101275576Savg	USB_QUIRK(HP, 880C, 0x0000, 0xffff, UQ_BROKEN_BIDIR),
102179237Sjb	USB_QUIRK(HP, 815C, 0x0000, 0xffff, UQ_BROKEN_BIDIR),
103179237Sjb	USB_QUIRK(HP, 810C, 0x0000, 0xffff, UQ_BROKEN_BIDIR),
104179237Sjb	USB_QUIRK(HP, 830C, 0x0000, 0xffff, UQ_BROKEN_BIDIR),
105179237Sjb	USB_QUIRK(HP, 1220C, 0x0000, 0xffff, UQ_BROKEN_BIDIR),
106179237Sjb	USB_QUIRK(XEROX, WCM15, 0x0000, 0xffff, UQ_BROKEN_BIDIR),
107179237Sjb	/* Devices which should be ignored by uhid */
108179237Sjb	USB_QUIRK(APC, UPS, 0x0000, 0xffff, UQ_HID_IGNORE),
109179237Sjb	USB_QUIRK(BELKIN, F6C550AVR, 0x0000, 0xffff, UQ_HID_IGNORE),
110179237Sjb	USB_QUIRK(CYBERPOWER, 1500CAVRLCD, 0x0000, 0xffff, UQ_HID_IGNORE),
111179237Sjb	USB_QUIRK(CYPRESS, SILVERSHIELD, 0x0000, 0xffff, UQ_HID_IGNORE),
112179237Sjb	USB_QUIRK(DELORME, EARTHMATE, 0x0000, 0xffff, UQ_HID_IGNORE),
113179237Sjb	USB_QUIRK(ITUNERNET, USBLCD2X20, 0x0000, 0xffff, UQ_HID_IGNORE),
114179237Sjb	USB_QUIRK(ITUNERNET, USBLCD4X20, 0x0000, 0xffff, UQ_HID_IGNORE),
115179237Sjb	USB_QUIRK(LIEBERT, POWERSURE_PXT, 0x0000, 0xffff, UQ_HID_IGNORE),
116233409Sgonzo	USB_QUIRK(LIEBERT2, PSI1000, 0x0000, 0xffff, UQ_HID_IGNORE),
117233409Sgonzo	USB_QUIRK(MGE, UPS1, 0x0000, 0xffff, UQ_HID_IGNORE),
118233409Sgonzo	USB_QUIRK(MGE, UPS2, 0x0000, 0xffff, UQ_HID_IGNORE),
119233409Sgonzo	USB_QUIRK(APPLE, IPHONE, 0x0000, 0xffff, UQ_HID_IGNORE),
120233409Sgonzo	USB_QUIRK(APPLE, IPHONE_3G, 0x0000, 0xffff, UQ_HID_IGNORE),
121233409Sgonzo	USB_QUIRK(MEGATEC, UPS, 0x0000, 0xffff, UQ_HID_IGNORE),
122233409Sgonzo	/* Devices which should be ignored by both ukbd and uhid */
123242723Sjhibbits	USB_QUIRK(CYPRESS, WISPY1A, 0x0000, 0xffff, UQ_KBD_IGNORE, UQ_HID_IGNORE),
124242723Sjhibbits	USB_QUIRK(METAGEEK, WISPY1B, 0x0000, 0xffff, UQ_KBD_IGNORE, UQ_HID_IGNORE),
125242723Sjhibbits	USB_QUIRK(METAGEEK, WISPY24X, 0x0000, 0xffff, UQ_KBD_IGNORE, UQ_HID_IGNORE),
126242723Sjhibbits	USB_QUIRK(METAGEEK2, WISPYDBX, 0x0000, 0xffff, UQ_KBD_IGNORE, UQ_HID_IGNORE),
127242723Sjhibbits	USB_QUIRK(TENX, UAUDIO0, 0x0101, 0x0101, UQ_AUDIO_SWAP_LR),
128242723Sjhibbits	/* MS keyboards do weird things */
129242723Sjhibbits	USB_QUIRK(MICROSOFT, NATURAL4000, 0x0000, 0xFFFF, UQ_KBD_BOOTPROTO),
130275576Savg	USB_QUIRK(MICROSOFT, WLINTELLIMOUSE, 0x0000, 0xffff, UQ_MS_LEADING_BYTE),
131275576Savg	/* Quirk for Corsair Vengeance K60 keyboard */
132278529Sgnn	USB_QUIRK(CORSAIR, K60, 0x0000, 0xffff, UQ_KBD_BOOTPROTO),
133278529Sgnn	/* umodem(4) device quirks */
134278529Sgnn	USB_QUIRK(METRICOM, RICOCHET_GS, 0x100, 0x100, UQ_ASSUME_CM_OVER_DATA),
135278529Sgnn	USB_QUIRK(SANYO, SCP4900, 0x000, 0x000, UQ_ASSUME_CM_OVER_DATA),
136278529Sgnn	USB_QUIRK(MOTOROLA2, T720C, 0x001, 0x001, UQ_ASSUME_CM_OVER_DATA),
137278529Sgnn	USB_QUIRK(EICON, DIVA852, 0x100, 0x100, UQ_ASSUME_CM_OVER_DATA),
138291855Sandrew	USB_QUIRK(SIEMENS2, ES75, 0x000, 0x000, UQ_ASSUME_CM_OVER_DATA),
139278529Sgnn	USB_QUIRK(QUALCOMM, CDMA_MSM, 0x0000, 0xffff, UQ_ASSUME_CM_OVER_DATA),
140278529Sgnn	USB_QUIRK(QUALCOMM2, CDMA_MSM, 0x0000, 0xffff, UQ_ASSUME_CM_OVER_DATA),
141285009Sbr	USB_QUIRK(CURITEL, UM150, 0x0000, 0xffff, UQ_ASSUME_CM_OVER_DATA),
142285009Sbr	USB_QUIRK(CURITEL, UM175, 0x0000, 0xffff, UQ_ASSUME_CM_OVER_DATA),
143285009Sbr	USB_QUIRK(VERTEX, VW110L, 0x0000, 0xffff, UQ_ASSUME_CM_OVER_DATA),
144285009Sbr
145285009Sbr	/* USB Mass Storage Class Quirks */
146300618Sbr	USB_QUIRK_VP(USB_VENDOR_ASAHIOPTICAL, 0, UQ_MSC_NO_RS_CLEAR_UA,
147300618Sbr	    UQ_MATCH_VENDOR_ONLY),
148300618Sbr	USB_QUIRK(ADDON, ATTACHE, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
149300618Sbr	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
150300618Sbr	USB_QUIRK(ADDON, A256MB, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
151179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
152179237Sjb	USB_QUIRK(ADDON, DISKPRO512, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
153179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
154179237Sjb	USB_QUIRK(ADDONICS2, CABLE_205, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
155275576Savg	    UQ_MSC_FORCE_PROTO_SCSI),
156179237Sjb	USB_QUIRK(AIPTEK, POCKETCAM3M, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
157179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI),
158275576Savg	USB_QUIRK(ALCOR, UMCR_9361, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
159275576Savg	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN),
160275576Savg	USB_QUIRK(ALCOR, TRANSCEND, 0x0000, 0xffff, UQ_MSC_NO_GETMAXLUN,
161275576Savg	    UQ_MSC_NO_SYNC_CACHE, UQ_MSC_NO_TEST_UNIT_READY),
162275576Savg	USB_QUIRK(APACER, HT202, 0x0000, 0xffff, UQ_MSC_NO_TEST_UNIT_READY,
163275576Savg	    UQ_MSC_NO_SYNC_CACHE),
164179237Sjb	USB_QUIRK(ASAHIOPTICAL, OPTIO230, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
165179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
166179237Sjb	USB_QUIRK(ASAHIOPTICAL, OPTIO330, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
167179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
168179237Sjb	USB_QUIRK(ATP, EUSB, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
169179237Sjb	USB_QUIRK(BELKIN, USB2SCSI, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
170275576Savg	    UQ_MSC_FORCE_PROTO_SCSI),
171275576Savg	USB_QUIRK(CASIO, QV_DIGICAM, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
172275576Savg	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
173179237Sjb	USB_QUIRK(CCYU, ED1064, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
174179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI),
175179237Sjb	USB_QUIRK(CENTURY, EX35QUAT, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
176179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_FORCE_SHORT_INQ,
177179237Sjb	    UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE),
178179237Sjb	USB_QUIRK(CYPRESS, XX6830XX, 0x0000, 0xffff, UQ_MSC_NO_GETMAXLUN,
179179237Sjb	    UQ_MSC_NO_SYNC_CACHE),
180179237Sjb	USB_QUIRK(DESKNOTE, UCR_61S2B, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
181179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI),
182179237Sjb	USB_QUIRK(DMI, CFSM_RW, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI,
183179237Sjb	    UQ_MSC_NO_GETMAXLUN),
184179237Sjb	USB_QUIRK(EMTEC, RUF2PS, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
185179237Sjb	USB_QUIRK(EPSON, STYLUS_875DC, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
186179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
187179237Sjb	USB_QUIRK(EPSON, STYLUS_895, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
188179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN),
189179237Sjb	USB_QUIRK(FEIYA, 5IN1, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
190179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI),
191179237Sjb	USB_QUIRK(FEIYA, ELANGO, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
192179237Sjb	USB_QUIRK(FREECOM, DVD, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI),
193179237Sjb	USB_QUIRK(FUJIPHOTO, MASS0100, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI_I,
194179237Sjb	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_RS_CLEAR_UA, UQ_MSC_NO_SYNC_CACHE),
195179237Sjb	USB_QUIRK(GENESYS, GL641USB2IDE, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
196179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_FORCE_SHORT_INQ,
197179237Sjb	    UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE, UQ_MSC_NO_SYNC_CACHE),
198179237Sjb	USB_QUIRK(GENESYS, GL641USB2IDE_2, 0x0000, 0xffff,
199179237Sjb	    UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_ATAPI,
200179237Sjb	    UQ_MSC_FORCE_SHORT_INQ, UQ_MSC_NO_START_STOP,
201179237Sjb	    UQ_MSC_IGNORE_RESIDUE),
202179237Sjb	USB_QUIRK(GENESYS, GL641USB, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
203179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_FORCE_SHORT_INQ,
204179237Sjb	    UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE),
205179237Sjb	USB_QUIRK(GENESYS, GL641USB_2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
206179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_WRONG_CSWSIG),
207179237Sjb	USB_QUIRK(HAGIWARA, FG, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
208179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI),
209179237Sjb	USB_QUIRK(HAGIWARA, FGSM, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
210179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI),
211179237Sjb	USB_QUIRK(HITACHI, DVDCAM_DZ_MV100A, 0x0000, 0xffff,
212179237Sjb	    UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_SCSI,
213179237Sjb	    UQ_MSC_NO_GETMAXLUN),
214179237Sjb	USB_QUIRK(HITACHI, DVDCAM_USB, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI_I,
215179237Sjb	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_INQUIRY),
216179237Sjb	USB_QUIRK(HP, CDW4E, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_ATAPI),
217179237Sjb	USB_QUIRK(HP, CDW8200, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI_I,
218179237Sjb	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_TEST_UNIT_READY,
219179237Sjb	    UQ_MSC_NO_START_STOP),
220179237Sjb	USB_QUIRK(IMAGINATION, DBX1, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
221179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_WRONG_CSWSIG),
222179237Sjb	USB_QUIRK(INSYSTEM, USBCABLE, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
223179237Sjb	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_TEST_UNIT_READY,
224179237Sjb	    UQ_MSC_NO_START_STOP, UQ_MSC_ALT_IFACE_1),
225179237Sjb	USB_QUIRK(INSYSTEM, ATAPI, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
226179237Sjb	    UQ_MSC_FORCE_PROTO_RBC),
227179237Sjb	USB_QUIRK(INSYSTEM, STORAGE_V2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
228179237Sjb	    UQ_MSC_FORCE_PROTO_RBC),
229179237Sjb	USB_QUIRK(IODATA, IU_CD2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
230179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI),
231179237Sjb	USB_QUIRK(IODATA, DVR_UEH8, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
232179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI),
233179237Sjb	USB_QUIRK(IOMEGA, ZIP100, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
234179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI,
235179237Sjb	    UQ_MSC_NO_TEST_UNIT_READY), /* XXX ZIP drives can also use ATAPI */
236179237Sjb	USB_QUIRK(JMICRON, JM20337, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
237179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI,
238179237Sjb	    UQ_MSC_NO_SYNC_CACHE),
239291855Sandrew	USB_QUIRK(KYOCERA, FINECAM_L3, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
240179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
241291855Sandrew	USB_QUIRK(KYOCERA, FINECAM_S3X, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
242291855Sandrew	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_INQUIRY),
243291855Sandrew	USB_QUIRK(KYOCERA, FINECAM_S4, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
244291855Sandrew	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_INQUIRY),
245291855Sandrew	USB_QUIRK(KYOCERA, FINECAM_S5, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
246275576Savg	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
247275576Savg	USB_QUIRK(LACIE, HD, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
248275576Savg	    UQ_MSC_FORCE_PROTO_RBC),
249275576Savg	USB_QUIRK(LEXAR, CF_READER, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
250275576Savg	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
251275576Savg	USB_QUIRK(LEXAR, JUMPSHOT, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI),
252275576Savg	USB_QUIRK(LOGITEC, LDR_H443SU2, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI),
253275576Savg	USB_QUIRK(LOGITEC, LDR_H443U2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
254275576Savg	    UQ_MSC_FORCE_PROTO_SCSI,),
255275576Savg	USB_QUIRK(MELCO, DUBPXXG, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
256275576Savg	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_FORCE_SHORT_INQ,
257275576Savg	    UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE),
258275576Savg	USB_QUIRK(MICROTECH, DPCM, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
259275576Savg	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_TEST_UNIT_READY,
260275576Savg	    UQ_MSC_NO_START_STOP),
261275576Savg	USB_QUIRK(MICRON, REALSSD, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
262275576Savg	USB_QUIRK(MICROTECH, SCSIDB25, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
263275576Savg	    UQ_MSC_FORCE_PROTO_SCSI),
264275576Savg	USB_QUIRK(MICROTECH, SCSIHD50, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
265275576Savg	    UQ_MSC_FORCE_PROTO_SCSI),
266275576Savg	USB_QUIRK(MINOLTA, E223, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI),
267275576Savg	USB_QUIRK(MINOLTA, F300, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
268179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI),
269179237Sjb	USB_QUIRK(MITSUMI, CDRRW, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI |
270179237Sjb	    UQ_MSC_FORCE_PROTO_ATAPI),
271179237Sjb	USB_QUIRK(MOTOROLA2, E398, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
272179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_FORCE_SHORT_INQ,
273179237Sjb	    UQ_MSC_NO_INQUIRY_EVPD, UQ_MSC_NO_GETMAXLUN),
274275576Savg	USB_QUIRK_VP(USB_VENDOR_MPMAN, 0, UQ_MSC_NO_SYNC_CACHE,
275275576Savg	    UQ_MATCH_VENDOR_ONLY),
276179237Sjb	USB_QUIRK(MSYSTEMS, DISKONKEY, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
277275576Savg	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE, UQ_MSC_NO_GETMAXLUN,
278179237Sjb	    UQ_MSC_NO_RS_CLEAR_UA),
279275576Savg	USB_QUIRK(MSYSTEMS, DISKONKEY2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
280275576Savg	    UQ_MSC_FORCE_PROTO_ATAPI),
281275576Savg	USB_QUIRK(MYSON, HEDEN, 0x0000, 0xffff, UQ_MSC_IGNORE_RESIDUE,
282275576Savg	    UQ_MSC_NO_SYNC_CACHE),
283275576Savg	USB_QUIRK(NEODIO, ND3260, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
284275576Savg	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_FORCE_SHORT_INQ),
285275576Savg	USB_QUIRK(NETAC, CF_CARD, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
286275576Savg	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
287275576Savg	USB_QUIRK(NETAC, ONLYDISK, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
288275576Savg	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
289275576Savg	USB_QUIRK(NETCHIP, CLIK_40, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_ATAPI,
290275576Savg	    UQ_MSC_NO_INQUIRY),
291275576Savg	USB_QUIRK(NETCHIP, POCKETBOOK, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
292275576Savg	USB_QUIRK(NIKON, D300, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
293275576Savg	    UQ_MSC_FORCE_PROTO_SCSI),
294275576Savg	USB_QUIRK(OLYMPUS, C1, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
295275576Savg	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_WRONG_CSWSIG),
296275576Savg	USB_QUIRK(OLYMPUS, C700, 0x0000, 0xffff, UQ_MSC_NO_GETMAXLUN),
297275576Savg	USB_QUIRK(ONSPEC, SDS_HOTFIND_D, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
298275576Savg	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN, UQ_MSC_NO_SYNC_CACHE),
299275576Savg	USB_QUIRK(ONSPEC, CFMS_RW, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI),
300179237Sjb	USB_QUIRK(ONSPEC, CFSM_COMBO, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI),
301275576Savg	USB_QUIRK(ONSPEC, CFSM_READER, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI),
302275576Savg	USB_QUIRK(ONSPEC, CFSM_READER2, 0x0000, 0xffff,
303179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI),
304179237Sjb	USB_QUIRK(ONSPEC, MDCFE_B_CF_READER, 0x0000, 0xffff,
305179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI),
306179237Sjb	USB_QUIRK(ONSPEC, MDSM_B_READER, 0x0000, 0xffff,
307179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
308179237Sjb	USB_QUIRK(ONSPEC, READER, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI),
309275576Savg	USB_QUIRK(ONSPEC, UCF100, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
310275576Savg	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_INQUIRY, UQ_MSC_NO_GETMAXLUN),
311179237Sjb	USB_QUIRK(ONSPEC2, IMAGEMATE_SDDR55, 0x0000, 0xffff,
312275576Savg	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN),
313275576Savg	USB_QUIRK(PANASONIC, KXL840AN, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
314275576Savg	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_GETMAXLUN),
315275576Savg	USB_QUIRK(PANASONIC, KXLCB20AN, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
316275576Savg	    UQ_MSC_FORCE_PROTO_SCSI),
317275576Savg	USB_QUIRK(PANASONIC, KXLCB35AN, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
318275576Savg	    UQ_MSC_FORCE_PROTO_SCSI),
319275576Savg	USB_QUIRK(PANASONIC, LS120CAM, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_UFI),
320275576Savg	USB_QUIRK(PLEXTOR, 40_12_40U, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
321275576Savg	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_TEST_UNIT_READY),
322275576Savg	USB_QUIRK(PNY, ATTACHE2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
323275576Savg	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE,
324275576Savg	    UQ_MSC_NO_START_STOP),
325275576Savg	USB_QUIRK(PROLIFIC, PL2506, 0x0000, 0xffff,
326275576Savg	    UQ_MSC_NO_SYNC_CACHE),
327275576Savg	USB_QUIRK_VP(USB_VENDOR_SAMSUNG_TECHWIN,
328275576Savg	    USB_PRODUCT_SAMSUNG_TECHWIN_DIGIMAX_410, UQ_MSC_FORCE_WIRE_BBB,
329275576Savg	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
330275576Savg	USB_QUIRK(SANDISK, SDDR05A, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
331275576Savg	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_READ_CAP_OFFBY1,
332179237Sjb	    UQ_MSC_NO_GETMAXLUN),
333179237Sjb	USB_QUIRK(SANDISK, SDDR09, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI,
334179237Sjb	    UQ_MSC_READ_CAP_OFFBY1, UQ_MSC_NO_GETMAXLUN),
335179237Sjb	USB_QUIRK(SANDISK, SDDR12, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
336179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_READ_CAP_OFFBY1,
337179237Sjb	    UQ_MSC_NO_GETMAXLUN),
338179237Sjb	USB_QUIRK(SANDISK, SDCZ2_128, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
339179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE,
340179237Sjb	    UQ_MSC_NO_SYNC_CACHE),
341179237Sjb	USB_QUIRK(SANDISK, SDCZ2_256, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
342179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
343179237Sjb	USB_QUIRK(SANDISK, SDCZ4_128, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
344179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
345179237Sjb	USB_QUIRK(SANDISK, SDCZ4_256, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
346179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
347179237Sjb	USB_QUIRK(SANDISK, SDDR31, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
348179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_READ_CAP_OFFBY1),
349179237Sjb	USB_QUIRK(SANDISK, IMAGEMATE_SDDR289, 0x0000, 0xffff,
350179237Sjb	    UQ_MSC_NO_SYNC_CACHE, UQ_MSC_NO_GETMAXLUN),
351179237Sjb	USB_QUIRK(SCANLOGIC, SL11R, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
352179237Sjb	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_INQUIRY),
353275576Savg	USB_QUIRK(SHUTTLE, EUSB, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI_I,
354179237Sjb	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_TEST_UNIT_READY,
355179237Sjb	    UQ_MSC_NO_START_STOP, UQ_MSC_SHUTTLE_INIT),
356275576Savg	USB_QUIRK(SHUTTLE, CDRW, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
357275576Savg	    UQ_MSC_FORCE_PROTO_ATAPI),
358283291Sjkim	USB_QUIRK(SHUTTLE, CF, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
359275576Savg	    UQ_MSC_FORCE_PROTO_ATAPI),
360179237Sjb	USB_QUIRK(SHUTTLE, EUSBATAPI, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
361179237Sjb	    UQ_MSC_FORCE_PROTO_ATAPI),
362179237Sjb	USB_QUIRK(SHUTTLE, EUSBCFSM, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI),
363291855Sandrew	USB_QUIRK(SHUTTLE, EUSCSI, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
364179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI),
365179237Sjb	USB_QUIRK(SHUTTLE, HIFD, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
366179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN),
367179237Sjb	USB_QUIRK(SHUTTLE, SDDR09, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI,
368179237Sjb	    UQ_MSC_NO_GETMAXLUN),
369179237Sjb	USB_QUIRK(SHUTTLE, ZIOMMC, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
370179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN),
371179237Sjb	USB_QUIRK(SIGMATEL, I_BEAD100, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
372179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_SHUTTLE_INIT),
373179237Sjb	USB_QUIRK(SIIG, WINTERREADER, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
374179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
375179237Sjb	USB_QUIRK(SKANHEX, MD_7425, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
376179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
377179237Sjb	USB_QUIRK(SKANHEX, SX_520Z, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
378179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
379179237Sjb	USB_QUIRK(SONY, HANDYCAM, 0x0500, 0x0500, UQ_MSC_FORCE_WIRE_CBI,
380179237Sjb	    UQ_MSC_FORCE_PROTO_RBC, UQ_MSC_RBC_PAD_TO_12),
381179237Sjb	USB_QUIRK(SONY, CLIE_40_MS, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
382179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
383179237Sjb	USB_QUIRK(SONY, DSC, 0x0500, 0x0500, UQ_MSC_FORCE_WIRE_CBI,
384179237Sjb	    UQ_MSC_FORCE_PROTO_RBC, UQ_MSC_RBC_PAD_TO_12),
385179237Sjb	USB_QUIRK(SONY, DSC, 0x0600, 0x0600, UQ_MSC_FORCE_WIRE_CBI,
386179237Sjb	    UQ_MSC_FORCE_PROTO_RBC, UQ_MSC_RBC_PAD_TO_12),
387179237Sjb	USB_QUIRK(SONY, DSC, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
388179237Sjb	    UQ_MSC_FORCE_PROTO_RBC),
389179237Sjb	USB_QUIRK(SONY, HANDYCAM, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
390179237Sjb	    UQ_MSC_FORCE_PROTO_RBC),
391179237Sjb	USB_QUIRK(SONY, MSC, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
392179237Sjb	    UQ_MSC_FORCE_PROTO_RBC),
393179237Sjb	USB_QUIRK(SONY, MS_MSC_U03, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
394179237Sjb	    UQ_MSC_FORCE_PROTO_UFI, UQ_MSC_NO_GETMAXLUN),
395179237Sjb	USB_QUIRK(SONY, MS_NW_MS7, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
396179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN),
397179237Sjb	USB_QUIRK(SONY, MS_PEG_N760C, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
398179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
399179237Sjb	USB_QUIRK(SONY, MSACUS1, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
400179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN),
401179237Sjb	USB_QUIRK(SONY, PORTABLE_HDD_V2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
402179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI),
403179237Sjb	USB_QUIRK(STMICRO, ST72682, 0x0000, 0xffff, UQ_MSC_NO_PREVENT_ALLOW),
404179237Sjb	USB_QUIRK(SUPERTOP, IDE, 0x0000, 0xffff, UQ_MSC_IGNORE_RESIDUE,
405179237Sjb	    UQ_MSC_NO_SYNC_CACHE),
406179237Sjb	USB_QUIRK(SUPERTOP, FLASHDRIVE, 0x0000, 0xffff, UQ_MSC_NO_TEST_UNIT_READY,
407179237Sjb	    UQ_MSC_NO_SYNC_CACHE),
408179237Sjb	USB_QUIRK(TAUGA, CAMERAMATE, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI),
409179237Sjb	USB_QUIRK(TEAC, FD05PUB, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
410179237Sjb	    UQ_MSC_FORCE_PROTO_UFI),
411179237Sjb	USB_QUIRK(TECLAST, TLC300, 0x0000, 0xffff, UQ_MSC_NO_TEST_UNIT_READY,
412179237Sjb	    UQ_MSC_NO_SYNC_CACHE),
413179237Sjb	USB_QUIRK(TREK, MEMKEY, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
414179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
415179237Sjb	USB_QUIRK(TREK, THUMBDRIVE_8MB, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
416179237Sjb	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_IGNORE_RESIDUE),
417179237Sjb	USB_QUIRK(TRUMPION, C3310, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
418179237Sjb	    UQ_MSC_FORCE_PROTO_UFI),
419179237Sjb	USB_QUIRK(TRUMPION, MP3, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_RBC),
420179237Sjb	USB_QUIRK(TRUMPION, T33520, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI),
421179237Sjb	USB_QUIRK(TWINMOS, MDIV, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
422179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI),
423179237Sjb	USB_QUIRK(VIA, USB2IDEBRIDGE, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
424179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_SYNC_CACHE),
425179237Sjb	USB_QUIRK(VIVITAR, 35XX, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
426179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
427179237Sjb	USB_QUIRK(WESTERN, COMBO, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
428179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_FORCE_SHORT_INQ,
429179237Sjb	    UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE),
430179237Sjb	USB_QUIRK(WESTERN, EXTHDD, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
431179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_FORCE_SHORT_INQ,
432179237Sjb	    UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE),
433179237Sjb	USB_QUIRK(WESTERN, MYBOOK, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
434179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY_EVPD,
435179237Sjb	    UQ_MSC_NO_SYNC_CACHE),
436179237Sjb	USB_QUIRK(WESTERN, MYPASSWORD, 0x0000, 0xffff, UQ_MSC_FORCE_SHORT_INQ),
437179237Sjb	USB_QUIRK(WESTERN, MYPASSPORT, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
438179237Sjb	USB_QUIRK(WINMAXGROUP, FLASH64MC, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
439179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
440179237Sjb	USB_QUIRK(YANO, FW800HD, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
441179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_FORCE_SHORT_INQ,
442179237Sjb	    UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE),
443179237Sjb	USB_QUIRK(YANO, U640MO, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI_I,
444179237Sjb	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_FORCE_SHORT_INQ),
445179237Sjb	USB_QUIRK(YEDATA, FLASHBUSTERU, 0x0000, 0x007F, UQ_MSC_FORCE_WIRE_CBI,
446179237Sjb	    UQ_MSC_FORCE_PROTO_UFI, UQ_MSC_NO_RS_CLEAR_UA, UQ_MSC_FLOPPY_SPEED,
447179237Sjb	    UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_GETMAXLUN),
448179237Sjb	USB_QUIRK(YEDATA, FLASHBUSTERU, 0x0080, 0x0080, UQ_MSC_FORCE_WIRE_CBI_I,
449179237Sjb	    UQ_MSC_FORCE_PROTO_UFI, UQ_MSC_NO_RS_CLEAR_UA, UQ_MSC_FLOPPY_SPEED,
450179237Sjb	    UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_GETMAXLUN),
451179237Sjb	USB_QUIRK(YEDATA, FLASHBUSTERU, 0x0081, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI_I,
452179237Sjb	    UQ_MSC_FORCE_PROTO_UFI, UQ_MSC_NO_RS_CLEAR_UA, UQ_MSC_FLOPPY_SPEED,
453179237Sjb	    UQ_MSC_NO_GETMAXLUN),
454179237Sjb	USB_QUIRK(ZORAN, EX20DSC, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
455179237Sjb	    UQ_MSC_FORCE_PROTO_ATAPI),
456179237Sjb	USB_QUIRK(MEIZU, M6_SL, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
457179237Sjb	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY, UQ_MSC_NO_SYNC_CACHE),
458179237Sjb	USB_QUIRK(TOSHIBA, TRANSMEMORY, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE,
459179237Sjb	    UQ_MSC_NO_PREVENT_ALLOW),
460179237Sjb	USB_QUIRK(VIALABS, USB30SATABRIDGE, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
461179237Sjb
462179237Sjb	/* Non-standard USB MIDI devices */
463179237Sjb	USB_QUIRK(ROLAND, UM1, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
464179237Sjb	USB_QUIRK(ROLAND, SC8850, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
465179237Sjb	USB_QUIRK(ROLAND, SD90, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
466179237Sjb	USB_QUIRK(ROLAND, UM880N, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
467179237Sjb	USB_QUIRK(ROLAND, UA100, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
468179237Sjb	USB_QUIRK(ROLAND, UM4, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
469179237Sjb	USB_QUIRK(ROLAND, U8, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
470179237Sjb	USB_QUIRK(ROLAND, UM2, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
471179237Sjb	USB_QUIRK(ROLAND, SC8820, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
472179237Sjb	USB_QUIRK(ROLAND, PC300, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
473179237Sjb	USB_QUIRK(ROLAND, SK500, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
474179237Sjb	USB_QUIRK(ROLAND, SCD70, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
475179237Sjb	USB_QUIRK(ROLAND, UM550, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
476179237Sjb	USB_QUIRK(ROLAND, SD20, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
477179237Sjb	USB_QUIRK(ROLAND, SD80, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
478179237Sjb	USB_QUIRK(ROLAND, UA700, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
479179237Sjb	USB_QUIRK(EGO, M4U, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI),
480179237Sjb	USB_QUIRK(LOGILINK, U2M, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI),
481179237Sjb	USB_QUIRK(MEDELI, DD305, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI, UQ_MATCH_VENDOR_ONLY),
482179237Sjb	USB_QUIRK(REDOCTANE, GHMIDI, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI),
483179237Sjb	USB_QUIRK(TEXTECH, U2M_1, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI),
484179237Sjb	USB_QUIRK(TEXTECH, U2M_2, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI),
485179237Sjb	USB_QUIRK(WCH2, U2M, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI),
486179237Sjb
487179237Sjb	/* Non-standard USB AUDIO devices */
488179237Sjb	USB_QUIRK(MAUDIO, FASTTRACKULTRA, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
489179237Sjb	USB_QUIRK(MAUDIO, FASTTRACKULTRA8R, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
490179237Sjb
491179237Sjb	/*
492179237Sjb	 * Quirks for manufacturers which USB devices does not respond
493179237Sjb	 * after issuing non-supported commands:
494179237Sjb	 */
495179237Sjb	USB_QUIRK(ALCOR, DUMMY, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE, UQ_MSC_NO_TEST_UNIT_READY, UQ_MATCH_VENDOR_ONLY),
496179237Sjb	USB_QUIRK(APPLE, DUMMY, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE, UQ_MATCH_VENDOR_ONLY),
497179237Sjb	USB_QUIRK(FEIYA, DUMMY, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE, UQ_MATCH_VENDOR_ONLY),
498179237Sjb	USB_QUIRK(REALTEK, DUMMY, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE, UQ_MATCH_VENDOR_ONLY),
499179237Sjb	USB_QUIRK(INITIO, DUMMY, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE, UQ_MATCH_VENDOR_ONLY),
500179237Sjb};
501179237Sjb#undef USB_QUIRK_VP
502179237Sjb#undef USB_QUIRK
503179237Sjb
504275576Savgstatic const char *usb_quirk_str[USB_QUIRK_MAX] = {
505179237Sjb	[UQ_NONE]		= "UQ_NONE",
506275576Savg	[UQ_MATCH_VENDOR_ONLY]	= "UQ_MATCH_VENDOR_ONLY",
507275576Savg	[UQ_AUDIO_SWAP_LR]	= "UQ_AUDIO_SWAP_LR",
508275576Savg	[UQ_AU_INP_ASYNC]	= "UQ_AU_INP_ASYNC",
509179237Sjb	[UQ_AU_NO_FRAC]		= "UQ_AU_NO_FRAC",
510179237Sjb	[UQ_AU_NO_XU]		= "UQ_AU_NO_XU",
511179237Sjb	[UQ_BAD_ADC]		= "UQ_BAD_ADC",
512179237Sjb	[UQ_BAD_AUDIO]		= "UQ_BAD_AUDIO",
513179237Sjb	[UQ_BROKEN_BIDIR]	= "UQ_BROKEN_BIDIR",
514179237Sjb	[UQ_BUS_POWERED]	= "UQ_BUS_POWERED",
515275576Savg	[UQ_HID_IGNORE]		= "UQ_HID_IGNORE",
516179237Sjb	[UQ_KBD_IGNORE]		= "UQ_KBD_IGNORE",
517179237Sjb	[UQ_KBD_BOOTPROTO]	= "UQ_KBD_BOOTPROTO",
518179237Sjb	[UQ_UMS_IGNORE]		= "UQ_UMS_IGNORE",
519179237Sjb	[UQ_MS_BAD_CLASS]	= "UQ_MS_BAD_CLASS",
520179237Sjb	[UQ_MS_LEADING_BYTE]	= "UQ_MS_LEADING_BYTE",
521179237Sjb	[UQ_MS_REVZ]		= "UQ_MS_REVZ",
522179237Sjb	[UQ_NO_STRINGS]		= "UQ_NO_STRINGS",
523179237Sjb	[UQ_POWER_CLAIM]	= "UQ_POWER_CLAIM",
524179237Sjb	[UQ_SPUR_BUT_UP]	= "UQ_SPUR_BUT_UP",
525179237Sjb	[UQ_SWAP_UNICODE]	= "UQ_SWAP_UNICODE",
526179237Sjb	[UQ_CFG_INDEX_1]	= "UQ_CFG_INDEX_1",
527179237Sjb	[UQ_CFG_INDEX_2]	= "UQ_CFG_INDEX_2",
528179237Sjb	[UQ_CFG_INDEX_3]	= "UQ_CFG_INDEX_3",
529179237Sjb	[UQ_CFG_INDEX_4]	= "UQ_CFG_INDEX_4",
530179237Sjb	[UQ_CFG_INDEX_0]	= "UQ_CFG_INDEX_0",
531179237Sjb	[UQ_ASSUME_CM_OVER_DATA]	= "UQ_ASSUME_CM_OVER_DATA",
532179237Sjb	[UQ_MSC_NO_TEST_UNIT_READY]	= "UQ_MSC_NO_TEST_UNIT_READY",
533179237Sjb	[UQ_MSC_NO_RS_CLEAR_UA]		= "UQ_MSC_NO_RS_CLEAR_UA",
534179237Sjb	[UQ_MSC_NO_START_STOP]		= "UQ_MSC_NO_START_STOP",
535179237Sjb	[UQ_MSC_NO_GETMAXLUN]		= "UQ_MSC_NO_GETMAXLUN",
536179237Sjb	[UQ_MSC_NO_INQUIRY]		= "UQ_MSC_NO_INQUIRY",
537179237Sjb	[UQ_MSC_NO_INQUIRY_EVPD]	= "UQ_MSC_NO_INQUIRY_EVPD",
538179237Sjb	[UQ_MSC_NO_PREVENT_ALLOW]	= "UQ_MSC_NO_PREVENT_ALLOW",
539179237Sjb	[UQ_MSC_NO_SYNC_CACHE]		= "UQ_MSC_NO_SYNC_CACHE",
540179237Sjb	[UQ_MSC_SHUTTLE_INIT]		= "UQ_MSC_SHUTTLE_INIT",
541179237Sjb	[UQ_MSC_ALT_IFACE_1]		= "UQ_MSC_ALT_IFACE_1",
542179237Sjb	[UQ_MSC_FLOPPY_SPEED]		= "UQ_MSC_FLOPPY_SPEED",
543179237Sjb	[UQ_MSC_IGNORE_RESIDUE]		= "UQ_MSC_IGNORE_RESIDUE",
544179237Sjb	[UQ_MSC_WRONG_CSWSIG]		= "UQ_MSC_WRONG_CSWSIG",
545179237Sjb	[UQ_MSC_RBC_PAD_TO_12]		= "UQ_MSC_RBC_PAD_TO_12",
546179237Sjb	[UQ_MSC_READ_CAP_OFFBY1]	= "UQ_MSC_READ_CAP_OFFBY1",
547179237Sjb	[UQ_MSC_FORCE_SHORT_INQ]	= "UQ_MSC_FORCE_SHORT_INQ",
548179237Sjb	[UQ_MSC_FORCE_WIRE_BBB]		= "UQ_MSC_FORCE_WIRE_BBB",
549179237Sjb	[UQ_MSC_FORCE_WIRE_CBI]		= "UQ_MSC_FORCE_WIRE_CBI",
550179237Sjb	[UQ_MSC_FORCE_WIRE_CBI_I]	= "UQ_MSC_FORCE_WIRE_CBI_I",
551179237Sjb	[UQ_MSC_FORCE_PROTO_SCSI]	= "UQ_MSC_FORCE_PROTO_SCSI",
552179237Sjb	[UQ_MSC_FORCE_PROTO_ATAPI]	= "UQ_MSC_FORCE_PROTO_ATAPI",
553179237Sjb	[UQ_MSC_FORCE_PROTO_UFI]	= "UQ_MSC_FORCE_PROTO_UFI",
554179237Sjb	[UQ_MSC_FORCE_PROTO_RBC]	= "UQ_MSC_FORCE_PROTO_RBC",
555179237Sjb	[UQ_MSC_EJECT_HUAWEI]		= "UQ_MSC_EJECT_HUAWEI",
556179237Sjb	[UQ_MSC_EJECT_SIERRA]		= "UQ_MSC_EJECT_SIERRA",
557179237Sjb	[UQ_MSC_EJECT_SCSIEJECT]	= "UQ_MSC_EJECT_SCSIEJECT",
558179237Sjb	[UQ_MSC_EJECT_REZERO]		= "UQ_MSC_EJECT_REZERO",
559179237Sjb	[UQ_MSC_EJECT_ZTESTOR]		= "UQ_MSC_EJECT_ZTESTOR",
560179237Sjb	[UQ_MSC_EJECT_CMOTECH]		= "UQ_MSC_EJECT_CMOTECH",
561179237Sjb	[UQ_MSC_EJECT_WAIT]		= "UQ_MSC_EJECT_WAIT",
562179237Sjb	[UQ_MSC_EJECT_SAEL_M460]	= "UQ_MSC_EJECT_SAEL_M460",
563179237Sjb	[UQ_MSC_EJECT_HUAWEISCSI]	= "UQ_MSC_EJECT_HUAWEISCSI",
564179237Sjb	[UQ_MSC_EJECT_TCT]		= "UQ_MSC_EJECT_TCT",
565179237Sjb	[UQ_BAD_MIDI]			= "UQ_BAD_MIDI",
566179237Sjb	[UQ_AU_VENDOR_CLASS]		= "UQ_AU_VENDOR_CLASS",
567179237Sjb	[UQ_SINGLE_CMD_MIDI]		= "UQ_SINGLE_CMD_MIDI",
568179237Sjb};
569179237Sjb
570179237Sjb/*------------------------------------------------------------------------*
571179237Sjb *	usb_quirkstr
572179237Sjb *
573179237Sjb * This function converts an USB quirk code into a string.
574179237Sjb *------------------------------------------------------------------------*/
575179237Sjbstatic const char *
576179237Sjbusb_quirkstr(uint16_t quirk)
577179237Sjb{
578179237Sjb	return ((quirk < USB_QUIRK_MAX) ?
579179237Sjb	    usb_quirk_str[quirk] : "USB_QUIRK_UNKNOWN");
580179237Sjb}
581179237Sjb
582179237Sjb/*------------------------------------------------------------------------*
583179237Sjb *	usb_test_quirk_by_info
584179237Sjb *
585179237Sjb * Returns:
586179237Sjb * 0: Quirk not found
587179237Sjb * Else: Quirk found
588179237Sjb *------------------------------------------------------------------------*/
589179237Sjbstatic uint8_t
590179237Sjbusb_test_quirk_by_info(const struct usbd_lookup_info *info, uint16_t quirk)
591275576Savg{
592275576Savg	uint16_t x;
593179237Sjb	uint16_t y;
594275576Savg
595275576Savg	if (quirk == UQ_NONE)
596275576Savg		goto done;
597275576Savg
598275576Savg	mtx_lock(&usb_quirk_mtx);
599275576Savg
600275576Savg	for (x = 0; x != USB_DEV_QUIRKS_MAX; x++) {
601275576Savg		/* see if quirk information does not match */
602275576Savg		if ((usb_quirks[x].vid != info->idVendor) ||
603275576Savg		    (usb_quirks[x].lo_rev > info->bcdDevice) ||
604275576Savg		    (usb_quirks[x].hi_rev < info->bcdDevice)) {
605275576Savg			continue;
606283291Sjkim		}
607275576Savg		/* see if quirk only should match vendor ID */
608275576Savg		if (usb_quirks[x].pid != info->idProduct) {
609275576Savg			if (usb_quirks[x].pid != 0)
610275576Savg				continue;
611275576Savg
612275576Savg			for (y = 0; y != USB_SUB_QUIRKS_MAX; y++) {
613275576Savg				if (usb_quirks[x].quirks[y] == UQ_MATCH_VENDOR_ONLY)
614275576Savg					break;
615275576Savg			}
616275576Savg			if (y == USB_SUB_QUIRKS_MAX)
617275576Savg				continue;
618275576Savg		}
619275576Savg		/* lookup quirk */
620275576Savg		for (y = 0; y != USB_SUB_QUIRKS_MAX; y++) {
621275576Savg			if (usb_quirks[x].quirks[y] == quirk) {
622275576Savg				mtx_unlock(&usb_quirk_mtx);
623275576Savg				DPRINTF("Found quirk '%s'.\n", usb_quirkstr(quirk));
624275576Savg				return (1);
625275576Savg			}
626275576Savg		}
627275576Savg		/* no quirk found */
628275576Savg		break;
629275576Savg	}
630275576Savg	mtx_unlock(&usb_quirk_mtx);
631275576Savgdone:
632275576Savg	return (0);			/* no quirk match */
633275576Savg}
634275576Savg
635275576Savgstatic struct usb_quirk_entry *
636275576Savgusb_quirk_get_entry(uint16_t vid, uint16_t pid,
637275576Savg    uint16_t lo_rev, uint16_t hi_rev, uint8_t do_alloc)
638275576Savg{
639275576Savg	uint16_t x;
640275576Savg
641275576Savg	mtx_assert(&usb_quirk_mtx, MA_OWNED);
642275576Savg
643275576Savg	if ((vid | pid | lo_rev | hi_rev) == 0) {
644275576Savg		/* all zero - special case */
645275576Savg		return (usb_quirks + USB_DEV_QUIRKS_MAX - 1);
646275576Savg	}
647275576Savg	/* search for an existing entry */
648275576Savg	for (x = 0; x != USB_DEV_QUIRKS_MAX; x++) {
649275576Savg		/* see if quirk information does not match */
650275576Savg		if ((usb_quirks[x].vid != vid) ||
651275576Savg		    (usb_quirks[x].pid != pid) ||
652275576Savg		    (usb_quirks[x].lo_rev != lo_rev) ||
653275576Savg		    (usb_quirks[x].hi_rev != hi_rev)) {
654275576Savg			continue;
655275576Savg		}
656275576Savg		return (usb_quirks + x);
657275576Savg	}
658275576Savg
659275576Savg	if (do_alloc == 0) {
660275576Savg		/* no match */
661275576Savg		return (NULL);
662275576Savg	}
663275576Savg	/* search for a free entry */
664275576Savg	for (x = 0; x != USB_DEV_QUIRKS_MAX; x++) {
665275576Savg		/* see if quirk information does not match */
666275576Savg		if ((usb_quirks[x].vid |
667179237Sjb		    usb_quirks[x].pid |
668179237Sjb		    usb_quirks[x].lo_rev |
669179237Sjb		    usb_quirks[x].hi_rev) != 0) {
670179237Sjb			continue;
671179237Sjb		}
672179237Sjb		usb_quirks[x].vid = vid;
673179237Sjb		usb_quirks[x].pid = pid;
674179237Sjb		usb_quirks[x].lo_rev = lo_rev;
675179237Sjb		usb_quirks[x].hi_rev = hi_rev;
676179237Sjb
677179237Sjb		return (usb_quirks + x);
678179237Sjb	}
679179237Sjb
680179237Sjb	/* no entry found */
681179237Sjb	return (NULL);
682179237Sjb}
683179237Sjb
684179237Sjb/*------------------------------------------------------------------------*
685179237Sjb *	usb_quirk_ioctl - handle quirk IOCTLs
686179237Sjb *
687179237Sjb * Returns:
688179237Sjb * 0: Success
689179237Sjb * Else: Failure
690179237Sjb *------------------------------------------------------------------------*/
691179237Sjbstatic int
692179237Sjbusb_quirk_ioctl(unsigned long cmd, caddr_t data,
693179237Sjb    int fflag, struct thread *td)
694179237Sjb{
695179237Sjb	struct usb_gen_quirk *pgq;
696179237Sjb	struct usb_quirk_entry *pqe;
697179237Sjb	uint32_t x;
698179237Sjb	uint32_t y;
699179237Sjb	int err;
700179237Sjb
701179237Sjb	switch (cmd) {
702179237Sjb	case USB_DEV_QUIRK_GET:
703179237Sjb		pgq = (void *)data;
704179237Sjb		x = pgq->index % USB_SUB_QUIRKS_MAX;
705179237Sjb		y = pgq->index / USB_SUB_QUIRKS_MAX;
706179237Sjb		if (y >= USB_DEV_QUIRKS_MAX) {
707179237Sjb			return (EINVAL);
708179237Sjb		}
709179237Sjb		mtx_lock(&usb_quirk_mtx);
710179237Sjb		/* copy out data */
711179237Sjb		pgq->vid = usb_quirks[y].vid;
712179237Sjb		pgq->pid = usb_quirks[y].pid;
713179237Sjb		pgq->bcdDeviceLow = usb_quirks[y].lo_rev;
714179237Sjb		pgq->bcdDeviceHigh = usb_quirks[y].hi_rev;
715179237Sjb		strlcpy(pgq->quirkname,
716179237Sjb		    usb_quirkstr(usb_quirks[y].quirks[x]),
717179237Sjb		    sizeof(pgq->quirkname));
718179237Sjb		mtx_unlock(&usb_quirk_mtx);
719179237Sjb		return (0);		/* success */
720179237Sjb
721179237Sjb	case USB_QUIRK_NAME_GET:
722179237Sjb		pgq = (void *)data;
723179237Sjb		x = pgq->index;
724179237Sjb		if (x >= USB_QUIRK_MAX) {
725179237Sjb			return (EINVAL);
726179237Sjb		}
727179237Sjb		strlcpy(pgq->quirkname,
728179237Sjb		    usb_quirkstr(x), sizeof(pgq->quirkname));
729179237Sjb		return (0);		/* success */
730
731	case USB_DEV_QUIRK_ADD:
732		pgq = (void *)data;
733
734		/* check privileges */
735		err = priv_check(curthread, PRIV_DRIVER);
736		if (err) {
737			return (err);
738		}
739		/* convert quirk string into numerical */
740		for (y = 0; y != USB_DEV_QUIRKS_MAX; y++) {
741			if (strcmp(pgq->quirkname, usb_quirkstr(y)) == 0) {
742				break;
743			}
744		}
745		if (y == USB_DEV_QUIRKS_MAX) {
746			return (EINVAL);
747		}
748		if (y == UQ_NONE) {
749			return (EINVAL);
750		}
751		mtx_lock(&usb_quirk_mtx);
752		pqe = usb_quirk_get_entry(pgq->vid, pgq->pid,
753		    pgq->bcdDeviceLow, pgq->bcdDeviceHigh, 1);
754		if (pqe == NULL) {
755			mtx_unlock(&usb_quirk_mtx);
756			return (EINVAL);
757		}
758		for (x = 0; x != USB_SUB_QUIRKS_MAX; x++) {
759			if (pqe->quirks[x] == UQ_NONE) {
760				pqe->quirks[x] = y;
761				break;
762			}
763		}
764		mtx_unlock(&usb_quirk_mtx);
765		if (x == USB_SUB_QUIRKS_MAX) {
766			return (ENOMEM);
767		}
768		return (0);		/* success */
769
770	case USB_DEV_QUIRK_REMOVE:
771		pgq = (void *)data;
772		/* check privileges */
773		err = priv_check(curthread, PRIV_DRIVER);
774		if (err) {
775			return (err);
776		}
777		/* convert quirk string into numerical */
778		for (y = 0; y != USB_DEV_QUIRKS_MAX; y++) {
779			if (strcmp(pgq->quirkname, usb_quirkstr(y)) == 0) {
780				break;
781			}
782		}
783		if (y == USB_DEV_QUIRKS_MAX) {
784			return (EINVAL);
785		}
786		if (y == UQ_NONE) {
787			return (EINVAL);
788		}
789		mtx_lock(&usb_quirk_mtx);
790		pqe = usb_quirk_get_entry(pgq->vid, pgq->pid,
791		    pgq->bcdDeviceLow, pgq->bcdDeviceHigh, 0);
792		if (pqe == NULL) {
793			mtx_unlock(&usb_quirk_mtx);
794			return (EINVAL);
795		}
796		for (x = 0; x != USB_SUB_QUIRKS_MAX; x++) {
797			if (pqe->quirks[x] == y) {
798				pqe->quirks[x] = UQ_NONE;
799				break;
800			}
801		}
802		if (x == USB_SUB_QUIRKS_MAX) {
803			mtx_unlock(&usb_quirk_mtx);
804			return (ENOMEM);
805		}
806		for (x = 0; x != USB_SUB_QUIRKS_MAX; x++) {
807			if (pqe->quirks[x] != UQ_NONE) {
808				break;
809			}
810		}
811		if (x == USB_SUB_QUIRKS_MAX) {
812			/* all quirk entries are unused - release */
813			memset(pqe, 0, sizeof(*pqe));
814		}
815		mtx_unlock(&usb_quirk_mtx);
816		return (0);		/* success */
817
818	default:
819		break;
820	}
821	return (ENOIOCTL);
822}
823
824static void
825usb_quirk_init(void *arg)
826{
827	/* initialize mutex */
828	mtx_init(&usb_quirk_mtx, "USB quirk", NULL, MTX_DEF);
829
830	/* register our function */
831	usb_test_quirk_p = &usb_test_quirk_by_info;
832	usb_quirk_ioctl_p = &usb_quirk_ioctl;
833}
834
835static void
836usb_quirk_uninit(void *arg)
837{
838	usb_quirk_unload(arg);
839
840	/* destroy mutex */
841	mtx_destroy(&usb_quirk_mtx);
842}
843
844SYSINIT(usb_quirk_init, SI_SUB_LOCK, SI_ORDER_FIRST, usb_quirk_init, NULL);
845SYSUNINIT(usb_quirk_uninit, SI_SUB_LOCK, SI_ORDER_ANY, usb_quirk_uninit, NULL);
846