| 1 | /* $NetBSD: usb_quirks.c,v 1.85 2016/10/16 18:47:49 nat Exp $ */ |
| 2 | /* $FreeBSD: src/sys/dev/usb/usb_quirks.c,v 1.30 2003/01/02 04:15:55 imp Exp $ */ |
| 3 | |
| 4 | /* |
| 5 | * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc. |
| 6 | * All rights reserved. |
| 7 | * |
| 8 | * This code is derived from software contributed to The NetBSD Foundation |
| 9 | * by Lennart Augustsson (lennart@augustsson.net) at |
| 10 | * Carlstedt Research & Technology. |
| 11 | * |
| 12 | * Redistribution and use in source and binary forms, with or without |
| 13 | * modification, are permitted provided that the following conditions |
| 14 | * are met: |
| 15 | * 1. Redistributions of source code must retain the above copyright |
| 16 | * notice, this list of conditions and the following disclaimer. |
| 17 | * 2. Redistributions in binary form must reproduce the above copyright |
| 18 | * notice, this list of conditions and the following disclaimer in the |
| 19 | * documentation and/or other materials provided with the distribution. |
| 20 | * |
| 21 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
| 22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
| 23 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 24 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
| 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 31 | * POSSIBILITY OF SUCH DAMAGE. |
| 32 | */ |
| 33 | |
| 34 | #include <sys/cdefs.h> |
| 35 | __KERNEL_RCSID(0, "$NetBSD: usb_quirks.c,v 1.85 2016/10/16 18:47:49 nat Exp $" ); |
| 36 | |
| 37 | #ifdef _KERNEL_OPT |
| 38 | #include "opt_usb.h" |
| 39 | #endif |
| 40 | |
| 41 | #include <sys/param.h> |
| 42 | #include <sys/systm.h> |
| 43 | |
| 44 | #include <dev/usb/usb.h> |
| 45 | #include <dev/usb/usbdevs.h> |
| 46 | #include <dev/usb/usb_quirks.h> |
| 47 | |
| 48 | #ifdef USB_DEBUG |
| 49 | extern int usbdebug; |
| 50 | #endif |
| 51 | |
| 52 | #define ANY 0xffff |
| 53 | |
| 54 | Static const struct usbd_quirk_entry { |
| 55 | uint16_t idVendor; |
| 56 | uint16_t idProduct; |
| 57 | uint16_t bcdDevice; |
| 58 | struct usbd_quirks quirks; |
| 59 | } usb_quirks[] = { |
| 60 | /* Devices which should be ignored by uhid */ |
| 61 | { USB_VENDOR_APC, USB_PRODUCT_APC_UPS, ANY, { UQ_HID_IGNORE }}, |
| 62 | { USB_VENDOR_CYBERPOWER, USB_PRODUCT_CYBERPOWER_UPS, ANY, { UQ_HID_IGNORE }}, |
| 63 | { USB_VENDOR_MGE, USB_PRODUCT_MGE_UPS1, ANY, { UQ_HID_IGNORE }}, |
| 64 | { USB_VENDOR_MGE, USB_PRODUCT_MGE_UPS2, ANY, { UQ_HID_IGNORE }}, |
| 65 | { USB_VENDOR_MICROCHIP, USB_PRODUCT_MICROCHIP_PICKIT1, |
| 66 | ANY, { UQ_HID_IGNORE }}, |
| 67 | { USB_VENDOR_TRIPPLITE2, ANY, ANY, { UQ_HID_IGNORE }}, |
| 68 | { USB_VENDOR_MISC, USB_PRODUCT_MISC_WISPY_24X, ANY, { UQ_HID_IGNORE }}, |
| 69 | { USB_VENDOR_WELTREND, USB_PRODUCT_WELTREND_HID, ANY, { UQ_HID_IGNORE }}, |
| 70 | { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_EC3, ANY, { UQ_HID_IGNORE }}, |
| 71 | { USB_VENDOR_TI, USB_PRODUCT_TI_MSP430, ANY, { UQ_HID_IGNORE }}, |
| 72 | |
| 73 | { USB_VENDOR_KYE, USB_PRODUCT_KYE_NICHE, 0x100, { UQ_NO_SET_PROTO}}, |
| 74 | { USB_VENDOR_INSIDEOUT, USB_PRODUCT_INSIDEOUT_EDGEPORT4, |
| 75 | 0x094, { UQ_SWAP_UNICODE}}, |
| 76 | { USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_J6502, 0x0a2, { UQ_BAD_ADC }}, |
| 77 | { USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_J6502, 0x0a2, { UQ_AU_NO_XU }}, |
| 78 | { USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ADA70, 0x103, { UQ_BAD_ADC }}, |
| 79 | { USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ASC495, 0x000, { UQ_BAD_AUDIO }}, |
| 80 | { USB_VENDOR_SONY, USB_PRODUCT_SONY_PS2EYETOY4, 0x000, { UQ_BAD_AUDIO }}, |
| 81 | { USB_VENDOR_SONY, USB_PRODUCT_SONY_PS2EYETOY5, 0x000, { UQ_BAD_AUDIO }}, |
| 82 | { USB_VENDOR_PHILIPS, USB_PRODUCT_PHILIPS_PCVC740K, ANY, { UQ_BAD_AUDIO }}, |
| 83 | { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_QUICKCAMPRONB, |
| 84 | 0x000, { UQ_BAD_AUDIO }}, |
| 85 | { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_QUICKCAMPRO4K, |
| 86 | 0x000, { UQ_BAD_AUDIO }}, |
| 87 | { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_QUICKCAMMESS, |
| 88 | 0x100, { UQ_BAD_ADC }}, |
| 89 | { USB_VENDOR_QTRONIX, USB_PRODUCT_QTRONIX_980N, 0x110, { UQ_SPUR_BUT_UP }}, |
| 90 | { USB_VENDOR_ALCOR2, USB_PRODUCT_ALCOR2_KBD_HUB, 0x001, { UQ_SPUR_BUT_UP }}, |
| 91 | { USB_VENDOR_METRICOM, USB_PRODUCT_METRICOM_RICOCHET_GS, |
| 92 | 0x100, { UQ_ASSUME_CM_OVER_DATA }}, |
| 93 | { USB_VENDOR_SANYO, USB_PRODUCT_SANYO_SCP4900, |
| 94 | 0x000, { UQ_ASSUME_CM_OVER_DATA }}, |
| 95 | { USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_T720C, |
| 96 | 0x001, { UQ_ASSUME_CM_OVER_DATA }}, |
| 97 | { USB_VENDOR_EICON, USB_PRODUCT_EICON_DIVA852, |
| 98 | 0x100, { UQ_ASSUME_CM_OVER_DATA }}, |
| 99 | { USB_VENDOR_SIEMENS2, USB_PRODUCT_SIEMENS2_MC75, |
| 100 | 0x000, { UQ_ASSUME_CM_OVER_DATA }}, |
| 101 | { USB_VENDOR_TELEX, USB_PRODUCT_TELEX_MIC1, 0x009, { UQ_AU_NO_FRAC }}, |
| 102 | { USB_VENDOR_SILICONPORTALS, USB_PRODUCT_SILICONPORTALS_YAPPHONE, |
| 103 | 0x100, { UQ_AU_INP_ASYNC }}, |
| 104 | { USB_VENDOR_AVANCELOGIC, USB_PRODUCT_AVANCELOGIC_USBAUDIO, |
| 105 | 0x101, { UQ_AU_INP_ASYNC }}, |
| 106 | { USB_VENDOR_PLANTRONICS, USB_PRODUCT_PLANTRONICS_HEADSET, |
| 107 | 0x004, { UQ_AU_INP_ASYNC }}, |
| 108 | { USB_VENDOR_CMEDIA, USB_PRODUCT_CMEDIA_USBAUDIO, ANY, { UQ_AU_INP_ASYNC }}, |
| 109 | /* XXX These should have a revision number, but I don't know what they are. */ |
| 110 | { USB_VENDOR_HP, USB_PRODUCT_HP_895C, ANY, { UQ_BROKEN_BIDIR }}, |
| 111 | { USB_VENDOR_HP, USB_PRODUCT_HP_880C, ANY, { UQ_BROKEN_BIDIR }}, |
| 112 | { USB_VENDOR_HP, USB_PRODUCT_HP_815C, ANY, { UQ_BROKEN_BIDIR }}, |
| 113 | { USB_VENDOR_HP, USB_PRODUCT_HP_810C, ANY, { UQ_BROKEN_BIDIR }}, |
| 114 | { USB_VENDOR_HP, USB_PRODUCT_HP_830C, ANY, { UQ_BROKEN_BIDIR }}, |
| 115 | { USB_VENDOR_HP, USB_PRODUCT_HP_885C, ANY, { UQ_BROKEN_BIDIR }}, |
| 116 | { USB_VENDOR_HP, USB_PRODUCT_HP_840C, ANY, { UQ_BROKEN_BIDIR }}, |
| 117 | { USB_VENDOR_HP, USB_PRODUCT_HP_816C, ANY, { UQ_BROKEN_BIDIR }}, |
| 118 | { USB_VENDOR_HP, USB_PRODUCT_HP_959C, ANY, { UQ_BROKEN_BIDIR }}, |
| 119 | { USB_VENDOR_MTK, USB_PRODUCT_MTK_GPS_RECEIVER, ANY, { UQ_NO_UNION_NRM }}, |
| 120 | { USB_VENDOR_NEC, USB_PRODUCT_NEC_PICTY900, ANY, { UQ_BROKEN_BIDIR }}, |
| 121 | { USB_VENDOR_NEC, USB_PRODUCT_NEC_PICTY760, ANY, { UQ_BROKEN_BIDIR }}, |
| 122 | { USB_VENDOR_NEC, USB_PRODUCT_NEC_PICTY920, ANY, { UQ_BROKEN_BIDIR }}, |
| 123 | { USB_VENDOR_NEC, USB_PRODUCT_NEC_PICTY800, ANY, { UQ_BROKEN_BIDIR }}, |
| 124 | |
| 125 | { USB_VENDOR_HP, USB_PRODUCT_HP_1220C, ANY, { UQ_BROKEN_BIDIR }}, |
| 126 | |
| 127 | /* Apple internal notebook ISO keyboards have swapped keys */ |
| 128 | { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_FOUNTAIN_ISO, |
| 129 | ANY, { UQ_APPLE_ISO }}, |
| 130 | { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_GEYSER_ISO, |
| 131 | ANY, { UQ_APPLE_ISO }}, |
| 132 | |
| 133 | /* HID and audio are both invalid on iPhone/iPod Touch */ |
| 134 | { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE, |
| 135 | ANY, { UQ_HID_IGNORE | UQ_BAD_AUDIO }}, |
| 136 | { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPOD_TOUCH, |
| 137 | ANY, { UQ_HID_IGNORE | UQ_BAD_AUDIO }}, |
| 138 | { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPOD_TOUCH_4G, |
| 139 | ANY, { UQ_HID_IGNORE | UQ_BAD_AUDIO }}, |
| 140 | { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_3G, |
| 141 | ANY, { UQ_HID_IGNORE | UQ_BAD_AUDIO }}, |
| 142 | { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_3GS, |
| 143 | ANY, { UQ_HID_IGNORE | UQ_BAD_AUDIO }}, |
| 144 | |
| 145 | { USB_VENDOR_QUALCOMM, USB_PRODUCT_QUALCOMM_CDMA_MSM, |
| 146 | ANY, { UQ_ASSUME_CM_OVER_DATA }}, |
| 147 | { USB_VENDOR_QUALCOMM2, USB_PRODUCT_QUALCOMM2_CDMA_MSM, |
| 148 | ANY, { UQ_ASSUME_CM_OVER_DATA }}, |
| 149 | { USB_VENDOR_HYUNDAI, USB_PRODUCT_HYUNDAI_UM175, |
| 150 | ANY, { UQ_ASSUME_CM_OVER_DATA }}, |
| 151 | { USB_VENDOR_ZOOM, USB_PRODUCT_ZOOM_3095, |
| 152 | ANY, { UQ_LOST_CS_DESC }}, |
| 153 | { 0, 0, 0, { 0 } } |
| 154 | }; |
| 155 | |
| 156 | const struct usbd_quirks usbd_no_quirk = { 0 }; |
| 157 | |
| 158 | const struct usbd_quirks * |
| 159 | usbd_find_quirk(usb_device_descriptor_t *d) |
| 160 | { |
| 161 | const struct usbd_quirk_entry *t; |
| 162 | uint16_t vendor = UGETW(d->idVendor); |
| 163 | uint16_t product = UGETW(d->idProduct); |
| 164 | uint16_t revision = UGETW(d->bcdDevice); |
| 165 | |
| 166 | for (t = usb_quirks; t->idVendor != 0; t++) { |
| 167 | if (t->idVendor == vendor && |
| 168 | (t->idProduct == ANY || t->idProduct == product) && |
| 169 | (t->bcdDevice == ANY || t->bcdDevice == revision)) |
| 170 | break; |
| 171 | } |
| 172 | #ifdef USB_DEBUG |
| 173 | if (usbdebug && t->quirks.uq_flags) |
| 174 | printf("usbd_find_quirk 0x%04x/0x%04x/%x: %d\n" , |
| 175 | UGETW(d->idVendor), UGETW(d->idProduct), |
| 176 | UGETW(d->bcdDevice), t->quirks.uq_flags); |
| 177 | #endif |
| 178 | return &t->quirks; |
| 179 | } |
| 180 | |