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 | |