xref: /freebsd-src/sys/dev/usb/quirk/usb_quirk.c (revision 9c0cce328363bd62f3c9add67bea7422208d9903)
102ac6454SAndrew Thompson /*-
2b61a5730SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni  *
402ac6454SAndrew Thompson  * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
502ac6454SAndrew Thompson  * Copyright (c) 1998 Lennart Augustsson. All rights reserved.
602ac6454SAndrew Thompson  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
702ac6454SAndrew Thompson  *
802ac6454SAndrew Thompson  * Redistribution and use in source and binary forms, with or without
902ac6454SAndrew Thompson  * modification, are permitted provided that the following conditions
1002ac6454SAndrew Thompson  * are met:
1102ac6454SAndrew Thompson  * 1. Redistributions of source code must retain the above copyright
1202ac6454SAndrew Thompson  *    notice, this list of conditions and the following disclaimer.
1302ac6454SAndrew Thompson  * 2. Redistributions in binary form must reproduce the above copyright
1402ac6454SAndrew Thompson  *    notice, this list of conditions and the following disclaimer in the
1502ac6454SAndrew Thompson  *    documentation and/or other materials provided with the distribution.
1602ac6454SAndrew Thompson  *
1702ac6454SAndrew Thompson  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1802ac6454SAndrew Thompson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1902ac6454SAndrew Thompson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2002ac6454SAndrew Thompson  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2102ac6454SAndrew Thompson  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2202ac6454SAndrew Thompson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2302ac6454SAndrew Thompson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2402ac6454SAndrew Thompson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2502ac6454SAndrew Thompson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2602ac6454SAndrew Thompson  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2702ac6454SAndrew Thompson  * SUCH DAMAGE.
2802ac6454SAndrew Thompson  */
2902ac6454SAndrew Thompson 
30ed6d949aSAndrew Thompson #include <sys/stdint.h>
31ed6d949aSAndrew Thompson #include <sys/stddef.h>
32ed6d949aSAndrew Thompson #include <sys/param.h>
33ed6d949aSAndrew Thompson #include <sys/queue.h>
34ed6d949aSAndrew Thompson #include <sys/types.h>
35ed6d949aSAndrew Thompson #include <sys/systm.h>
36ed6d949aSAndrew Thompson #include <sys/kernel.h>
37ed6d949aSAndrew Thompson #include <sys/bus.h>
38ed6d949aSAndrew Thompson #include <sys/module.h>
39ed6d949aSAndrew Thompson #include <sys/lock.h>
40ed6d949aSAndrew Thompson #include <sys/mutex.h>
41ed6d949aSAndrew Thompson #include <sys/condvar.h>
42ed6d949aSAndrew Thompson #include <sys/sysctl.h>
43ed6d949aSAndrew Thompson #include <sys/sx.h>
44ed6d949aSAndrew Thompson #include <sys/unistd.h>
45ed6d949aSAndrew Thompson #include <sys/callout.h>
46ed6d949aSAndrew Thompson #include <sys/malloc.h>
47ed6d949aSAndrew Thompson #include <sys/priv.h>
48ed6d949aSAndrew Thompson 
4902ac6454SAndrew Thompson #include <dev/usb/usb.h>
5002ac6454SAndrew Thompson #include <dev/usb/usb_ioctl.h>
51ed6d949aSAndrew Thompson #include <dev/usb/usbdi.h>
5202ac6454SAndrew Thompson #include "usbdevs.h"
5302ac6454SAndrew Thompson 
54a593f6b8SAndrew Thompson #define	USB_DEBUG_VAR usb_debug
5502ac6454SAndrew Thompson #include <dev/usb/usb_debug.h>
5602ac6454SAndrew Thompson #include <dev/usb/usb_dynamic.h>
5702ac6454SAndrew Thompson 
5802ac6454SAndrew Thompson #include <dev/usb/quirk/usb_quirk.h>
5902ac6454SAndrew Thompson 
6002ac6454SAndrew Thompson MODULE_DEPEND(usb_quirk, usb, 1, 1, 1);
6102ac6454SAndrew Thompson MODULE_VERSION(usb_quirk, 1);
6202ac6454SAndrew Thompson 
63cfb13951SHans Petter Selasky #define	USB_DEV_QUIRKS_MAX 384
6402ac6454SAndrew Thompson #define	USB_SUB_QUIRKS_MAX 8
65a130076fSHans Petter Selasky #define	USB_QUIRK_ENVROOT "hw.usb.quirk."
6602ac6454SAndrew Thompson 
67a593f6b8SAndrew Thompson struct usb_quirk_entry {
6802ac6454SAndrew Thompson 	uint16_t vid;
6902ac6454SAndrew Thompson 	uint16_t pid;
7002ac6454SAndrew Thompson 	uint16_t lo_rev;
7102ac6454SAndrew Thompson 	uint16_t hi_rev;
7202ac6454SAndrew Thompson 	uint16_t quirks[USB_SUB_QUIRKS_MAX];
7302ac6454SAndrew Thompson };
7402ac6454SAndrew Thompson 
75a593f6b8SAndrew Thompson static struct mtx usb_quirk_mtx;
7602ac6454SAndrew Thompson 
77881ae768SAhmad Khalifa #define	USB_QUIRK(v, p, ...) { \
78881ae768SAhmad Khalifa   .vid = USB_VENDOR_##v, .pid = USB_PRODUCT_##v##_##p, .lo_rev = 0x0000, \
79881ae768SAhmad Khalifa   .hi_rev = 0xffff, .quirks = { __VA_ARGS__ } \
8064e05e90SAhmad Khalifa }
8164e05e90SAhmad Khalifa 
8264e05e90SAhmad Khalifa /* Vendor only */
8364e05e90SAhmad Khalifa #define	USB_QUIRK_VO(v, ...) { \
8464e05e90SAhmad Khalifa   .vid = USB_VENDOR_##v, .pid = 0x0000, .lo_rev = 0x0000, .hi_rev = 0xffff, \
8564e05e90SAhmad Khalifa   .quirks = { UQ_MATCH_VENDOR_ONLY, __VA_ARGS__ } \
8664e05e90SAhmad Khalifa }
87b55b073fSAndrew Thompson 
88881ae768SAhmad Khalifa /* Specific revision(s) */
89881ae768SAhmad Khalifa #define	USB_QUIRK_REV(v, p, l, h, ...) { \
90881ae768SAhmad Khalifa   .vid = USB_VENDOR_##v, .pid = USB_PRODUCT_##v##_##p, .lo_rev = (l), \
91881ae768SAhmad Khalifa   .hi_rev = (h), .quirks = { __VA_ARGS__ } \
92881ae768SAhmad Khalifa }
93881ae768SAhmad Khalifa 
94a593f6b8SAndrew Thompson static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
95881ae768SAhmad Khalifa 	USB_QUIRK(ASUS, LCM, UQ_HID_IGNORE),
96881ae768SAhmad Khalifa 	USB_QUIRK_REV(INSIDEOUT, EDGEPORT4, 0x094, 0x094, UQ_SWAP_UNICODE),
97881ae768SAhmad Khalifa 	USB_QUIRK_REV(DALLAS, J6502, 0x0a2, 0x0a2, UQ_BAD_ADC),
98881ae768SAhmad Khalifa 	USB_QUIRK_REV(DALLAS, J6502, 0x0a2, 0x0a2, UQ_AU_NO_XU),
99881ae768SAhmad Khalifa 	USB_QUIRK_REV(ALTEC, ADA70, 0x103, 0x103, UQ_BAD_ADC),
100881ae768SAhmad Khalifa 	USB_QUIRK_REV(ALTEC, ASC495, 0x000, 0x000, UQ_BAD_AUDIO),
101881ae768SAhmad Khalifa 	USB_QUIRK_REV(QTRONIX, 980N, 0x110, 0x110, UQ_SPUR_BUT_UP),
102881ae768SAhmad Khalifa 	USB_QUIRK_REV(ALCOR2, KBD_HUB, 0x001, 0x001, UQ_SPUR_BUT_UP),
103881ae768SAhmad Khalifa 	USB_QUIRK_REV(MCT, HUB0100, 0x102, 0x102, UQ_BUS_POWERED),
104881ae768SAhmad Khalifa 	USB_QUIRK_REV(MCT, USB232, 0x102, 0x102, UQ_BUS_POWERED),
105881ae768SAhmad Khalifa 	USB_QUIRK_REV(TI, UTUSB41, 0x110, 0x110, UQ_POWER_CLAIM),
106881ae768SAhmad Khalifa 	USB_QUIRK_REV(TELEX, MIC1, 0x009, 0x009, UQ_AU_NO_FRAC),
107881ae768SAhmad Khalifa 	USB_QUIRK_REV(SILICONPORTALS, YAPPHONE, 0x100, 0x100, UQ_AU_INP_ASYNC),
108881ae768SAhmad Khalifa 	USB_QUIRK(LOGITECH, UN53B, UQ_NO_STRINGS),
109881ae768SAhmad Khalifa 	USB_QUIRK(LOGITECH, G510S, UQ_KBD_BOOTPROTO),
110881ae768SAhmad Khalifa 	USB_QUIRK(REALTEK, RTL8196EU, UQ_CFG_INDEX_1),
111881ae768SAhmad Khalifa 	USB_QUIRK(ELSA, MODEM1, UQ_CFG_INDEX_1),
112881ae768SAhmad Khalifa 	USB_QUIRK(PLANEX2, MZKUE150N, UQ_CFG_INDEX_1),
113881ae768SAhmad Khalifa 	USB_QUIRK(CISCOLINKSYS, USB3GIGV1, UQ_CFG_INDEX_1),
11425b74dabSHans Petter Selasky 	/* Quirks for printer devices */
115881ae768SAhmad Khalifa 	USB_QUIRK(HP, 895C, UQ_BROKEN_BIDIR),
116881ae768SAhmad Khalifa 	USB_QUIRK(HP, 880C, UQ_BROKEN_BIDIR),
117881ae768SAhmad Khalifa 	USB_QUIRK(HP, 815C, UQ_BROKEN_BIDIR),
118881ae768SAhmad Khalifa 	USB_QUIRK(HP, 810C, UQ_BROKEN_BIDIR),
119881ae768SAhmad Khalifa 	USB_QUIRK(HP, 830C, UQ_BROKEN_BIDIR),
120881ae768SAhmad Khalifa 	USB_QUIRK(HP, 1220C, UQ_BROKEN_BIDIR),
121881ae768SAhmad Khalifa 	USB_QUIRK(XEROX, WCM15, UQ_BROKEN_BIDIR),
12202ac6454SAndrew Thompson 	/* Devices which should be ignored by uhid */
123881ae768SAhmad Khalifa 	USB_QUIRK(APC, UPS, UQ_HID_IGNORE),
124881ae768SAhmad Khalifa 	USB_QUIRK(APC, UPS1000, UQ_HID_IGNORE),
125881ae768SAhmad Khalifa 	USB_QUIRK(BELKIN, F6H375USB, UQ_HID_IGNORE),
126881ae768SAhmad Khalifa 	USB_QUIRK(BELKIN, F6C550AVR, UQ_HID_IGNORE),
127881ae768SAhmad Khalifa 	USB_QUIRK(BELKIN, F6C1250TWRK, UQ_HID_IGNORE),
128881ae768SAhmad Khalifa 	USB_QUIRK(BELKIN, F6C1500TWRK, UQ_HID_IGNORE),
129881ae768SAhmad Khalifa 	USB_QUIRK(BELKIN, F6C900UNV, UQ_HID_IGNORE),
130881ae768SAhmad Khalifa 	USB_QUIRK(BELKIN, F6C100UNV, UQ_HID_IGNORE),
131881ae768SAhmad Khalifa 	USB_QUIRK(BELKIN, F6C120UNV, UQ_HID_IGNORE),
132881ae768SAhmad Khalifa 	USB_QUIRK(BELKIN, F6C800UNV, UQ_HID_IGNORE),
133881ae768SAhmad Khalifa 	USB_QUIRK(BELKIN, F6C1100UNV, UQ_HID_IGNORE),
134881ae768SAhmad Khalifa 	USB_QUIRK(CYBERPOWER, BC900D, UQ_HID_IGNORE),
135881ae768SAhmad Khalifa 	USB_QUIRK(CYBERPOWER, 1500CAVRLCD, UQ_HID_IGNORE),
136881ae768SAhmad Khalifa 	USB_QUIRK(CYBERPOWER, OR2200LCDRM2U, UQ_HID_IGNORE),
137881ae768SAhmad Khalifa 	USB_QUIRK(DELL2, VARIOUS_UPS, UQ_HID_IGNORE),
138881ae768SAhmad Khalifa 	USB_QUIRK(CYPRESS, SILVERSHIELD, UQ_HID_IGNORE),
139881ae768SAhmad Khalifa 	USB_QUIRK(DELORME, EARTHMATE, UQ_HID_IGNORE),
140881ae768SAhmad Khalifa 	USB_QUIRK(DREAMLINK, DL100B, UQ_HID_IGNORE),
141881ae768SAhmad Khalifa 	USB_QUIRK(MICROCHIP, PICOLCD20X2, UQ_HID_IGNORE),
142881ae768SAhmad Khalifa 	USB_QUIRK(MICROCHIP, PICOLCD4X20, UQ_HID_IGNORE),
143881ae768SAhmad Khalifa 	USB_QUIRK(LIEBERT, POWERSURE_PXT, UQ_HID_IGNORE),
144881ae768SAhmad Khalifa 	USB_QUIRK(LIEBERT2, PSI1000, UQ_HID_IGNORE),
145881ae768SAhmad Khalifa 	USB_QUIRK(LIEBERT2, POWERSURE_PSA, UQ_HID_IGNORE),
146881ae768SAhmad Khalifa 	USB_QUIRK(MGE, UPS1, UQ_HID_IGNORE),
147881ae768SAhmad Khalifa 	USB_QUIRK(MGE, UPS2, UQ_HID_IGNORE),
148881ae768SAhmad Khalifa 	USB_QUIRK(POWERCOM, IMPERIAL_SERIES, UQ_HID_IGNORE),
149881ae768SAhmad Khalifa 	USB_QUIRK(POWERCOM, SMART_KING_PRO, UQ_HID_IGNORE),
150881ae768SAhmad Khalifa 	USB_QUIRK(POWERCOM, WOW, UQ_HID_IGNORE),
151881ae768SAhmad Khalifa 	USB_QUIRK(POWERCOM, VANGUARD, UQ_HID_IGNORE),
152881ae768SAhmad Khalifa 	USB_QUIRK(POWERCOM, BLACK_KNIGHT_PRO, UQ_HID_IGNORE),
153881ae768SAhmad Khalifa 	USB_QUIRK(TRIPPLITE2, AVR550U, UQ_HID_IGNORE),
154881ae768SAhmad Khalifa 	USB_QUIRK(TRIPPLITE2, AVR750U, UQ_HID_IGNORE),
155881ae768SAhmad Khalifa 	USB_QUIRK(TRIPPLITE2, ECO550UPS, UQ_HID_IGNORE),
156881ae768SAhmad Khalifa 	USB_QUIRK(TRIPPLITE2, T750_INTL, UQ_HID_IGNORE),
157881ae768SAhmad Khalifa 	USB_QUIRK(TRIPPLITE2, RT_2200_INTL, UQ_HID_IGNORE),
158881ae768SAhmad Khalifa 	USB_QUIRK(TRIPPLITE2, OMNI1000LCD, UQ_HID_IGNORE),
159881ae768SAhmad Khalifa 	USB_QUIRK(TRIPPLITE2, OMNI900LCD, UQ_HID_IGNORE),
160881ae768SAhmad Khalifa 	USB_QUIRK(TRIPPLITE2, SMART_2200RMXL2U, UQ_HID_IGNORE),
161881ae768SAhmad Khalifa 	USB_QUIRK(TRIPPLITE2, UPS_3014, UQ_HID_IGNORE),
162881ae768SAhmad Khalifa 	USB_QUIRK(TRIPPLITE2, SU1500RTXL2UA, UQ_HID_IGNORE),
163881ae768SAhmad Khalifa 	USB_QUIRK(TRIPPLITE2, SU6000RT4U, UQ_HID_IGNORE),
164881ae768SAhmad Khalifa 	USB_QUIRK(TRIPPLITE2, SU1500RTXL2UA_2, UQ_HID_IGNORE),
165881ae768SAhmad Khalifa 	USB_QUIRK(APPLE, IPHONE, UQ_HID_IGNORE),
166881ae768SAhmad Khalifa 	USB_QUIRK(APPLE, IPHONE_3G, UQ_HID_IGNORE),
167881ae768SAhmad Khalifa 	USB_QUIRK(MEGATEC, UPS, UQ_HID_IGNORE),
16802ac6454SAndrew Thompson 	/* Devices which should be ignored by both ukbd and uhid */
169881ae768SAhmad Khalifa 	USB_QUIRK(CYPRESS, WISPY1A, UQ_KBD_IGNORE, UQ_HID_IGNORE),
170881ae768SAhmad Khalifa 	USB_QUIRK(METAGEEK, WISPY1B, UQ_KBD_IGNORE, UQ_HID_IGNORE),
171881ae768SAhmad Khalifa 	USB_QUIRK(METAGEEK, WISPY24X, UQ_KBD_IGNORE, UQ_HID_IGNORE),
172881ae768SAhmad Khalifa 	USB_QUIRK(METAGEEK2, WISPYDBX, UQ_KBD_IGNORE, UQ_HID_IGNORE),
173881ae768SAhmad Khalifa 	USB_QUIRK_REV(TENX, UAUDIO0, 0x0101, 0x0101, UQ_AUDIO_SWAP_LR),
17402ac6454SAndrew Thompson 	/* MS keyboards do weird things */
175881ae768SAhmad Khalifa 	USB_QUIRK(MICROSOFT, NATURAL4000, UQ_KBD_BOOTPROTO),
176881ae768SAhmad Khalifa 	USB_QUIRK(MICROSOFT, WLINTELLIMOUSE, UQ_MS_LEADING_BYTE),
17784e1a128SHans Petter Selasky 	/* Quirk for Corsair Vengeance K60 keyboard */
178881ae768SAhmad Khalifa 	USB_QUIRK(CORSAIR, K60, UQ_KBD_BOOTPROTO),
1798824a2edSOleksandr Tymoshenko 	/* Quirk for Corsair Gaming K68 keyboard */
180881ae768SAhmad Khalifa 	USB_QUIRK(CORSAIR, K68, UQ_KBD_BOOTPROTO),
18163015748SHans Petter Selasky 	/* Quirk for Corsair Vengeance K70 keyboard */
182881ae768SAhmad Khalifa 	USB_QUIRK(CORSAIR, K70, UQ_KBD_BOOTPROTO),
183abf52ec0SHans Petter Selasky 	/* Quirk for Corsair K70 RGB keyboard */
184881ae768SAhmad Khalifa 	USB_QUIRK(CORSAIR, K70_RGB, UQ_KBD_BOOTPROTO),
185be4e639dSHans Petter Selasky 	/* Quirk for Corsair STRAFE Gaming keyboard */
186881ae768SAhmad Khalifa 	USB_QUIRK(CORSAIR, STRAFE, UQ_KBD_BOOTPROTO),
187881ae768SAhmad Khalifa 	USB_QUIRK(CORSAIR, STRAFE2, UQ_KBD_BOOTPROTO),
188ab4f740bSVladimir Kondratyev 	/* Quirk for Kensington Slimblade Trackball */
189881ae768SAhmad Khalifa 	USB_QUIRK(KENSINGTON, SLIMBLADE, UQ_MS_VENDOR_BTN),
1904b5437a1SAndrew Thompson 	/* umodem(4) device quirks */
191881ae768SAhmad Khalifa 	USB_QUIRK_REV(METRICOM, RICOCHET_GS, 0x100, 0x100, UQ_ASSUME_CM_OVER_DATA),
192881ae768SAhmad Khalifa 	USB_QUIRK_REV(SANYO, SCP4900, 0x000, 0x000, UQ_ASSUME_CM_OVER_DATA),
193881ae768SAhmad Khalifa 	USB_QUIRK_REV(MOTOROLA2, T720C, 0x001, 0x001, UQ_ASSUME_CM_OVER_DATA),
194881ae768SAhmad Khalifa 	USB_QUIRK_REV(EICON, DIVA852, 0x100, 0x100, UQ_ASSUME_CM_OVER_DATA),
195881ae768SAhmad Khalifa 	USB_QUIRK_REV(SIEMENS2, ES75, 0x000, 0x000, UQ_ASSUME_CM_OVER_DATA),
196881ae768SAhmad Khalifa 	USB_QUIRK(QUALCOMM, CDMA_MSM, UQ_ASSUME_CM_OVER_DATA),
197881ae768SAhmad Khalifa 	USB_QUIRK(QUALCOMM2, CDMA_MSM, UQ_ASSUME_CM_OVER_DATA),
198881ae768SAhmad Khalifa 	USB_QUIRK(CURITEL, UM150, UQ_ASSUME_CM_OVER_DATA),
199881ae768SAhmad Khalifa 	USB_QUIRK(CURITEL, UM175, UQ_ASSUME_CM_OVER_DATA),
200881ae768SAhmad Khalifa 	USB_QUIRK(VERTEX, VW110L, UQ_ASSUME_CM_OVER_DATA),
201881ae768SAhmad Khalifa 	USB_QUIRK(BALTECH, SMARTCARDREADER, UQ_IGNORE_CDC_CM),
2024b5437a1SAndrew Thompson 
203eb584416SAndrew Thompson 	/* USB Mass Storage Class Quirks */
20464e05e90SAhmad Khalifa 	USB_QUIRK_VO(ASAHIOPTICAL, UQ_MSC_NO_RS_CLEAR_UA),
205881ae768SAhmad Khalifa 	USB_QUIRK(ADDON, ATTACHE, UQ_MSC_FORCE_WIRE_BBB,
206b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
207881ae768SAhmad Khalifa 	USB_QUIRK(ADDON, A256MB, UQ_MSC_FORCE_WIRE_BBB,
208b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
209881ae768SAhmad Khalifa 	USB_QUIRK(ADDON, DISKPRO512, UQ_MSC_FORCE_WIRE_BBB,
210b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
211881ae768SAhmad Khalifa 	USB_QUIRK(ADDONICS2, CABLE_205, UQ_MSC_FORCE_WIRE_BBB,
212b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI),
213881ae768SAhmad Khalifa 	USB_QUIRK(AIPTEK, POCKETCAM3M, UQ_MSC_FORCE_WIRE_BBB,
214b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI),
215881ae768SAhmad Khalifa 	USB_QUIRK(ALCOR, UMCR_9361, UQ_MSC_FORCE_WIRE_BBB,
216b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN),
217881ae768SAhmad Khalifa 	USB_QUIRK(ALCOR, TRANSCEND, UQ_MSC_NO_GETMAXLUN, UQ_MSC_NO_SYNC_CACHE,
218881ae768SAhmad Khalifa 	    UQ_MSC_NO_TEST_UNIT_READY),
219881ae768SAhmad Khalifa 	USB_QUIRK(APACER, HT202, UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_SYNC_CACHE),
220881ae768SAhmad Khalifa 	USB_QUIRK(ASAHIOPTICAL, OPTIO230, UQ_MSC_FORCE_WIRE_BBB,
221b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
222881ae768SAhmad Khalifa 	USB_QUIRK(ASAHIOPTICAL, OPTIO330, UQ_MSC_FORCE_WIRE_BBB,
223b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
224881ae768SAhmad Khalifa 	USB_QUIRK(ATP, EUSB, UQ_MSC_NO_SYNC_CACHE),
225881ae768SAhmad Khalifa 	USB_QUIRK(BELKIN, USB2SCSI, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI),
226881ae768SAhmad Khalifa 	USB_QUIRK(CASIO, QV_DIGICAM, UQ_MSC_FORCE_WIRE_CBI,
227b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
228881ae768SAhmad Khalifa 	USB_QUIRK(CCYU, ED1064, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI),
229881ae768SAhmad Khalifa 	USB_QUIRK(CENTURY, EX35QUAT, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
230881ae768SAhmad Khalifa 	    UQ_MSC_FORCE_SHORT_INQ, UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE),
231881ae768SAhmad Khalifa 	USB_QUIRK_REV(CREATIVE, NOMAD, 0x0001, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
232d60f35d9SWarner Losh 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_READ_CAP_OFFBY1),
233881ae768SAhmad Khalifa 	USB_QUIRK(CYPRESS, XX6830XX, UQ_MSC_NO_GETMAXLUN, UQ_MSC_NO_SYNC_CACHE),
234881ae768SAhmad Khalifa 	USB_QUIRK(EMTEC, DANEELEC4GB, UQ_MSC_NO_SYNC_CACHE),
235881ae768SAhmad Khalifa 	USB_QUIRK(DESKNOTE, UCR_61S2B, UQ_MSC_FORCE_WIRE_BBB,
236b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI),
237881ae768SAhmad Khalifa 	USB_QUIRK(DMI, CFSM_RW, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN),
238881ae768SAhmad Khalifa 	USB_QUIRK(EMTEC, RUF2PS, UQ_MSC_NO_SYNC_CACHE),
239881ae768SAhmad Khalifa 	USB_QUIRK(EPSON, STYLUS_875DC, UQ_MSC_FORCE_WIRE_CBI,
240b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
241881ae768SAhmad Khalifa 	USB_QUIRK(EPSON, STYLUS_895, UQ_MSC_FORCE_WIRE_BBB,
242b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN),
243881ae768SAhmad Khalifa 	USB_QUIRK(FEIYA, 5IN1, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI),
244881ae768SAhmad Khalifa 	USB_QUIRK(FEIYA, ELANGO, UQ_MSC_NO_SYNC_CACHE),
245881ae768SAhmad Khalifa 	USB_QUIRK(FREECOM, DVD, UQ_MSC_FORCE_PROTO_SCSI),
246881ae768SAhmad Khalifa 	USB_QUIRK(FUJIPHOTO, MASS0100, UQ_MSC_FORCE_WIRE_CBI_I,
2476001d011SHans Petter Selasky 	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_RS_CLEAR_UA, UQ_MSC_NO_SYNC_CACHE),
248881ae768SAhmad Khalifa 	USB_QUIRK(GARMIN, DAKOTA20, UQ_MSC_NO_INQUIRY),
249881ae768SAhmad Khalifa 	USB_QUIRK(GARMIN, FORERUNNER230, UQ_MSC_NO_INQUIRY),
250881ae768SAhmad Khalifa 	USB_QUIRK(GARMIN, GPSMAP62S, UQ_MSC_NO_INQUIRY),
251881ae768SAhmad Khalifa 	USB_QUIRK(GARMIN, EDGETOURINGPLUS, UQ_MSC_NO_INQUIRY),
252881ae768SAhmad Khalifa 	USB_QUIRK(GARMIN, INSTINCTSOLAR, UQ_MSC_NO_INQUIRY),
253881ae768SAhmad Khalifa 	USB_QUIRK(GENESYS, GL641USB2IDE, UQ_MSC_FORCE_WIRE_BBB,
254881ae768SAhmad Khalifa 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_FORCE_SHORT_INQ, UQ_MSC_NO_START_STOP,
255881ae768SAhmad Khalifa 	    UQ_MSC_IGNORE_RESIDUE, UQ_MSC_NO_SYNC_CACHE),
256881ae768SAhmad Khalifa 	USB_QUIRK(GENESYS, GL641USB2IDE_2, UQ_MSC_FORCE_WIRE_BBB,
257881ae768SAhmad Khalifa 	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_FORCE_SHORT_INQ,
258b55b073fSAndrew Thompson 	    UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE),
259881ae768SAhmad Khalifa 	USB_QUIRK(GENESYS, GL641USB, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
260881ae768SAhmad Khalifa 	    UQ_MSC_FORCE_SHORT_INQ, UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE),
261881ae768SAhmad Khalifa 	USB_QUIRK(GENESYS, GL641USB_2, UQ_MSC_FORCE_WIRE_BBB,
262b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_WRONG_CSWSIG),
263881ae768SAhmad Khalifa 	USB_QUIRK(GENESYS, GL3220, UQ_MSC_NO_INQUIRY, UQ_MSC_NO_RS_CLEAR_UA),
264881ae768SAhmad Khalifa 	USB_QUIRK(HAGIWARA, FG, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI),
265881ae768SAhmad Khalifa 	USB_QUIRK(HAGIWARA, FGSM, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI),
266881ae768SAhmad Khalifa 	USB_QUIRK(HITACHI, DVDCAM_DZ_MV100A, UQ_MSC_FORCE_WIRE_CBI,
267881ae768SAhmad Khalifa 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN),
268881ae768SAhmad Khalifa 	USB_QUIRK(HITACHI, DVDCAM_USB, UQ_MSC_FORCE_WIRE_CBI_I,
269b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_INQUIRY),
270881ae768SAhmad Khalifa 	USB_QUIRK(HP, CDW4E, UQ_MSC_FORCE_PROTO_ATAPI),
271881ae768SAhmad Khalifa 	USB_QUIRK(HP, CDW8200, UQ_MSC_FORCE_WIRE_CBI_I, UQ_MSC_FORCE_PROTO_ATAPI,
272881ae768SAhmad Khalifa 	    UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_START_STOP),
273881ae768SAhmad Khalifa 	USB_QUIRK(HUAWEI, E3372_INIT, UQ_MSC_NO_INQUIRY, UQ_MSC_NO_GETMAXLUN),
274881ae768SAhmad Khalifa 	USB_QUIRK(IMAGINATION, DBX1, UQ_MSC_FORCE_WIRE_BBB,
275b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_WRONG_CSWSIG),
276881ae768SAhmad Khalifa 	USB_QUIRK(INSYSTEM, USBCABLE, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_ATAPI,
277881ae768SAhmad Khalifa 	    UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_START_STOP, UQ_MSC_ALT_IFACE_1),
278881ae768SAhmad Khalifa 	USB_QUIRK(INSYSTEM, ATAPI, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_RBC),
279881ae768SAhmad Khalifa 	USB_QUIRK(INSYSTEM, STORAGE_V2, UQ_MSC_FORCE_WIRE_CBI,
280b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_RBC),
281881ae768SAhmad Khalifa 	USB_QUIRK(VIALABS, VL701, UQ_MSC_NO_INQUIRY),
282881ae768SAhmad Khalifa 	USB_QUIRK(IODATA, IU_CD2, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI),
283881ae768SAhmad Khalifa 	USB_QUIRK(IODATA, DVR_UEH8, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI),
284881ae768SAhmad Khalifa 	USB_QUIRK(IOMEGA, ZIP100, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
285b55b073fSAndrew Thompson 	    UQ_MSC_NO_TEST_UNIT_READY), /* XXX ZIP drives can also use ATAPI */
286881ae768SAhmad Khalifa 	USB_QUIRK(JMICRON, JMS566, UQ_MSC_NO_GETMAXLUN),
287881ae768SAhmad Khalifa 	USB_QUIRK(JMICRON, JMS567, UQ_MSC_NO_GETMAXLUN),
288881ae768SAhmad Khalifa 	USB_QUIRK(JMICRON, JM20337, UQ_MSC_FORCE_WIRE_BBB,
289881ae768SAhmad Khalifa 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_SYNC_CACHE),
290881ae768SAhmad Khalifa 	USB_QUIRK(KINGSTON, HYPERX3_0, UQ_MSC_NO_INQUIRY),
291881ae768SAhmad Khalifa 	USB_QUIRK(KINGSTON, DATATRAVELER3_0, UQ_MSC_NO_PREVENT_ALLOW,
2921feda9b4SAndrew Thompson 	    UQ_MSC_NO_SYNC_CACHE),
293881ae768SAhmad Khalifa 	USB_QUIRK(KYOCERA, FINECAM_L3, UQ_MSC_FORCE_WIRE_BBB,
294b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
295881ae768SAhmad Khalifa 	USB_QUIRK(KYOCERA, FINECAM_S3X, UQ_MSC_FORCE_WIRE_CBI,
296b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_INQUIRY),
297881ae768SAhmad Khalifa 	USB_QUIRK(KYOCERA, FINECAM_S4, UQ_MSC_FORCE_WIRE_CBI,
298b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_INQUIRY),
299881ae768SAhmad Khalifa 	USB_QUIRK(KYOCERA, FINECAM_S5, UQ_MSC_FORCE_WIRE_BBB,
300b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
301881ae768SAhmad Khalifa 	USB_QUIRK(LACIE, HD, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_RBC),
302881ae768SAhmad Khalifa 	USB_QUIRK(LEXAR, CF_READER, UQ_MSC_FORCE_WIRE_BBB,
303b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
304881ae768SAhmad Khalifa 	USB_QUIRK(LEXAR, JUMPSHOT, UQ_MSC_FORCE_PROTO_SCSI),
305881ae768SAhmad Khalifa 	USB_QUIRK(LEXAR, JUMPDRIVE, UQ_MSC_NO_INQUIRY),
306881ae768SAhmad Khalifa 	USB_QUIRK(LOGITEC, LDR_H443SU2, UQ_MSC_FORCE_PROTO_SCSI),
307881ae768SAhmad Khalifa 	USB_QUIRK(LOGITEC, LDR_H443U2, UQ_MSC_FORCE_WIRE_BBB,
308b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI),
309881ae768SAhmad Khalifa 	USB_QUIRK(MELCO, DUBPXXG, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
310881ae768SAhmad Khalifa 	    UQ_MSC_FORCE_SHORT_INQ, UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE),
311881ae768SAhmad Khalifa 	USB_QUIRK(MICROTECH, DPCM, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_SCSI,
312881ae768SAhmad Khalifa 	    UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_START_STOP),
313881ae768SAhmad Khalifa 	USB_QUIRK(MICRON, REALSSD, UQ_MSC_NO_SYNC_CACHE),
314881ae768SAhmad Khalifa 	USB_QUIRK(MICROTECH, SCSIDB25, UQ_MSC_FORCE_WIRE_BBB,
315b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI),
316881ae768SAhmad Khalifa 	USB_QUIRK(MICROTECH, SCSIHD50, UQ_MSC_FORCE_WIRE_BBB,
317b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI),
318881ae768SAhmad Khalifa 	USB_QUIRK(MINOLTA, E223, UQ_MSC_FORCE_PROTO_SCSI),
319881ae768SAhmad Khalifa 	USB_QUIRK(MINOLTA, F300, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI),
320881ae768SAhmad Khalifa 	USB_QUIRK(MITSUMI, CDRRW, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_ATAPI),
321881ae768SAhmad Khalifa 	USB_QUIRK(MOTOROLA2, E398, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
322881ae768SAhmad Khalifa 	    UQ_MSC_FORCE_SHORT_INQ, UQ_MSC_NO_INQUIRY_EVPD, UQ_MSC_NO_GETMAXLUN),
32364e05e90SAhmad Khalifa 	USB_QUIRK_VO(MPMAN, UQ_MSC_NO_SYNC_CACHE),
324881ae768SAhmad Khalifa 	USB_QUIRK(MSYSTEMS, DISKONKEY, UQ_MSC_FORCE_WIRE_BBB,
325b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE, UQ_MSC_NO_GETMAXLUN,
326b55b073fSAndrew Thompson 	    UQ_MSC_NO_RS_CLEAR_UA),
327881ae768SAhmad Khalifa 	USB_QUIRK(MSYSTEMS, DISKONKEY2, UQ_MSC_FORCE_WIRE_BBB,
328b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_ATAPI),
329881ae768SAhmad Khalifa 	USB_QUIRK(MYSON, HEDEN, UQ_MSC_IGNORE_RESIDUE, UQ_MSC_NO_SYNC_CACHE),
330881ae768SAhmad Khalifa 	USB_QUIRK(NEODIO, ND3260, UQ_MSC_FORCE_WIRE_BBB,
331b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_FORCE_SHORT_INQ),
332881ae768SAhmad Khalifa 	USB_QUIRK(NETAC, CF_CARD, UQ_MSC_FORCE_WIRE_BBB,
333b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
334881ae768SAhmad Khalifa 	USB_QUIRK(NETAC, ONLYDISK, UQ_MSC_FORCE_WIRE_BBB,
335b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
336881ae768SAhmad Khalifa 	USB_QUIRK(NETCHIP, CLIK_40, UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_INQUIRY),
337881ae768SAhmad Khalifa 	USB_QUIRK(NETCHIP, POCKETBOOK, UQ_MSC_NO_SYNC_CACHE),
338881ae768SAhmad Khalifa 	USB_QUIRK(NIKON, D300, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI),
339881ae768SAhmad Khalifa 	USB_QUIRK(NORELSYS, NS1081, UQ_MSC_NO_RS_CLEAR_UA, UQ_MSC_NO_INQUIRY),
340881ae768SAhmad Khalifa 	USB_QUIRK(OLYMPUS, C1, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
341881ae768SAhmad Khalifa 	    UQ_MSC_WRONG_CSWSIG),
342881ae768SAhmad Khalifa 	USB_QUIRK(OLYMPUS, C700, UQ_MSC_NO_GETMAXLUN),
34331e076d7SGreg Lehey         /* Selected Olympus DSLR and EVIL models.  See ../usbdevs for more
34431e076d7SGreg Lehey 	 * details.
34531e076d7SGreg Lehey 	 *
34631e076d7SGreg Lehey 	 * Not all quirks apply to all models.  The commented-out entries are
34731e076d7SGreg Lehey 	 * correct for that model.
34831e076d7SGreg Lehey 	 */
349881ae768SAhmad Khalifa 	USB_QUIRK(OLYMPUS, E_1, UQ_MSC_NO_GETMAXLUN, UQ_MSC_NO_TEST_UNIT_READY,
350881ae768SAhmad Khalifa 	    UQ_MSC_NO_PREVENT_ALLOW, UQ_MSC_NO_SYNC_CACHE),
35131e076d7SGreg Lehey 	/*
35231e076d7SGreg Lehey 	 * Product code 0x118.
353881ae768SAhmad Khalifa 	 * USB_QUIRK(OLYMPUS, E_300, UQ_MSC_NO_GETMAXLUN,
35431e076d7SGreg Lehey 	 *     UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_PREVENT_ALLOW,
35531e076d7SGreg Lehey          *     UQ_MSC_NO_SYNC_CACHE),
356881ae768SAhmad Khalifa 	 * USB_QUIRK(OLYMPUS, E_30, UQ_MSC_NO_GETMAXLUN,
35731e076d7SGreg Lehey 	 *     UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_PREVENT_ALLOW,
35831e076d7SGreg Lehey          *     UQ_MSC_NO_SYNC_CACHE), */
359881ae768SAhmad Khalifa 	USB_QUIRK(OLYMPUS, E_330, UQ_MSC_NO_GETMAXLUN, UQ_MSC_NO_TEST_UNIT_READY,
360881ae768SAhmad Khalifa 	    UQ_MSC_NO_PREVENT_ALLOW, UQ_MSC_NO_SYNC_CACHE, UQ_MSC_NO_START_STOP),
361881ae768SAhmad Khalifa 	USB_QUIRK(OLYMPUS, E_PM1, UQ_MSC_NO_GETMAXLUN, UQ_MSC_NO_TEST_UNIT_READY,
362881ae768SAhmad Khalifa 	    UQ_MSC_NO_PREVENT_ALLOW, UQ_MSC_NO_SYNC_CACHE, UQ_MSC_NO_START_STOP),
36331e076d7SGreg Lehey         /* Product code 0x12e.
364881ae768SAhmad Khalifa 	 * USB_QUIRK(OLYMPUS, E_PM2, 0),
365881ae768SAhmad Khalifa 	 * USB_QUIRK(OLYMPUS, E_M1MarkII, UQ_MSC_NO_GETMAXLUN,
36631e076d7SGreg Lehey 	 *     UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_PREVENT_ALLOW,
36731e076d7SGreg Lehey 	 *     UQ_MSC_NO_SYNC_CACHE),
368881ae768SAhmad Khalifa 	 * USB_QUIRK(OLYMPUS, E_M5MarkIII, 0),
36931e076d7SGreg Lehey 	 */
370881ae768SAhmad Khalifa 	USB_QUIRK(OLYMPUS, E_M1, UQ_MSC_NO_GETMAXLUN, UQ_MSC_NO_TEST_UNIT_READY,
371881ae768SAhmad Khalifa 	    UQ_MSC_NO_PREVENT_ALLOW, UQ_MSC_NO_SYNC_CACHE, UQ_MSC_NO_START_STOP),
372881ae768SAhmad Khalifa 	USB_QUIRK(ONSPEC, SDS_HOTFIND_D, UQ_MSC_FORCE_WIRE_BBB,
373b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN, UQ_MSC_NO_SYNC_CACHE),
374881ae768SAhmad Khalifa 	USB_QUIRK(ONSPEC, CFMS_RW, UQ_MSC_FORCE_PROTO_SCSI),
375881ae768SAhmad Khalifa 	USB_QUIRK(ONSPEC, CFSM_COMBO, UQ_MSC_FORCE_PROTO_SCSI),
376881ae768SAhmad Khalifa 	USB_QUIRK(ONSPEC, CFSM_READER, UQ_MSC_FORCE_PROTO_SCSI),
377881ae768SAhmad Khalifa 	USB_QUIRK(ONSPEC, CFSM_READER2, UQ_MSC_FORCE_PROTO_SCSI),
378881ae768SAhmad Khalifa 	USB_QUIRK(ONSPEC, MDCFE_B_CF_READER, UQ_MSC_FORCE_PROTO_SCSI),
379881ae768SAhmad Khalifa 	USB_QUIRK(ONSPEC, MDSM_B_READER, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
380881ae768SAhmad Khalifa 	USB_QUIRK(ONSPEC, READER, UQ_MSC_FORCE_PROTO_SCSI),
381881ae768SAhmad Khalifa 	USB_QUIRK(ONSPEC, UCF100, UQ_MSC_FORCE_WIRE_BBB,
382a9216e0bSHans Petter Selasky 	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_INQUIRY, UQ_MSC_NO_GETMAXLUN),
383881ae768SAhmad Khalifa 	USB_QUIRK(ONSPEC2, IMAGEMATE_SDDR55, UQ_MSC_FORCE_PROTO_SCSI,
384881ae768SAhmad Khalifa 	    UQ_MSC_NO_GETMAXLUN),
385881ae768SAhmad Khalifa 	USB_QUIRK(PANASONIC, KXL840AN, UQ_MSC_FORCE_WIRE_BBB,
386b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_GETMAXLUN),
387881ae768SAhmad Khalifa 	USB_QUIRK(PANASONIC, KXLCB20AN, UQ_MSC_FORCE_WIRE_BBB,
388b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI),
389881ae768SAhmad Khalifa 	USB_QUIRK(PANASONIC, KXLCB35AN, UQ_MSC_FORCE_WIRE_BBB,
390b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI),
391881ae768SAhmad Khalifa 	USB_QUIRK(PANASONIC, LS120CAM, UQ_MSC_FORCE_PROTO_UFI),
392881ae768SAhmad Khalifa 	USB_QUIRK(PLEXTOR, 40_12_40U, UQ_MSC_FORCE_WIRE_BBB,
393b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_TEST_UNIT_READY),
394881ae768SAhmad Khalifa 	USB_QUIRK(PNY, ATTACHE2, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
395881ae768SAhmad Khalifa 	    UQ_MSC_IGNORE_RESIDUE, UQ_MSC_NO_START_STOP),
396881ae768SAhmad Khalifa 	USB_QUIRK(PROLIFIC, PL2506, UQ_MSC_NO_SYNC_CACHE, UQ_MSC_NO_PREVENT_ALLOW),
397881ae768SAhmad Khalifa 	USB_QUIRK(SAMSUNG_TECHWIN, DIGIMAX_410, UQ_MSC_FORCE_WIRE_BBB,
398b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
399881ae768SAhmad Khalifa 	USB_QUIRK(SANDISK, SDDR05A, UQ_MSC_FORCE_WIRE_CBI,
400881ae768SAhmad Khalifa 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_READ_CAP_OFFBY1, UQ_MSC_NO_GETMAXLUN),
401881ae768SAhmad Khalifa 	USB_QUIRK(SANDISK, SDDR09, UQ_MSC_FORCE_PROTO_SCSI,
402b55b073fSAndrew Thompson 	    UQ_MSC_READ_CAP_OFFBY1, UQ_MSC_NO_GETMAXLUN),
403881ae768SAhmad Khalifa 	USB_QUIRK(SANDISK, SDDR12, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_SCSI,
404881ae768SAhmad Khalifa 	    UQ_MSC_READ_CAP_OFFBY1, UQ_MSC_NO_GETMAXLUN),
405881ae768SAhmad Khalifa 	USB_QUIRK(SANDISK, SDCZ2_128, UQ_MSC_FORCE_WIRE_BBB,
406881ae768SAhmad Khalifa 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE, UQ_MSC_NO_SYNC_CACHE),
407881ae768SAhmad Khalifa 	USB_QUIRK(SANDISK, SDCZ2_256, UQ_MSC_FORCE_WIRE_BBB,
408b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
409881ae768SAhmad Khalifa 	USB_QUIRK(SANDISK, SDCZ4_128, UQ_MSC_FORCE_WIRE_BBB,
410b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
411881ae768SAhmad Khalifa 	USB_QUIRK(SANDISK, SDCZ4_256, UQ_MSC_FORCE_WIRE_BBB,
412b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
413881ae768SAhmad Khalifa 	USB_QUIRK(SANDISK, SDCZ48_32, UQ_MSC_NO_SYNC_CACHE,
414d97d4331SHans Petter Selasky 	    UQ_MSC_NO_TEST_UNIT_READY),
415881ae768SAhmad Khalifa 	USB_QUIRK(SANDISK, SDDR31, UQ_MSC_FORCE_WIRE_BBB,
416b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_READ_CAP_OFFBY1),
417881ae768SAhmad Khalifa 	USB_QUIRK(SANDISK, IMAGEMATE_SDDR289, UQ_MSC_NO_SYNC_CACHE,
418881ae768SAhmad Khalifa 	    UQ_MSC_NO_GETMAXLUN),
419881ae768SAhmad Khalifa 	USB_QUIRK(SCANLOGIC, SL11R, UQ_MSC_FORCE_WIRE_BBB,
420b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_INQUIRY),
421881ae768SAhmad Khalifa 	USB_QUIRK(SHUTTLE, EUSB, UQ_MSC_FORCE_WIRE_CBI_I, UQ_MSC_FORCE_PROTO_ATAPI,
422881ae768SAhmad Khalifa 	    UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_START_STOP, UQ_MSC_SHUTTLE_INIT),
423881ae768SAhmad Khalifa 	USB_QUIRK(SHUTTLE, CDRW, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_ATAPI),
424881ae768SAhmad Khalifa 	USB_QUIRK(SHUTTLE, CF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_ATAPI),
425881ae768SAhmad Khalifa 	USB_QUIRK(SHUTTLE, EUSBATAPI, UQ_MSC_FORCE_WIRE_CBI,
426b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_ATAPI),
427881ae768SAhmad Khalifa 	USB_QUIRK(SHUTTLE, EUSBCFSM, UQ_MSC_FORCE_PROTO_SCSI),
428881ae768SAhmad Khalifa 	USB_QUIRK(SHUTTLE, EUSCSI, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI),
429881ae768SAhmad Khalifa 	USB_QUIRK(SHUTTLE, HIFD, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_SCSI,
430b55b073fSAndrew Thompson 	    UQ_MSC_NO_GETMAXLUN),
431881ae768SAhmad Khalifa 	USB_QUIRK(SHUTTLE, SDDR09, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN),
432881ae768SAhmad Khalifa 	USB_QUIRK(SHUTTLE, ZIOMMC, UQ_MSC_FORCE_WIRE_CBI,
433b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN),
434881ae768SAhmad Khalifa 	USB_QUIRK(SIGMATEL, I_BEAD100, UQ_MSC_FORCE_WIRE_BBB,
435b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_SHUTTLE_INIT),
436881ae768SAhmad Khalifa 	USB_QUIRK(SIIG, WINTERREADER, UQ_MSC_FORCE_WIRE_BBB,
437b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
438881ae768SAhmad Khalifa 	USB_QUIRK(SKANHEX, MD_7425, UQ_MSC_FORCE_WIRE_BBB,
439b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
440881ae768SAhmad Khalifa 	USB_QUIRK(SKANHEX, SX_520Z, UQ_MSC_FORCE_WIRE_BBB,
441b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
442881ae768SAhmad Khalifa 	USB_QUIRK_REV(SONY, HANDYCAM, 0x0500, 0x0500, UQ_MSC_FORCE_WIRE_CBI,
443b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_RBC, UQ_MSC_RBC_PAD_TO_12),
444881ae768SAhmad Khalifa 	USB_QUIRK(SONY, CLIE_40_MS, UQ_MSC_FORCE_WIRE_BBB,
445b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
446881ae768SAhmad Khalifa 	USB_QUIRK_REV(SONY, DSC, 0x0500, 0x0500, UQ_MSC_FORCE_WIRE_CBI,
447b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_RBC, UQ_MSC_RBC_PAD_TO_12),
448881ae768SAhmad Khalifa 	USB_QUIRK_REV(SONY, DSC, 0x0600, 0x0600, UQ_MSC_FORCE_WIRE_CBI,
449b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_RBC, UQ_MSC_RBC_PAD_TO_12),
450881ae768SAhmad Khalifa 	USB_QUIRK(SONY, DSC, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_RBC),
451881ae768SAhmad Khalifa 	USB_QUIRK(SONY, HANDYCAM, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_RBC),
452881ae768SAhmad Khalifa 	USB_QUIRK(SONY, MSC, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_RBC),
453881ae768SAhmad Khalifa 	USB_QUIRK(SONY, MS_MSC_U03, UQ_MSC_FORCE_WIRE_CBI,
454b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_UFI, UQ_MSC_NO_GETMAXLUN),
455881ae768SAhmad Khalifa 	USB_QUIRK(SONY, MS_NW_MS7, UQ_MSC_FORCE_WIRE_BBB,
456b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN),
457881ae768SAhmad Khalifa 	USB_QUIRK(SONY, MS_PEG_N760C, UQ_MSC_FORCE_WIRE_BBB,
458b55b073fSAndrew Thompson 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
459881ae768SAhmad Khalifa 	USB_QUIRK(SONY, MSACUS1, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
460b55b073fSAndrew Thompson 	    UQ_MSC_NO_GETMAXLUN),
461881ae768SAhmad Khalifa 	USB_QUIRK(SONY, PORTABLE_HDD_V2, UQ_MSC_FORCE_WIRE_BBB,
462881ae768SAhmad Khalifa 	    UQ_MSC_FORCE_PROTO_SCSI),
463881ae768SAhmad Khalifa 	USB_QUIRK(STMICRO, ST72682, UQ_MSC_NO_PREVENT_ALLOW),
464881ae768SAhmad Khalifa 	USB_QUIRK(SUPERTOP, IDE, UQ_MSC_IGNORE_RESIDUE, UQ_MSC_NO_SYNC_CACHE),
465881ae768SAhmad Khalifa 	USB_QUIRK(SUPERTOP, FLASHDRIVE, UQ_MSC_NO_TEST_UNIT_READY,
466881ae768SAhmad Khalifa 	    UQ_MSC_NO_SYNC_CACHE),
467881ae768SAhmad Khalifa 	USB_QUIRK(TAUGA, CAMERAMATE, UQ_MSC_FORCE_PROTO_SCSI),
468881ae768SAhmad Khalifa 	USB_QUIRK(TEAC, FD05PUB, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_UFI),
469881ae768SAhmad Khalifa 	USB_QUIRK(TECLAST, TLC300, UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_SYNC_CACHE),
470881ae768SAhmad Khalifa 	USB_QUIRK(TREK, MEMKEY, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
471881ae768SAhmad Khalifa 	    UQ_MSC_NO_INQUIRY),
472881ae768SAhmad Khalifa 	USB_QUIRK(TREK, THUMBDRIVE_8MB, UQ_MSC_FORCE_WIRE_BBB,
473881ae768SAhmad Khalifa 	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_IGNORE_RESIDUE),
474881ae768SAhmad Khalifa 	USB_QUIRK(TRUMPION, C3310, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_UFI),
475881ae768SAhmad Khalifa 	USB_QUIRK(TRUMPION, MP3, UQ_MSC_FORCE_PROTO_RBC),
476881ae768SAhmad Khalifa 	USB_QUIRK(TRUMPION, T33520, UQ_MSC_FORCE_PROTO_SCSI),
477881ae768SAhmad Khalifa 	USB_QUIRK(TWINMOS, MDIV, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI),
478881ae768SAhmad Khalifa 	USB_QUIRK(VIA, USB2IDEBRIDGE, UQ_MSC_FORCE_WIRE_BBB,
479881ae768SAhmad Khalifa 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_SYNC_CACHE),
480881ae768SAhmad Khalifa 	USB_QUIRK(VIVITAR, 35XX, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
481881ae768SAhmad Khalifa 	    UQ_MSC_NO_INQUIRY),
482881ae768SAhmad Khalifa 	USB_QUIRK(WESTERN, COMBO, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
483881ae768SAhmad Khalifa 	    UQ_MSC_FORCE_SHORT_INQ, UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE),
484881ae768SAhmad Khalifa 	USB_QUIRK(WESTERN, EXTHDD, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
485881ae768SAhmad Khalifa 	    UQ_MSC_FORCE_SHORT_INQ, UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE),
486881ae768SAhmad Khalifa 	USB_QUIRK(WESTERN, MYBOOK, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
487881ae768SAhmad Khalifa 	    UQ_MSC_NO_INQUIRY_EVPD, UQ_MSC_NO_SYNC_CACHE),
488881ae768SAhmad Khalifa 	USB_QUIRK(WESTERN, MYPASSPORT_00, UQ_MSC_FORCE_SHORT_INQ),
489881ae768SAhmad Khalifa 	USB_QUIRK(WESTERN, MYPASSPORT_01, UQ_MSC_NO_SYNC_CACHE),
490881ae768SAhmad Khalifa 	USB_QUIRK(WESTERN, MYPASSPORT_02, UQ_MSC_NO_SYNC_CACHE),
491881ae768SAhmad Khalifa 	USB_QUIRK(WESTERN, MYPASSPORT_03, UQ_MSC_NO_SYNC_CACHE),
492881ae768SAhmad Khalifa 	USB_QUIRK(WESTERN, MYPASSPORT_04, UQ_MSC_NO_SYNC_CACHE),
493881ae768SAhmad Khalifa 	USB_QUIRK(WESTERN, MYPASSPORT_05, UQ_MSC_NO_SYNC_CACHE),
494881ae768SAhmad Khalifa 	USB_QUIRK(WESTERN, MYPASSPORT_06, UQ_MSC_NO_SYNC_CACHE),
495881ae768SAhmad Khalifa 	USB_QUIRK(WESTERN, MYPASSPORT_07, UQ_MSC_NO_SYNC_CACHE),
496881ae768SAhmad Khalifa 	USB_QUIRK(WESTERN, MYPASSPORT_08, UQ_MSC_NO_SYNC_CACHE),
497881ae768SAhmad Khalifa 	USB_QUIRK(WESTERN, MYPASSPORT_09, UQ_MSC_NO_SYNC_CACHE),
498881ae768SAhmad Khalifa 	USB_QUIRK(WESTERN, MYPASSPORT_10, UQ_MSC_NO_SYNC_CACHE),
499881ae768SAhmad Khalifa 	USB_QUIRK(WESTERN, MYPASSPORT_11, UQ_MSC_NO_SYNC_CACHE),
500881ae768SAhmad Khalifa 	USB_QUIRK(WESTERN, MYPASSPORTES_00, UQ_MSC_NO_SYNC_CACHE),
501881ae768SAhmad Khalifa 	USB_QUIRK(WESTERN, MYPASSPORTES_01, UQ_MSC_NO_SYNC_CACHE),
502881ae768SAhmad Khalifa 	USB_QUIRK(WESTERN, MYPASSPORTES_02, UQ_MSC_NO_SYNC_CACHE),
503881ae768SAhmad Khalifa 	USB_QUIRK(WESTERN, MYPASSPORTES_03, UQ_MSC_NO_SYNC_CACHE),
504881ae768SAhmad Khalifa 	USB_QUIRK(WESTERN, MYPASSPORTES_04, UQ_MSC_NO_SYNC_CACHE),
505881ae768SAhmad Khalifa 	USB_QUIRK(WESTERN, MYPASSPORTES_05, UQ_MSC_NO_SYNC_CACHE),
506881ae768SAhmad Khalifa 	USB_QUIRK(WESTERN, MYPASSPORTES_06, UQ_MSC_NO_SYNC_CACHE),
507881ae768SAhmad Khalifa 	USB_QUIRK(WESTERN, MYPASSPORTES_07, UQ_MSC_NO_SYNC_CACHE),
508881ae768SAhmad Khalifa 	USB_QUIRK(WESTERN, MYPASSPORTES_08, UQ_MSC_NO_SYNC_CACHE),
509881ae768SAhmad Khalifa 	USB_QUIRK(WESTERN, MYPASSPORTES_09, UQ_MSC_NO_SYNC_CACHE),
510881ae768SAhmad Khalifa 	USB_QUIRK(WESTERN, MYPASSPORTUL_00, UQ_MSC_NO_TEST_UNIT_READY),
511881ae768SAhmad Khalifa 	USB_QUIRK(WINMAXGROUP, FLASH64MC, UQ_MSC_FORCE_WIRE_BBB,
512881ae768SAhmad Khalifa 	    UQ_MSC_NO_INQUIRY, UQ_MSC_FORCE_PROTO_SCSI),
513881ae768SAhmad Khalifa 	USB_QUIRK(YANO, FW800HD, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
514881ae768SAhmad Khalifa 	    UQ_MSC_FORCE_SHORT_INQ, UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE),
515881ae768SAhmad Khalifa 	USB_QUIRK(YANO, U640MO, UQ_MSC_FORCE_WIRE_CBI_I,
516881ae768SAhmad Khalifa 	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_FORCE_SHORT_INQ),
517881ae768SAhmad Khalifa 	USB_QUIRK_REV(YEDATA, FLASHBUSTERU, 0x0000, 0x007F, UQ_MSC_FORCE_WIRE_CBI,
518881ae768SAhmad Khalifa 	    UQ_MSC_FORCE_PROTO_UFI, UQ_MSC_NO_RS_CLEAR_UA, UQ_MSC_FLOPPY_SPEED,
519881ae768SAhmad Khalifa 	    UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_GETMAXLUN),
520881ae768SAhmad Khalifa 	USB_QUIRK_REV(YEDATA, FLASHBUSTERU, 0x0080, 0x0080,
521881ae768SAhmad Khalifa 	    UQ_MSC_FORCE_WIRE_CBI_I, UQ_MSC_FORCE_PROTO_UFI,
522881ae768SAhmad Khalifa 	    UQ_MSC_NO_RS_CLEAR_UA, UQ_MSC_FLOPPY_SPEED,
523881ae768SAhmad Khalifa 	    UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_GETMAXLUN),
524881ae768SAhmad Khalifa 	USB_QUIRK_REV(YEDATA, FLASHBUSTERU, 0x0081, 0xFFFF,
525881ae768SAhmad Khalifa 	    UQ_MSC_FORCE_WIRE_CBI_I, UQ_MSC_FORCE_PROTO_UFI,
526881ae768SAhmad Khalifa 	    UQ_MSC_NO_RS_CLEAR_UA, UQ_MSC_FLOPPY_SPEED, UQ_MSC_NO_GETMAXLUN),
527881ae768SAhmad Khalifa 	USB_QUIRK(ZORAN, EX20DSC, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_ATAPI),
528881ae768SAhmad Khalifa 	USB_QUIRK(MEIZU, M6_SL, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
529881ae768SAhmad Khalifa 	    UQ_MSC_NO_INQUIRY, UQ_MSC_NO_SYNC_CACHE),
530881ae768SAhmad Khalifa 	USB_QUIRK(TOSHIBA, TRANSMEMORY, UQ_MSC_NO_SYNC_CACHE,
531860fe6b9SHans Petter Selasky 	    UQ_MSC_NO_PREVENT_ALLOW),
532881ae768SAhmad Khalifa 	USB_QUIRK(VIALABS, USB30SATABRIDGE, UQ_MSC_NO_SYNC_CACHE),
533881ae768SAhmad Khalifa 	USB_QUIRK(QUALCOMMINC, ZTE_MF730M, UQ_MSC_NO_GETMAXLUN,
53468492bc2SHans Petter Selasky 	    UQ_MSC_NO_INQUIRY, UQ_CFG_INDEX_0),
535881ae768SAhmad Khalifa 	USB_QUIRK(SMART2, G2MEMKEY, UQ_MSC_NO_INQUIRY),
536881ae768SAhmad Khalifa 	USB_QUIRK_REV(RALINK, RT_STOR, 0x0001, 0x0001, UQ_MSC_IGNORE),
537*9c0cce32SBjoern A. Zeeb 	USB_QUIRK(REALTEK, RTW8821CU_CD, UQ_MSC_IGNORE),
53825b74dabSHans Petter Selasky 	/* Non-standard USB MIDI devices */
539881ae768SAhmad Khalifa 	USB_QUIRK(ROLAND, UM1, UQ_AU_VENDOR_CLASS),
540881ae768SAhmad Khalifa 	USB_QUIRK(ROLAND, SC8850, UQ_AU_VENDOR_CLASS),
541881ae768SAhmad Khalifa 	USB_QUIRK(ROLAND, SD90, UQ_AU_VENDOR_CLASS),
542881ae768SAhmad Khalifa 	USB_QUIRK(ROLAND, UM880N, UQ_AU_VENDOR_CLASS),
543881ae768SAhmad Khalifa 	USB_QUIRK(ROLAND, UA100, UQ_AU_VENDOR_CLASS),
544881ae768SAhmad Khalifa 	USB_QUIRK(ROLAND, UM4, UQ_AU_VENDOR_CLASS),
545881ae768SAhmad Khalifa 	USB_QUIRK(ROLAND, U8, UQ_AU_VENDOR_CLASS),
546881ae768SAhmad Khalifa 	USB_QUIRK(ROLAND, UM2, UQ_AU_VENDOR_CLASS),
547881ae768SAhmad Khalifa 	USB_QUIRK(ROLAND, SC8820, UQ_AU_VENDOR_CLASS),
548881ae768SAhmad Khalifa 	USB_QUIRK(ROLAND, PC300, UQ_AU_VENDOR_CLASS),
549881ae768SAhmad Khalifa 	USB_QUIRK(ROLAND, SK500, UQ_AU_VENDOR_CLASS),
550881ae768SAhmad Khalifa 	USB_QUIRK(ROLAND, SCD70, UQ_AU_VENDOR_CLASS),
551881ae768SAhmad Khalifa 	USB_QUIRK(ROLAND, UM550, UQ_AU_VENDOR_CLASS),
552881ae768SAhmad Khalifa 	USB_QUIRK(ROLAND, SD20, UQ_AU_VENDOR_CLASS),
553881ae768SAhmad Khalifa 	USB_QUIRK(ROLAND, SD80, UQ_AU_VENDOR_CLASS),
554881ae768SAhmad Khalifa 	USB_QUIRK(ROLAND, UA700, UQ_AU_VENDOR_CLASS),
555881ae768SAhmad Khalifa 	USB_QUIRK(ROLAND, PCR300, UQ_AU_VENDOR_CLASS),
556881ae768SAhmad Khalifa 	USB_QUIRK(EGO, M4U, UQ_SINGLE_CMD_MIDI),
557881ae768SAhmad Khalifa 	USB_QUIRK(LOGILINK, U2M, UQ_SINGLE_CMD_MIDI),
558881ae768SAhmad Khalifa 	USB_QUIRK(MEDELI, DD305, UQ_SINGLE_CMD_MIDI, UQ_MATCH_VENDOR_ONLY),
559881ae768SAhmad Khalifa 	USB_QUIRK(REDOCTANE, GHMIDI, UQ_SINGLE_CMD_MIDI),
560881ae768SAhmad Khalifa 	USB_QUIRK(TEXTECH, U2M_1, UQ_SINGLE_CMD_MIDI),
561881ae768SAhmad Khalifa 	USB_QUIRK(TEXTECH, U2M_2, UQ_SINGLE_CMD_MIDI),
562881ae768SAhmad Khalifa 	USB_QUIRK(WCH2, U2M, UQ_SINGLE_CMD_MIDI),
5632325ea82SHans Petter Selasky 
5643557aa50SHans Petter Selasky 	/* Non-standard USB AUDIO devices */
565881ae768SAhmad Khalifa 	USB_QUIRK(MAUDIO, FASTTRACKULTRA, UQ_AU_VENDOR_CLASS),
566881ae768SAhmad Khalifa 	USB_QUIRK(MAUDIO, FASTTRACKULTRA8R, UQ_AU_VENDOR_CLASS),
567881ae768SAhmad Khalifa 	USB_QUIRK(CMEDIA, CM6206, UQ_AU_SET_SPDIF_CM6206),
568881ae768SAhmad Khalifa 	USB_QUIRK(PLOYTEC, SPL_CRIMSON_1, UQ_CFG_INDEX_1),
569881ae768SAhmad Khalifa 	USB_QUIRK(ROLAND, UA25EX_AD, UQ_AU_VENDOR_CLASS),
5703557aa50SHans Petter Selasky 
5712325ea82SHans Petter Selasky 	/*
5722325ea82SHans Petter Selasky 	 * Quirks for manufacturers which USB devices does not respond
5732325ea82SHans Petter Selasky 	 * after issuing non-supported commands:
5742325ea82SHans Petter Selasky 	 */
57564e05e90SAhmad Khalifa 	USB_QUIRK_VO(ALCOR, UQ_MSC_NO_SYNC_CACHE, UQ_MSC_NO_TEST_UNIT_READY),
57664e05e90SAhmad Khalifa 	USB_QUIRK_VO(APPLE, UQ_MSC_NO_SYNC_CACHE),
57764e05e90SAhmad Khalifa 	USB_QUIRK_VO(FEIYA, UQ_MSC_NO_SYNC_CACHE),
57864e05e90SAhmad Khalifa 	USB_QUIRK_VO(REALTEK, UQ_MSC_NO_SYNC_CACHE),
57964e05e90SAhmad Khalifa 	USB_QUIRK_VO(INITIO, UQ_MSC_NO_SYNC_CACHE),
580415bcd89SHans Petter Selasky 
581415bcd89SHans Petter Selasky 	/* DYMO LabelManager Pnp */
582881ae768SAhmad Khalifa 	USB_QUIRK(DYMO, LABELMANAGERPNP, UQ_MSC_DYMO_EJECT),
583348256dfSHans Petter Selasky 
584348256dfSHans Petter Selasky 	/* Holtek USB gaming keyboard */
585881ae768SAhmad Khalifa 	USB_QUIRK(HOLTEK, F85, UQ_KBD_BOOTPROTO),
586f17b69fdSPoul-Henning Kamp 
587f17b69fdSPoul-Henning Kamp 	/* This works much better with if_cdce than if_ure */
588881ae768SAhmad Khalifa 	USB_QUIRK(LENOVO, TBT3LAN, UQ_CFG_INDEX_1),
58902ac6454SAndrew Thompson };
59064e05e90SAhmad Khalifa #undef USB_QUIRK_VO
591881ae768SAhmad Khalifa #undef USB_QUIRK_REV
59247d54fbbSAndrew Thompson #undef USB_QUIRK
59302ac6454SAndrew Thompson 
59402ac6454SAndrew Thompson static const char *usb_quirk_str[USB_QUIRK_MAX] = {
59502ac6454SAndrew Thompson 	[UQ_NONE]		= "UQ_NONE",
596eb584416SAndrew Thompson 	[UQ_MATCH_VENDOR_ONLY]	= "UQ_MATCH_VENDOR_ONLY",
59702ac6454SAndrew Thompson 	[UQ_AUDIO_SWAP_LR]	= "UQ_AUDIO_SWAP_LR",
59802ac6454SAndrew Thompson 	[UQ_AU_INP_ASYNC]	= "UQ_AU_INP_ASYNC",
59902ac6454SAndrew Thompson 	[UQ_AU_NO_FRAC]		= "UQ_AU_NO_FRAC",
60002ac6454SAndrew Thompson 	[UQ_AU_NO_XU]		= "UQ_AU_NO_XU",
60102ac6454SAndrew Thompson 	[UQ_BAD_ADC]		= "UQ_BAD_ADC",
60202ac6454SAndrew Thompson 	[UQ_BAD_AUDIO]		= "UQ_BAD_AUDIO",
60302ac6454SAndrew Thompson 	[UQ_BROKEN_BIDIR]	= "UQ_BROKEN_BIDIR",
60402ac6454SAndrew Thompson 	[UQ_BUS_POWERED]	= "UQ_BUS_POWERED",
60502ac6454SAndrew Thompson 	[UQ_HID_IGNORE]		= "UQ_HID_IGNORE",
60602ac6454SAndrew Thompson 	[UQ_KBD_IGNORE]		= "UQ_KBD_IGNORE",
607b60541a9SAndrew Thompson 	[UQ_KBD_BOOTPROTO]	= "UQ_KBD_BOOTPROTO",
608d7dd1341SHans Petter Selasky 	[UQ_UMS_IGNORE]		= "UQ_UMS_IGNORE",
60902ac6454SAndrew Thompson 	[UQ_MS_BAD_CLASS]	= "UQ_MS_BAD_CLASS",
61002ac6454SAndrew Thompson 	[UQ_MS_LEADING_BYTE]	= "UQ_MS_LEADING_BYTE",
61102ac6454SAndrew Thompson 	[UQ_MS_REVZ]		= "UQ_MS_REVZ",
612ab4f740bSVladimir Kondratyev 	[UQ_MS_VENDOR_BTN]	= "UQ_MS_VENDOR_BTN",
61302ac6454SAndrew Thompson 	[UQ_NO_STRINGS]		= "UQ_NO_STRINGS",
61402ac6454SAndrew Thompson 	[UQ_POWER_CLAIM]	= "UQ_POWER_CLAIM",
61502ac6454SAndrew Thompson 	[UQ_SPUR_BUT_UP]	= "UQ_SPUR_BUT_UP",
61602ac6454SAndrew Thompson 	[UQ_SWAP_UNICODE]	= "UQ_SWAP_UNICODE",
61702ac6454SAndrew Thompson 	[UQ_CFG_INDEX_1]	= "UQ_CFG_INDEX_1",
61802ac6454SAndrew Thompson 	[UQ_CFG_INDEX_2]	= "UQ_CFG_INDEX_2",
61902ac6454SAndrew Thompson 	[UQ_CFG_INDEX_3]	= "UQ_CFG_INDEX_3",
62002ac6454SAndrew Thompson 	[UQ_CFG_INDEX_4]	= "UQ_CFG_INDEX_4",
62102ac6454SAndrew Thompson 	[UQ_CFG_INDEX_0]	= "UQ_CFG_INDEX_0",
6224b5437a1SAndrew Thompson 	[UQ_ASSUME_CM_OVER_DATA]	= "UQ_ASSUME_CM_OVER_DATA",
62373c3e8b1SSteffen Dirkwinkel 	[UQ_IGNORE_CDC_CM]	= "UQ_IGNORE_CDC_CM",
624eb584416SAndrew Thompson 	[UQ_MSC_NO_TEST_UNIT_READY]	= "UQ_MSC_NO_TEST_UNIT_READY",
625eb584416SAndrew Thompson 	[UQ_MSC_NO_RS_CLEAR_UA]		= "UQ_MSC_NO_RS_CLEAR_UA",
626eb584416SAndrew Thompson 	[UQ_MSC_NO_START_STOP]		= "UQ_MSC_NO_START_STOP",
627eb584416SAndrew Thompson 	[UQ_MSC_NO_GETMAXLUN]		= "UQ_MSC_NO_GETMAXLUN",
628eb584416SAndrew Thompson 	[UQ_MSC_NO_INQUIRY]		= "UQ_MSC_NO_INQUIRY",
629eb584416SAndrew Thompson 	[UQ_MSC_NO_INQUIRY_EVPD]	= "UQ_MSC_NO_INQUIRY_EVPD",
630ef3afaddSMarcel Moolenaar 	[UQ_MSC_NO_PREVENT_ALLOW]	= "UQ_MSC_NO_PREVENT_ALLOW",
631eb584416SAndrew Thompson 	[UQ_MSC_NO_SYNC_CACHE]		= "UQ_MSC_NO_SYNC_CACHE",
632eb584416SAndrew Thompson 	[UQ_MSC_SHUTTLE_INIT]		= "UQ_MSC_SHUTTLE_INIT",
633eb584416SAndrew Thompson 	[UQ_MSC_ALT_IFACE_1]		= "UQ_MSC_ALT_IFACE_1",
634eb584416SAndrew Thompson 	[UQ_MSC_FLOPPY_SPEED]		= "UQ_MSC_FLOPPY_SPEED",
635eb584416SAndrew Thompson 	[UQ_MSC_IGNORE_RESIDUE]		= "UQ_MSC_IGNORE_RESIDUE",
636eb584416SAndrew Thompson 	[UQ_MSC_WRONG_CSWSIG]		= "UQ_MSC_WRONG_CSWSIG",
637eb584416SAndrew Thompson 	[UQ_MSC_RBC_PAD_TO_12]		= "UQ_MSC_RBC_PAD_TO_12",
638eb584416SAndrew Thompson 	[UQ_MSC_READ_CAP_OFFBY1]	= "UQ_MSC_READ_CAP_OFFBY1",
639eb584416SAndrew Thompson 	[UQ_MSC_FORCE_SHORT_INQ]	= "UQ_MSC_FORCE_SHORT_INQ",
640eb584416SAndrew Thompson 	[UQ_MSC_FORCE_WIRE_BBB]		= "UQ_MSC_FORCE_WIRE_BBB",
641eb584416SAndrew Thompson 	[UQ_MSC_FORCE_WIRE_CBI]		= "UQ_MSC_FORCE_WIRE_CBI",
642eb584416SAndrew Thompson 	[UQ_MSC_FORCE_WIRE_CBI_I]	= "UQ_MSC_FORCE_WIRE_CBI_I",
643eb584416SAndrew Thompson 	[UQ_MSC_FORCE_PROTO_SCSI]	= "UQ_MSC_FORCE_PROTO_SCSI",
644eb584416SAndrew Thompson 	[UQ_MSC_FORCE_PROTO_ATAPI]	= "UQ_MSC_FORCE_PROTO_ATAPI",
645eb584416SAndrew Thompson 	[UQ_MSC_FORCE_PROTO_UFI]	= "UQ_MSC_FORCE_PROTO_UFI",
646eb584416SAndrew Thompson 	[UQ_MSC_FORCE_PROTO_RBC]	= "UQ_MSC_FORCE_PROTO_RBC",
6479d2d0446SBjoern A. Zeeb 	[UQ_MSC_IGNORE]			= "UQ_MSC_IGNORE",
648e7702e9eSNick Hibma 	[UQ_MSC_EJECT_HUAWEI]		= "UQ_MSC_EJECT_HUAWEI",
649e7702e9eSNick Hibma 	[UQ_MSC_EJECT_SIERRA]		= "UQ_MSC_EJECT_SIERRA",
650e7702e9eSNick Hibma 	[UQ_MSC_EJECT_SCSIEJECT]	= "UQ_MSC_EJECT_SCSIEJECT",
651e7702e9eSNick Hibma 	[UQ_MSC_EJECT_REZERO]		= "UQ_MSC_EJECT_REZERO",
652e7702e9eSNick Hibma 	[UQ_MSC_EJECT_ZTESTOR]		= "UQ_MSC_EJECT_ZTESTOR",
653e7702e9eSNick Hibma 	[UQ_MSC_EJECT_CMOTECH]		= "UQ_MSC_EJECT_CMOTECH",
654e7702e9eSNick Hibma 	[UQ_MSC_EJECT_WAIT]		= "UQ_MSC_EJECT_WAIT",
655e7702e9eSNick Hibma 	[UQ_MSC_EJECT_SAEL_M460]	= "UQ_MSC_EJECT_SAEL_M460",
656e7702e9eSNick Hibma 	[UQ_MSC_EJECT_HUAWEISCSI]	= "UQ_MSC_EJECT_HUAWEISCSI",
657c5377460SNick Hibma 	[UQ_MSC_EJECT_HUAWEISCSI2]	= "UQ_MSC_EJECT_HUAWEISCSI2",
65864fd867fSMichael Paepcke 	[UQ_MSC_EJECT_HUAWEISCSI3]	= "UQ_MSC_EJECT_HUAWEISCSI3",
65964fd867fSMichael Paepcke 	[UQ_MSC_EJECT_HUAWEISCSI4]	= "UQ_MSC_EJECT_HUAWEISCSI4",
660e7702e9eSNick Hibma 	[UQ_MSC_EJECT_TCT]		= "UQ_MSC_EJECT_TCT",
66125b74dabSHans Petter Selasky 	[UQ_BAD_MIDI]			= "UQ_BAD_MIDI",
66225b74dabSHans Petter Selasky 	[UQ_AU_VENDOR_CLASS]		= "UQ_AU_VENDOR_CLASS",
6634944c3a8SHans Petter Selasky 	[UQ_SINGLE_CMD_MIDI]		= "UQ_SINGLE_CMD_MIDI",
664415bcd89SHans Petter Selasky 	[UQ_MSC_DYMO_EJECT]		= "UQ_MSC_DYMO_EJECT",
665067e471aSHans Petter Selasky 	[UQ_AU_SET_SPDIF_CM6206]	= "UQ_AU_SET_SPDIF_CM6206",
66676136d20SVladimir Kondratyev 	[UQ_WMT_IGNORE]			= "UQ_WMT_IGNORE",
66702ac6454SAndrew Thompson };
66802ac6454SAndrew Thompson 
66902ac6454SAndrew Thompson /*------------------------------------------------------------------------*
670a593f6b8SAndrew Thompson  *	usb_quirkstr
67102ac6454SAndrew Thompson  *
67202ac6454SAndrew Thompson  * This function converts an USB quirk code into a string.
67302ac6454SAndrew Thompson  *------------------------------------------------------------------------*/
67402ac6454SAndrew Thompson static const char *
675a593f6b8SAndrew Thompson usb_quirkstr(uint16_t quirk)
67602ac6454SAndrew Thompson {
677a130076fSHans Petter Selasky 	return ((quirk < USB_QUIRK_MAX && usb_quirk_str[quirk] != NULL) ?
678a130076fSHans Petter Selasky 	    usb_quirk_str[quirk] : "UQ_UNKNOWN");
679a130076fSHans Petter Selasky }
680a130076fSHans Petter Selasky 
681a130076fSHans Petter Selasky /*------------------------------------------------------------------------*
682a130076fSHans Petter Selasky  *	usb_strquirk
683a130076fSHans Petter Selasky  *
684a130076fSHans Petter Selasky  * This function converts a string into a USB quirk code.
685a130076fSHans Petter Selasky  *
686a130076fSHans Petter Selasky  * Returns:
687a130076fSHans Petter Selasky  * Less than USB_QUIRK_MAX: Quirk code
688a130076fSHans Petter Selasky  * Else: Quirk code not found
689a130076fSHans Petter Selasky  *------------------------------------------------------------------------*/
690a130076fSHans Petter Selasky static uint16_t
691a130076fSHans Petter Selasky usb_strquirk(const char *str, size_t len)
692a130076fSHans Petter Selasky {
693a130076fSHans Petter Selasky 	const char *quirk;
694a130076fSHans Petter Selasky 	uint16_t x;
695a130076fSHans Petter Selasky 
696a130076fSHans Petter Selasky 	for (x = 0; x != USB_QUIRK_MAX; x++) {
697a130076fSHans Petter Selasky 		quirk = usb_quirkstr(x);
698a130076fSHans Petter Selasky 		if (strncmp(str, quirk, len) == 0 &&
699a130076fSHans Petter Selasky 		    quirk[len] == 0)
700a130076fSHans Petter Selasky 			break;
701a130076fSHans Petter Selasky 	}
702a130076fSHans Petter Selasky 	return (x);
70302ac6454SAndrew Thompson }
70402ac6454SAndrew Thompson 
70502ac6454SAndrew Thompson /*------------------------------------------------------------------------*
706a593f6b8SAndrew Thompson  *	usb_test_quirk_by_info
70702ac6454SAndrew Thompson  *
70802ac6454SAndrew Thompson  * Returns:
70902ac6454SAndrew Thompson  * 0: Quirk not found
71002ac6454SAndrew Thompson  * Else: Quirk found
71102ac6454SAndrew Thompson  *------------------------------------------------------------------------*/
71202ac6454SAndrew Thompson static uint8_t
713a593f6b8SAndrew Thompson usb_test_quirk_by_info(const struct usbd_lookup_info *info, uint16_t quirk)
71402ac6454SAndrew Thompson {
71502ac6454SAndrew Thompson 	uint16_t x;
71602ac6454SAndrew Thompson 	uint16_t y;
71702ac6454SAndrew Thompson 
718d46dc4adSHans Petter Selasky 	if (quirk == UQ_NONE)
719d46dc4adSHans Petter Selasky 		goto done;
720d46dc4adSHans Petter Selasky 
7210eb8d462SHans Petter Selasky 	USB_MTX_LOCK(&usb_quirk_mtx);
72202ac6454SAndrew Thompson 
72302ac6454SAndrew Thompson 	for (x = 0; x != USB_DEV_QUIRKS_MAX; x++) {
72402ac6454SAndrew Thompson 		/* see if quirk information does not match */
725a593f6b8SAndrew Thompson 		if ((usb_quirks[x].vid != info->idVendor) ||
726a593f6b8SAndrew Thompson 		    (usb_quirks[x].lo_rev > info->bcdDevice) ||
727a593f6b8SAndrew Thompson 		    (usb_quirks[x].hi_rev < info->bcdDevice)) {
72802ac6454SAndrew Thompson 			continue;
72902ac6454SAndrew Thompson 		}
730eb584416SAndrew Thompson 		/* see if quirk only should match vendor ID */
731eb584416SAndrew Thompson 		if (usb_quirks[x].pid != info->idProduct) {
732eb584416SAndrew Thompson 			if (usb_quirks[x].pid != 0)
733eb584416SAndrew Thompson 				continue;
734eb584416SAndrew Thompson 
735eb584416SAndrew Thompson 			for (y = 0; y != USB_SUB_QUIRKS_MAX; y++) {
736eb584416SAndrew Thompson 				if (usb_quirks[x].quirks[y] == UQ_MATCH_VENDOR_ONLY)
737eb584416SAndrew Thompson 					break;
738eb584416SAndrew Thompson 			}
739eb584416SAndrew Thompson 			if (y == USB_SUB_QUIRKS_MAX)
740eb584416SAndrew Thompson 				continue;
741eb584416SAndrew Thompson 		}
74202ac6454SAndrew Thompson 		/* lookup quirk */
74302ac6454SAndrew Thompson 		for (y = 0; y != USB_SUB_QUIRKS_MAX; y++) {
744a593f6b8SAndrew Thompson 			if (usb_quirks[x].quirks[y] == quirk) {
7450eb8d462SHans Petter Selasky 				USB_MTX_UNLOCK(&usb_quirk_mtx);
746a593f6b8SAndrew Thompson 				DPRINTF("Found quirk '%s'.\n", usb_quirkstr(quirk));
74702ac6454SAndrew Thompson 				return (1);
74802ac6454SAndrew Thompson 			}
74902ac6454SAndrew Thompson 		}
75002ac6454SAndrew Thompson 	}
7510eb8d462SHans Petter Selasky 	USB_MTX_UNLOCK(&usb_quirk_mtx);
752d46dc4adSHans Petter Selasky done:
7533f37fb62SHans Petter Selasky 	return (0);			/* no quirk match */
75402ac6454SAndrew Thompson }
75502ac6454SAndrew Thompson 
756a593f6b8SAndrew Thompson static struct usb_quirk_entry *
757a593f6b8SAndrew Thompson usb_quirk_get_entry(uint16_t vid, uint16_t pid,
75802ac6454SAndrew Thompson     uint16_t lo_rev, uint16_t hi_rev, uint8_t do_alloc)
75902ac6454SAndrew Thompson {
76002ac6454SAndrew Thompson 	uint16_t x;
76102ac6454SAndrew Thompson 
7620eb8d462SHans Petter Selasky 	USB_MTX_ASSERT(&usb_quirk_mtx, MA_OWNED);
76302ac6454SAndrew Thompson 
76402ac6454SAndrew Thompson 	if ((vid | pid | lo_rev | hi_rev) == 0) {
76502ac6454SAndrew Thompson 		/* all zero - special case */
766a593f6b8SAndrew Thompson 		return (usb_quirks + USB_DEV_QUIRKS_MAX - 1);
76702ac6454SAndrew Thompson 	}
76802ac6454SAndrew Thompson 	/* search for an existing entry */
76902ac6454SAndrew Thompson 	for (x = 0; x != USB_DEV_QUIRKS_MAX; x++) {
77002ac6454SAndrew Thompson 		/* see if quirk information does not match */
771a593f6b8SAndrew Thompson 		if ((usb_quirks[x].vid != vid) ||
772a593f6b8SAndrew Thompson 		    (usb_quirks[x].pid != pid) ||
773a593f6b8SAndrew Thompson 		    (usb_quirks[x].lo_rev != lo_rev) ||
774a593f6b8SAndrew Thompson 		    (usb_quirks[x].hi_rev != hi_rev)) {
77502ac6454SAndrew Thompson 			continue;
77602ac6454SAndrew Thompson 		}
777a593f6b8SAndrew Thompson 		return (usb_quirks + x);
77802ac6454SAndrew Thompson 	}
77902ac6454SAndrew Thompson 
78002ac6454SAndrew Thompson 	if (do_alloc == 0) {
78102ac6454SAndrew Thompson 		/* no match */
78202ac6454SAndrew Thompson 		return (NULL);
78302ac6454SAndrew Thompson 	}
78402ac6454SAndrew Thompson 	/* search for a free entry */
78502ac6454SAndrew Thompson 	for (x = 0; x != USB_DEV_QUIRKS_MAX; x++) {
78602ac6454SAndrew Thompson 		/* see if quirk information does not match */
787a593f6b8SAndrew Thompson 		if ((usb_quirks[x].vid |
788a593f6b8SAndrew Thompson 		    usb_quirks[x].pid |
789a593f6b8SAndrew Thompson 		    usb_quirks[x].lo_rev |
790a593f6b8SAndrew Thompson 		    usb_quirks[x].hi_rev) != 0) {
79102ac6454SAndrew Thompson 			continue;
79202ac6454SAndrew Thompson 		}
793a593f6b8SAndrew Thompson 		usb_quirks[x].vid = vid;
794a593f6b8SAndrew Thompson 		usb_quirks[x].pid = pid;
795a593f6b8SAndrew Thompson 		usb_quirks[x].lo_rev = lo_rev;
796a593f6b8SAndrew Thompson 		usb_quirks[x].hi_rev = hi_rev;
79702ac6454SAndrew Thompson 
798a593f6b8SAndrew Thompson 		return (usb_quirks + x);
79902ac6454SAndrew Thompson 	}
80002ac6454SAndrew Thompson 
80102ac6454SAndrew Thompson 	/* no entry found */
80202ac6454SAndrew Thompson 	return (NULL);
80302ac6454SAndrew Thompson }
80402ac6454SAndrew Thompson 
80502ac6454SAndrew Thompson /*------------------------------------------------------------------------*
806a593f6b8SAndrew Thompson  *	usb_quirk_ioctl - handle quirk IOCTLs
80702ac6454SAndrew Thompson  *
80802ac6454SAndrew Thompson  * Returns:
80902ac6454SAndrew Thompson  * 0: Success
81002ac6454SAndrew Thompson  * Else: Failure
81102ac6454SAndrew Thompson  *------------------------------------------------------------------------*/
81202ac6454SAndrew Thompson static int
813a593f6b8SAndrew Thompson usb_quirk_ioctl(unsigned long cmd, caddr_t data,
81402ac6454SAndrew Thompson     int fflag, struct thread *td)
81502ac6454SAndrew Thompson {
816760bc48eSAndrew Thompson 	struct usb_gen_quirk *pgq;
817a593f6b8SAndrew Thompson 	struct usb_quirk_entry *pqe;
81802ac6454SAndrew Thompson 	uint32_t x;
81902ac6454SAndrew Thompson 	uint32_t y;
82002ac6454SAndrew Thompson 	int err;
82102ac6454SAndrew Thompson 
82202ac6454SAndrew Thompson 	switch (cmd) {
82302ac6454SAndrew Thompson 	case USB_DEV_QUIRK_GET:
82402ac6454SAndrew Thompson 		pgq = (void *)data;
82502ac6454SAndrew Thompson 		x = pgq->index % USB_SUB_QUIRKS_MAX;
82602ac6454SAndrew Thompson 		y = pgq->index / USB_SUB_QUIRKS_MAX;
82702ac6454SAndrew Thompson 		if (y >= USB_DEV_QUIRKS_MAX) {
82802ac6454SAndrew Thompson 			return (EINVAL);
82902ac6454SAndrew Thompson 		}
8300eb8d462SHans Petter Selasky 		USB_MTX_LOCK(&usb_quirk_mtx);
83102ac6454SAndrew Thompson 		/* copy out data */
832a593f6b8SAndrew Thompson 		pgq->vid = usb_quirks[y].vid;
833a593f6b8SAndrew Thompson 		pgq->pid = usb_quirks[y].pid;
834a593f6b8SAndrew Thompson 		pgq->bcdDeviceLow = usb_quirks[y].lo_rev;
835a593f6b8SAndrew Thompson 		pgq->bcdDeviceHigh = usb_quirks[y].hi_rev;
83602ac6454SAndrew Thompson 		strlcpy(pgq->quirkname,
837a593f6b8SAndrew Thompson 		    usb_quirkstr(usb_quirks[y].quirks[x]),
83802ac6454SAndrew Thompson 		    sizeof(pgq->quirkname));
8390eb8d462SHans Petter Selasky 		USB_MTX_UNLOCK(&usb_quirk_mtx);
84002ac6454SAndrew Thompson 		return (0);		/* success */
84102ac6454SAndrew Thompson 
84202ac6454SAndrew Thompson 	case USB_QUIRK_NAME_GET:
84302ac6454SAndrew Thompson 		pgq = (void *)data;
84402ac6454SAndrew Thompson 		x = pgq->index;
84502ac6454SAndrew Thompson 		if (x >= USB_QUIRK_MAX) {
84602ac6454SAndrew Thompson 			return (EINVAL);
84702ac6454SAndrew Thompson 		}
84802ac6454SAndrew Thompson 		strlcpy(pgq->quirkname,
849a593f6b8SAndrew Thompson 		    usb_quirkstr(x), sizeof(pgq->quirkname));
85002ac6454SAndrew Thompson 		return (0);		/* success */
85102ac6454SAndrew Thompson 
85202ac6454SAndrew Thompson 	case USB_DEV_QUIRK_ADD:
85302ac6454SAndrew Thompson 		pgq = (void *)data;
85402ac6454SAndrew Thompson 
85502ac6454SAndrew Thompson 		/* check privileges */
85602ac6454SAndrew Thompson 		err = priv_check(curthread, PRIV_DRIVER);
85702ac6454SAndrew Thompson 		if (err) {
85802ac6454SAndrew Thompson 			return (err);
85902ac6454SAndrew Thompson 		}
86002ac6454SAndrew Thompson 		/* convert quirk string into numerical */
86102ac6454SAndrew Thompson 		for (y = 0; y != USB_DEV_QUIRKS_MAX; y++) {
862a593f6b8SAndrew Thompson 			if (strcmp(pgq->quirkname, usb_quirkstr(y)) == 0) {
86302ac6454SAndrew Thompson 				break;
86402ac6454SAndrew Thompson 			}
86502ac6454SAndrew Thompson 		}
86602ac6454SAndrew Thompson 		if (y == USB_DEV_QUIRKS_MAX) {
86702ac6454SAndrew Thompson 			return (EINVAL);
86802ac6454SAndrew Thompson 		}
86902ac6454SAndrew Thompson 		if (y == UQ_NONE) {
87002ac6454SAndrew Thompson 			return (EINVAL);
87102ac6454SAndrew Thompson 		}
8720eb8d462SHans Petter Selasky 		USB_MTX_LOCK(&usb_quirk_mtx);
873a593f6b8SAndrew Thompson 		pqe = usb_quirk_get_entry(pgq->vid, pgq->pid,
87402ac6454SAndrew Thompson 		    pgq->bcdDeviceLow, pgq->bcdDeviceHigh, 1);
8754d69093fSAndrew Thompson 		if (pqe == NULL) {
8760eb8d462SHans Petter Selasky 			USB_MTX_UNLOCK(&usb_quirk_mtx);
8774d69093fSAndrew Thompson 			return (EINVAL);
8784d69093fSAndrew Thompson 		}
87902ac6454SAndrew Thompson 		for (x = 0; x != USB_SUB_QUIRKS_MAX; x++) {
88002ac6454SAndrew Thompson 			if (pqe->quirks[x] == UQ_NONE) {
88102ac6454SAndrew Thompson 				pqe->quirks[x] = y;
88202ac6454SAndrew Thompson 				break;
88302ac6454SAndrew Thompson 			}
88402ac6454SAndrew Thompson 		}
8850eb8d462SHans Petter Selasky 		USB_MTX_UNLOCK(&usb_quirk_mtx);
88602ac6454SAndrew Thompson 		if (x == USB_SUB_QUIRKS_MAX) {
88702ac6454SAndrew Thompson 			return (ENOMEM);
88802ac6454SAndrew Thompson 		}
88902ac6454SAndrew Thompson 		return (0);		/* success */
89002ac6454SAndrew Thompson 
89102ac6454SAndrew Thompson 	case USB_DEV_QUIRK_REMOVE:
89202ac6454SAndrew Thompson 		pgq = (void *)data;
89302ac6454SAndrew Thompson 		/* check privileges */
89402ac6454SAndrew Thompson 		err = priv_check(curthread, PRIV_DRIVER);
89502ac6454SAndrew Thompson 		if (err) {
89602ac6454SAndrew Thompson 			return (err);
89702ac6454SAndrew Thompson 		}
89802ac6454SAndrew Thompson 		/* convert quirk string into numerical */
89902ac6454SAndrew Thompson 		for (y = 0; y != USB_DEV_QUIRKS_MAX; y++) {
900a593f6b8SAndrew Thompson 			if (strcmp(pgq->quirkname, usb_quirkstr(y)) == 0) {
90102ac6454SAndrew Thompson 				break;
90202ac6454SAndrew Thompson 			}
90302ac6454SAndrew Thompson 		}
90402ac6454SAndrew Thompson 		if (y == USB_DEV_QUIRKS_MAX) {
90502ac6454SAndrew Thompson 			return (EINVAL);
90602ac6454SAndrew Thompson 		}
90702ac6454SAndrew Thompson 		if (y == UQ_NONE) {
90802ac6454SAndrew Thompson 			return (EINVAL);
90902ac6454SAndrew Thompson 		}
9100eb8d462SHans Petter Selasky 		USB_MTX_LOCK(&usb_quirk_mtx);
911a593f6b8SAndrew Thompson 		pqe = usb_quirk_get_entry(pgq->vid, pgq->pid,
91202ac6454SAndrew Thompson 		    pgq->bcdDeviceLow, pgq->bcdDeviceHigh, 0);
9134d69093fSAndrew Thompson 		if (pqe == NULL) {
9140eb8d462SHans Petter Selasky 			USB_MTX_UNLOCK(&usb_quirk_mtx);
9154d69093fSAndrew Thompson 			return (EINVAL);
9164d69093fSAndrew Thompson 		}
91702ac6454SAndrew Thompson 		for (x = 0; x != USB_SUB_QUIRKS_MAX; x++) {
91802ac6454SAndrew Thompson 			if (pqe->quirks[x] == y) {
91902ac6454SAndrew Thompson 				pqe->quirks[x] = UQ_NONE;
92002ac6454SAndrew Thompson 				break;
92102ac6454SAndrew Thompson 			}
92202ac6454SAndrew Thompson 		}
92302ac6454SAndrew Thompson 		if (x == USB_SUB_QUIRKS_MAX) {
9240eb8d462SHans Petter Selasky 			USB_MTX_UNLOCK(&usb_quirk_mtx);
92502ac6454SAndrew Thompson 			return (ENOMEM);
92602ac6454SAndrew Thompson 		}
92702ac6454SAndrew Thompson 		for (x = 0; x != USB_SUB_QUIRKS_MAX; x++) {
92802ac6454SAndrew Thompson 			if (pqe->quirks[x] != UQ_NONE) {
92902ac6454SAndrew Thompson 				break;
93002ac6454SAndrew Thompson 			}
93102ac6454SAndrew Thompson 		}
93202ac6454SAndrew Thompson 		if (x == USB_SUB_QUIRKS_MAX) {
93302ac6454SAndrew Thompson 			/* all quirk entries are unused - release */
934bdf43bb5SHans Petter Selasky 			memset(pqe, 0, sizeof(*pqe));
93502ac6454SAndrew Thompson 		}
9360eb8d462SHans Petter Selasky 		USB_MTX_UNLOCK(&usb_quirk_mtx);
93702ac6454SAndrew Thompson 		return (0);		/* success */
93802ac6454SAndrew Thompson 
93902ac6454SAndrew Thompson 	default:
94002ac6454SAndrew Thompson 		break;
94102ac6454SAndrew Thompson 	}
94202ac6454SAndrew Thompson 	return (ENOIOCTL);
94302ac6454SAndrew Thompson }
94402ac6454SAndrew Thompson 
945a130076fSHans Petter Selasky /*------------------------------------------------------------------------*
946a130076fSHans Petter Selasky  *	usb_quirk_strtou16
947a130076fSHans Petter Selasky  *
948a130076fSHans Petter Selasky  * Helper function to scan a 16-bit integer.
949a130076fSHans Petter Selasky  *------------------------------------------------------------------------*/
950a130076fSHans Petter Selasky static uint16_t
951a130076fSHans Petter Selasky usb_quirk_strtou16(const char **pptr, const char *name, const char *what)
952a130076fSHans Petter Selasky {
953a130076fSHans Petter Selasky 	unsigned long value;
954a130076fSHans Petter Selasky 	char *end;
955a130076fSHans Petter Selasky 
956a130076fSHans Petter Selasky 	value = strtoul(*pptr, &end, 0);
957a130076fSHans Petter Selasky 	if (value > 65535 || *pptr == end || (*end != ' ' && *end != '\t')) {
958a130076fSHans Petter Selasky 		printf("%s: %s 16-bit %s value set to zero\n",
959a130076fSHans Petter Selasky 		    name, what, *end == 0 ? "incomplete" : "invalid");
960a130076fSHans Petter Selasky 		return (0);
961a130076fSHans Petter Selasky 	}
962a130076fSHans Petter Selasky 	*pptr = end + 1;
963a130076fSHans Petter Selasky 	return ((uint16_t)value);
964a130076fSHans Petter Selasky }
965a130076fSHans Petter Selasky 
966a130076fSHans Petter Selasky /*------------------------------------------------------------------------*
967a130076fSHans Petter Selasky  *	usb_quirk_add_entry_from_str
968a130076fSHans Petter Selasky  *
969a130076fSHans Petter Selasky  * Add a USB quirk entry from string.
970a130076fSHans Petter Selasky  *     "VENDOR PRODUCT LO_REV HI_REV QUIRK[,QUIRK[,...]]"
971a130076fSHans Petter Selasky  *------------------------------------------------------------------------*/
972a130076fSHans Petter Selasky static void
973a130076fSHans Petter Selasky usb_quirk_add_entry_from_str(const char *name, const char *env)
974a130076fSHans Petter Selasky {
975a130076fSHans Petter Selasky 	struct usb_quirk_entry entry = { };
976a130076fSHans Petter Selasky 	struct usb_quirk_entry *new;
977a130076fSHans Petter Selasky 	uint16_t quirk_idx;
978a130076fSHans Petter Selasky 	uint16_t quirk;
979a130076fSHans Petter Selasky 	const char *end;
980a130076fSHans Petter Selasky 
981a130076fSHans Petter Selasky 	/* check for invalid environment variable */
982a130076fSHans Petter Selasky 	if (name == NULL || env == NULL)
983a130076fSHans Petter Selasky 		return;
984a130076fSHans Petter Selasky 
985a130076fSHans Petter Selasky 	if (bootverbose)
986a130076fSHans Petter Selasky 		printf("Adding USB QUIRK '%s' = '%s'\n", name, env);
987a130076fSHans Petter Selasky 
988a130076fSHans Petter Selasky 	/* parse device information */
989a130076fSHans Petter Selasky 	entry.vid = usb_quirk_strtou16(&env, name, "Vendor ID");
990a130076fSHans Petter Selasky 	entry.pid = usb_quirk_strtou16(&env, name, "Product ID");
991a130076fSHans Petter Selasky 	entry.lo_rev = usb_quirk_strtou16(&env, name, "Low revision");
992a130076fSHans Petter Selasky 	entry.hi_rev = usb_quirk_strtou16(&env, name, "High revision");
993a130076fSHans Petter Selasky 
994a130076fSHans Petter Selasky 	/* parse quirk information */
995a130076fSHans Petter Selasky 	quirk_idx = 0;
996a130076fSHans Petter Selasky 	while (*env != 0 && quirk_idx != USB_SUB_QUIRKS_MAX) {
997a130076fSHans Petter Selasky 		/* skip whitespace before quirks */
998a130076fSHans Petter Selasky 		while (*env == ' ' || *env == '\t')
999a130076fSHans Petter Selasky 			env++;
1000a130076fSHans Petter Selasky 
1001a130076fSHans Petter Selasky 		/* look for quirk separation character */
1002a130076fSHans Petter Selasky 		end = strchr(env, ',');
1003a130076fSHans Petter Selasky 		if (end == NULL)
1004a130076fSHans Petter Selasky 			end = env + strlen(env);
1005a130076fSHans Petter Selasky 
1006a130076fSHans Petter Selasky 		/* lookup quirk in string table */
1007a130076fSHans Petter Selasky 		quirk = usb_strquirk(env, end - env);
1008a130076fSHans Petter Selasky 		if (quirk < USB_QUIRK_MAX) {
1009a130076fSHans Petter Selasky 			entry.quirks[quirk_idx++] = quirk;
1010a130076fSHans Petter Selasky 		} else {
1011a130076fSHans Petter Selasky 			printf("%s: unknown USB quirk '%.*s' (skipped)\n",
1012a130076fSHans Petter Selasky 			    name, (int)(end - env), env);
1013a130076fSHans Petter Selasky 		}
1014a130076fSHans Petter Selasky 		env = end;
1015a130076fSHans Petter Selasky 
1016a130076fSHans Petter Selasky 		/* skip quirk delimiter, if any */
1017a130076fSHans Petter Selasky 		if (*env != 0)
1018a130076fSHans Petter Selasky 			env++;
1019a130076fSHans Petter Selasky 	}
1020a130076fSHans Petter Selasky 
1021a130076fSHans Petter Selasky 	/* register quirk */
1022a130076fSHans Petter Selasky 	if (quirk_idx != 0) {
1023a130076fSHans Petter Selasky 		if (*env != 0) {
1024a130076fSHans Petter Selasky 			printf("%s: Too many USB quirks, only %d allowed!\n",
1025a130076fSHans Petter Selasky 			    name, USB_SUB_QUIRKS_MAX);
1026a130076fSHans Petter Selasky 		}
10270eb8d462SHans Petter Selasky 		USB_MTX_LOCK(&usb_quirk_mtx);
1028a130076fSHans Petter Selasky 		new = usb_quirk_get_entry(entry.vid, entry.pid,
1029a130076fSHans Petter Selasky 		    entry.lo_rev, entry.hi_rev, 1);
1030a130076fSHans Petter Selasky 		if (new == NULL)
1031a130076fSHans Petter Selasky 			printf("%s: USB quirks table is full!\n", name);
1032a130076fSHans Petter Selasky 		else
1033a130076fSHans Petter Selasky 			memcpy(new->quirks, entry.quirks, sizeof(entry.quirks));
10340eb8d462SHans Petter Selasky 		USB_MTX_UNLOCK(&usb_quirk_mtx);
1035a130076fSHans Petter Selasky 	} else {
1036a130076fSHans Petter Selasky 		printf("%s: No USB quirks found!\n", name);
1037a130076fSHans Petter Selasky 	}
1038a130076fSHans Petter Selasky }
1039a130076fSHans Petter Selasky 
104002ac6454SAndrew Thompson static void
1041a593f6b8SAndrew Thompson usb_quirk_init(void *arg)
104202ac6454SAndrew Thompson {
1043a130076fSHans Petter Selasky 	char envkey[sizeof(USB_QUIRK_ENVROOT) + 2];	/* 2 digits max, 0 to 99 */
1044a130076fSHans Petter Selasky 	int i;
1045a130076fSHans Petter Selasky 
104602ac6454SAndrew Thompson 	/* initialize mutex */
1047a593f6b8SAndrew Thompson 	mtx_init(&usb_quirk_mtx, "USB quirk", NULL, MTX_DEF);
104802ac6454SAndrew Thompson 
1049a130076fSHans Petter Selasky 	/* look for quirks defined by the environment variable */
1050a130076fSHans Petter Selasky 	for (i = 0; i != 100; i++) {
1051a130076fSHans Petter Selasky 		snprintf(envkey, sizeof(envkey), USB_QUIRK_ENVROOT "%d", i);
1052a130076fSHans Petter Selasky 
1053a130076fSHans Petter Selasky 		/* Stop at first undefined var */
1054a130076fSHans Petter Selasky 		if (!testenv(envkey))
1055a130076fSHans Petter Selasky 			break;
1056a130076fSHans Petter Selasky 
1057a130076fSHans Petter Selasky 		/* parse environment variable */
1058a130076fSHans Petter Selasky 		usb_quirk_add_entry_from_str(envkey, kern_getenv(envkey));
1059a130076fSHans Petter Selasky 	}
1060a130076fSHans Petter Selasky 
106102ac6454SAndrew Thompson 	/* register our function */
1062a593f6b8SAndrew Thompson 	usb_test_quirk_p = &usb_test_quirk_by_info;
1063a593f6b8SAndrew Thompson 	usb_quirk_ioctl_p = &usb_quirk_ioctl;
106402ac6454SAndrew Thompson }
106502ac6454SAndrew Thompson 
106602ac6454SAndrew Thompson static void
1067a593f6b8SAndrew Thompson usb_quirk_uninit(void *arg)
106802ac6454SAndrew Thompson {
1069a593f6b8SAndrew Thompson 	usb_quirk_unload(arg);
107002ac6454SAndrew Thompson 
107102ac6454SAndrew Thompson 	/* destroy mutex */
1072a593f6b8SAndrew Thompson 	mtx_destroy(&usb_quirk_mtx);
107302ac6454SAndrew Thompson }
107402ac6454SAndrew Thompson 
1075a593f6b8SAndrew Thompson SYSINIT(usb_quirk_init, SI_SUB_LOCK, SI_ORDER_FIRST, usb_quirk_init, NULL);
1076a593f6b8SAndrew Thompson SYSUNINIT(usb_quirk_uninit, SI_SUB_LOCK, SI_ORDER_ANY, usb_quirk_uninit, NULL);
1077