xref: /dragonfly/sys/bus/u4b/quirk/usb_quirk.c (revision 2b3f93ea)
1520083baSSascha Wildner /* $FreeBSD: head/sys/dev/usb/quirk/usb_quirk.c 329195 2018-02-13 08:13:20Z hselasky $ */
212bd3c8bSSascha Wildner /*-
3520083baSSascha Wildner  * SPDX-License-Identifier: BSD-2-Clause-NetBSD
4520083baSSascha Wildner  *
512bd3c8bSSascha Wildner  * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
612bd3c8bSSascha Wildner  * Copyright (c) 1998 Lennart Augustsson. All rights reserved.
712bd3c8bSSascha Wildner  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
812bd3c8bSSascha Wildner  *
912bd3c8bSSascha Wildner  * Redistribution and use in source and binary forms, with or without
1012bd3c8bSSascha Wildner  * modification, are permitted provided that the following conditions
1112bd3c8bSSascha Wildner  * are met:
1212bd3c8bSSascha Wildner  * 1. Redistributions of source code must retain the above copyright
1312bd3c8bSSascha Wildner  *    notice, this list of conditions and the following disclaimer.
1412bd3c8bSSascha Wildner  * 2. Redistributions in binary form must reproduce the above copyright
1512bd3c8bSSascha Wildner  *    notice, this list of conditions and the following disclaimer in the
1612bd3c8bSSascha Wildner  *    documentation and/or other materials provided with the distribution.
1712bd3c8bSSascha Wildner  *
1812bd3c8bSSascha Wildner  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1912bd3c8bSSascha Wildner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2012bd3c8bSSascha Wildner  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2112bd3c8bSSascha Wildner  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2212bd3c8bSSascha Wildner  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2312bd3c8bSSascha Wildner  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2412bd3c8bSSascha Wildner  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2512bd3c8bSSascha Wildner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2612bd3c8bSSascha Wildner  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2712bd3c8bSSascha Wildner  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2812bd3c8bSSascha Wildner  * SUCH DAMAGE.
2912bd3c8bSSascha Wildner  */
3012bd3c8bSSascha Wildner 
3112bd3c8bSSascha Wildner #include <sys/stdint.h>
3212bd3c8bSSascha Wildner #include <sys/param.h>
3312bd3c8bSSascha Wildner #include <sys/queue.h>
3412bd3c8bSSascha Wildner #include <sys/types.h>
3512bd3c8bSSascha Wildner #include <sys/systm.h>
3612bd3c8bSSascha Wildner #include <sys/kernel.h>
3712bd3c8bSSascha Wildner #include <sys/bus.h>
3812bd3c8bSSascha Wildner #include <sys/module.h>
3912bd3c8bSSascha Wildner #include <sys/lock.h>
4012bd3c8bSSascha Wildner #include <sys/condvar.h>
4112bd3c8bSSascha Wildner #include <sys/sysctl.h>
4212bd3c8bSSascha Wildner #include <sys/unistd.h>
4312bd3c8bSSascha Wildner #include <sys/callout.h>
4412bd3c8bSSascha Wildner #include <sys/malloc.h>
45*2b3f93eaSMatthew Dillon #include <sys/caps.h>
4612bd3c8bSSascha Wildner 
47ac499a8fSSascha Wildner #include <bus/u4b/usb.h>
48ac499a8fSSascha Wildner #include <bus/u4b/usb_ioctl.h>
49ac499a8fSSascha Wildner #include <bus/u4b/usbdi.h>
50ef4aa9ffSSascha Wildner #include "usbdevs.h"
5112bd3c8bSSascha Wildner 
5212bd3c8bSSascha Wildner #define	USB_DEBUG_VAR usb_debug
53ac499a8fSSascha Wildner #include <bus/u4b/usb_debug.h>
54ac499a8fSSascha Wildner #include <bus/u4b/usb_dynamic.h>
5512bd3c8bSSascha Wildner 
56ac499a8fSSascha Wildner #include <bus/u4b/quirk/usb_quirk.h>
5712bd3c8bSSascha Wildner 
5812bd3c8bSSascha Wildner MODULE_DEPEND(usb_quirk, usb, 1, 1, 1);
5912bd3c8bSSascha Wildner MODULE_VERSION(usb_quirk, 1);
6012bd3c8bSSascha Wildner 
61ff811b0aSSascha Wildner #define	USB_DEV_QUIRKS_MAX 384
6212bd3c8bSSascha Wildner #define	USB_SUB_QUIRKS_MAX 8
63520083baSSascha Wildner #define	USB_QUIRK_ENVROOT "hw.usb.quirk."
6412bd3c8bSSascha Wildner 
6512bd3c8bSSascha Wildner struct usb_quirk_entry {
6612bd3c8bSSascha Wildner 	uint16_t vid;
6712bd3c8bSSascha Wildner 	uint16_t pid;
6812bd3c8bSSascha Wildner 	uint16_t lo_rev;
6912bd3c8bSSascha Wildner 	uint16_t hi_rev;
7012bd3c8bSSascha Wildner 	uint16_t quirks[USB_SUB_QUIRKS_MAX];
7112bd3c8bSSascha Wildner };
7212bd3c8bSSascha Wildner 
73ac499a8fSSascha Wildner static struct lock usb_quirk_lock;
7412bd3c8bSSascha Wildner 
7512bd3c8bSSascha Wildner #define	USB_QUIRK_VP(v,p,l,h,...) \
7612bd3c8bSSascha Wildner   { .vid = (v), .pid = (p), .lo_rev = (l), .hi_rev = (h), \
7712bd3c8bSSascha Wildner     .quirks = { __VA_ARGS__ } }
7812bd3c8bSSascha Wildner #define	USB_QUIRK(v,p,l,h,...) \
7912bd3c8bSSascha Wildner   USB_QUIRK_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, l, h, __VA_ARGS__)
8012bd3c8bSSascha Wildner 
8112bd3c8bSSascha Wildner static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
8212bd3c8bSSascha Wildner 	USB_QUIRK(ASUS, LCM, 0x0000, 0xffff, UQ_HID_IGNORE),
8312bd3c8bSSascha Wildner 	USB_QUIRK(INSIDEOUT, EDGEPORT4, 0x094, 0x094, UQ_SWAP_UNICODE),
8412bd3c8bSSascha Wildner 	USB_QUIRK(DALLAS, J6502, 0x0a2, 0x0a2, UQ_BAD_ADC),
8512bd3c8bSSascha Wildner 	USB_QUIRK(DALLAS, J6502, 0x0a2, 0x0a2, UQ_AU_NO_XU),
8612bd3c8bSSascha Wildner 	USB_QUIRK(ALTEC, ADA70, 0x103, 0x103, UQ_BAD_ADC),
8712bd3c8bSSascha Wildner 	USB_QUIRK(ALTEC, ASC495, 0x000, 0x000, UQ_BAD_AUDIO),
8812bd3c8bSSascha Wildner 	USB_QUIRK(QTRONIX, 980N, 0x110, 0x110, UQ_SPUR_BUT_UP),
8912bd3c8bSSascha Wildner 	USB_QUIRK(ALCOR2, KBD_HUB, 0x001, 0x001, UQ_SPUR_BUT_UP),
9012bd3c8bSSascha Wildner 	USB_QUIRK(MCT, HUB0100, 0x102, 0x102, UQ_BUS_POWERED),
9112bd3c8bSSascha Wildner 	USB_QUIRK(MCT, USB232, 0x102, 0x102, UQ_BUS_POWERED),
9212bd3c8bSSascha Wildner 	USB_QUIRK(TI, UTUSB41, 0x110, 0x110, UQ_POWER_CLAIM),
9312bd3c8bSSascha Wildner 	USB_QUIRK(TELEX, MIC1, 0x009, 0x009, UQ_AU_NO_FRAC),
9412bd3c8bSSascha Wildner 	USB_QUIRK(SILICONPORTALS, YAPPHONE, 0x100, 0x100, UQ_AU_INP_ASYNC),
9512bd3c8bSSascha Wildner 	USB_QUIRK(LOGITECH, UN53B, 0x0000, 0xffff, UQ_NO_STRINGS),
96ff811b0aSSascha Wildner 	USB_QUIRK(REALTEK, RTL8196EU, 0x0000, 0xffff, UQ_CFG_INDEX_1),
97520083baSSascha Wildner 	USB_QUIRK(REALTEK, RTL8153, 0x0000, 0xffff, UQ_CFG_INDEX_1),
9812bd3c8bSSascha Wildner 	USB_QUIRK(ELSA, MODEM1, 0x0000, 0xffff, UQ_CFG_INDEX_1),
9957bed822SMarkus Pfeiffer 	USB_QUIRK(PLANEX2, MZKUE150N, 0x0000, 0xffff, UQ_CFG_INDEX_1),
100520083baSSascha Wildner 	USB_QUIRK(CISCOLINKSYS, USB3GIGV1, 0x0000, 0xffff, UQ_CFG_INDEX_1),
10112bd3c8bSSascha Wildner 	/* Quirks for printer devices */
10212bd3c8bSSascha Wildner 	USB_QUIRK(HP, 895C, 0x0000, 0xffff, UQ_BROKEN_BIDIR),
10312bd3c8bSSascha Wildner 	USB_QUIRK(HP, 880C, 0x0000, 0xffff, UQ_BROKEN_BIDIR),
10412bd3c8bSSascha Wildner 	USB_QUIRK(HP, 815C, 0x0000, 0xffff, UQ_BROKEN_BIDIR),
10512bd3c8bSSascha Wildner 	USB_QUIRK(HP, 810C, 0x0000, 0xffff, UQ_BROKEN_BIDIR),
10612bd3c8bSSascha Wildner 	USB_QUIRK(HP, 830C, 0x0000, 0xffff, UQ_BROKEN_BIDIR),
10712bd3c8bSSascha Wildner 	USB_QUIRK(HP, 1220C, 0x0000, 0xffff, UQ_BROKEN_BIDIR),
10812bd3c8bSSascha Wildner 	USB_QUIRK(XEROX, WCM15, 0x0000, 0xffff, UQ_BROKEN_BIDIR),
10912bd3c8bSSascha Wildner 	/* Devices which should be ignored by uhid */
11012bd3c8bSSascha Wildner 	USB_QUIRK(APC, UPS, 0x0000, 0xffff, UQ_HID_IGNORE),
11112bd3c8bSSascha Wildner 	USB_QUIRK(BELKIN, F6C550AVR, 0x0000, 0xffff, UQ_HID_IGNORE),
11212bd3c8bSSascha Wildner 	USB_QUIRK(CYBERPOWER, 1500CAVRLCD, 0x0000, 0xffff, UQ_HID_IGNORE),
11312bd3c8bSSascha Wildner 	USB_QUIRK(CYPRESS, SILVERSHIELD, 0x0000, 0xffff, UQ_HID_IGNORE),
11412bd3c8bSSascha Wildner 	USB_QUIRK(DELORME, EARTHMATE, 0x0000, 0xffff, UQ_HID_IGNORE),
115ff811b0aSSascha Wildner 	USB_QUIRK(DREAMLINK, DL100B, 0x0000, 0xffff, UQ_HID_IGNORE),
11612bd3c8bSSascha Wildner 	USB_QUIRK(ITUNERNET, USBLCD2X20, 0x0000, 0xffff, UQ_HID_IGNORE),
11712bd3c8bSSascha Wildner 	USB_QUIRK(ITUNERNET, USBLCD4X20, 0x0000, 0xffff, UQ_HID_IGNORE),
11812bd3c8bSSascha Wildner 	USB_QUIRK(LIEBERT, POWERSURE_PXT, 0x0000, 0xffff, UQ_HID_IGNORE),
11957bed822SMarkus Pfeiffer 	USB_QUIRK(LIEBERT2, PSI1000, 0x0000, 0xffff, UQ_HID_IGNORE),
12012bd3c8bSSascha Wildner 	USB_QUIRK(MGE, UPS1, 0x0000, 0xffff, UQ_HID_IGNORE),
12112bd3c8bSSascha Wildner 	USB_QUIRK(MGE, UPS2, 0x0000, 0xffff, UQ_HID_IGNORE),
12212bd3c8bSSascha Wildner 	USB_QUIRK(APPLE, IPHONE, 0x0000, 0xffff, UQ_HID_IGNORE),
12312bd3c8bSSascha Wildner 	USB_QUIRK(APPLE, IPHONE_3G, 0x0000, 0xffff, UQ_HID_IGNORE),
12412bd3c8bSSascha Wildner 	USB_QUIRK(MEGATEC, UPS, 0x0000, 0xffff, UQ_HID_IGNORE),
12512bd3c8bSSascha Wildner 	/* Devices which should be ignored by both ukbd and uhid */
12612bd3c8bSSascha Wildner 	USB_QUIRK(CYPRESS, WISPY1A, 0x0000, 0xffff, UQ_KBD_IGNORE, UQ_HID_IGNORE),
12712bd3c8bSSascha Wildner 	USB_QUIRK(METAGEEK, WISPY1B, 0x0000, 0xffff, UQ_KBD_IGNORE, UQ_HID_IGNORE),
12812bd3c8bSSascha Wildner 	USB_QUIRK(METAGEEK, WISPY24X, 0x0000, 0xffff, UQ_KBD_IGNORE, UQ_HID_IGNORE),
12912bd3c8bSSascha Wildner 	USB_QUIRK(METAGEEK2, WISPYDBX, 0x0000, 0xffff, UQ_KBD_IGNORE, UQ_HID_IGNORE),
13012bd3c8bSSascha Wildner 	USB_QUIRK(TENX, UAUDIO0, 0x0101, 0x0101, UQ_AUDIO_SWAP_LR),
13112bd3c8bSSascha Wildner 	/* MS keyboards do weird things */
13257bed822SMarkus Pfeiffer 	USB_QUIRK(MICROSOFT, NATURAL4000, 0x0000, 0xFFFF, UQ_KBD_BOOTPROTO),
13312bd3c8bSSascha Wildner 	USB_QUIRK(MICROSOFT, WLINTELLIMOUSE, 0x0000, 0xffff, UQ_MS_LEADING_BYTE),
13457bed822SMarkus Pfeiffer 	/* Quirk for Corsair Vengeance K60 keyboard */
13557bed822SMarkus Pfeiffer 	USB_QUIRK(CORSAIR, K60, 0x0000, 0xffff, UQ_KBD_BOOTPROTO),
136ff811b0aSSascha Wildner 	/* Quirk for Corsair Vengeance K70 keyboard */
137ff811b0aSSascha Wildner 	USB_QUIRK(CORSAIR, K70, 0x0000, 0xffff, UQ_KBD_BOOTPROTO),
138520083baSSascha Wildner 	/* Quirk for Corsair K70 RGB keyboard */
139520083baSSascha Wildner 	USB_QUIRK(CORSAIR, K70_RGB, 0x0000, 0xffff, UQ_KBD_BOOTPROTO),
140fe8b458aSMatthew Dillon 	USB_QUIRK(CORSAIR, K70_RGB, 0x0000, 0xffff, UQ_KBD_DELAY_INIT),
141fe8b458aSMatthew Dillon 	USB_QUIRK(CORSAIR, K70_RGB, 0x0000, 0xffff, UQ_KBD_DELAY_CTRL_MSG),
14257587a56SSascha Wildner 	/* Quirk for Corsair STRAFE Gaming keyboard */
14357587a56SSascha Wildner 	USB_QUIRK(CORSAIR, STRAFE, 0x0000, 0xffff, UQ_KBD_BOOTPROTO),
144fe8b458aSMatthew Dillon 	USB_QUIRK(CORSAIR, STRAFE, 0x0000, 0xffff, UQ_KBD_DELAY_INIT),
145fe8b458aSMatthew Dillon 	USB_QUIRK(CORSAIR, STRAFE, 0x0000, 0xffff, UQ_KBD_DELAY_CTRL_MSG),
146fe8b458aSMatthew Dillon 	/* Quirk for Corsair STRAFE RGB Gaming keyboard */
147fe8b458aSMatthew Dillon 	USB_QUIRK(CORSAIR, STRAFE_RGB, 0x0000, 0xffff, UQ_KBD_BOOTPROTO),
148fe8b458aSMatthew Dillon 	USB_QUIRK(CORSAIR, STRAFE_RGB, 0x0000, 0xffff, UQ_KBD_DELAY_INIT),
149fe8b458aSMatthew Dillon 	USB_QUIRK(CORSAIR, STRAFE_RGB, 0x0000, 0xffff, UQ_KBD_DELAY_CTRL_MSG),
15012bd3c8bSSascha Wildner 	/* umodem(4) device quirks */
15112bd3c8bSSascha Wildner 	USB_QUIRK(METRICOM, RICOCHET_GS, 0x100, 0x100, UQ_ASSUME_CM_OVER_DATA),
15212bd3c8bSSascha Wildner 	USB_QUIRK(SANYO, SCP4900, 0x000, 0x000, UQ_ASSUME_CM_OVER_DATA),
15312bd3c8bSSascha Wildner 	USB_QUIRK(MOTOROLA2, T720C, 0x001, 0x001, UQ_ASSUME_CM_OVER_DATA),
15412bd3c8bSSascha Wildner 	USB_QUIRK(EICON, DIVA852, 0x100, 0x100, UQ_ASSUME_CM_OVER_DATA),
15512bd3c8bSSascha Wildner 	USB_QUIRK(SIEMENS2, ES75, 0x000, 0x000, UQ_ASSUME_CM_OVER_DATA),
15612bd3c8bSSascha Wildner 	USB_QUIRK(QUALCOMM, CDMA_MSM, 0x0000, 0xffff, UQ_ASSUME_CM_OVER_DATA),
15712bd3c8bSSascha Wildner 	USB_QUIRK(QUALCOMM2, CDMA_MSM, 0x0000, 0xffff, UQ_ASSUME_CM_OVER_DATA),
15812bd3c8bSSascha Wildner 	USB_QUIRK(CURITEL, UM150, 0x0000, 0xffff, UQ_ASSUME_CM_OVER_DATA),
15912bd3c8bSSascha Wildner 	USB_QUIRK(CURITEL, UM175, 0x0000, 0xffff, UQ_ASSUME_CM_OVER_DATA),
16012bd3c8bSSascha Wildner 	USB_QUIRK(VERTEX, VW110L, 0x0000, 0xffff, UQ_ASSUME_CM_OVER_DATA),
16112bd3c8bSSascha Wildner 
16212bd3c8bSSascha Wildner 	/* USB Mass Storage Class Quirks */
16312bd3c8bSSascha Wildner 	USB_QUIRK_VP(USB_VENDOR_ASAHIOPTICAL, 0, UQ_MSC_NO_RS_CLEAR_UA,
16412bd3c8bSSascha Wildner 	    UQ_MATCH_VENDOR_ONLY),
16512bd3c8bSSascha Wildner 	USB_QUIRK(ADDON, ATTACHE, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
16612bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
16712bd3c8bSSascha Wildner 	USB_QUIRK(ADDON, A256MB, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
16812bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
16912bd3c8bSSascha Wildner 	USB_QUIRK(ADDON, DISKPRO512, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
17012bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
17112bd3c8bSSascha Wildner 	USB_QUIRK(ADDONICS2, CABLE_205, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
17212bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI),
17312bd3c8bSSascha Wildner 	USB_QUIRK(AIPTEK, POCKETCAM3M, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
17412bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI),
17512bd3c8bSSascha Wildner 	USB_QUIRK(ALCOR, UMCR_9361, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
17612bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN),
17712bd3c8bSSascha Wildner 	USB_QUIRK(ALCOR, TRANSCEND, 0x0000, 0xffff, UQ_MSC_NO_GETMAXLUN,
17812bd3c8bSSascha Wildner 	    UQ_MSC_NO_SYNC_CACHE, UQ_MSC_NO_TEST_UNIT_READY),
17912bd3c8bSSascha Wildner 	USB_QUIRK(APACER, HT202, 0x0000, 0xffff, UQ_MSC_NO_TEST_UNIT_READY,
18012bd3c8bSSascha Wildner 	    UQ_MSC_NO_SYNC_CACHE),
18112bd3c8bSSascha Wildner 	USB_QUIRK(ASAHIOPTICAL, OPTIO230, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
18212bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
18312bd3c8bSSascha Wildner 	USB_QUIRK(ASAHIOPTICAL, OPTIO330, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
18412bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
185ff811b0aSSascha Wildner 	USB_QUIRK(ATP, EUSB, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
18612bd3c8bSSascha Wildner 	USB_QUIRK(BELKIN, USB2SCSI, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
18712bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI),
18812bd3c8bSSascha Wildner 	USB_QUIRK(CASIO, QV_DIGICAM, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
18912bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
19012bd3c8bSSascha Wildner 	USB_QUIRK(CCYU, ED1064, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
19112bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI),
19212bd3c8bSSascha Wildner 	USB_QUIRK(CENTURY, EX35QUAT, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
19312bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_FORCE_SHORT_INQ,
19412bd3c8bSSascha Wildner 	    UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE),
19512bd3c8bSSascha Wildner 	USB_QUIRK(CYPRESS, XX6830XX, 0x0000, 0xffff, UQ_MSC_NO_GETMAXLUN,
19612bd3c8bSSascha Wildner 	    UQ_MSC_NO_SYNC_CACHE),
19712bd3c8bSSascha Wildner 	USB_QUIRK(DESKNOTE, UCR_61S2B, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
19812bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI),
19912bd3c8bSSascha Wildner 	USB_QUIRK(DMI, CFSM_RW, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI,
20012bd3c8bSSascha Wildner 	    UQ_MSC_NO_GETMAXLUN),
20157bed822SMarkus Pfeiffer 	USB_QUIRK(EMTEC, RUF2PS, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
20212bd3c8bSSascha Wildner 	USB_QUIRK(EPSON, STYLUS_875DC, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
20312bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
20412bd3c8bSSascha Wildner 	USB_QUIRK(EPSON, STYLUS_895, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
20512bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN),
20612bd3c8bSSascha Wildner 	USB_QUIRK(FEIYA, 5IN1, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
20712bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI),
20857bed822SMarkus Pfeiffer 	USB_QUIRK(FEIYA, ELANGO, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
20912bd3c8bSSascha Wildner 	USB_QUIRK(FREECOM, DVD, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI),
21012bd3c8bSSascha Wildner 	USB_QUIRK(FUJIPHOTO, MASS0100, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI_I,
21112bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_RS_CLEAR_UA, UQ_MSC_NO_SYNC_CACHE),
212520083baSSascha Wildner 	USB_QUIRK(GARMIN, FORERUNNER230, 0x0000, 0xffff, UQ_MSC_NO_INQUIRY),
21312bd3c8bSSascha Wildner 	USB_QUIRK(GENESYS, GL641USB2IDE, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
21412bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_FORCE_SHORT_INQ,
21512bd3c8bSSascha Wildner 	    UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE, UQ_MSC_NO_SYNC_CACHE),
21612bd3c8bSSascha Wildner 	USB_QUIRK(GENESYS, GL641USB2IDE_2, 0x0000, 0xffff,
21712bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_ATAPI,
21812bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_SHORT_INQ, UQ_MSC_NO_START_STOP,
21912bd3c8bSSascha Wildner 	    UQ_MSC_IGNORE_RESIDUE),
22012bd3c8bSSascha Wildner 	USB_QUIRK(GENESYS, GL641USB, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
22112bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_FORCE_SHORT_INQ,
22212bd3c8bSSascha Wildner 	    UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE),
22312bd3c8bSSascha Wildner 	USB_QUIRK(GENESYS, GL641USB_2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
22412bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_WRONG_CSWSIG),
22512bd3c8bSSascha Wildner 	USB_QUIRK(HAGIWARA, FG, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
22612bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI),
22712bd3c8bSSascha Wildner 	USB_QUIRK(HAGIWARA, FGSM, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
22812bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI),
22912bd3c8bSSascha Wildner 	USB_QUIRK(HITACHI, DVDCAM_DZ_MV100A, 0x0000, 0xffff,
23012bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_SCSI,
23112bd3c8bSSascha Wildner 	    UQ_MSC_NO_GETMAXLUN),
23212bd3c8bSSascha Wildner 	USB_QUIRK(HITACHI, DVDCAM_USB, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI_I,
23312bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_INQUIRY),
23412bd3c8bSSascha Wildner 	USB_QUIRK(HP, CDW4E, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_ATAPI),
23512bd3c8bSSascha Wildner 	USB_QUIRK(HP, CDW8200, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI_I,
23612bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_TEST_UNIT_READY,
23712bd3c8bSSascha Wildner 	    UQ_MSC_NO_START_STOP),
23812bd3c8bSSascha Wildner 	USB_QUIRK(IMAGINATION, DBX1, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
23912bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_WRONG_CSWSIG),
24012bd3c8bSSascha Wildner 	USB_QUIRK(INSYSTEM, USBCABLE, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
24112bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_TEST_UNIT_READY,
24212bd3c8bSSascha Wildner 	    UQ_MSC_NO_START_STOP, UQ_MSC_ALT_IFACE_1),
24312bd3c8bSSascha Wildner 	USB_QUIRK(INSYSTEM, ATAPI, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
24412bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_RBC),
24512bd3c8bSSascha Wildner 	USB_QUIRK(INSYSTEM, STORAGE_V2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
24612bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_RBC),
247520083baSSascha Wildner 	USB_QUIRK(INTENSO, MEMORY_BOX, 0x0000, 0xffff, UQ_MSC_NO_INQUIRY),
24812bd3c8bSSascha Wildner 	USB_QUIRK(IODATA, IU_CD2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
24912bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI),
25012bd3c8bSSascha Wildner 	USB_QUIRK(IODATA, DVR_UEH8, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
25112bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI),
25212bd3c8bSSascha Wildner 	USB_QUIRK(IOMEGA, ZIP100, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
25312bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI,
25412bd3c8bSSascha Wildner 	    UQ_MSC_NO_TEST_UNIT_READY), /* XXX ZIP drives can also use ATAPI */
255520083baSSascha Wildner 	USB_QUIRK(JMICRON, JMS567, 0x0000, 0xffff, UQ_MSC_NO_GETMAXLUN),
25612bd3c8bSSascha Wildner 	USB_QUIRK(JMICRON, JM20337, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
25712bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI,
25812bd3c8bSSascha Wildner 	    UQ_MSC_NO_SYNC_CACHE),
259ff811b0aSSascha Wildner 	USB_QUIRK(KINGSTON, HYPERX3_0, 0x0000, 0xffff, UQ_MSC_NO_INQUIRY),
26012bd3c8bSSascha Wildner 	USB_QUIRK(KYOCERA, FINECAM_L3, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
26112bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
26212bd3c8bSSascha Wildner 	USB_QUIRK(KYOCERA, FINECAM_S3X, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
26312bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_INQUIRY),
26412bd3c8bSSascha Wildner 	USB_QUIRK(KYOCERA, FINECAM_S4, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
26512bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_INQUIRY),
26612bd3c8bSSascha Wildner 	USB_QUIRK(KYOCERA, FINECAM_S5, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
26712bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
26812bd3c8bSSascha Wildner 	USB_QUIRK(LACIE, HD, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
26912bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_RBC),
27012bd3c8bSSascha Wildner 	USB_QUIRK(LEXAR, CF_READER, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
27112bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
27212bd3c8bSSascha Wildner 	USB_QUIRK(LEXAR, JUMPSHOT, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI),
273ff811b0aSSascha Wildner 	USB_QUIRK(LEXAR, JUMPDRIVE, 0x0000, 0xffff, UQ_MSC_NO_INQUIRY),
27412bd3c8bSSascha Wildner 	USB_QUIRK(LOGITEC, LDR_H443SU2, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI),
27512bd3c8bSSascha Wildner 	USB_QUIRK(LOGITEC, LDR_H443U2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
27612bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI,),
27712bd3c8bSSascha Wildner 	USB_QUIRK(MELCO, DUBPXXG, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
27812bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_FORCE_SHORT_INQ,
27912bd3c8bSSascha Wildner 	    UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE),
28012bd3c8bSSascha Wildner 	USB_QUIRK(MICROTECH, DPCM, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
28112bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_TEST_UNIT_READY,
28212bd3c8bSSascha Wildner 	    UQ_MSC_NO_START_STOP),
28312bd3c8bSSascha Wildner 	USB_QUIRK(MICRON, REALSSD, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
28412bd3c8bSSascha Wildner 	USB_QUIRK(MICROTECH, SCSIDB25, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
28512bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI),
28612bd3c8bSSascha Wildner 	USB_QUIRK(MICROTECH, SCSIHD50, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
28712bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI),
28812bd3c8bSSascha Wildner 	USB_QUIRK(MINOLTA, E223, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI),
28912bd3c8bSSascha Wildner 	USB_QUIRK(MINOLTA, F300, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
29012bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI),
29112bd3c8bSSascha Wildner 	USB_QUIRK(MITSUMI, CDRRW, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI |
29212bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_ATAPI),
29312bd3c8bSSascha Wildner 	USB_QUIRK(MOTOROLA2, E398, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
29412bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_FORCE_SHORT_INQ,
29512bd3c8bSSascha Wildner 	    UQ_MSC_NO_INQUIRY_EVPD, UQ_MSC_NO_GETMAXLUN),
29612bd3c8bSSascha Wildner 	USB_QUIRK_VP(USB_VENDOR_MPMAN, 0, UQ_MSC_NO_SYNC_CACHE,
29712bd3c8bSSascha Wildner 	    UQ_MATCH_VENDOR_ONLY),
29812bd3c8bSSascha Wildner 	USB_QUIRK(MSYSTEMS, DISKONKEY, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
29912bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE, UQ_MSC_NO_GETMAXLUN,
30012bd3c8bSSascha Wildner 	    UQ_MSC_NO_RS_CLEAR_UA),
30112bd3c8bSSascha Wildner 	USB_QUIRK(MSYSTEMS, DISKONKEY2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
30212bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_ATAPI),
30312bd3c8bSSascha Wildner 	USB_QUIRK(MYSON, HEDEN, 0x0000, 0xffff, UQ_MSC_IGNORE_RESIDUE,
30412bd3c8bSSascha Wildner 	    UQ_MSC_NO_SYNC_CACHE),
30512bd3c8bSSascha Wildner 	USB_QUIRK(NEODIO, ND3260, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
30612bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_FORCE_SHORT_INQ),
30712bd3c8bSSascha Wildner 	USB_QUIRK(NETAC, CF_CARD, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
30812bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
30912bd3c8bSSascha Wildner 	USB_QUIRK(NETAC, ONLYDISK, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
31012bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
31112bd3c8bSSascha Wildner 	USB_QUIRK(NETCHIP, CLIK_40, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_ATAPI,
31212bd3c8bSSascha Wildner 	    UQ_MSC_NO_INQUIRY),
313ff811b0aSSascha Wildner 	USB_QUIRK(NETCHIP, POCKETBOOK, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
31412bd3c8bSSascha Wildner 	USB_QUIRK(NIKON, D300, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
31512bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI),
31612bd3c8bSSascha Wildner 	USB_QUIRK(OLYMPUS, C1, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
31712bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_WRONG_CSWSIG),
31812bd3c8bSSascha Wildner 	USB_QUIRK(OLYMPUS, C700, 0x0000, 0xffff, UQ_MSC_NO_GETMAXLUN),
31912bd3c8bSSascha Wildner 	USB_QUIRK(ONSPEC, SDS_HOTFIND_D, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
32012bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN, UQ_MSC_NO_SYNC_CACHE),
32112bd3c8bSSascha Wildner 	USB_QUIRK(ONSPEC, CFMS_RW, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI),
32212bd3c8bSSascha Wildner 	USB_QUIRK(ONSPEC, CFSM_COMBO, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI),
32312bd3c8bSSascha Wildner 	USB_QUIRK(ONSPEC, CFSM_READER, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI),
32412bd3c8bSSascha Wildner 	USB_QUIRK(ONSPEC, CFSM_READER2, 0x0000, 0xffff,
32512bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI),
32612bd3c8bSSascha Wildner 	USB_QUIRK(ONSPEC, MDCFE_B_CF_READER, 0x0000, 0xffff,
32712bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI),
32812bd3c8bSSascha Wildner 	USB_QUIRK(ONSPEC, MDSM_B_READER, 0x0000, 0xffff,
32912bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
33012bd3c8bSSascha Wildner 	USB_QUIRK(ONSPEC, READER, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI),
33112bd3c8bSSascha Wildner 	USB_QUIRK(ONSPEC, UCF100, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
33257bed822SMarkus Pfeiffer 	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_INQUIRY, UQ_MSC_NO_GETMAXLUN),
33312bd3c8bSSascha Wildner 	USB_QUIRK(ONSPEC2, IMAGEMATE_SDDR55, 0x0000, 0xffff,
33412bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN),
33512bd3c8bSSascha Wildner 	USB_QUIRK(PANASONIC, KXL840AN, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
33612bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_GETMAXLUN),
33712bd3c8bSSascha Wildner 	USB_QUIRK(PANASONIC, KXLCB20AN, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
33812bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI),
33912bd3c8bSSascha Wildner 	USB_QUIRK(PANASONIC, KXLCB35AN, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
34012bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI),
34112bd3c8bSSascha Wildner 	USB_QUIRK(PANASONIC, LS120CAM, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_UFI),
34212bd3c8bSSascha Wildner 	USB_QUIRK(PLEXTOR, 40_12_40U, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
34312bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_TEST_UNIT_READY),
34412bd3c8bSSascha Wildner 	USB_QUIRK(PNY, ATTACHE2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
34512bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE,
34612bd3c8bSSascha Wildner 	    UQ_MSC_NO_START_STOP),
34712bd3c8bSSascha Wildner 	USB_QUIRK(PROLIFIC, PL2506, 0x0000, 0xffff,
34812bd3c8bSSascha Wildner 	    UQ_MSC_NO_SYNC_CACHE),
34912bd3c8bSSascha Wildner 	USB_QUIRK_VP(USB_VENDOR_SAMSUNG_TECHWIN,
35012bd3c8bSSascha Wildner 	    USB_PRODUCT_SAMSUNG_TECHWIN_DIGIMAX_410, UQ_MSC_FORCE_WIRE_BBB,
35112bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
35212bd3c8bSSascha Wildner 	USB_QUIRK(SANDISK, SDDR05A, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
35312bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_READ_CAP_OFFBY1,
35412bd3c8bSSascha Wildner 	    UQ_MSC_NO_GETMAXLUN),
35512bd3c8bSSascha Wildner 	USB_QUIRK(SANDISK, SDDR09, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI,
35612bd3c8bSSascha Wildner 	    UQ_MSC_READ_CAP_OFFBY1, UQ_MSC_NO_GETMAXLUN),
35712bd3c8bSSascha Wildner 	USB_QUIRK(SANDISK, SDDR12, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
35812bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_READ_CAP_OFFBY1,
35912bd3c8bSSascha Wildner 	    UQ_MSC_NO_GETMAXLUN),
360ff811b0aSSascha Wildner 	USB_QUIRK(SANDISK, SDCZ2_128, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
361ff811b0aSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE,
362ff811b0aSSascha Wildner 	    UQ_MSC_NO_SYNC_CACHE),
36312bd3c8bSSascha Wildner 	USB_QUIRK(SANDISK, SDCZ2_256, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
36412bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
36512bd3c8bSSascha Wildner 	USB_QUIRK(SANDISK, SDCZ4_128, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
36612bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
36712bd3c8bSSascha Wildner 	USB_QUIRK(SANDISK, SDCZ4_256, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
36812bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
36912bd3c8bSSascha Wildner 	USB_QUIRK(SANDISK, SDDR31, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
37012bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_READ_CAP_OFFBY1),
37157bed822SMarkus Pfeiffer 	USB_QUIRK(SANDISK, IMAGEMATE_SDDR289, 0x0000, 0xffff,
37257bed822SMarkus Pfeiffer 	    UQ_MSC_NO_SYNC_CACHE, UQ_MSC_NO_GETMAXLUN),
37312bd3c8bSSascha Wildner 	USB_QUIRK(SCANLOGIC, SL11R, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
37412bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_INQUIRY),
37512bd3c8bSSascha Wildner 	USB_QUIRK(SHUTTLE, EUSB, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI_I,
37612bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_TEST_UNIT_READY,
37712bd3c8bSSascha Wildner 	    UQ_MSC_NO_START_STOP, UQ_MSC_SHUTTLE_INIT),
37812bd3c8bSSascha Wildner 	USB_QUIRK(SHUTTLE, CDRW, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
37912bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_ATAPI),
38012bd3c8bSSascha Wildner 	USB_QUIRK(SHUTTLE, CF, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
38112bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_ATAPI),
38212bd3c8bSSascha Wildner 	USB_QUIRK(SHUTTLE, EUSBATAPI, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
38312bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_ATAPI),
38412bd3c8bSSascha Wildner 	USB_QUIRK(SHUTTLE, EUSBCFSM, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI),
38512bd3c8bSSascha Wildner 	USB_QUIRK(SHUTTLE, EUSCSI, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
38612bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI),
38712bd3c8bSSascha Wildner 	USB_QUIRK(SHUTTLE, HIFD, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
38812bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN),
38912bd3c8bSSascha Wildner 	USB_QUIRK(SHUTTLE, SDDR09, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI,
39012bd3c8bSSascha Wildner 	    UQ_MSC_NO_GETMAXLUN),
39112bd3c8bSSascha Wildner 	USB_QUIRK(SHUTTLE, ZIOMMC, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
39212bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN),
39312bd3c8bSSascha Wildner 	USB_QUIRK(SIGMATEL, I_BEAD100, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
39412bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_SHUTTLE_INIT),
39512bd3c8bSSascha Wildner 	USB_QUIRK(SIIG, WINTERREADER, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
39612bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_IGNORE_RESIDUE),
39712bd3c8bSSascha Wildner 	USB_QUIRK(SKANHEX, MD_7425, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
39812bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
39912bd3c8bSSascha Wildner 	USB_QUIRK(SKANHEX, SX_520Z, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
40012bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
40112bd3c8bSSascha Wildner 	USB_QUIRK(SONY, HANDYCAM, 0x0500, 0x0500, UQ_MSC_FORCE_WIRE_CBI,
40212bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_RBC, UQ_MSC_RBC_PAD_TO_12),
40312bd3c8bSSascha Wildner 	USB_QUIRK(SONY, CLIE_40_MS, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
40412bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
40512bd3c8bSSascha Wildner 	USB_QUIRK(SONY, DSC, 0x0500, 0x0500, UQ_MSC_FORCE_WIRE_CBI,
40612bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_RBC, UQ_MSC_RBC_PAD_TO_12),
40712bd3c8bSSascha Wildner 	USB_QUIRK(SONY, DSC, 0x0600, 0x0600, UQ_MSC_FORCE_WIRE_CBI,
40812bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_RBC, UQ_MSC_RBC_PAD_TO_12),
40912bd3c8bSSascha Wildner 	USB_QUIRK(SONY, DSC, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
41012bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_RBC),
41112bd3c8bSSascha Wildner 	USB_QUIRK(SONY, HANDYCAM, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
41212bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_RBC),
41312bd3c8bSSascha Wildner 	USB_QUIRK(SONY, MSC, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
41412bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_RBC),
41512bd3c8bSSascha Wildner 	USB_QUIRK(SONY, MS_MSC_U03, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
41612bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_UFI, UQ_MSC_NO_GETMAXLUN),
41712bd3c8bSSascha Wildner 	USB_QUIRK(SONY, MS_NW_MS7, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
41812bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN),
41912bd3c8bSSascha Wildner 	USB_QUIRK(SONY, MS_PEG_N760C, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
42012bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
42112bd3c8bSSascha Wildner 	USB_QUIRK(SONY, MSACUS1, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
42212bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN),
42312bd3c8bSSascha Wildner 	USB_QUIRK(SONY, PORTABLE_HDD_V2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
42412bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI),
42557bed822SMarkus Pfeiffer 	USB_QUIRK(STMICRO, ST72682, 0x0000, 0xffff, UQ_MSC_NO_PREVENT_ALLOW),
42612bd3c8bSSascha Wildner 	USB_QUIRK(SUPERTOP, IDE, 0x0000, 0xffff, UQ_MSC_IGNORE_RESIDUE,
42712bd3c8bSSascha Wildner 	    UQ_MSC_NO_SYNC_CACHE),
42857bed822SMarkus Pfeiffer 	USB_QUIRK(SUPERTOP, FLASHDRIVE, 0x0000, 0xffff, UQ_MSC_NO_TEST_UNIT_READY,
42957bed822SMarkus Pfeiffer 	    UQ_MSC_NO_SYNC_CACHE),
43012bd3c8bSSascha Wildner 	USB_QUIRK(TAUGA, CAMERAMATE, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI),
43112bd3c8bSSascha Wildner 	USB_QUIRK(TEAC, FD05PUB, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
43212bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_UFI),
43312bd3c8bSSascha Wildner 	USB_QUIRK(TECLAST, TLC300, 0x0000, 0xffff, UQ_MSC_NO_TEST_UNIT_READY,
43412bd3c8bSSascha Wildner 	    UQ_MSC_NO_SYNC_CACHE),
43512bd3c8bSSascha Wildner 	USB_QUIRK(TREK, MEMKEY, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
43612bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
43712bd3c8bSSascha Wildner 	USB_QUIRK(TREK, THUMBDRIVE_8MB, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
43812bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_IGNORE_RESIDUE),
43912bd3c8bSSascha Wildner 	USB_QUIRK(TRUMPION, C3310, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
44012bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_UFI),
44112bd3c8bSSascha Wildner 	USB_QUIRK(TRUMPION, MP3, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_RBC),
44212bd3c8bSSascha Wildner 	USB_QUIRK(TRUMPION, T33520, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI),
44312bd3c8bSSascha Wildner 	USB_QUIRK(TWINMOS, MDIV, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
44412bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI),
44512bd3c8bSSascha Wildner 	USB_QUIRK(VIA, USB2IDEBRIDGE, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
44612bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_SYNC_CACHE),
44712bd3c8bSSascha Wildner 	USB_QUIRK(VIVITAR, 35XX, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
44812bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
44912bd3c8bSSascha Wildner 	USB_QUIRK(WESTERN, COMBO, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
45012bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_FORCE_SHORT_INQ,
45112bd3c8bSSascha Wildner 	    UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE),
45212bd3c8bSSascha Wildner 	USB_QUIRK(WESTERN, EXTHDD, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
45312bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_FORCE_SHORT_INQ,
45412bd3c8bSSascha Wildner 	    UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE),
45512bd3c8bSSascha Wildner 	USB_QUIRK(WESTERN, MYBOOK, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
45612bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY_EVPD,
45712bd3c8bSSascha Wildner 	    UQ_MSC_NO_SYNC_CACHE),
458ff811b0aSSascha Wildner 	USB_QUIRK(WESTERN, MYPASSPORT_00, 0x0000, 0xffff, UQ_MSC_FORCE_SHORT_INQ),
459ff811b0aSSascha Wildner 	USB_QUIRK(WESTERN, MYPASSPORT_01, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
460ff811b0aSSascha Wildner 	USB_QUIRK(WESTERN, MYPASSPORT_02, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
461ff811b0aSSascha Wildner 	USB_QUIRK(WESTERN, MYPASSPORT_03, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
462ff811b0aSSascha Wildner 	USB_QUIRK(WESTERN, MYPASSPORT_04, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
463ff811b0aSSascha Wildner 	USB_QUIRK(WESTERN, MYPASSPORT_05, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
464ff811b0aSSascha Wildner 	USB_QUIRK(WESTERN, MYPASSPORT_06, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
465ff811b0aSSascha Wildner 	USB_QUIRK(WESTERN, MYPASSPORT_07, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
466ff811b0aSSascha Wildner 	USB_QUIRK(WESTERN, MYPASSPORT_08, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
467ff811b0aSSascha Wildner 	USB_QUIRK(WESTERN, MYPASSPORT_09, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
468ff811b0aSSascha Wildner 	USB_QUIRK(WESTERN, MYPASSPORT_10, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
469ff811b0aSSascha Wildner 	USB_QUIRK(WESTERN, MYPASSPORT_11, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
470ff811b0aSSascha Wildner 	USB_QUIRK(WESTERN, MYPASSPORTES_00, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
471ff811b0aSSascha Wildner 	USB_QUIRK(WESTERN, MYPASSPORTES_01, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
472ff811b0aSSascha Wildner 	USB_QUIRK(WESTERN, MYPASSPORTES_02, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
473ff811b0aSSascha Wildner 	USB_QUIRK(WESTERN, MYPASSPORTES_03, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
474ff811b0aSSascha Wildner 	USB_QUIRK(WESTERN, MYPASSPORTES_04, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
475ff811b0aSSascha Wildner 	USB_QUIRK(WESTERN, MYPASSPORTES_05, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
476ff811b0aSSascha Wildner 	USB_QUIRK(WESTERN, MYPASSPORTES_06, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
477ff811b0aSSascha Wildner 	USB_QUIRK(WESTERN, MYPASSPORTES_07, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
478ff811b0aSSascha Wildner 	USB_QUIRK(WESTERN, MYPASSPORTES_08, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
479ff811b0aSSascha Wildner 	USB_QUIRK(WESTERN, MYPASSPORTES_09, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
48012bd3c8bSSascha Wildner 	USB_QUIRK(WINMAXGROUP, FLASH64MC, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
48112bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
48212bd3c8bSSascha Wildner 	USB_QUIRK(YANO, FW800HD, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
48312bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_FORCE_SHORT_INQ,
48412bd3c8bSSascha Wildner 	    UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE),
48512bd3c8bSSascha Wildner 	USB_QUIRK(YANO, U640MO, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI_I,
48612bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_FORCE_SHORT_INQ),
48712bd3c8bSSascha Wildner 	USB_QUIRK(YEDATA, FLASHBUSTERU, 0x0000, 0x007F, UQ_MSC_FORCE_WIRE_CBI,
48812bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_UFI, UQ_MSC_NO_RS_CLEAR_UA, UQ_MSC_FLOPPY_SPEED,
48912bd3c8bSSascha Wildner 	    UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_GETMAXLUN),
49012bd3c8bSSascha Wildner 	USB_QUIRK(YEDATA, FLASHBUSTERU, 0x0080, 0x0080, UQ_MSC_FORCE_WIRE_CBI_I,
49112bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_UFI, UQ_MSC_NO_RS_CLEAR_UA, UQ_MSC_FLOPPY_SPEED,
49212bd3c8bSSascha Wildner 	    UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_GETMAXLUN),
49312bd3c8bSSascha Wildner 	USB_QUIRK(YEDATA, FLASHBUSTERU, 0x0081, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI_I,
49412bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_UFI, UQ_MSC_NO_RS_CLEAR_UA, UQ_MSC_FLOPPY_SPEED,
49512bd3c8bSSascha Wildner 	    UQ_MSC_NO_GETMAXLUN),
49612bd3c8bSSascha Wildner 	USB_QUIRK(ZORAN, EX20DSC, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
49712bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_ATAPI),
49812bd3c8bSSascha Wildner 	USB_QUIRK(MEIZU, M6_SL, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
49912bd3c8bSSascha Wildner 	    UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY, UQ_MSC_NO_SYNC_CACHE),
500ff811b0aSSascha Wildner 	USB_QUIRK(TOSHIBA, TRANSMEMORY, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE,
501ff811b0aSSascha Wildner 	    UQ_MSC_NO_PREVENT_ALLOW),
50257bed822SMarkus Pfeiffer 	USB_QUIRK(VIALABS, USB30SATABRIDGE, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
503dd681da6SMatthew Dillon 	USB_QUIRK(QUALCOMMINC, ZTE_MF730M, 0x0000, 0xffff, UQ_MSC_NO_GETMAXLUN,
504dd681da6SMatthew Dillon 	    UQ_MSC_NO_INQUIRY, UQ_CFG_INDEX_0),
50512bd3c8bSSascha Wildner 	/* Non-standard USB MIDI devices */
50612bd3c8bSSascha Wildner 	USB_QUIRK(ROLAND, UM1, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
50712bd3c8bSSascha Wildner 	USB_QUIRK(ROLAND, SC8850, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
50812bd3c8bSSascha Wildner 	USB_QUIRK(ROLAND, SD90, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
50912bd3c8bSSascha Wildner 	USB_QUIRK(ROLAND, UM880N, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
51012bd3c8bSSascha Wildner 	USB_QUIRK(ROLAND, UA100, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
51112bd3c8bSSascha Wildner 	USB_QUIRK(ROLAND, UM4, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
51212bd3c8bSSascha Wildner 	USB_QUIRK(ROLAND, U8, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
51312bd3c8bSSascha Wildner 	USB_QUIRK(ROLAND, UM2, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
51412bd3c8bSSascha Wildner 	USB_QUIRK(ROLAND, SC8820, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
51512bd3c8bSSascha Wildner 	USB_QUIRK(ROLAND, PC300, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
51612bd3c8bSSascha Wildner 	USB_QUIRK(ROLAND, SK500, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
51712bd3c8bSSascha Wildner 	USB_QUIRK(ROLAND, SCD70, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
51812bd3c8bSSascha Wildner 	USB_QUIRK(ROLAND, UM550, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
51912bd3c8bSSascha Wildner 	USB_QUIRK(ROLAND, SD20, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
52012bd3c8bSSascha Wildner 	USB_QUIRK(ROLAND, SD80, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
52112bd3c8bSSascha Wildner 	USB_QUIRK(ROLAND, UA700, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
522520083baSSascha Wildner 	USB_QUIRK(ROLAND, PCR300, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
52357bed822SMarkus Pfeiffer 	USB_QUIRK(EGO, M4U, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI),
52457bed822SMarkus Pfeiffer 	USB_QUIRK(LOGILINK, U2M, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI),
52512bd3c8bSSascha Wildner 	USB_QUIRK(MEDELI, DD305, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI, UQ_MATCH_VENDOR_ONLY),
52657bed822SMarkus Pfeiffer 	USB_QUIRK(REDOCTANE, GHMIDI, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI),
52757bed822SMarkus Pfeiffer 	USB_QUIRK(TEXTECH, U2M_1, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI),
52857bed822SMarkus Pfeiffer 	USB_QUIRK(TEXTECH, U2M_2, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI),
52957bed822SMarkus Pfeiffer 	USB_QUIRK(WCH2, U2M, 0x0000, 0xffff, UQ_SINGLE_CMD_MIDI),
53057bed822SMarkus Pfeiffer 
53157bed822SMarkus Pfeiffer 	/* Non-standard USB AUDIO devices */
53257bed822SMarkus Pfeiffer 	USB_QUIRK(MAUDIO, FASTTRACKULTRA, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
53357bed822SMarkus Pfeiffer 	USB_QUIRK(MAUDIO, FASTTRACKULTRA8R, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
534520083baSSascha Wildner 	USB_QUIRK(CMEDIA, CM6206, 0x0000, 0xffff, UQ_AU_SET_SPDIF_CM6206),
53512bd3c8bSSascha Wildner 
53612bd3c8bSSascha Wildner 	/*
53712bd3c8bSSascha Wildner 	 * Quirks for manufacturers which USB devices does not respond
53812bd3c8bSSascha Wildner 	 * after issuing non-supported commands:
53912bd3c8bSSascha Wildner 	 */
54012bd3c8bSSascha Wildner 	USB_QUIRK(ALCOR, DUMMY, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE, UQ_MSC_NO_TEST_UNIT_READY, UQ_MATCH_VENDOR_ONLY),
54157bed822SMarkus Pfeiffer 	USB_QUIRK(APPLE, DUMMY, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE, UQ_MATCH_VENDOR_ONLY),
54212bd3c8bSSascha Wildner 	USB_QUIRK(FEIYA, DUMMY, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE, UQ_MATCH_VENDOR_ONLY),
54312bd3c8bSSascha Wildner 	USB_QUIRK(REALTEK, DUMMY, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE, UQ_MATCH_VENDOR_ONLY),
54412bd3c8bSSascha Wildner 	USB_QUIRK(INITIO, DUMMY, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE, UQ_MATCH_VENDOR_ONLY),
545520083baSSascha Wildner 
546520083baSSascha Wildner 	/* DYMO LabelManager Pnp */
547520083baSSascha Wildner 	USB_QUIRK(DYMO, LABELMANAGERPNP, 0x0000, 0xffff, UQ_MSC_DYMO_EJECT),
548520083baSSascha Wildner 
549520083baSSascha Wildner 	/* Holtek USB gaming keyboard */
550520083baSSascha Wildner 	USB_QUIRK(HOLTEK, F85, 0x0000, 0xffff, UQ_KBD_BOOTPROTO),
55112bd3c8bSSascha Wildner };
55212bd3c8bSSascha Wildner #undef USB_QUIRK_VP
55312bd3c8bSSascha Wildner #undef USB_QUIRK
55412bd3c8bSSascha Wildner 
55512bd3c8bSSascha Wildner static const char *usb_quirk_str[USB_QUIRK_MAX] = {
55612bd3c8bSSascha Wildner 	[UQ_NONE]		= "UQ_NONE",
55712bd3c8bSSascha Wildner 	[UQ_MATCH_VENDOR_ONLY]	= "UQ_MATCH_VENDOR_ONLY",
55812bd3c8bSSascha Wildner 	[UQ_AUDIO_SWAP_LR]	= "UQ_AUDIO_SWAP_LR",
55912bd3c8bSSascha Wildner 	[UQ_AU_INP_ASYNC]	= "UQ_AU_INP_ASYNC",
56012bd3c8bSSascha Wildner 	[UQ_AU_NO_FRAC]		= "UQ_AU_NO_FRAC",
56112bd3c8bSSascha Wildner 	[UQ_AU_NO_XU]		= "UQ_AU_NO_XU",
56212bd3c8bSSascha Wildner 	[UQ_BAD_ADC]		= "UQ_BAD_ADC",
56312bd3c8bSSascha Wildner 	[UQ_BAD_AUDIO]		= "UQ_BAD_AUDIO",
56412bd3c8bSSascha Wildner 	[UQ_BROKEN_BIDIR]	= "UQ_BROKEN_BIDIR",
56512bd3c8bSSascha Wildner 	[UQ_BUS_POWERED]	= "UQ_BUS_POWERED",
56612bd3c8bSSascha Wildner 	[UQ_HID_IGNORE]		= "UQ_HID_IGNORE",
56712bd3c8bSSascha Wildner 	[UQ_KBD_IGNORE]		= "UQ_KBD_IGNORE",
56812bd3c8bSSascha Wildner 	[UQ_KBD_BOOTPROTO]	= "UQ_KBD_BOOTPROTO",
569fe8b458aSMatthew Dillon 	[UQ_KBD_DELAY_INIT]	= "UQ_KBD_DELAY_INIT",
570fe8b458aSMatthew Dillon 	[UQ_KBD_DELAY_CTRL_MSG]	= "UQ_KBD_DELAY_CTRL_MSG",
57157bed822SMarkus Pfeiffer 	[UQ_UMS_IGNORE]		= "UQ_UMS_IGNORE",
57212bd3c8bSSascha Wildner 	[UQ_MS_BAD_CLASS]	= "UQ_MS_BAD_CLASS",
57312bd3c8bSSascha Wildner 	[UQ_MS_LEADING_BYTE]	= "UQ_MS_LEADING_BYTE",
57412bd3c8bSSascha Wildner 	[UQ_MS_REVZ]		= "UQ_MS_REVZ",
57512bd3c8bSSascha Wildner 	[UQ_NO_STRINGS]		= "UQ_NO_STRINGS",
57612bd3c8bSSascha Wildner 	[UQ_POWER_CLAIM]	= "UQ_POWER_CLAIM",
57712bd3c8bSSascha Wildner 	[UQ_SPUR_BUT_UP]	= "UQ_SPUR_BUT_UP",
57812bd3c8bSSascha Wildner 	[UQ_SWAP_UNICODE]	= "UQ_SWAP_UNICODE",
57912bd3c8bSSascha Wildner 	[UQ_CFG_INDEX_1]	= "UQ_CFG_INDEX_1",
58012bd3c8bSSascha Wildner 	[UQ_CFG_INDEX_2]	= "UQ_CFG_INDEX_2",
58112bd3c8bSSascha Wildner 	[UQ_CFG_INDEX_3]	= "UQ_CFG_INDEX_3",
58212bd3c8bSSascha Wildner 	[UQ_CFG_INDEX_4]	= "UQ_CFG_INDEX_4",
58312bd3c8bSSascha Wildner 	[UQ_CFG_INDEX_0]	= "UQ_CFG_INDEX_0",
58412bd3c8bSSascha Wildner 	[UQ_ASSUME_CM_OVER_DATA]	= "UQ_ASSUME_CM_OVER_DATA",
58512bd3c8bSSascha Wildner 	[UQ_MSC_NO_TEST_UNIT_READY]	= "UQ_MSC_NO_TEST_UNIT_READY",
58612bd3c8bSSascha Wildner 	[UQ_MSC_NO_RS_CLEAR_UA]		= "UQ_MSC_NO_RS_CLEAR_UA",
58712bd3c8bSSascha Wildner 	[UQ_MSC_NO_START_STOP]		= "UQ_MSC_NO_START_STOP",
58812bd3c8bSSascha Wildner 	[UQ_MSC_NO_GETMAXLUN]		= "UQ_MSC_NO_GETMAXLUN",
58912bd3c8bSSascha Wildner 	[UQ_MSC_NO_INQUIRY]		= "UQ_MSC_NO_INQUIRY",
59012bd3c8bSSascha Wildner 	[UQ_MSC_NO_INQUIRY_EVPD]	= "UQ_MSC_NO_INQUIRY_EVPD",
59157bed822SMarkus Pfeiffer 	[UQ_MSC_NO_PREVENT_ALLOW]	= "UQ_MSC_NO_PREVENT_ALLOW",
59212bd3c8bSSascha Wildner 	[UQ_MSC_NO_SYNC_CACHE]		= "UQ_MSC_NO_SYNC_CACHE",
59312bd3c8bSSascha Wildner 	[UQ_MSC_SHUTTLE_INIT]		= "UQ_MSC_SHUTTLE_INIT",
59412bd3c8bSSascha Wildner 	[UQ_MSC_ALT_IFACE_1]		= "UQ_MSC_ALT_IFACE_1",
59512bd3c8bSSascha Wildner 	[UQ_MSC_FLOPPY_SPEED]		= "UQ_MSC_FLOPPY_SPEED",
59612bd3c8bSSascha Wildner 	[UQ_MSC_IGNORE_RESIDUE]		= "UQ_MSC_IGNORE_RESIDUE",
59712bd3c8bSSascha Wildner 	[UQ_MSC_WRONG_CSWSIG]		= "UQ_MSC_WRONG_CSWSIG",
59812bd3c8bSSascha Wildner 	[UQ_MSC_RBC_PAD_TO_12]		= "UQ_MSC_RBC_PAD_TO_12",
59912bd3c8bSSascha Wildner 	[UQ_MSC_READ_CAP_OFFBY1]	= "UQ_MSC_READ_CAP_OFFBY1",
60012bd3c8bSSascha Wildner 	[UQ_MSC_FORCE_SHORT_INQ]	= "UQ_MSC_FORCE_SHORT_INQ",
60112bd3c8bSSascha Wildner 	[UQ_MSC_FORCE_WIRE_BBB]		= "UQ_MSC_FORCE_WIRE_BBB",
60212bd3c8bSSascha Wildner 	[UQ_MSC_FORCE_WIRE_CBI]		= "UQ_MSC_FORCE_WIRE_CBI",
60312bd3c8bSSascha Wildner 	[UQ_MSC_FORCE_WIRE_CBI_I]	= "UQ_MSC_FORCE_WIRE_CBI_I",
60412bd3c8bSSascha Wildner 	[UQ_MSC_FORCE_PROTO_SCSI]	= "UQ_MSC_FORCE_PROTO_SCSI",
60512bd3c8bSSascha Wildner 	[UQ_MSC_FORCE_PROTO_ATAPI]	= "UQ_MSC_FORCE_PROTO_ATAPI",
60612bd3c8bSSascha Wildner 	[UQ_MSC_FORCE_PROTO_UFI]	= "UQ_MSC_FORCE_PROTO_UFI",
60712bd3c8bSSascha Wildner 	[UQ_MSC_FORCE_PROTO_RBC]	= "UQ_MSC_FORCE_PROTO_RBC",
60812bd3c8bSSascha Wildner 	[UQ_MSC_EJECT_HUAWEI]		= "UQ_MSC_EJECT_HUAWEI",
60912bd3c8bSSascha Wildner 	[UQ_MSC_EJECT_SIERRA]		= "UQ_MSC_EJECT_SIERRA",
61012bd3c8bSSascha Wildner 	[UQ_MSC_EJECT_SCSIEJECT]	= "UQ_MSC_EJECT_SCSIEJECT",
61112bd3c8bSSascha Wildner 	[UQ_MSC_EJECT_REZERO]		= "UQ_MSC_EJECT_REZERO",
61212bd3c8bSSascha Wildner 	[UQ_MSC_EJECT_ZTESTOR]		= "UQ_MSC_EJECT_ZTESTOR",
61312bd3c8bSSascha Wildner 	[UQ_MSC_EJECT_CMOTECH]		= "UQ_MSC_EJECT_CMOTECH",
61412bd3c8bSSascha Wildner 	[UQ_MSC_EJECT_WAIT]		= "UQ_MSC_EJECT_WAIT",
61512bd3c8bSSascha Wildner 	[UQ_MSC_EJECT_SAEL_M460]	= "UQ_MSC_EJECT_SAEL_M460",
61612bd3c8bSSascha Wildner 	[UQ_MSC_EJECT_HUAWEISCSI]	= "UQ_MSC_EJECT_HUAWEISCSI",
617ff811b0aSSascha Wildner 	[UQ_MSC_EJECT_HUAWEISCSI2]	= "UQ_MSC_EJECT_HUAWEISCSI2",
61812bd3c8bSSascha Wildner 	[UQ_MSC_EJECT_TCT]		= "UQ_MSC_EJECT_TCT",
61912bd3c8bSSascha Wildner 	[UQ_BAD_MIDI]			= "UQ_BAD_MIDI",
62012bd3c8bSSascha Wildner 	[UQ_AU_VENDOR_CLASS]		= "UQ_AU_VENDOR_CLASS",
62112bd3c8bSSascha Wildner 	[UQ_SINGLE_CMD_MIDI]		= "UQ_SINGLE_CMD_MIDI",
622520083baSSascha Wildner 	[UQ_MSC_DYMO_EJECT]		= "UQ_MSC_DYMO_EJECT",
623520083baSSascha Wildner 	[UQ_AU_SET_SPDIF_CM6206]	= "UQ_AU_SET_SPDIF_CM6206",
62412bd3c8bSSascha Wildner };
62512bd3c8bSSascha Wildner 
62612bd3c8bSSascha Wildner /*------------------------------------------------------------------------*
62712bd3c8bSSascha Wildner  *	usb_quirkstr
62812bd3c8bSSascha Wildner  *
62912bd3c8bSSascha Wildner  * This function converts an USB quirk code into a string.
63012bd3c8bSSascha Wildner  *------------------------------------------------------------------------*/
63112bd3c8bSSascha Wildner static const char *
usb_quirkstr(uint16_t quirk)63212bd3c8bSSascha Wildner usb_quirkstr(uint16_t quirk)
63312bd3c8bSSascha Wildner {
634520083baSSascha Wildner 	return ((quirk < USB_QUIRK_MAX && usb_quirk_str[quirk] != NULL) ?
635520083baSSascha Wildner 	    usb_quirk_str[quirk] : "UQ_UNKNOWN");
636520083baSSascha Wildner }
637520083baSSascha Wildner 
638520083baSSascha Wildner /*------------------------------------------------------------------------*
639520083baSSascha Wildner  *	usb_strquirk
640520083baSSascha Wildner  *
641520083baSSascha Wildner  * This function converts a string into a USB quirk code.
642520083baSSascha Wildner  *
643520083baSSascha Wildner  * Returns:
644520083baSSascha Wildner  * Less than USB_QUIRK_MAX: Quirk code
645520083baSSascha Wildner  * Else: Quirk code not found
646520083baSSascha Wildner  *------------------------------------------------------------------------*/
647520083baSSascha Wildner static uint16_t
usb_strquirk(const char * str,size_t len)648520083baSSascha Wildner usb_strquirk(const char *str, size_t len)
649520083baSSascha Wildner {
650520083baSSascha Wildner 	const char *quirk;
651520083baSSascha Wildner 	uint16_t x;
652520083baSSascha Wildner 
653520083baSSascha Wildner 	for (x = 0; x != USB_QUIRK_MAX; x++) {
654520083baSSascha Wildner 		quirk = usb_quirkstr(x);
655520083baSSascha Wildner 		if (strncmp(str, quirk, len) == 0 &&
656520083baSSascha Wildner 		    quirk[len] == 0)
657520083baSSascha Wildner 			break;
658520083baSSascha Wildner 	}
659520083baSSascha Wildner 	return (x);
66012bd3c8bSSascha Wildner }
66112bd3c8bSSascha Wildner 
66212bd3c8bSSascha Wildner /*------------------------------------------------------------------------*
66312bd3c8bSSascha Wildner  *	usb_test_quirk_by_info
66412bd3c8bSSascha Wildner  *
66512bd3c8bSSascha Wildner  * Returns:
66612bd3c8bSSascha Wildner  * 0: Quirk not found
66712bd3c8bSSascha Wildner  * Else: Quirk found
66812bd3c8bSSascha Wildner  *------------------------------------------------------------------------*/
66912bd3c8bSSascha Wildner static uint8_t
usb_test_quirk_by_info(const struct usbd_lookup_info * info,uint16_t quirk)67012bd3c8bSSascha Wildner usb_test_quirk_by_info(const struct usbd_lookup_info *info, uint16_t quirk)
67112bd3c8bSSascha Wildner {
67212bd3c8bSSascha Wildner 	uint16_t x;
67312bd3c8bSSascha Wildner 	uint16_t y;
67412bd3c8bSSascha Wildner 
67512bd3c8bSSascha Wildner 	if (quirk == UQ_NONE)
67612bd3c8bSSascha Wildner 		goto done;
67712bd3c8bSSascha Wildner 
678ac499a8fSSascha Wildner 	lockmgr(&usb_quirk_lock, LK_EXCLUSIVE);
67912bd3c8bSSascha Wildner 
68012bd3c8bSSascha Wildner 	for (x = 0; x != USB_DEV_QUIRKS_MAX; x++) {
68112bd3c8bSSascha Wildner 		/* see if quirk information does not match */
68212bd3c8bSSascha Wildner 		if ((usb_quirks[x].vid != info->idVendor) ||
68312bd3c8bSSascha Wildner 		    (usb_quirks[x].lo_rev > info->bcdDevice) ||
68412bd3c8bSSascha Wildner 		    (usb_quirks[x].hi_rev < info->bcdDevice)) {
68512bd3c8bSSascha Wildner 			continue;
68612bd3c8bSSascha Wildner 		}
68712bd3c8bSSascha Wildner 		/* see if quirk only should match vendor ID */
68812bd3c8bSSascha Wildner 		if (usb_quirks[x].pid != info->idProduct) {
68912bd3c8bSSascha Wildner 			if (usb_quirks[x].pid != 0)
69012bd3c8bSSascha Wildner 				continue;
69112bd3c8bSSascha Wildner 
69212bd3c8bSSascha Wildner 			for (y = 0; y != USB_SUB_QUIRKS_MAX; y++) {
69312bd3c8bSSascha Wildner 				if (usb_quirks[x].quirks[y] == UQ_MATCH_VENDOR_ONLY)
69412bd3c8bSSascha Wildner 					break;
69512bd3c8bSSascha Wildner 			}
69612bd3c8bSSascha Wildner 			if (y == USB_SUB_QUIRKS_MAX)
69712bd3c8bSSascha Wildner 				continue;
69812bd3c8bSSascha Wildner 		}
69912bd3c8bSSascha Wildner 		/* lookup quirk */
70012bd3c8bSSascha Wildner 		for (y = 0; y != USB_SUB_QUIRKS_MAX; y++) {
70112bd3c8bSSascha Wildner 			if (usb_quirks[x].quirks[y] == quirk) {
702ac499a8fSSascha Wildner 				lockmgr(&usb_quirk_lock, LK_RELEASE);
70312bd3c8bSSascha Wildner 				DPRINTF("Found quirk '%s'.\n", usb_quirkstr(quirk));
70412bd3c8bSSascha Wildner 				return (1);
70512bd3c8bSSascha Wildner 			}
70612bd3c8bSSascha Wildner 		}
70712bd3c8bSSascha Wildner 	}
708ac499a8fSSascha Wildner 	lockmgr(&usb_quirk_lock, LK_RELEASE);
70912bd3c8bSSascha Wildner done:
71012bd3c8bSSascha Wildner 	return (0);			/* no quirk match */
71112bd3c8bSSascha Wildner }
71212bd3c8bSSascha Wildner 
71312bd3c8bSSascha Wildner static struct usb_quirk_entry *
usb_quirk_get_entry(uint16_t vid,uint16_t pid,uint16_t lo_rev,uint16_t hi_rev,uint8_t do_alloc)71412bd3c8bSSascha Wildner usb_quirk_get_entry(uint16_t vid, uint16_t pid,
71512bd3c8bSSascha Wildner     uint16_t lo_rev, uint16_t hi_rev, uint8_t do_alloc)
71612bd3c8bSSascha Wildner {
71712bd3c8bSSascha Wildner 	uint16_t x;
71812bd3c8bSSascha Wildner 
719ac499a8fSSascha Wildner 	KKASSERT(lockowned(&usb_quirk_lock));
72012bd3c8bSSascha Wildner 
72112bd3c8bSSascha Wildner 	if ((vid | pid | lo_rev | hi_rev) == 0) {
72212bd3c8bSSascha Wildner 		/* all zero - special case */
72312bd3c8bSSascha Wildner 		return (usb_quirks + USB_DEV_QUIRKS_MAX - 1);
72412bd3c8bSSascha Wildner 	}
72512bd3c8bSSascha Wildner 	/* search for an existing entry */
72612bd3c8bSSascha Wildner 	for (x = 0; x != USB_DEV_QUIRKS_MAX; x++) {
72712bd3c8bSSascha Wildner 		/* see if quirk information does not match */
72812bd3c8bSSascha Wildner 		if ((usb_quirks[x].vid != vid) ||
72912bd3c8bSSascha Wildner 		    (usb_quirks[x].pid != pid) ||
73012bd3c8bSSascha Wildner 		    (usb_quirks[x].lo_rev != lo_rev) ||
73112bd3c8bSSascha Wildner 		    (usb_quirks[x].hi_rev != hi_rev)) {
73212bd3c8bSSascha Wildner 			continue;
73312bd3c8bSSascha Wildner 		}
73412bd3c8bSSascha Wildner 		return (usb_quirks + x);
73512bd3c8bSSascha Wildner 	}
73612bd3c8bSSascha Wildner 
73712bd3c8bSSascha Wildner 	if (do_alloc == 0) {
73812bd3c8bSSascha Wildner 		/* no match */
73912bd3c8bSSascha Wildner 		return (NULL);
74012bd3c8bSSascha Wildner 	}
74112bd3c8bSSascha Wildner 	/* search for a free entry */
74212bd3c8bSSascha Wildner 	for (x = 0; x != USB_DEV_QUIRKS_MAX; x++) {
74312bd3c8bSSascha Wildner 		/* see if quirk information does not match */
74412bd3c8bSSascha Wildner 		if ((usb_quirks[x].vid |
74512bd3c8bSSascha Wildner 		    usb_quirks[x].pid |
74612bd3c8bSSascha Wildner 		    usb_quirks[x].lo_rev |
74712bd3c8bSSascha Wildner 		    usb_quirks[x].hi_rev) != 0) {
74812bd3c8bSSascha Wildner 			continue;
74912bd3c8bSSascha Wildner 		}
75012bd3c8bSSascha Wildner 		usb_quirks[x].vid = vid;
75112bd3c8bSSascha Wildner 		usb_quirks[x].pid = pid;
75212bd3c8bSSascha Wildner 		usb_quirks[x].lo_rev = lo_rev;
75312bd3c8bSSascha Wildner 		usb_quirks[x].hi_rev = hi_rev;
75412bd3c8bSSascha Wildner 
75512bd3c8bSSascha Wildner 		return (usb_quirks + x);
75612bd3c8bSSascha Wildner 	}
75712bd3c8bSSascha Wildner 
75812bd3c8bSSascha Wildner 	/* no entry found */
75912bd3c8bSSascha Wildner 	return (NULL);
76012bd3c8bSSascha Wildner }
76112bd3c8bSSascha Wildner 
76212bd3c8bSSascha Wildner /*------------------------------------------------------------------------*
76312bd3c8bSSascha Wildner  *	usb_quirk_ioctl - handle quirk IOCTLs
76412bd3c8bSSascha Wildner  *
76512bd3c8bSSascha Wildner  * Returns:
76612bd3c8bSSascha Wildner  * 0: Success
76712bd3c8bSSascha Wildner  * Else: Failure
76812bd3c8bSSascha Wildner  *------------------------------------------------------------------------*/
76912bd3c8bSSascha Wildner static int
usb_quirk_ioctl(unsigned long cmd,caddr_t data,int fflag,struct thread * td)77012bd3c8bSSascha Wildner usb_quirk_ioctl(unsigned long cmd, caddr_t data,
77112bd3c8bSSascha Wildner     int fflag, struct thread *td)
77212bd3c8bSSascha Wildner {
77312bd3c8bSSascha Wildner 	struct usb_gen_quirk *pgq;
77412bd3c8bSSascha Wildner 	struct usb_quirk_entry *pqe;
77512bd3c8bSSascha Wildner 	uint32_t x;
77612bd3c8bSSascha Wildner 	uint32_t y;
77712bd3c8bSSascha Wildner 	int err;
77812bd3c8bSSascha Wildner 
77912bd3c8bSSascha Wildner 	switch (cmd) {
78012bd3c8bSSascha Wildner 	case USB_DEV_QUIRK_GET:
78112bd3c8bSSascha Wildner 		pgq = (void *)data;
78212bd3c8bSSascha Wildner 		x = pgq->index % USB_SUB_QUIRKS_MAX;
78312bd3c8bSSascha Wildner 		y = pgq->index / USB_SUB_QUIRKS_MAX;
78412bd3c8bSSascha Wildner 		if (y >= USB_DEV_QUIRKS_MAX) {
78512bd3c8bSSascha Wildner 			return (EINVAL);
78612bd3c8bSSascha Wildner 		}
787ac499a8fSSascha Wildner 		lockmgr(&usb_quirk_lock, LK_EXCLUSIVE);
78812bd3c8bSSascha Wildner 		/* copy out data */
78912bd3c8bSSascha Wildner 		pgq->vid = usb_quirks[y].vid;
79012bd3c8bSSascha Wildner 		pgq->pid = usb_quirks[y].pid;
79112bd3c8bSSascha Wildner 		pgq->bcdDeviceLow = usb_quirks[y].lo_rev;
79212bd3c8bSSascha Wildner 		pgq->bcdDeviceHigh = usb_quirks[y].hi_rev;
79312bd3c8bSSascha Wildner 		strlcpy(pgq->quirkname,
79412bd3c8bSSascha Wildner 		    usb_quirkstr(usb_quirks[y].quirks[x]),
79512bd3c8bSSascha Wildner 		    sizeof(pgq->quirkname));
796ac499a8fSSascha Wildner 		lockmgr(&usb_quirk_lock, LK_RELEASE);
79712bd3c8bSSascha Wildner 		return (0);		/* success */
79812bd3c8bSSascha Wildner 
79912bd3c8bSSascha Wildner 	case USB_QUIRK_NAME_GET:
80012bd3c8bSSascha Wildner 		pgq = (void *)data;
80112bd3c8bSSascha Wildner 		x = pgq->index;
80212bd3c8bSSascha Wildner 		if (x >= USB_QUIRK_MAX) {
80312bd3c8bSSascha Wildner 			return (EINVAL);
80412bd3c8bSSascha Wildner 		}
80512bd3c8bSSascha Wildner 		strlcpy(pgq->quirkname,
80612bd3c8bSSascha Wildner 		    usb_quirkstr(x), sizeof(pgq->quirkname));
80712bd3c8bSSascha Wildner 		return (0);		/* success */
80812bd3c8bSSascha Wildner 
80912bd3c8bSSascha Wildner 	case USB_DEV_QUIRK_ADD:
81012bd3c8bSSascha Wildner 		pgq = (void *)data;
81112bd3c8bSSascha Wildner 
81212bd3c8bSSascha Wildner 		/* check privileges */
813*2b3f93eaSMatthew Dillon 		err = caps_priv_check_self(SYSCAP_NODRIVER);
81412bd3c8bSSascha Wildner 		if (err) {
81512bd3c8bSSascha Wildner 			return (err);
81612bd3c8bSSascha Wildner 		}
81712bd3c8bSSascha Wildner 		/* convert quirk string into numerical */
81812bd3c8bSSascha Wildner 		for (y = 0; y != USB_DEV_QUIRKS_MAX; y++) {
81912bd3c8bSSascha Wildner 			if (strcmp(pgq->quirkname, usb_quirkstr(y)) == 0) {
82012bd3c8bSSascha Wildner 				break;
82112bd3c8bSSascha Wildner 			}
82212bd3c8bSSascha Wildner 		}
82312bd3c8bSSascha Wildner 		if (y == USB_DEV_QUIRKS_MAX) {
82412bd3c8bSSascha Wildner 			return (EINVAL);
82512bd3c8bSSascha Wildner 		}
82612bd3c8bSSascha Wildner 		if (y == UQ_NONE) {
82712bd3c8bSSascha Wildner 			return (EINVAL);
82812bd3c8bSSascha Wildner 		}
829ac499a8fSSascha Wildner 		lockmgr(&usb_quirk_lock, LK_EXCLUSIVE);
83012bd3c8bSSascha Wildner 		pqe = usb_quirk_get_entry(pgq->vid, pgq->pid,
83112bd3c8bSSascha Wildner 		    pgq->bcdDeviceLow, pgq->bcdDeviceHigh, 1);
83212bd3c8bSSascha Wildner 		if (pqe == NULL) {
833ac499a8fSSascha Wildner 			lockmgr(&usb_quirk_lock, LK_RELEASE);
83412bd3c8bSSascha Wildner 			return (EINVAL);
83512bd3c8bSSascha Wildner 		}
83612bd3c8bSSascha Wildner 		for (x = 0; x != USB_SUB_QUIRKS_MAX; x++) {
83712bd3c8bSSascha Wildner 			if (pqe->quirks[x] == UQ_NONE) {
83812bd3c8bSSascha Wildner 				pqe->quirks[x] = y;
83912bd3c8bSSascha Wildner 				break;
84012bd3c8bSSascha Wildner 			}
84112bd3c8bSSascha Wildner 		}
842ac499a8fSSascha Wildner 		lockmgr(&usb_quirk_lock, LK_RELEASE);
84312bd3c8bSSascha Wildner 		if (x == USB_SUB_QUIRKS_MAX) {
84412bd3c8bSSascha Wildner 			return (ENOMEM);
84512bd3c8bSSascha Wildner 		}
84612bd3c8bSSascha Wildner 		return (0);		/* success */
84712bd3c8bSSascha Wildner 
84812bd3c8bSSascha Wildner 	case USB_DEV_QUIRK_REMOVE:
84912bd3c8bSSascha Wildner 		pgq = (void *)data;
850*2b3f93eaSMatthew Dillon 
85112bd3c8bSSascha Wildner 		/* check privileges */
852*2b3f93eaSMatthew Dillon 		err = caps_priv_check_self(SYSCAP_NODRIVER);
85312bd3c8bSSascha Wildner 		if (err) {
85412bd3c8bSSascha Wildner 			return (err);
85512bd3c8bSSascha Wildner 		}
85612bd3c8bSSascha Wildner 		/* convert quirk string into numerical */
85712bd3c8bSSascha Wildner 		for (y = 0; y != USB_DEV_QUIRKS_MAX; y++) {
85812bd3c8bSSascha Wildner 			if (strcmp(pgq->quirkname, usb_quirkstr(y)) == 0) {
85912bd3c8bSSascha Wildner 				break;
86012bd3c8bSSascha Wildner 			}
86112bd3c8bSSascha Wildner 		}
86212bd3c8bSSascha Wildner 		if (y == USB_DEV_QUIRKS_MAX) {
86312bd3c8bSSascha Wildner 			return (EINVAL);
86412bd3c8bSSascha Wildner 		}
86512bd3c8bSSascha Wildner 		if (y == UQ_NONE) {
86612bd3c8bSSascha Wildner 			return (EINVAL);
86712bd3c8bSSascha Wildner 		}
868ac499a8fSSascha Wildner 		lockmgr(&usb_quirk_lock, LK_EXCLUSIVE);
86912bd3c8bSSascha Wildner 		pqe = usb_quirk_get_entry(pgq->vid, pgq->pid,
87012bd3c8bSSascha Wildner 		    pgq->bcdDeviceLow, pgq->bcdDeviceHigh, 0);
87112bd3c8bSSascha Wildner 		if (pqe == NULL) {
872ac499a8fSSascha Wildner 			lockmgr(&usb_quirk_lock, LK_RELEASE);
87312bd3c8bSSascha Wildner 			return (EINVAL);
87412bd3c8bSSascha Wildner 		}
87512bd3c8bSSascha Wildner 		for (x = 0; x != USB_SUB_QUIRKS_MAX; x++) {
87612bd3c8bSSascha Wildner 			if (pqe->quirks[x] == y) {
87712bd3c8bSSascha Wildner 				pqe->quirks[x] = UQ_NONE;
87812bd3c8bSSascha Wildner 				break;
87912bd3c8bSSascha Wildner 			}
88012bd3c8bSSascha Wildner 		}
88112bd3c8bSSascha Wildner 		if (x == USB_SUB_QUIRKS_MAX) {
882ac499a8fSSascha Wildner 			lockmgr(&usb_quirk_lock, LK_RELEASE);
88312bd3c8bSSascha Wildner 			return (ENOMEM);
88412bd3c8bSSascha Wildner 		}
88512bd3c8bSSascha Wildner 		for (x = 0; x != USB_SUB_QUIRKS_MAX; x++) {
88612bd3c8bSSascha Wildner 			if (pqe->quirks[x] != UQ_NONE) {
88712bd3c8bSSascha Wildner 				break;
88812bd3c8bSSascha Wildner 			}
88912bd3c8bSSascha Wildner 		}
89012bd3c8bSSascha Wildner 		if (x == USB_SUB_QUIRKS_MAX) {
89112bd3c8bSSascha Wildner 			/* all quirk entries are unused - release */
892cc194c56SSascha Wildner 			memset(pqe, 0, sizeof(*pqe));
89312bd3c8bSSascha Wildner 		}
894ac499a8fSSascha Wildner 		lockmgr(&usb_quirk_lock, LK_RELEASE);
89512bd3c8bSSascha Wildner 		return (0);		/* success */
89612bd3c8bSSascha Wildner 
89712bd3c8bSSascha Wildner 	default:
89812bd3c8bSSascha Wildner 		break;
89912bd3c8bSSascha Wildner 	}
90012bd3c8bSSascha Wildner 	return (ENOIOCTL);
90112bd3c8bSSascha Wildner }
90212bd3c8bSSascha Wildner 
903520083baSSascha Wildner /*------------------------------------------------------------------------*
904520083baSSascha Wildner  *	usb_quirk_strtou16
905520083baSSascha Wildner  *
906520083baSSascha Wildner  * Helper function to scan a 16-bit integer.
907520083baSSascha Wildner  *------------------------------------------------------------------------*/
908520083baSSascha Wildner static uint16_t
usb_quirk_strtou16(const char ** pptr,const char * name,const char * what)909520083baSSascha Wildner usb_quirk_strtou16(const char **pptr, const char *name, const char *what)
910520083baSSascha Wildner {
911520083baSSascha Wildner 	unsigned long value;
912520083baSSascha Wildner 	char *end;
913520083baSSascha Wildner 
914520083baSSascha Wildner 	value = strtoul(*pptr, &end, 0);
915520083baSSascha Wildner 	if (value > 65535 || *pptr == end || (*end != ' ' && *end != '\t')) {
916520083baSSascha Wildner 		kprintf("%s: %s 16-bit %s value set to zero\n",
917520083baSSascha Wildner 		    name, what, *end == 0 ? "incomplete" : "invalid");
918520083baSSascha Wildner 		return (0);
919520083baSSascha Wildner 	}
920520083baSSascha Wildner 	*pptr = end + 1;
921520083baSSascha Wildner 	return ((uint16_t)value);
922520083baSSascha Wildner }
923520083baSSascha Wildner 
924520083baSSascha Wildner /*------------------------------------------------------------------------*
925520083baSSascha Wildner  *	usb_quirk_add_entry_from_str
926520083baSSascha Wildner  *
927520083baSSascha Wildner  * Add a USB quirk entry from string.
928520083baSSascha Wildner  *     "VENDOR PRODUCT LO_REV HI_REV QUIRK[,QUIRK[,...]]"
929520083baSSascha Wildner  *------------------------------------------------------------------------*/
930520083baSSascha Wildner static void
usb_quirk_add_entry_from_str(const char * name,const char * env)931520083baSSascha Wildner usb_quirk_add_entry_from_str(const char *name, const char *env)
932520083baSSascha Wildner {
933520083baSSascha Wildner 	struct usb_quirk_entry entry = { };
934520083baSSascha Wildner 	struct usb_quirk_entry *new;
935520083baSSascha Wildner 	uint16_t quirk_idx;
936520083baSSascha Wildner 	uint16_t quirk;
937520083baSSascha Wildner 	const char *end;
938520083baSSascha Wildner 
939520083baSSascha Wildner 	/* check for invalid environment variable */
940520083baSSascha Wildner 	if (name == NULL || env == NULL)
941520083baSSascha Wildner 		return;
942520083baSSascha Wildner 
943520083baSSascha Wildner 	if (bootverbose)
944520083baSSascha Wildner 		kprintf("Adding USB QUIRK '%s' = '%s'\n", name, env);
945520083baSSascha Wildner 
946520083baSSascha Wildner 	/* parse device information */
947520083baSSascha Wildner 	entry.vid = usb_quirk_strtou16(&env, name, "Vendor ID");
948520083baSSascha Wildner 	entry.pid = usb_quirk_strtou16(&env, name, "Product ID");
949520083baSSascha Wildner 	entry.lo_rev = usb_quirk_strtou16(&env, name, "Low revision");
950520083baSSascha Wildner 	entry.hi_rev = usb_quirk_strtou16(&env, name, "High revision");
951520083baSSascha Wildner 
952520083baSSascha Wildner 	/* parse quirk information */
953520083baSSascha Wildner 	quirk_idx = 0;
954520083baSSascha Wildner 	while (*env != 0 && quirk_idx != USB_SUB_QUIRKS_MAX) {
955520083baSSascha Wildner 		/* skip whitespace before quirks */
956520083baSSascha Wildner 		while (*env == ' ' || *env == '\t')
957520083baSSascha Wildner 			env++;
958520083baSSascha Wildner 
959520083baSSascha Wildner 		/* look for quirk separation character */
960520083baSSascha Wildner 		end = strchr(env, ',');
961520083baSSascha Wildner 		if (end == NULL)
962520083baSSascha Wildner 			end = env + strlen(env);
963520083baSSascha Wildner 
964520083baSSascha Wildner 		/* lookup quirk in string table */
965520083baSSascha Wildner 		quirk = usb_strquirk(env, end - env);
966520083baSSascha Wildner 		if (quirk < USB_QUIRK_MAX) {
967520083baSSascha Wildner 			entry.quirks[quirk_idx++] = quirk;
968520083baSSascha Wildner 		} else {
969520083baSSascha Wildner 			kprintf("%s: unknown USB quirk '%.*s' (skipped)\n",
970520083baSSascha Wildner 			    name, (int)(end - env), env);
971520083baSSascha Wildner 		}
972520083baSSascha Wildner 		env = end;
973520083baSSascha Wildner 
974520083baSSascha Wildner 		/* skip quirk delimiter, if any */
975520083baSSascha Wildner 		if (*env != 0)
976520083baSSascha Wildner 			env++;
977520083baSSascha Wildner 	}
978520083baSSascha Wildner 
979520083baSSascha Wildner 	/* register quirk */
980520083baSSascha Wildner 	if (quirk_idx != 0) {
981520083baSSascha Wildner 		if (*env != 0) {
982520083baSSascha Wildner 			kprintf("%s: Too many USB quirks, only %d allowed!\n",
983520083baSSascha Wildner 			    name, USB_SUB_QUIRKS_MAX);
984520083baSSascha Wildner 		}
985520083baSSascha Wildner 		lockmgr(&usb_quirk_lock, LK_EXCLUSIVE);
986520083baSSascha Wildner 		new = usb_quirk_get_entry(entry.vid, entry.pid,
987520083baSSascha Wildner 		    entry.lo_rev, entry.hi_rev, 1);
988520083baSSascha Wildner 		if (new == NULL)
989520083baSSascha Wildner 			kprintf("%s: USB quirks table is full!\n", name);
990520083baSSascha Wildner 		else
991520083baSSascha Wildner 			memcpy(new->quirks, entry.quirks, sizeof(entry.quirks));
992520083baSSascha Wildner 		lockmgr(&usb_quirk_lock, LK_RELEASE);
993520083baSSascha Wildner 	} else {
994520083baSSascha Wildner 		kprintf("%s: No USB quirks found!\n", name);
995520083baSSascha Wildner 	}
996520083baSSascha Wildner }
997520083baSSascha Wildner 
99812bd3c8bSSascha Wildner static void
usb_quirk_init(void * arg)99912bd3c8bSSascha Wildner usb_quirk_init(void *arg)
100012bd3c8bSSascha Wildner {
1001520083baSSascha Wildner 	char envkey[sizeof(USB_QUIRK_ENVROOT) + 2];	/* 2 digits max, 0 to 99 */
1002520083baSSascha Wildner 	int i;
1003520083baSSascha Wildner 
100412bd3c8bSSascha Wildner 	/* initialize mutex */
1005ac499a8fSSascha Wildner 	lockinit(&usb_quirk_lock, "USB quirk", 0, 0);
100612bd3c8bSSascha Wildner 
1007520083baSSascha Wildner 	/* look for quirks defined by the environment variable */
1008520083baSSascha Wildner 	for (i = 0; i != 100; i++) {
1009520083baSSascha Wildner 		ksnprintf(envkey, sizeof(envkey), USB_QUIRK_ENVROOT "%d", i);
1010520083baSSascha Wildner 
1011520083baSSascha Wildner 		/* Stop at first undefined var */
1012520083baSSascha Wildner 		if (!ktestenv(envkey))
1013520083baSSascha Wildner 			break;
1014520083baSSascha Wildner 
1015520083baSSascha Wildner 		/* parse environment variable */
1016520083baSSascha Wildner 		usb_quirk_add_entry_from_str(envkey, kgetenv(envkey));
1017520083baSSascha Wildner 	}
1018520083baSSascha Wildner 
101912bd3c8bSSascha Wildner 	/* register our function */
102012bd3c8bSSascha Wildner 	usb_test_quirk_p = &usb_test_quirk_by_info;
102112bd3c8bSSascha Wildner 	usb_quirk_ioctl_p = &usb_quirk_ioctl;
102212bd3c8bSSascha Wildner }
102312bd3c8bSSascha Wildner 
102412bd3c8bSSascha Wildner static void
usb_quirk_uninit(void * arg)102512bd3c8bSSascha Wildner usb_quirk_uninit(void *arg)
102612bd3c8bSSascha Wildner {
102712bd3c8bSSascha Wildner 	usb_quirk_unload(arg);
102812bd3c8bSSascha Wildner 
102912bd3c8bSSascha Wildner 	/* destroy mutex */
1030ac499a8fSSascha Wildner 	lockuninit(&usb_quirk_lock);
103112bd3c8bSSascha Wildner }
103212bd3c8bSSascha Wildner 
1033ac499a8fSSascha Wildner SYSINIT(usb_quirk_init, SI_SUB_DRIVERS, SI_ORDER_FIRST, usb_quirk_init, NULL);
1034ac499a8fSSascha Wildner SYSUNINIT(usb_quirk_uninit, SI_SUB_DRIVERS, SI_ORDER_ANY, usb_quirk_uninit, NULL);
1035