usb_quirk.c revision 200886
11590Srgrimes/* $FreeBSD: head/sys/dev/usb/quirk/usb_quirk.c 200886 2009-12-23 01:16:24Z thompsa $ */
21590Srgrimes/*-
31590Srgrimes * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
41590Srgrimes * Copyright (c) 1998 Lennart Augustsson. All rights reserved.
51590Srgrimes * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
61590Srgrimes *
71590Srgrimes * Redistribution and use in source and binary forms, with or without
81590Srgrimes * modification, are permitted provided that the following conditions
91590Srgrimes * are met:
101590Srgrimes * 1. Redistributions of source code must retain the above copyright
111590Srgrimes *    notice, this list of conditions and the following disclaimer.
121590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
131590Srgrimes *    notice, this list of conditions and the following disclaimer in the
141590Srgrimes *    documentation and/or other materials provided with the distribution.
151590Srgrimes *
161590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
171590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
181590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
191590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
201590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
211590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
221590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
231590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
241590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
251590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
261590Srgrimes * SUCH DAMAGE.
271590Srgrimes */
281590Srgrimes
291590Srgrimes#include <sys/stdint.h>
301590Srgrimes#include <sys/stddef.h>
311590Srgrimes#include <sys/param.h>
321590Srgrimes#include <sys/queue.h>
3387628Sdwmalone#include <sys/types.h>
3487628Sdwmalone#include <sys/systm.h>
3587628Sdwmalone#include <sys/kernel.h>
3687628Sdwmalone#include <sys/bus.h>
3787628Sdwmalone#include <sys/linker_set.h>
3887628Sdwmalone#include <sys/module.h>
3987231Smarkm#include <sys/lock.h>
4087231Smarkm#include <sys/mutex.h>
4187231Smarkm#include <sys/condvar.h>
4267189Sbrian#include <sys/sysctl.h>
43204761Sjh#include <sys/sx.h>
441590Srgrimes#include <sys/unistd.h>
451590Srgrimes#include <sys/callout.h>
461590Srgrimes#include <sys/malloc.h>
471590Srgrimes#include <sys/priv.h>
48204761Sjh
491590Srgrimes#include <dev/usb/usb.h>
501590Srgrimes#include <dev/usb/usb_ioctl.h>
511590Srgrimes#include <dev/usb/usbdi.h>
521590Srgrimes#include "usbdevs.h"
531590Srgrimes
541590Srgrimes#define	USB_DEBUG_VAR usb_debug
551590Srgrimes#include <dev/usb/usb_debug.h>
5671326Swill#include <dev/usb/usb_dynamic.h>
571590Srgrimes
58245048Sdelphij#include <dev/usb/quirk/usb_quirk.h>
5971326Swill
6070692SwillMODULE_DEPEND(usb_quirk, usb, 1, 1, 1);
611590SrgrimesMODULE_VERSION(usb_quirk, 1);
62204761Sjh
63204761Sjh/*
64204761Sjh * The following macro adds one or more quirks for a USB device:
65204761Sjh */
6671326Swill#define	USB_QUIRK_ENTRY(v,p,l,h,...) \
67204761Sjh  .vid = (v), .pid = (p), .lo_rev = (l), .hi_rev = (h), .quirks = { __VA_ARGS__ }
68204761Sjh
691590Srgrimes#define	USB_DEV_QUIRKS_MAX 256
701590Srgrimes#define	USB_SUB_QUIRKS_MAX 8
711590Srgrimes
721590Srgrimesstruct usb_quirk_entry {
7370672Swill	uint16_t vid;
741590Srgrimes	uint16_t pid;
751590Srgrimes	uint16_t lo_rev;
761590Srgrimes	uint16_t hi_rev;
771590Srgrimes	uint16_t quirks[USB_SUB_QUIRKS_MAX];
7854157Scharnier};
791590Srgrimes
801590Srgrimesstatic struct mtx usb_quirk_mtx;
811590Srgrimes
821590Srgrimesstatic struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
831590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_ASUS, USB_PRODUCT_ASUS_LCM,
841590Srgrimes	    0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
851590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_INSIDEOUT, USB_PRODUCT_INSIDEOUT_EDGEPORT4,
861590Srgrimes	    0x094, 0x094, UQ_SWAP_UNICODE, UQ_NONE)},
871590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_J6502,
8854157Scharnier	    0x0a2, 0x0a2, UQ_BAD_ADC, UQ_NONE)},
891590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_J6502,
901590Srgrimes	    0x0a2, 0x0a2, UQ_AU_NO_XU, UQ_NONE)},
911590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ADA70,
921590Srgrimes	    0x103, 0x103, UQ_BAD_ADC, UQ_NONE)},
931590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ASC495,
941590Srgrimes	    0x000, 0x000, UQ_BAD_AUDIO, UQ_NONE)},
951590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_QTRONIX, USB_PRODUCT_QTRONIX_980N,
961590Srgrimes	    0x110, 0x110, UQ_SPUR_BUT_UP, UQ_NONE)},
971590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_ALCOR2, USB_PRODUCT_ALCOR2_KBD_HUB,
981590Srgrimes	    0x001, 0x001, UQ_SPUR_BUT_UP, UQ_NONE)},
991590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_MCT, USB_PRODUCT_MCT_HUB0100,
1001590Srgrimes	    0x102, 0x102, UQ_BUS_POWERED, UQ_NONE)},
1011590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_MCT, USB_PRODUCT_MCT_USB232,
1021590Srgrimes	    0x102, 0x102, UQ_BUS_POWERED, UQ_NONE)},
1031590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_TI, USB_PRODUCT_TI_UTUSB41,
1041590Srgrimes	    0x110, 0x110, UQ_POWER_CLAIM, UQ_NONE)},
1051590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_TELEX, USB_PRODUCT_TELEX_MIC1,
1061590Srgrimes	    0x009, 0x009, UQ_AU_NO_FRAC, UQ_NONE)},
1071590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_SILICONPORTALS,
1081590Srgrimes	    USB_PRODUCT_SILICONPORTALS_YAPPHONE,
1091590Srgrimes	    0x100, 0x100, UQ_AU_INP_ASYNC, UQ_NONE)},
1101590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_UN53B,
1111590Srgrimes	    0x0000, 0xFFFF, UQ_NO_STRINGS, UQ_NONE)},
1121590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_ELSA, USB_PRODUCT_ELSA_MODEM1,
11370692Swill	    0x0000, 0xFFFF, UQ_CFG_INDEX_1, UQ_NONE)},
11470692Swill
11570692Swill	/*
11670692Swill	 * XXX The following quirks should have a more specific revision
11770692Swill	 * number:
11870692Swill	 */
11970692Swill	{USB_QUIRK_ENTRY(USB_VENDOR_HP, USB_PRODUCT_HP_895C,
12070692Swill	    0x0000, 0xFFFF, UQ_BROKEN_BIDIR, UQ_NONE)},
12170692Swill	{USB_QUIRK_ENTRY(USB_VENDOR_HP, USB_PRODUCT_HP_880C,
12270692Swill	    0x0000, 0xFFFF, UQ_BROKEN_BIDIR, UQ_NONE)},
12370692Swill	{USB_QUIRK_ENTRY(USB_VENDOR_HP, USB_PRODUCT_HP_815C,
12470692Swill	    0x0000, 0xFFFF, UQ_BROKEN_BIDIR, UQ_NONE)},
12570692Swill	{USB_QUIRK_ENTRY(USB_VENDOR_HP, USB_PRODUCT_HP_810C,
12670692Swill	    0x0000, 0xFFFF, UQ_BROKEN_BIDIR, UQ_NONE)},
12770692Swill	{USB_QUIRK_ENTRY(USB_VENDOR_HP, USB_PRODUCT_HP_830C,
12870692Swill	    0x0000, 0xFFFF, UQ_BROKEN_BIDIR, UQ_NONE)},
1291590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_HP, USB_PRODUCT_HP_1220C,
1301590Srgrimes	    0x0000, 0xFFFF, UQ_BROKEN_BIDIR, UQ_NONE)},
1311590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_XEROX, USB_PRODUCT_XEROX_WCM15,
13270692Swill	    0x0000, 0xFFFF, UQ_BROKEN_BIDIR, UQ_NONE)},
13370692Swill	/* Devices which should be ignored by uhid */
1341590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_APC, USB_PRODUCT_APC_UPS,
13571326Swill	    0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
13671326Swill	{USB_QUIRK_ENTRY(USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F6C550AVR,
13770692Swill	    0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
1381590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_CYBERPOWER,
1398874Srgrimes	    USB_PRODUCT_CYBERPOWER_1500CAVRLCD,
1401590Srgrimes	    0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
1411590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_DELORME, USB_PRODUCT_DELORME_EARTHMATE,
1421590Srgrimes	    0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
1431590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_ITUNERNET, USB_PRODUCT_ITUNERNET_USBLCD2X20,
1441590Srgrimes	    0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
1451590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_ITUNERNET, USB_PRODUCT_ITUNERNET_USBLCD4X20,
14670692Swill	    0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
14782057Sbrian	{USB_QUIRK_ENTRY(USB_VENDOR_MGE, USB_PRODUCT_MGE_UPS1,
148204761Sjh	    0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
14970692Swill	{USB_QUIRK_ENTRY(USB_VENDOR_MGE, USB_PRODUCT_MGE_UPS2,
15071615Swill	    0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
15170692Swill	{USB_QUIRK_ENTRY(USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE,
15270692Swill	    0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
15382057Sbrian	{USB_QUIRK_ENTRY(USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_3G,
154204761Sjh	    0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
15570692Swill	/* Devices which should be ignored by both ukbd and uhid */
15671615Swill	{USB_QUIRK_ENTRY(USB_VENDOR_CYPRESS, USB_PRODUCT_CYPRESS_WISPY1A,
15770692Swill	    0x0000, 0xFFFF, UQ_KBD_IGNORE, UQ_HID_IGNORE, UQ_NONE)},
1581590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_METAGEEK, USB_PRODUCT_METAGEEK_WISPY1B,
1591590Srgrimes	    0x0000, 0xFFFF, UQ_KBD_IGNORE, UQ_HID_IGNORE, UQ_NONE)},
1601590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_TENX, USB_PRODUCT_TENX_UAUDIO0,
1611590Srgrimes	    0x0101, 0x0101, UQ_AUDIO_SWAP_LR, UQ_NONE)},
1621590Srgrimes	/* MS keyboards do weird things */
1631590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_MICROSOFT,
1641590Srgrimes	    USB_PRODUCT_MICROSOFT_WLINTELLIMOUSE,
1651590Srgrimes	    0x0000, 0xFFFF, UQ_MS_LEADING_BYTE, UQ_NONE)},
16670692Swill	{USB_QUIRK_ENTRY(USB_VENDOR_METAGEEK, USB_PRODUCT_METAGEEK_WISPY24X,
16782057Sbrian	    0x0000, 0xFFFF, UQ_KBD_IGNORE, UQ_HID_IGNORE, UQ_NONE)},
168204761Sjh	/* umodem(4) device quirks */
1691590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_METRICOM, USB_PRODUCT_METRICOM_RICOCHET_GS,
1701590Srgrimes	    0x100, 0x100, UQ_ASSUME_CM_OVER_DATA)},
1711590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_SANYO, USB_PRODUCT_SANYO_SCP4900,
172204761Sjh	    0x000, 0x000, UQ_ASSUME_CM_OVER_DATA)},
173204761Sjh	{USB_QUIRK_ENTRY(USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_T720C,
1741590Srgrimes	    0x001, 0x001, UQ_ASSUME_CM_OVER_DATA)},
1751590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_EICON, USB_PRODUCT_EICON_DIVA852,
176204761Sjh	    0x100, 0x100, UQ_ASSUME_CM_OVER_DATA)},
177204761Sjh	{USB_QUIRK_ENTRY(USB_VENDOR_SIEMENS2, USB_PRODUCT_SIEMENS2_ES75,
1781590Srgrimes	    0x000, 0x000, UQ_ASSUME_CM_OVER_DATA)},
1791590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_QUALCOMM, USB_PRODUCT_QUALCOMM_CDMA_MSM,
1801590Srgrimes	    0x0000, 0xFFFF, UQ_ASSUME_CM_OVER_DATA)},
1811590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_QUALCOMM2, USB_PRODUCT_QUALCOMM2_CDMA_MSM,
1821590Srgrimes	    0x0000, 0xFFFF, UQ_ASSUME_CM_OVER_DATA)},
1831590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_CURITEL, USB_PRODUCT_CURITEL_UM175,
184204761Sjh	    0x0000, 0xFFFF, UQ_ASSUME_CM_OVER_DATA)},
1851590Srgrimes
186204761Sjh	/* USB Mass Storage Class Quirks */
18770692Swill	{USB_QUIRK_ENTRY(USB_VENDOR_ASAHIOPTICAL, 0,
188204761Sjh	    0x0000, 0xFFFF, UQ_MSC_NO_RS_CLEAR_UA, UQ_MATCH_VENDOR_ONLY)},
189204761Sjh	{USB_QUIRK_ENTRY(USB_VENDOR_ADDON, USB_PRODUCT_ADDON_ATTACHE, 0x0000,
190204761Sjh	    0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
191204761Sjh	    UQ_MSC_IGNORE_RESIDUE)},
192204761Sjh	{USB_QUIRK_ENTRY(USB_VENDOR_ADDON, USB_PRODUCT_ADDON_A256MB,
193204761Sjh	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
194204761Sjh	    UQ_MSC_IGNORE_RESIDUE)},
195204761Sjh	{USB_QUIRK_ENTRY(USB_VENDOR_ADDON, USB_PRODUCT_ADDON_DISKPRO512,
196204761Sjh	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
197204761Sjh	    UQ_MSC_IGNORE_RESIDUE)},
1981590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_ADDONICS2, USB_PRODUCT_ADDONICS2_CABLE_205,
1991590Srgrimes	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
200204761Sjh	{USB_QUIRK_ENTRY(USB_VENDOR_AIPTEK, USB_PRODUCT_AIPTEK_POCKETCAM3M,
2011590Srgrimes	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
2021590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_AIPTEK2, USB_PRODUCT_AIPTEK2_SUNPLUS_TECH,
2031590Srgrimes	    0x0000, 0xFFFF, UQ_MSC_NO_SYNC_CACHE)},
204204761Sjh	{USB_QUIRK_ENTRY(USB_VENDOR_ALCOR, USB_PRODUCT_ALCOR_SDCR_6335,
2051590Srgrimes	    0x0000, 0xFFFF, UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_SYNC_CACHE)},
206204761Sjh	{USB_QUIRK_ENTRY(USB_VENDOR_ALCOR, USB_PRODUCT_ALCOR_AU6390,
2071590Srgrimes	    0x0000, 0xFFFF, UQ_MSC_NO_SYNC_CACHE)},
2081590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_ALCOR, USB_PRODUCT_ALCOR_UMCR_9361,
2091590Srgrimes	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
2101590Srgrimes	    UQ_MSC_NO_GETMAXLUN)},
2111590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_ALCOR, USB_PRODUCT_ALCOR_TRANSCEND,
212204761Sjh	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
21370692Swill	    UQ_MSC_NO_GETMAXLUN)},
214204761Sjh	{USB_QUIRK_ENTRY(USB_VENDOR_ASAHIOPTICAL, USB_PRODUCT_ASAHIOPTICAL_OPTIO230,
21570692Swill	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
2161590Srgrimes	    UQ_MSC_NO_INQUIRY)},
2171590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_ASAHIOPTICAL, USB_PRODUCT_ASAHIOPTICAL_OPTIO330,
2181590Srgrimes	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
2191590Srgrimes	    UQ_MSC_NO_INQUIRY)},
22070692Swill	{USB_QUIRK_ENTRY(USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_USB2SCSI,
22170692Swill	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
22270692Swill	{USB_QUIRK_ENTRY(USB_VENDOR_CASIO, USB_PRODUCT_CASIO_QV_DIGICAM,
2231590Srgrimes	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_SCSI,
22470692Swill	    UQ_MSC_NO_INQUIRY)},
225245048Sdelphij	{USB_QUIRK_ENTRY(USB_VENDOR_CCYU, USB_PRODUCT_CCYU_ED1064,
2261590Srgrimes	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
2271590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_CENTURY, USB_PRODUCT_CENTURY_EX35QUAT,
22843928Seivind	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
2291590Srgrimes	    UQ_MSC_FORCE_SHORT_INQ, UQ_MSC_NO_START_STOP,
2301590Srgrimes	    UQ_MSC_IGNORE_RESIDUE)},
23170672Swill	{USB_QUIRK_ENTRY(USB_VENDOR_CYPRESS, USB_PRODUCT_CYPRESS_XX6830XX,
2321590Srgrimes	    0x0000, 0xFFFF, UQ_MSC_NO_GETMAXLUN, UQ_MSC_NO_SYNC_CACHE)},
2331590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_DESKNOTE, USB_PRODUCT_DESKNOTE_UCR_61S2B,
2341590Srgrimes	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
23560706Skris	{USB_QUIRK_ENTRY(USB_VENDOR_DMI, USB_PRODUCT_DMI_CFSM_RW,
2361590Srgrimes	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN)},
23760706Skris	{USB_QUIRK_ENTRY(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_STYLUS_875DC,
2381590Srgrimes	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_SCSI,
2391590Srgrimes	    UQ_MSC_NO_INQUIRY)},
24079452Sbrian	{USB_QUIRK_ENTRY(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_STYLUS_895,
24170692Swill	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
24260706Skris	    UQ_MSC_NO_GETMAXLUN)},
2431590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_FEIYA, USB_PRODUCT_FEIYA_5IN1,
2441590Srgrimes	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
2451590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_FREECOM, USB_PRODUCT_FREECOM_DVD,
24643928Seivind	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI)},
2471590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_FUJIPHOTO, USB_PRODUCT_FUJIPHOTO_MASS0100,
2481590Srgrimes	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI_I, UQ_MSC_FORCE_PROTO_ATAPI,
2491590Srgrimes	    UQ_MSC_NO_RS_CLEAR_UA)},
25043928Seivind	{USB_QUIRK_ENTRY(USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL641USB2IDE,
2511590Srgrimes	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
2521590Srgrimes	    UQ_MSC_FORCE_SHORT_INQ, UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE,
253245048Sdelphij	    UQ_MSC_NO_SYNC_CACHE)},
25499984Salfred	{USB_QUIRK_ENTRY(USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL641USB2IDE_2,
2551590Srgrimes	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_ATAPI,
2561590Srgrimes	    UQ_MSC_FORCE_SHORT_INQ, UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE)},
2571590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL641USB,
25870672Swill	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
2591590Srgrimes	    UQ_MSC_FORCE_SHORT_INQ, UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE)},
2601590Srgrimes	{USB_QUIRK_ENTRY(USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL641USB_2,
261	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
262	    UQ_MSC_WRONG_CSWSIG)},
263	{USB_QUIRK_ENTRY(USB_VENDOR_HAGIWARA, USB_PRODUCT_HAGIWARA_FG,
264	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
265	{USB_QUIRK_ENTRY(USB_VENDOR_HAGIWARA, USB_PRODUCT_HAGIWARA_FGSM,
266	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
267	{USB_QUIRK_ENTRY(USB_VENDOR_HITACHI, USB_PRODUCT_HITACHI_DVDCAM_DZ_MV100A,
268	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_SCSI,
269	    UQ_MSC_NO_GETMAXLUN)},
270	{USB_QUIRK_ENTRY(USB_VENDOR_HITACHI, USB_PRODUCT_HITACHI_DVDCAM_USB,
271	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI_I, UQ_MSC_FORCE_PROTO_ATAPI,
272	    UQ_MSC_NO_INQUIRY)},
273	{USB_QUIRK_ENTRY(USB_VENDOR_HP, USB_PRODUCT_HP_CDW4E,
274	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_ATAPI)},
275	{USB_QUIRK_ENTRY(USB_VENDOR_HP, USB_PRODUCT_HP_CDW8200,
276	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI_I, UQ_MSC_FORCE_PROTO_ATAPI,
277	    UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_START_STOP)},
278	{USB_QUIRK_ENTRY(USB_VENDOR_IMAGINATION, USB_PRODUCT_IMAGINATION_DBX1,
279	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
280	    UQ_MSC_WRONG_CSWSIG)},
281	{USB_QUIRK_ENTRY(USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_USBCABLE,
282	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_ATAPI,
283	    UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_START_STOP, UQ_MSC_ALT_IFACE_1)},
284	{USB_QUIRK_ENTRY(USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_ATAPI,
285	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_RBC)},
286	{USB_QUIRK_ENTRY(USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_STORAGE_V2,
287	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_RBC)},
288	{USB_QUIRK_ENTRY(USB_VENDOR_IODATA, USB_PRODUCT_IODATA_IU_CD2,
289	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
290	{USB_QUIRK_ENTRY(USB_VENDOR_IODATA, USB_PRODUCT_IODATA_DVR_UEH8,
291	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
292	{USB_QUIRK_ENTRY(USB_VENDOR_IOMEGA, USB_PRODUCT_IOMEGA_ZIP100,
293	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
294	    UQ_MSC_NO_TEST_UNIT_READY)}, /* XXX ZIP drives can also use ATAPI */
295	{USB_QUIRK_ENTRY(USB_VENDOR_KYOCERA, USB_PRODUCT_KYOCERA_FINECAM_L3,
296	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
297	    UQ_MSC_NO_INQUIRY)},
298	{USB_QUIRK_ENTRY(USB_VENDOR_KYOCERA, USB_PRODUCT_KYOCERA_FINECAM_S3X,
299	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_ATAPI,
300	    UQ_MSC_NO_INQUIRY)},
301	{USB_QUIRK_ENTRY(USB_VENDOR_KYOCERA, USB_PRODUCT_KYOCERA_FINECAM_S4,
302	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_ATAPI,
303	    UQ_MSC_NO_INQUIRY)},
304	{USB_QUIRK_ENTRY(USB_VENDOR_KYOCERA, USB_PRODUCT_KYOCERA_FINECAM_S5,
305	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
306	    UQ_MSC_NO_INQUIRY)},
307	{USB_QUIRK_ENTRY(USB_VENDOR_LACIE, USB_PRODUCT_LACIE_HD,
308	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_RBC)},
309	{USB_QUIRK_ENTRY(USB_VENDOR_LEXAR, USB_PRODUCT_LEXAR_CF_READER,
310	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
311	    UQ_MSC_NO_INQUIRY)},
312	{USB_QUIRK_ENTRY(USB_VENDOR_LEXAR, USB_PRODUCT_LEXAR_JUMPSHOT,
313	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI)},
314	{USB_QUIRK_ENTRY(USB_VENDOR_LOGITEC, USB_PRODUCT_LOGITEC_LDR_H443SU2,
315	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI)},
316	{USB_QUIRK_ENTRY(USB_VENDOR_LOGITEC, USB_PRODUCT_LOGITEC_LDR_H443U2,
317	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,)},
318	{USB_QUIRK_ENTRY(USB_VENDOR_MELCO, USB_PRODUCT_MELCO_DUBPXXG,
319	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
320	    UQ_MSC_FORCE_SHORT_INQ, UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE)},
321	{USB_QUIRK_ENTRY(USB_VENDOR_MICROTECH, USB_PRODUCT_MICROTECH_DPCM,
322	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_SCSI,
323	    UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_START_STOP)},
324	{USB_QUIRK_ENTRY(USB_VENDOR_MICROTECH, USB_PRODUCT_MICROTECH_SCSIDB25,
325	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
326	{USB_QUIRK_ENTRY(USB_VENDOR_MICROTECH, USB_PRODUCT_MICROTECH_SCSIHD50,
327	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
328	{USB_QUIRK_ENTRY(USB_VENDOR_MINOLTA, USB_PRODUCT_MINOLTA_E223,
329	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI)},
330	{USB_QUIRK_ENTRY(USB_VENDOR_MINOLTA, USB_PRODUCT_MINOLTA_F300,
331	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
332	{USB_QUIRK_ENTRY(USB_VENDOR_MITSUMI, USB_PRODUCT_MITSUMI_CDRRW,
333	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI | UQ_MSC_FORCE_PROTO_ATAPI)},
334	{USB_QUIRK_ENTRY(USB_VENDOR_MITSUMI, USB_PRODUCT_MITSUMI_FDD,
335	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
336	    UQ_MSC_NO_GETMAXLUN)},
337	{USB_QUIRK_ENTRY(USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_E398,
338	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
339	    UQ_MSC_FORCE_SHORT_INQ, UQ_MSC_NO_INQUIRY_EVPD, UQ_MSC_NO_GETMAXLUN)},
340	{USB_QUIRK_ENTRY(USB_VENDOR_MPMAN, 0,
341	    0x0000, 0xFFFF, UQ_MSC_NO_SYNC_CACHE, UQ_MATCH_VENDOR_ONLY)},
342	{USB_QUIRK_ENTRY(USB_VENDOR_MSYSTEMS, USB_PRODUCT_MSYSTEMS_DISKONKEY,
343	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
344	    UQ_MSC_IGNORE_RESIDUE, UQ_MSC_NO_GETMAXLUN, UQ_MSC_NO_RS_CLEAR_UA)},
345	{USB_QUIRK_ENTRY(USB_VENDOR_MSYSTEMS, USB_PRODUCT_MSYSTEMS_DISKONKEY2,
346	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_ATAPI)},
347	{USB_QUIRK_ENTRY(USB_VENDOR_MYSON, USB_PRODUCT_MYSON_HEDEN,
348	    0x0000, 0xFFFF, UQ_MSC_IGNORE_RESIDUE, UQ_MSC_NO_SYNC_CACHE)},
349	{USB_QUIRK_ENTRY(USB_VENDOR_MYSON, USB_PRODUCT_MYSON_HEDEN_8813,
350	    0x0000, 0xFFFF, UQ_MSC_NO_SYNC_CACHE)},
351	{USB_QUIRK_ENTRY(USB_VENDOR_MYSON, USB_PRODUCT_MYSON_STARREADER,
352	    0x0000, 0xFFFF, UQ_MSC_NO_SYNC_CACHE)},
353	{USB_QUIRK_ENTRY(USB_VENDOR_NEODIO, USB_PRODUCT_NEODIO_ND3260,
354	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
355	    UQ_MSC_FORCE_SHORT_INQ)},
356	{USB_QUIRK_ENTRY(USB_VENDOR_NETAC, USB_PRODUCT_NETAC_CF_CARD,
357	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
358	    UQ_MSC_NO_INQUIRY)},
359	{USB_QUIRK_ENTRY(USB_VENDOR_NETAC, USB_PRODUCT_NETAC_ONLYDISK,
360	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
361	    UQ_MSC_IGNORE_RESIDUE)},
362	{USB_QUIRK_ENTRY(USB_VENDOR_NETCHIP, USB_PRODUCT_NETCHIP_CLIK_40,
363	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_INQUIRY)},
364	{USB_QUIRK_ENTRY(USB_VENDOR_NIKON, USB_PRODUCT_NIKON_D300,
365	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
366	{USB_QUIRK_ENTRY(USB_VENDOR_OLYMPUS, USB_PRODUCT_OLYMPUS_C1,
367	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
368	    UQ_MSC_WRONG_CSWSIG)},
369	{USB_QUIRK_ENTRY(USB_VENDOR_OLYMPUS, USB_PRODUCT_OLYMPUS_C700,
370	    0x0000, 0xFFFF, UQ_MSC_NO_GETMAXLUN)},
371	{USB_QUIRK_ENTRY(USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_SDS_HOTFIND_D,
372	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
373	    UQ_MSC_NO_GETMAXLUN, UQ_MSC_NO_SYNC_CACHE)},
374	{USB_QUIRK_ENTRY(USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_CFMS_RW,
375	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI)},
376	{USB_QUIRK_ENTRY(USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_CFSM_COMBO,
377	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI)},
378	{USB_QUIRK_ENTRY(USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_CFSM_READER,
379	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI)},
380	{USB_QUIRK_ENTRY(USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_CFSM_READER2,
381	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI)},
382	{USB_QUIRK_ENTRY(USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_MDCFE_B_CF_READER,
383	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI)},
384	{USB_QUIRK_ENTRY(USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_MDSM_B_READER,
385	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY)},
386	{USB_QUIRK_ENTRY(USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_READER,
387	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI)},
388	{USB_QUIRK_ENTRY(USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_UCF100,
389	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_ATAPI,
390	    UQ_MSC_NO_INQUIRY | UQ_MSC_NO_GETMAXLUN)},
391	{USB_QUIRK_ENTRY(USB_VENDOR_ONSPEC2, USB_PRODUCT_ONSPEC2_IMAGEMATE_SDDR55,
392	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN)},
393	{USB_QUIRK_ENTRY(USB_VENDOR_PANASONIC, USB_PRODUCT_PANASONIC_KXL840AN,
394	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_ATAPI,
395	    UQ_MSC_NO_GETMAXLUN)},
396	{USB_QUIRK_ENTRY(USB_VENDOR_PANASONIC, USB_PRODUCT_PANASONIC_KXLCB20AN,
397	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
398	{USB_QUIRK_ENTRY(USB_VENDOR_PANASONIC, USB_PRODUCT_PANASONIC_KXLCB35AN,
399	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
400	{USB_QUIRK_ENTRY(USB_VENDOR_PANASONIC, USB_PRODUCT_PANASONIC_LS120CAM,
401	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_UFI)},
402	{USB_QUIRK_ENTRY(USB_VENDOR_PHILIPS, USB_PRODUCT_PHILIPS_SPE3030CC,
403	    0x0000, 0xFFFF, UQ_MSC_NO_SYNC_CACHE)},
404	{USB_QUIRK_ENTRY(USB_VENDOR_PLEXTOR, USB_PRODUCT_PLEXTOR_40_12_40U,
405	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
406	    UQ_MSC_NO_TEST_UNIT_READY)},
407	{USB_QUIRK_ENTRY(USB_VENDOR_PNY, USB_PRODUCT_PNY_ATTACHE2,
408	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
409	    UQ_MSC_IGNORE_RESIDUE, UQ_MSC_NO_START_STOP)},
410	{USB_QUIRK_ENTRY(USB_VENDOR_SAMSUNG_TECHWIN, USB_PRODUCT_SAMSUNG_TECHWIN_DIGIMAX_410,
411	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
412	    UQ_MSC_NO_INQUIRY)},
413	{USB_QUIRK_ENTRY(USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDDR05A,
414	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_SCSI,
415	    UQ_MSC_READ_CAP_OFFBY1, UQ_MSC_NO_GETMAXLUN)},
416	{USB_QUIRK_ENTRY(USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDDR09,
417	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_READ_CAP_OFFBY1,
418	    UQ_MSC_NO_GETMAXLUN)},
419	{USB_QUIRK_ENTRY(USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDDR12,
420	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_SCSI,
421	    UQ_MSC_READ_CAP_OFFBY1, UQ_MSC_NO_GETMAXLUN)},
422	{USB_QUIRK_ENTRY(USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDCZ2_256,
423	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
424	    UQ_MSC_IGNORE_RESIDUE)},
425	{USB_QUIRK_ENTRY(USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDCZ4_128,
426	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
427	    UQ_MSC_IGNORE_RESIDUE)},
428	{USB_QUIRK_ENTRY(USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDCZ4_256,
429	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
430	    UQ_MSC_IGNORE_RESIDUE)},
431	{USB_QUIRK_ENTRY(USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDDR31,
432	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
433	    UQ_MSC_READ_CAP_OFFBY1)},
434	{USB_QUIRK_ENTRY(USB_VENDOR_SCANLOGIC, USB_PRODUCT_SCANLOGIC_SL11R,
435	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_ATAPI,
436	    UQ_MSC_NO_INQUIRY)},
437	{USB_QUIRK_ENTRY(USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSB,
438	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI_I, UQ_MSC_FORCE_PROTO_ATAPI,
439	    UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_START_STOP, UQ_MSC_SHUTTLE_INIT)},
440	{USB_QUIRK_ENTRY(USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_CDRW,
441	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_ATAPI)},
442	{USB_QUIRK_ENTRY(USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_CF,
443	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_ATAPI)},
444	{USB_QUIRK_ENTRY(USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSBATAPI,
445	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_ATAPI)},
446	{USB_QUIRK_ENTRY(USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSBCFSM,
447	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI)},
448	{USB_QUIRK_ENTRY(USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSCSI,
449	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
450	{USB_QUIRK_ENTRY(USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_HIFD,
451	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_SCSI,
452	    UQ_MSC_NO_GETMAXLUN)},
453	{USB_QUIRK_ENTRY(USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_SDDR09,
454	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN)},
455	{USB_QUIRK_ENTRY(USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_ZIOMMC,
456	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_SCSI,
457	    UQ_MSC_NO_GETMAXLUN)},
458	{USB_QUIRK_ENTRY(USB_VENDOR_SIGMATEL, USB_PRODUCT_SIGMATEL_I_BEAD100,
459	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
460	    UQ_MSC_SHUTTLE_INIT)},
461	{USB_QUIRK_ENTRY(USB_VENDOR_SIIG, USB_PRODUCT_SIIG_WINTERREADER,
462	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
463	    UQ_MSC_IGNORE_RESIDUE)},
464	{USB_QUIRK_ENTRY(USB_VENDOR_SKANHEX, USB_PRODUCT_SKANHEX_MD_7425,
465	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
466	    UQ_MSC_NO_INQUIRY)},
467	{USB_QUIRK_ENTRY(USB_VENDOR_SKANHEX, USB_PRODUCT_SKANHEX_SX_520Z,
468	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
469	    UQ_MSC_NO_INQUIRY)},
470	{USB_QUIRK_ENTRY(USB_VENDOR_SONY, USB_PRODUCT_SONY_HANDYCAM,
471	    0x0500, 0x0500, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_RBC,
472	    UQ_MSC_RBC_PAD_TO_12)},
473	{USB_QUIRK_ENTRY(USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_40_MS,
474	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
475	    UQ_MSC_NO_INQUIRY)},
476	{USB_QUIRK_ENTRY(USB_VENDOR_SONY, USB_PRODUCT_SONY_DSC,
477	    0x0500, 0x0500, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_RBC,
478	    UQ_MSC_RBC_PAD_TO_12)},
479	{USB_QUIRK_ENTRY(USB_VENDOR_SONY, USB_PRODUCT_SONY_DSC,
480	    0x0600, 0x0600, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_RBC,
481	    UQ_MSC_RBC_PAD_TO_12)},
482	{USB_QUIRK_ENTRY(USB_VENDOR_SONY, USB_PRODUCT_SONY_DSC,
483	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_RBC)},
484	{USB_QUIRK_ENTRY(USB_VENDOR_SONY, USB_PRODUCT_SONY_HANDYCAM,
485	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_RBC)},
486	{USB_QUIRK_ENTRY(USB_VENDOR_SONY, USB_PRODUCT_SONY_MSC,
487	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_RBC)},
488	{USB_QUIRK_ENTRY(USB_VENDOR_SONY, USB_PRODUCT_SONY_MS_MSC_U03,
489	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_UFI,
490	    UQ_MSC_NO_GETMAXLUN)},
491	{USB_QUIRK_ENTRY(USB_VENDOR_SONY, USB_PRODUCT_SONY_MS_NW_MS7,
492	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
493	    UQ_MSC_NO_GETMAXLUN)},
494	{USB_QUIRK_ENTRY(USB_VENDOR_SONY, USB_PRODUCT_SONY_MS_PEG_N760C,
495	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
496	    UQ_MSC_NO_INQUIRY)},
497	{USB_QUIRK_ENTRY(USB_VENDOR_SONY, USB_PRODUCT_SONY_MSACUS1,
498	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
499	    UQ_MSC_NO_GETMAXLUN)},
500	{USB_QUIRK_ENTRY(USB_VENDOR_SONY, USB_PRODUCT_SONY_PORTABLE_HDD_V2,
501	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
502	{USB_QUIRK_ENTRY(USB_VENDOR_SUPERTOP, USB_PRODUCT_SUPERTOP_IDE,
503	    0x0000, 0xFFFF, UQ_MSC_IGNORE_RESIDUE, UQ_MSC_NO_SYNC_CACHE)},
504	{USB_QUIRK_ENTRY(USB_VENDOR_TAUGA, USB_PRODUCT_TAUGA_CAMERAMATE,
505	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI)},
506	{USB_QUIRK_ENTRY(USB_VENDOR_TEAC, USB_PRODUCT_TEAC_FD05PUB,
507	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_UFI)},
508	{USB_QUIRK_ENTRY(USB_VENDOR_TECLAST, USB_PRODUCT_TECLAST_TLC300,
509	    0x0000, 0xFFFF, UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_SYNC_CACHE)},
510	{USB_QUIRK_ENTRY(USB_VENDOR_TREK, USB_PRODUCT_TREK_MEMKEY,
511	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
512	    UQ_MSC_NO_INQUIRY)},
513	{USB_QUIRK_ENTRY(USB_VENDOR_TREK, USB_PRODUCT_TREK_THUMBDRIVE_8MB,
514	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_ATAPI,
515	    UQ_MSC_IGNORE_RESIDUE)},
516	{USB_QUIRK_ENTRY(USB_VENDOR_TRUMPION, USB_PRODUCT_TRUMPION_C3310,
517	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_UFI)},
518	{USB_QUIRK_ENTRY(USB_VENDOR_TRUMPION, USB_PRODUCT_TRUMPION_MP3,
519	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_RBC)},
520	{USB_QUIRK_ENTRY(USB_VENDOR_TRUMPION, USB_PRODUCT_TRUMPION_T33520,
521	    0x0000, 0xFFFF, UQ_MSC_FORCE_PROTO_SCSI)},
522	{USB_QUIRK_ENTRY(USB_VENDOR_TWINMOS, USB_PRODUCT_TWINMOS_MDIV,
523	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI)},
524	{USB_QUIRK_ENTRY(USB_VENDOR_VIA, USB_PRODUCT_VIA_USB2IDEBRIDGE,
525	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
526	    UQ_MSC_NO_SYNC_CACHE)},
527	{USB_QUIRK_ENTRY(USB_VENDOR_VIVITAR, USB_PRODUCT_VIVITAR_35XX,
528	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
529	    UQ_MSC_NO_INQUIRY)},
530	{USB_QUIRK_ENTRY(USB_VENDOR_WESTERN, USB_PRODUCT_WESTERN_COMBO,
531	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
532	    UQ_MSC_FORCE_SHORT_INQ, UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE)},
533	{USB_QUIRK_ENTRY(USB_VENDOR_WESTERN, USB_PRODUCT_WESTERN_EXTHDD,
534	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
535	    UQ_MSC_FORCE_SHORT_INQ, UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE)},
536	{USB_QUIRK_ENTRY(USB_VENDOR_WESTERN, USB_PRODUCT_WESTERN_MYBOOK,
537	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
538	    UQ_MSC_NO_INQUIRY_EVPD)},
539	{USB_QUIRK_ENTRY(USB_VENDOR_WESTERN, USB_PRODUCT_WESTERN_MYPASSWORD,
540	    0x0000, 0xFFFF, UQ_MSC_FORCE_SHORT_INQ)},
541	{USB_QUIRK_ENTRY(USB_VENDOR_WINMAXGROUP, USB_PRODUCT_WINMAXGROUP_FLASH64MC,
542	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
543	    UQ_MSC_NO_INQUIRY)},
544	{USB_QUIRK_ENTRY(USB_VENDOR_YANO, USB_PRODUCT_YANO_FW800HD,
545	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
546	    UQ_MSC_FORCE_SHORT_INQ, UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE)},
547	{USB_QUIRK_ENTRY(USB_VENDOR_YANO, USB_PRODUCT_YANO_U640MO,
548	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI_I, UQ_MSC_FORCE_PROTO_ATAPI,
549	    UQ_MSC_FORCE_SHORT_INQ)},
550	{USB_QUIRK_ENTRY(USB_VENDOR_YEDATA, USB_PRODUCT_YEDATA_FLASHBUSTERU,
551	    0x0000, 0x007F, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_UFI,
552	    UQ_MSC_NO_RS_CLEAR_UA, UQ_MSC_FLOPPY_SPEED,
553	    UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_GETMAXLUN)},
554	{USB_QUIRK_ENTRY(USB_VENDOR_YEDATA, USB_PRODUCT_YEDATA_FLASHBUSTERU,
555	    0x0080, 0x0080, UQ_MSC_FORCE_WIRE_CBI_I, UQ_MSC_FORCE_PROTO_UFI,
556	    UQ_MSC_NO_RS_CLEAR_UA, UQ_MSC_FLOPPY_SPEED,
557	    UQ_MSC_NO_TEST_UNIT_READY, UQ_MSC_NO_GETMAXLUN)},
558	{USB_QUIRK_ENTRY(USB_VENDOR_YEDATA, USB_PRODUCT_YEDATA_FLASHBUSTERU,
559	    0x0081, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI_I, UQ_MSC_FORCE_PROTO_UFI,
560	    UQ_MSC_NO_RS_CLEAR_UA, UQ_MSC_FLOPPY_SPEED, UQ_MSC_NO_GETMAXLUN)},
561	{USB_QUIRK_ENTRY(USB_VENDOR_ZORAN, USB_PRODUCT_ZORAN_EX20DSC,
562	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_CBI, UQ_MSC_FORCE_PROTO_ATAPI)},
563	{USB_QUIRK_ENTRY(USB_VENDOR_MEIZU, USB_PRODUCT_MEIZU_M6_SL,
564	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
565	    UQ_MSC_NO_INQUIRY, UQ_MSC_NO_SYNC_CACHE)},
566	{USB_QUIRK_ENTRY(USB_VENDOR_ACTIONS, USB_PRODUCT_ACTIONS_MP4,
567	    0x0000, 0xFFFF, UQ_MSC_FORCE_WIRE_BBB, UQ_MSC_FORCE_PROTO_SCSI,
568	    UQ_MSC_NO_SYNC_CACHE)},
569	{USB_QUIRK_ENTRY(USB_VENDOR_ASUS, USB_PRODUCT_ASUS_GMSC,
570	    0x0000, 0xFFFF, UQ_MSC_NO_SYNC_CACHE)},
571};
572
573static const char *usb_quirk_str[USB_QUIRK_MAX] = {
574	[UQ_NONE]		= "UQ_NONE",
575	[UQ_MATCH_VENDOR_ONLY]	= "UQ_MATCH_VENDOR_ONLY",
576	[UQ_AUDIO_SWAP_LR]	= "UQ_AUDIO_SWAP_LR",
577	[UQ_AU_INP_ASYNC]	= "UQ_AU_INP_ASYNC",
578	[UQ_AU_NO_FRAC]		= "UQ_AU_NO_FRAC",
579	[UQ_AU_NO_XU]		= "UQ_AU_NO_XU",
580	[UQ_BAD_ADC]		= "UQ_BAD_ADC",
581	[UQ_BAD_AUDIO]		= "UQ_BAD_AUDIO",
582	[UQ_BROKEN_BIDIR]	= "UQ_BROKEN_BIDIR",
583	[UQ_BUS_POWERED]	= "UQ_BUS_POWERED",
584	[UQ_HID_IGNORE]		= "UQ_HID_IGNORE",
585	[UQ_KBD_IGNORE]		= "UQ_KBD_IGNORE",
586	[UQ_MS_BAD_CLASS]	= "UQ_MS_BAD_CLASS",
587	[UQ_MS_LEADING_BYTE]	= "UQ_MS_LEADING_BYTE",
588	[UQ_MS_REVZ]		= "UQ_MS_REVZ",
589	[UQ_NO_STRINGS]		= "UQ_NO_STRINGS",
590	[UQ_OPEN_CLEARSTALL]	= "UQ_OPEN_CLEARSTALL",
591	[UQ_POWER_CLAIM]	= "UQ_POWER_CLAIM",
592	[UQ_SPUR_BUT_UP]	= "UQ_SPUR_BUT_UP",
593	[UQ_SWAP_UNICODE]	= "UQ_SWAP_UNICODE",
594	[UQ_CFG_INDEX_1]	= "UQ_CFG_INDEX_1",
595	[UQ_CFG_INDEX_2]	= "UQ_CFG_INDEX_2",
596	[UQ_CFG_INDEX_3]	= "UQ_CFG_INDEX_3",
597	[UQ_CFG_INDEX_4]	= "UQ_CFG_INDEX_4",
598	[UQ_CFG_INDEX_0]	= "UQ_CFG_INDEX_0",
599	[UQ_ASSUME_CM_OVER_DATA]	= "UQ_ASSUME_CM_OVER_DATA",
600	[UQ_MSC_NO_TEST_UNIT_READY]	= "UQ_MSC_NO_TEST_UNIT_READY",
601	[UQ_MSC_NO_RS_CLEAR_UA]		= "UQ_MSC_NO_RS_CLEAR_UA",
602	[UQ_MSC_NO_START_STOP]		= "UQ_MSC_NO_START_STOP",
603	[UQ_MSC_NO_GETMAXLUN]		= "UQ_MSC_NO_GETMAXLUN",
604	[UQ_MSC_NO_INQUIRY]		= "UQ_MSC_NO_INQUIRY",
605	[UQ_MSC_NO_INQUIRY_EVPD]	= "UQ_MSC_NO_INQUIRY_EVPD",
606	[UQ_MSC_NO_SYNC_CACHE]		= "UQ_MSC_NO_SYNC_CACHE",
607	[UQ_MSC_SHUTTLE_INIT]		= "UQ_MSC_SHUTTLE_INIT",
608	[UQ_MSC_ALT_IFACE_1]		= "UQ_MSC_ALT_IFACE_1",
609	[UQ_MSC_FLOPPY_SPEED]		= "UQ_MSC_FLOPPY_SPEED",
610	[UQ_MSC_IGNORE_RESIDUE]		= "UQ_MSC_IGNORE_RESIDUE",
611	[UQ_MSC_WRONG_CSWSIG]		= "UQ_MSC_WRONG_CSWSIG",
612	[UQ_MSC_RBC_PAD_TO_12]		= "UQ_MSC_RBC_PAD_TO_12",
613	[UQ_MSC_READ_CAP_OFFBY1]	= "UQ_MSC_READ_CAP_OFFBY1",
614	[UQ_MSC_FORCE_SHORT_INQ]	= "UQ_MSC_FORCE_SHORT_INQ",
615	[UQ_MSC_FORCE_WIRE_BBB]		= "UQ_MSC_FORCE_WIRE_BBB",
616	[UQ_MSC_FORCE_WIRE_CBI]		= "UQ_MSC_FORCE_WIRE_CBI",
617	[UQ_MSC_FORCE_WIRE_CBI_I]	= "UQ_MSC_FORCE_WIRE_CBI_I",
618	[UQ_MSC_FORCE_PROTO_SCSI]	= "UQ_MSC_FORCE_PROTO_SCSI",
619	[UQ_MSC_FORCE_PROTO_ATAPI]	= "UQ_MSC_FORCE_PROTO_ATAPI",
620	[UQ_MSC_FORCE_PROTO_UFI]	= "UQ_MSC_FORCE_PROTO_UFI",
621	[UQ_MSC_FORCE_PROTO_RBC]	= "UQ_MSC_FORCE_PROTO_RBC",
622};
623
624/*------------------------------------------------------------------------*
625 *	usb_quirkstr
626 *
627 * This function converts an USB quirk code into a string.
628 *------------------------------------------------------------------------*/
629static const char *
630usb_quirkstr(uint16_t quirk)
631{
632	return ((quirk < USB_QUIRK_MAX) ?
633	    usb_quirk_str[quirk] : "USB_QUIRK_UNKNOWN");
634}
635
636/*------------------------------------------------------------------------*
637 *	usb_test_quirk_by_info
638 *
639 * Returns:
640 * 0: Quirk not found
641 * Else: Quirk found
642 *------------------------------------------------------------------------*/
643static uint8_t
644usb_test_quirk_by_info(const struct usbd_lookup_info *info, uint16_t quirk)
645{
646	uint16_t x;
647	uint16_t y;
648
649	if (quirk == UQ_NONE) {
650		return (0);
651	}
652	mtx_lock(&usb_quirk_mtx);
653
654	for (x = 0; x != USB_DEV_QUIRKS_MAX; x++) {
655		/* see if quirk information does not match */
656		if ((usb_quirks[x].vid != info->idVendor) ||
657		    (usb_quirks[x].lo_rev > info->bcdDevice) ||
658		    (usb_quirks[x].hi_rev < info->bcdDevice)) {
659			continue;
660		}
661		/* see if quirk only should match vendor ID */
662		if (usb_quirks[x].pid != info->idProduct) {
663			if (usb_quirks[x].pid != 0)
664				continue;
665
666			for (y = 0; y != USB_SUB_QUIRKS_MAX; y++) {
667				if (usb_quirks[x].quirks[y] == UQ_MATCH_VENDOR_ONLY)
668					break;
669			}
670			if (y == USB_SUB_QUIRKS_MAX)
671				continue;
672		}
673		/* lookup quirk */
674		for (y = 0; y != USB_SUB_QUIRKS_MAX; y++) {
675			if (usb_quirks[x].quirks[y] == quirk) {
676				mtx_unlock(&usb_quirk_mtx);
677				DPRINTF("Found quirk '%s'.\n", usb_quirkstr(quirk));
678				return (1);
679			}
680		}
681		/* no quirk found */
682		break;
683	}
684	mtx_unlock(&usb_quirk_mtx);
685	return (0);
686}
687
688static struct usb_quirk_entry *
689usb_quirk_get_entry(uint16_t vid, uint16_t pid,
690    uint16_t lo_rev, uint16_t hi_rev, uint8_t do_alloc)
691{
692	uint16_t x;
693
694	mtx_assert(&usb_quirk_mtx, MA_OWNED);
695
696	if ((vid | pid | lo_rev | hi_rev) == 0) {
697		/* all zero - special case */
698		return (usb_quirks + USB_DEV_QUIRKS_MAX - 1);
699	}
700	/* search for an existing entry */
701	for (x = 0; x != USB_DEV_QUIRKS_MAX; x++) {
702		/* see if quirk information does not match */
703		if ((usb_quirks[x].vid != vid) ||
704		    (usb_quirks[x].pid != pid) ||
705		    (usb_quirks[x].lo_rev != lo_rev) ||
706		    (usb_quirks[x].hi_rev != hi_rev)) {
707			continue;
708		}
709		return (usb_quirks + x);
710	}
711
712	if (do_alloc == 0) {
713		/* no match */
714		return (NULL);
715	}
716	/* search for a free entry */
717	for (x = 0; x != USB_DEV_QUIRKS_MAX; x++) {
718		/* see if quirk information does not match */
719		if ((usb_quirks[x].vid |
720		    usb_quirks[x].pid |
721		    usb_quirks[x].lo_rev |
722		    usb_quirks[x].hi_rev) != 0) {
723			continue;
724		}
725		usb_quirks[x].vid = vid;
726		usb_quirks[x].pid = pid;
727		usb_quirks[x].lo_rev = lo_rev;
728		usb_quirks[x].hi_rev = hi_rev;
729
730		return (usb_quirks + x);
731	}
732
733	/* no entry found */
734	return (NULL);
735}
736
737/*------------------------------------------------------------------------*
738 *	usb_quirk_ioctl - handle quirk IOCTLs
739 *
740 * Returns:
741 * 0: Success
742 * Else: Failure
743 *------------------------------------------------------------------------*/
744static int
745usb_quirk_ioctl(unsigned long cmd, caddr_t data,
746    int fflag, struct thread *td)
747{
748	struct usb_gen_quirk *pgq;
749	struct usb_quirk_entry *pqe;
750	uint32_t x;
751	uint32_t y;
752	int err;
753
754	switch (cmd) {
755	case USB_DEV_QUIRK_GET:
756		pgq = (void *)data;
757		x = pgq->index % USB_SUB_QUIRKS_MAX;
758		y = pgq->index / USB_SUB_QUIRKS_MAX;
759		if (y >= USB_DEV_QUIRKS_MAX) {
760			return (EINVAL);
761		}
762		mtx_lock(&usb_quirk_mtx);
763		/* copy out data */
764		pgq->vid = usb_quirks[y].vid;
765		pgq->pid = usb_quirks[y].pid;
766		pgq->bcdDeviceLow = usb_quirks[y].lo_rev;
767		pgq->bcdDeviceHigh = usb_quirks[y].hi_rev;
768		strlcpy(pgq->quirkname,
769		    usb_quirkstr(usb_quirks[y].quirks[x]),
770		    sizeof(pgq->quirkname));
771		mtx_unlock(&usb_quirk_mtx);
772		return (0);		/* success */
773
774	case USB_QUIRK_NAME_GET:
775		pgq = (void *)data;
776		x = pgq->index;
777		if (x >= USB_QUIRK_MAX) {
778			return (EINVAL);
779		}
780		strlcpy(pgq->quirkname,
781		    usb_quirkstr(x), sizeof(pgq->quirkname));
782		return (0);		/* success */
783
784	case USB_DEV_QUIRK_ADD:
785		pgq = (void *)data;
786
787		/* check privileges */
788		err = priv_check(curthread, PRIV_DRIVER);
789		if (err) {
790			return (err);
791		}
792		/* convert quirk string into numerical */
793		for (y = 0; y != USB_DEV_QUIRKS_MAX; y++) {
794			if (strcmp(pgq->quirkname, usb_quirkstr(y)) == 0) {
795				break;
796			}
797		}
798		if (y == USB_DEV_QUIRKS_MAX) {
799			return (EINVAL);
800		}
801		if (y == UQ_NONE) {
802			return (EINVAL);
803		}
804		mtx_lock(&usb_quirk_mtx);
805		pqe = usb_quirk_get_entry(pgq->vid, pgq->pid,
806		    pgq->bcdDeviceLow, pgq->bcdDeviceHigh, 1);
807		for (x = 0; x != USB_SUB_QUIRKS_MAX; x++) {
808			if (pqe->quirks[x] == UQ_NONE) {
809				pqe->quirks[x] = y;
810				break;
811			}
812		}
813		mtx_unlock(&usb_quirk_mtx);
814		if (x == USB_SUB_QUIRKS_MAX) {
815			return (ENOMEM);
816		}
817		return (0);		/* success */
818
819	case USB_DEV_QUIRK_REMOVE:
820		pgq = (void *)data;
821		/* check privileges */
822		err = priv_check(curthread, PRIV_DRIVER);
823		if (err) {
824			return (err);
825		}
826		/* convert quirk string into numerical */
827		for (y = 0; y != USB_DEV_QUIRKS_MAX; y++) {
828			if (strcmp(pgq->quirkname, usb_quirkstr(y)) == 0) {
829				break;
830			}
831		}
832		if (y == USB_DEV_QUIRKS_MAX) {
833			return (EINVAL);
834		}
835		if (y == UQ_NONE) {
836			return (EINVAL);
837		}
838		mtx_lock(&usb_quirk_mtx);
839		pqe = usb_quirk_get_entry(pgq->vid, pgq->pid,
840		    pgq->bcdDeviceLow, pgq->bcdDeviceHigh, 0);
841		for (x = 0; x != USB_SUB_QUIRKS_MAX; x++) {
842			if (pqe->quirks[x] == y) {
843				pqe->quirks[x] = UQ_NONE;
844				break;
845			}
846		}
847		if (x == USB_SUB_QUIRKS_MAX) {
848			mtx_unlock(&usb_quirk_mtx);
849			return (ENOMEM);
850		}
851		for (x = 0; x != USB_SUB_QUIRKS_MAX; x++) {
852			if (pqe->quirks[x] != UQ_NONE) {
853				break;
854			}
855		}
856		if (x == USB_SUB_QUIRKS_MAX) {
857			/* all quirk entries are unused - release */
858			memset(pqe, 0, sizeof(pqe));
859		}
860		mtx_unlock(&usb_quirk_mtx);
861		return (0);		/* success */
862
863	default:
864		break;
865	}
866	return (ENOIOCTL);
867}
868
869static void
870usb_quirk_init(void *arg)
871{
872	/* initialize mutex */
873	mtx_init(&usb_quirk_mtx, "USB quirk", NULL, MTX_DEF);
874
875	/* register our function */
876	usb_test_quirk_p = &usb_test_quirk_by_info;
877	usb_quirk_ioctl_p = &usb_quirk_ioctl;
878}
879
880static void
881usb_quirk_uninit(void *arg)
882{
883	usb_quirk_unload(arg);
884
885	/* destroy mutex */
886	mtx_destroy(&usb_quirk_mtx);
887}
888
889SYSINIT(usb_quirk_init, SI_SUB_LOCK, SI_ORDER_FIRST, usb_quirk_init, NULL);
890SYSUNINIT(usb_quirk_uninit, SI_SUB_LOCK, SI_ORDER_ANY, usb_quirk_uninit, NULL);
891