File: | dev/usb/umsm.c |
Warning: | line 761, column 8 2nd function call argument is an uninitialized value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: umsm.c,v 1.120 2022/01/09 05:43:01 jsg Exp $ */ | |||
2 | ||||
3 | /* | |||
4 | * Copyright (c) 2008 Yojiro UO <yuo@nui.org> | |||
5 | * Copyright (c) 2006 Jonathan Gray <jsg@openbsd.org> | |||
6 | * | |||
7 | * Permission to use, copy, modify, and distribute this software for any | |||
8 | * purpose with or without fee is hereby granted, provided that the above | |||
9 | * copyright notice and this permission notice appear in all copies. | |||
10 | * | |||
11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |||
12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |||
13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |||
14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |||
15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |||
16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |||
17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||
18 | */ | |||
19 | ||||
20 | /* Driver for Qualcomm MSM EVDO and UMTS communication devices */ | |||
21 | ||||
22 | #include <sys/param.h> | |||
23 | #include <sys/systm.h> | |||
24 | #include <sys/kernel.h> | |||
25 | #include <sys/malloc.h> | |||
26 | #include <sys/device.h> | |||
27 | #include <sys/conf.h> | |||
28 | #include <sys/tty.h> | |||
29 | ||||
30 | #include <dev/usb/usb.h> | |||
31 | #include <dev/usb/usbdi.h> | |||
32 | #include <dev/usb/usbdevs.h> | |||
33 | #include <dev/usb/ucomvar.h> | |||
34 | #include <dev/usb/usbcdc.h> | |||
35 | #include <dev/usb/umassvar.h> | |||
36 | #undef DPRINTF /* undef DPRINTF for umass */ | |||
37 | ||||
38 | #ifdef UMSM_DEBUG | |||
39 | int umsmdebug = 0; | |||
40 | #define DPRINTFN(n, x) do { if (umsmdebug > (n)) printf x; } while (0) | |||
41 | #else | |||
42 | #define DPRINTFN(n, x) | |||
43 | #endif | |||
44 | ||||
45 | #define DPRINTF(x) DPRINTFN(0, x) | |||
46 | ||||
47 | #define UMSMBUFSZ4096 4096 | |||
48 | #define UMSM_INTR_INTERVAL100 100 /* ms */ | |||
49 | #define E220_MODE_CHANGE_REQUEST0x2 0x2 | |||
50 | #define TRUINSTALL_CHANGEMODE_REQUEST0x0b 0x0b | |||
51 | ||||
52 | int umsm_match(struct device *, void *, void *); | |||
53 | void umsm_attach(struct device *, struct device *, void *); | |||
54 | int umsm_detach(struct device *, int); | |||
55 | ||||
56 | int umsm_open(void *, int); | |||
57 | void umsm_close(void *, int); | |||
58 | void umsm_intr(struct usbd_xfer *, void *, usbd_status); | |||
59 | void umsm_get_status(void *, int, u_char *, u_char *); | |||
60 | void umsm_set(void *, int, int, int); | |||
61 | ||||
62 | struct umsm_softc { | |||
63 | struct device sc_dev; | |||
64 | struct usbd_device *sc_udev; | |||
65 | struct usbd_interface *sc_iface; | |||
66 | int sc_iface_no; | |||
67 | struct device *sc_subdev; | |||
68 | uint16_t sc_flag; | |||
69 | ||||
70 | /* interrupt ep */ | |||
71 | int sc_intr_number; | |||
72 | struct usbd_pipe *sc_intr_pipe; | |||
73 | u_char *sc_intr_buf; | |||
74 | int sc_isize; | |||
75 | ||||
76 | u_char sc_lsr; /* Local status register */ | |||
77 | u_char sc_msr; /* status register */ | |||
78 | u_char sc_dtr; /* current DTR state */ | |||
79 | u_char sc_rts; /* current RTS state */ | |||
80 | }; | |||
81 | ||||
82 | usbd_status umsm_huawei_changemode(struct usbd_device *); | |||
83 | usbd_status umsm_truinstall_changemode(struct usbd_device *); | |||
84 | usbd_status umsm_umass_changemode(struct umsm_softc *); | |||
85 | ||||
86 | struct ucom_methods umsm_methods = { | |||
87 | umsm_get_status, | |||
88 | umsm_set, | |||
89 | NULL((void *)0), | |||
90 | NULL((void *)0), | |||
91 | umsm_open, | |||
92 | umsm_close, | |||
93 | NULL((void *)0), | |||
94 | NULL((void *)0), | |||
95 | }; | |||
96 | ||||
97 | struct umsm_type { | |||
98 | struct usb_devno umsm_dev; | |||
99 | uint16_t umsm_flag; | |||
100 | /* device type */ | |||
101 | #define DEV_NORMAL0x0000 0x0000 | |||
102 | #define DEV_HUAWEI0x0001 0x0001 | |||
103 | #define DEV_TRUINSTALL0x0002 0x0002 | |||
104 | #define DEV_UMASS10x0010 0x0010 | |||
105 | #define DEV_UMASS20x0020 0x0020 | |||
106 | #define DEV_UMASS30x0040 0x0040 | |||
107 | #define DEV_UMASS40x0080 0x0080 | |||
108 | #define DEV_UMASS50x0100 0x0100 | |||
109 | #define DEV_UMASS60x0200 0x0200 | |||
110 | #define DEV_UMASS70x0400 0x0400 | |||
111 | #define DEV_UMASS80x1000 0x1000 | |||
112 | #define DEV_UMASS(0x0010 | 0x0020 | 0x0040 | 0x0080 | 0x0100 | 0x0200 | 0x0400 | 0x1000) (DEV_UMASS10x0010 | DEV_UMASS20x0020 | DEV_UMASS30x0040 | DEV_UMASS40x0080 | \ | |||
113 | DEV_UMASS50x0100 | DEV_UMASS60x0200 | DEV_UMASS70x0400 | DEV_UMASS80x1000) | |||
114 | }; | |||
115 | ||||
116 | static const struct umsm_type umsm_devs[] = { | |||
117 | {{ USB_VENDOR_AIRPRIME0x0f3d, USB_PRODUCT_AIRPRIME_PC52200x0112 }, 0}, | |||
118 | {{ USB_VENDOR_AIRPRIME0x0f3d, USB_PRODUCT_AIRPRIME_AIRCARD_313U0x68aa }, 0}, | |||
119 | ||||
120 | {{ USB_VENDOR_ANYDATA0x16d5, USB_PRODUCT_ANYDATA_A25020x6202 }, 0}, | |||
121 | {{ USB_VENDOR_ANYDATA0x16d5, USB_PRODUCT_ANYDATA_ADU_500A0x6502 }, 0}, | |||
122 | {{ USB_VENDOR_ANYDATA0x16d5, USB_PRODUCT_ANYDATA_ADU_E100H0x6501 }, 0}, | |||
123 | ||||
124 | {{ USB_VENDOR_DELL0x413c, USB_PRODUCT_DELL_EU870D0x8138 }, 0}, | |||
125 | {{ USB_VENDOR_DELL0x413c, USB_PRODUCT_DELL_U7400x8135 }, 0}, | |||
126 | {{ USB_VENDOR_DELL0x413c, USB_PRODUCT_DELL_W55000x8115 }, 0}, | |||
127 | ||||
128 | {{ USB_VENDOR_HUAWEI0x12d1, USB_PRODUCT_HUAWEI_E1610x1446 }, DEV_UMASS50x0100}, | |||
129 | {{ USB_VENDOR_HUAWEI0x12d1, USB_PRODUCT_HUAWEI_E173S_INIT0x1c0b }, DEV_UMASS50x0100}, | |||
130 | {{ USB_VENDOR_HUAWEI0x12d1, USB_PRODUCT_HUAWEI_E173S0x1c05 }, 0}, | |||
131 | {{ USB_VENDOR_HUAWEI0x12d1, USB_PRODUCT_HUAWEI_E1800x140c }, DEV_HUAWEI0x0001}, | |||
132 | {{ USB_VENDOR_HUAWEI0x12d1, USB_PRODUCT_HUAWEI_E1810x1414 }, DEV_HUAWEI0x0001}, | |||
133 | {{ USB_VENDOR_HUAWEI0x12d1, USB_PRODUCT_HUAWEI_E1820x1429 }, DEV_UMASS50x0100}, | |||
134 | {{ USB_VENDOR_HUAWEI0x12d1, USB_PRODUCT_HUAWEI_E18200x14ac }, DEV_UMASS50x0100}, | |||
135 | {{ USB_VENDOR_HUAWEI0x12d1, USB_PRODUCT_HUAWEI_E2200x1003 }, DEV_HUAWEI0x0001}, | |||
136 | {{ USB_VENDOR_HUAWEI0x12d1, USB_PRODUCT_HUAWEI_E3030x1f01 }, DEV_UMASS50x0100}, | |||
137 | {{ USB_VENDOR_HUAWEI0x12d1, USB_PRODUCT_HUAWEI_E353_INIT0x14fe }, DEV_UMASS50x0100}, | |||
138 | {{ USB_VENDOR_HUAWEI0x12d1, USB_PRODUCT_HUAWEI_E5100x1411 }, DEV_HUAWEI0x0001}, | |||
139 | {{ USB_VENDOR_HUAWEI0x12d1, USB_PRODUCT_HUAWEI_E6180x1001 }, DEV_HUAWEI0x0001}, | |||
140 | {{ USB_VENDOR_HUAWEI0x12d1, USB_PRODUCT_HUAWEI_E392_INIT0x1505 }, DEV_UMASS50x0100}, | |||
141 | {{ USB_VENDOR_HUAWEI0x12d1, USB_PRODUCT_HUAWEI_EM770W0x1404 }, 0}, | |||
142 | {{ USB_VENDOR_HUAWEI0x12d1, USB_PRODUCT_HUAWEI_MOBILE0x1008 }, DEV_HUAWEI0x0001}, | |||
143 | {{ USB_VENDOR_HUAWEI0x12d1, USB_PRODUCT_HUAWEI_K3765_INIT0x1520 }, DEV_UMASS50x0100}, | |||
144 | {{ USB_VENDOR_HUAWEI0x12d1, USB_PRODUCT_HUAWEI_K37650x1465 }, 0}, | |||
145 | {{ USB_VENDOR_HUAWEI0x12d1, USB_PRODUCT_HUAWEI_K3772_INIT0x1526 }, DEV_UMASS50x0100}, | |||
146 | {{ USB_VENDOR_HUAWEI0x12d1, USB_PRODUCT_HUAWEI_K37720x14cf }, 0}, | |||
147 | {{ USB_VENDOR_HUAWEI0x12d1, USB_PRODUCT_HUAWEI_MU6090x1573 }, DEV_TRUINSTALL0x0002}, | |||
148 | {{ USB_VENDOR_HUAWEI0x12d1, USB_PRODUCT_HUAWEI_K45100x14c5 }, DEV_UMASS50x0100}, | |||
149 | {{ USB_VENDOR_HUAWEI0x12d1, USB_PRODUCT_HUAWEI_K45110x14b7 }, DEV_UMASS50x0100}, | |||
150 | {{ USB_VENDOR_HUAWEI0x12d1, USB_PRODUCT_HUAWEI_E17500x1406 }, DEV_UMASS50x0100}, | |||
151 | {{ USB_VENDOR_HUAWEI0x12d1, USB_PRODUCT_HUAWEI_E17520x1417 }, 0}, | |||
152 | {{ USB_VENDOR_HUAWEI0x12d1, USB_PRODUCT_HUAWEI_E33720x1442 }, DEV_UMASS50x0100}, | |||
153 | ||||
154 | {{ USB_VENDOR_HYUNDAI0x106c, USB_PRODUCT_HYUNDAI_UM1750x3714 }, 0}, | |||
155 | ||||
156 | {{ USB_VENDOR_LONGCHEER0x1c9e, USB_PRODUCT_LONGCHEER_D21LCMASS0x9401 }, DEV_UMASS30x0040}, | |||
157 | {{ USB_VENDOR_LONGCHEER0x1c9e, USB_PRODUCT_LONGCHEER_D21LC0x9404 }, 0}, | |||
158 | {{ USB_VENDOR_LONGCHEER0x1c9e, USB_PRODUCT_LONGCHEER_510FUMASS0x98ff }, DEV_UMASS30x0040}, | |||
159 | {{ USB_VENDOR_LONGCHEER0x1c9e, USB_PRODUCT_LONGCHEER_510FU0x9801 }, 0}, | |||
160 | ||||
161 | {{ USB_VENDOR_KYOCERA20x0c88, USB_PRODUCT_KYOCERA2_KPC6500x17da }, 0}, | |||
162 | ||||
163 | {{ USB_VENDOR_MEDIATEK0x0e8d, USB_PRODUCT_MEDIATEK_UMASS0x0002 }, DEV_UMASS80x1000}, | |||
164 | {{ USB_VENDOR_MEDIATEK0x0e8d, USB_PRODUCT_MEDIATEK_DC_4COM0x00a5 }, 0}, | |||
165 | ||||
166 | /* XXX Some qualcomm devices are missing */ | |||
167 | {{ USB_VENDOR_QUALCOMM0x05c6, USB_PRODUCT_QUALCOMM_MSM_DRIVER0x1000 }, DEV_UMASS10x0010}, | |||
168 | {{ USB_VENDOR_QUALCOMM0x05c6, USB_PRODUCT_QUALCOMM_MSM_DRIVER20xf000 }, DEV_UMASS40x0080}, | |||
169 | {{ USB_VENDOR_QUALCOMM0x05c6, USB_PRODUCT_QUALCOMM_MSM_HSDPA0x6613 }, 0}, | |||
170 | {{ USB_VENDOR_QUALCOMM0x05c6, USB_PRODUCT_QUALCOMM_MSM_HSDPA20x6000 }, 0}, | |||
171 | {{ USB_VENDOR_QUALCOMM0x05c6, USB_PRODUCT_QUALCOMM_MSM_HSDPA30x9000 }, 0}, | |||
172 | ||||
173 | {{ USB_VENDOR_QUANTA20x0408, USB_PRODUCT_QUANTA2_UMASS0x1000 }, DEV_UMASS40x0080}, | |||
174 | {{ USB_VENDOR_QUANTA20x0408, USB_PRODUCT_QUANTA2_Q1010xea02 }, 0}, | |||
175 | ||||
176 | {{ USB_VENDOR_QUECTEL0x2c7c, USB_PRODUCT_QUECTEL_EC250x0125 }, 0}, | |||
177 | ||||
178 | {{ USB_VENDOR_ZTE0x19d2, USB_PRODUCT_ZTE_AC27460xfff1 }, 0}, | |||
179 | {{ USB_VENDOR_ZTE0x19d2, USB_PRODUCT_ZTE_UMASS_INSTALLER0x2000 }, DEV_UMASS40x0080}, | |||
180 | {{ USB_VENDOR_ZTE0x19d2, USB_PRODUCT_ZTE_UMASS_INSTALLER20x0103 }, DEV_UMASS60x0200}, | |||
181 | {{ USB_VENDOR_ZTE0x19d2, USB_PRODUCT_ZTE_UMASS_INSTALLER30xfff5 }, DEV_UMASS70x0400}, | |||
182 | {{ USB_VENDOR_ZTE0x19d2, USB_PRODUCT_ZTE_UMASS_INSTALLER40x0083 }, DEV_UMASS40x0080}, | |||
183 | {{ USB_VENDOR_ZTE0x19d2, USB_PRODUCT_ZTE_K3565Z0x0063 }, 0}, | |||
184 | {{ USB_VENDOR_ZTE0x19d2, USB_PRODUCT_ZTE_MF1120x0117 }, DEV_UMASS40x0080}, | |||
185 | {{ USB_VENDOR_ZTE0x19d2, USB_PRODUCT_ZTE_MF6330x0016 }, 0}, | |||
186 | {{ USB_VENDOR_ZTE0x19d2, USB_PRODUCT_ZTE_MF6370x0031 }, 0}, | |||
187 | {{ USB_VENDOR_ZTE0x19d2, USB_PRODUCT_ZTE_MSA110UP0x0091 }, 0}, | |||
188 | ||||
189 | {{ USB_VENDOR_NOVATEL0x1410, USB_PRODUCT_NOVATEL_EXPRESSCARD0x1100 }, 0}, | |||
190 | {{ USB_VENDOR_NOVATEL0x1410, USB_PRODUCT_NOVATEL_MERLINV6200x1110 }, 0}, | |||
191 | {{ USB_VENDOR_NOVATEL0x1410, USB_PRODUCT_NOVATEL_MERLINV7400x1120 }, 0}, | |||
192 | {{ USB_VENDOR_NOVATEL0x1410, USB_PRODUCT_NOVATEL_V7200x1130 }, 0}, | |||
193 | {{ USB_VENDOR_NOVATEL0x1410, USB_PRODUCT_NOVATEL_MERLINU7400x1400 }, 0}, | |||
194 | {{ USB_VENDOR_NOVATEL0x1410, USB_PRODUCT_NOVATEL_MERLINU740_20x1410 }, 0}, | |||
195 | {{ USB_VENDOR_NOVATEL0x1410, USB_PRODUCT_NOVATEL_U8700x1420 }, 0}, | |||
196 | {{ USB_VENDOR_NOVATEL0x1410, USB_PRODUCT_NOVATEL_XU8700x1430 }, 0}, | |||
197 | {{ USB_VENDOR_NOVATEL0x1410, USB_PRODUCT_NOVATEL_EU870D0x2420 }, 0}, | |||
198 | {{ USB_VENDOR_NOVATEL0x1410, USB_PRODUCT_NOVATEL_X950D0x1450 }, 0}, | |||
199 | {{ USB_VENDOR_NOVATEL0x1410, USB_PRODUCT_NOVATEL_ES6200x2100 }, 0}, | |||
200 | {{ USB_VENDOR_NOVATEL0x1410, USB_PRODUCT_NOVATEL_U7200x2110 }, 0}, | |||
201 | {{ USB_VENDOR_NOVATEL0x1410, USB_PRODUCT_NOVATEL_U7270x4100 }, DEV_UMASS10x0010}, | |||
202 | {{ USB_VENDOR_NOVATEL0x1410, USB_PRODUCT_NOVATEL_MC950D0x4400 }, 0}, | |||
203 | {{ USB_VENDOR_NOVATEL0x1410, USB_PRODUCT_NOVATEL_MERLINX950D0x5010 }, DEV_UMASS40x0080}, | |||
204 | {{ USB_VENDOR_NOVATEL0x1410, USB_PRODUCT_NOVATEL_ZEROCD20x5030 }, DEV_UMASS40x0080}, | |||
205 | {{ USB_VENDOR_NOVATEL0x1410, USB_PRODUCT_NOVATEL_U7600x6000 }, DEV_UMASS40x0080}, | |||
206 | {{ USB_VENDOR_NOVATEL0x1410, USB_PRODUCT_NOVATEL_MC7600x6002 }, 0}, | |||
207 | {{ USB_VENDOR_NOVATEL0x1410, USB_PRODUCT_NOVATEL_MC760CD0x5031 }, DEV_UMASS40x0080}, | |||
208 | ||||
209 | {{ USB_VENDOR_NOVATEL10x09d7, USB_PRODUCT_NOVATEL1_FLEXPACKGPS0x0100 }, 0}, | |||
210 | ||||
211 | {{ USB_VENDOR_NOKIA20x0421, USB_PRODUCT_NOKIA2_CS15UMASS0x0610 }, DEV_UMASS40x0080}, | |||
212 | {{ USB_VENDOR_NOKIA20x0421, USB_PRODUCT_NOKIA2_CS150x0612 }, 0}, | |||
213 | ||||
214 | {{ USB_VENDOR_OPTION0x0af0, USB_PRODUCT_OPTION_GT3GFUSION0x6000 }, 0}, | |||
215 | {{ USB_VENDOR_OPTION0x0af0, USB_PRODUCT_OPTION_GT3GPLUS0x6721 }, 0}, | |||
216 | {{ USB_VENDOR_OPTION0x0af0, USB_PRODUCT_OPTION_GT3GQUAD0x6300 }, 0}, | |||
217 | {{ USB_VENDOR_OPTION0x0af0, USB_PRODUCT_OPTION_GT3GQUADPLUS0x6600 }, 0}, | |||
218 | {{ USB_VENDOR_OPTION0x0af0, USB_PRODUCT_OPTION_GSICON720x6911 }, DEV_UMASS10x0010}, | |||
219 | {{ USB_VENDOR_OPTION0x0af0, USB_PRODUCT_OPTION_GTHSUPA380E0x7211 }, 0}, | |||
220 | {{ USB_VENDOR_OPTION0x0af0, USB_PRODUCT_OPTION_GTMAX360x6701 }, 0}, | |||
221 | {{ USB_VENDOR_OPTION0x0af0, USB_PRODUCT_OPTION_ICON2250x6971 }, DEV_UMASS20x0020}, | |||
222 | {{ USB_VENDOR_OPTION0x0af0, USB_PRODUCT_OPTION_ICON5050xd055 }, DEV_UMASS10x0010}, | |||
223 | {{ USB_VENDOR_OPTION0x0af0, USB_PRODUCT_OPTION_SCORPION0x6901 }, 0}, | |||
224 | {{ USB_VENDOR_OPTION0x0af0, USB_PRODUCT_OPTION_VODAFONEMC3G0x5000 }, 0}, | |||
225 | ||||
226 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_EM56250x0017 }, 0}, | |||
227 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_MC57200x0018 }, 0}, | |||
228 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_AIRCARD_5950x0019 }, 0}, | |||
229 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_MC57250x0020 }, 0}, | |||
230 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_AC597E0x0021 }, 0}, | |||
231 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_C5970x0023 }, 0}, | |||
232 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_AC595U0x0120 }, 0}, | |||
233 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_AIRCARD_5800x0112 }, 0}, | |||
234 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_MC5720_20x0218 }, 0}, | |||
235 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_MC5725_20x0220 }, 0}, | |||
236 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_MC8755_20x6802 }, 0}, | |||
237 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_MC87650x6803 }, 0}, | |||
238 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_MC87550x6804 }, 0}, | |||
239 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_MC87750x6812 }, 0}, | |||
240 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_MC8755_30x6813 }, 0}, | |||
241 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_MC8775_20x6815 }, 0}, | |||
242 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_AIRCARD_8750x6820 }, 0}, | |||
243 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_MC87800x6832 }, 0}, | |||
244 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_MC87810x6833 }, 0}, | |||
245 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_MC87900x683c }, 0}, | |||
246 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_AC8800x6850 }, 0}, | |||
247 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_AC8810x6851 }, 0}, | |||
248 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_AC880E0x6852 }, 0}, | |||
249 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_AC881E0x6853 }, 0}, | |||
250 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_AC880U0x6855 }, 0}, | |||
251 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_AC881U0x6856 }, 0}, | |||
252 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_AC885U0x6880 }, 0}, | |||
253 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_C01SW0x6890 }, 0}, | |||
254 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_USB3050x68a3}, 0}, | |||
255 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_MC73040x68c0}, 0}, | |||
256 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_TRUINSTALL0x0fff }, DEV_TRUINSTALL0x0002}, | |||
257 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_MC83550x9013}, 0}, | |||
258 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_AIRCARD_340U0x9051}, 0}, | |||
259 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_AIRCARD_770S0x9053}, 0}, | |||
260 | {{ USB_VENDOR_SIERRA0x1199, USB_PRODUCT_SIERRA_MC74550x9071}, 0}, | |||
261 | ||||
262 | {{ USB_VENDOR_SIMCOM0x1e0e, USB_PRODUCT_SIMCOM_SIM7600E0x9001}, 0}, | |||
263 | ||||
264 | {{ USB_VENDOR_TCTMOBILE0x1bbb, USB_PRODUCT_TCTMOBILE_UMASS0xf000 }, DEV_UMASS30x0040}, | |||
265 | {{ USB_VENDOR_TCTMOBILE0x1bbb, USB_PRODUCT_TCTMOBILE_UMASS_20xf017 }, DEV_UMASS30x0040}, | |||
266 | {{ USB_VENDOR_TCTMOBILE0x1bbb, USB_PRODUCT_TCTMOBILE_UMSM0x0000 }, 0}, | |||
267 | {{ USB_VENDOR_TCTMOBILE0x1bbb, USB_PRODUCT_TCTMOBILE_UMSM_20x0017 }, 0}, | |||
268 | {{ USB_VENDOR_TCTMOBILE0x1bbb, USB_PRODUCT_TCTMOBILE_UMSM_30x011e }, 0}, | |||
269 | ||||
270 | {{ USB_VENDOR_TOSHIBA0x0930, USB_PRODUCT_TOSHIBA_HSDPA0x1302 }, 0}, | |||
271 | ||||
272 | {{ USB_VENDOR_HP0x03f0, USB_PRODUCT_HP_HS23000x1e1d }, 0}, | |||
273 | ||||
274 | {{ USB_VENDOR_CMOTECH0x16d8, USB_PRODUCT_CMOTECH_CNU5100x5141 }, 0}, /* ??? */ | |||
275 | {{ USB_VENDOR_CMOTECH0x16d8, USB_PRODUCT_CMOTECH_CCU5500x5533 }, 0}, /* ??? */ | |||
276 | {{ USB_VENDOR_CMOTECH0x16d8, USB_PRODUCT_CMOTECH_CGU6280x6006 }, DEV_UMASS10x0010}, | |||
277 | {{ USB_VENDOR_CMOTECH0x16d8, USB_PRODUCT_CMOTECH_CGU628_DISK0xf000 }, 0}, | |||
278 | {{ USB_VENDOR_CMOTECH0x16d8, USB_PRODUCT_CMOTECH_CNU6800x6803 }, DEV_UMASS10x0010}, | |||
279 | }; | |||
280 | ||||
281 | #define umsm_lookup(v, p)((const struct umsm_type *)usbd_match_device((const struct usb_devno *)(umsm_devs), sizeof (umsm_devs) / sizeof ((umsm_devs)[0]), sizeof ((umsm_devs)[0]), (v), (p))) ((const struct umsm_type *)usb_lookup(umsm_devs, v, p)usbd_match_device((const struct usb_devno *)(umsm_devs), sizeof (umsm_devs) / sizeof ((umsm_devs)[0]), sizeof ((umsm_devs)[0 ]), (v), (p))) | |||
282 | ||||
283 | struct cfdriver umsm_cd = { | |||
284 | NULL((void *)0), "umsm", DV_DULL | |||
285 | }; | |||
286 | ||||
287 | const struct cfattach umsm_ca = { | |||
288 | sizeof(struct umsm_softc), umsm_match, umsm_attach, umsm_detach | |||
289 | }; | |||
290 | ||||
291 | int | |||
292 | umsm_match(struct device *parent, void *match, void *aux) | |||
293 | { | |||
294 | struct usb_attach_arg *uaa = aux; | |||
295 | usb_interface_descriptor_t *id; | |||
296 | uint16_t flag; | |||
297 | ||||
298 | if (uaa->iface == NULL((void *)0)) | |||
299 | return UMATCH_NONE0; | |||
300 | ||||
301 | /* | |||
302 | * Some devices (eg Huawei E220) have multiple interfaces and some | |||
303 | * of them are of class umass. Don't claim ownership in such case. | |||
304 | */ | |||
305 | if (umsm_lookup(uaa->vendor, uaa->product)((const struct umsm_type *)usbd_match_device((const struct usb_devno *)(umsm_devs), sizeof (umsm_devs) / sizeof ((umsm_devs)[0]), sizeof ((umsm_devs)[0]), (uaa->vendor), (uaa->product) )) != NULL((void *)0)) { | |||
306 | id = usbd_get_interface_descriptor(uaa->iface); | |||
307 | flag = umsm_lookup(uaa->vendor, uaa->product)((const struct umsm_type *)usbd_match_device((const struct usb_devno *)(umsm_devs), sizeof (umsm_devs) / sizeof ((umsm_devs)[0]), sizeof ((umsm_devs)[0]), (uaa->vendor), (uaa->product) ))->umsm_flag; | |||
308 | ||||
309 | if (id == NULL((void *)0) || id->bInterfaceClass == UICLASS_MASS0x08) { | |||
310 | /* | |||
311 | * Some high-speed modems require special care. | |||
312 | */ | |||
313 | if (flag & DEV_HUAWEI0x0001) { | |||
314 | if (uaa->ifaceno != 2) | |||
315 | return UMATCH_VENDOR_IFACESUBCLASS6; | |||
316 | else | |||
317 | return UMATCH_NONE0; | |||
318 | } else if (flag & DEV_UMASS(0x0010 | 0x0020 | 0x0040 | 0x0080 | 0x0100 | 0x0200 | 0x0400 | 0x1000)) { | |||
319 | return UMATCH_VENDOR_IFACESUBCLASS6; | |||
320 | } else if (flag & DEV_TRUINSTALL0x0002) { | |||
321 | return UMATCH_VENDOR_IFACESUBCLASS6; | |||
322 | } else | |||
323 | return UMATCH_NONE0; | |||
324 | /* | |||
325 | * Some devices have interfaces which fail to attach but in | |||
326 | * addition seem to make the remaining interfaces unusable. Only | |||
327 | * attach whitelisted interfaces in this case. | |||
328 | */ | |||
329 | } else if ((uaa->vendor == USB_VENDOR_MEDIATEK0x0e8d && | |||
330 | uaa->product == USB_PRODUCT_MEDIATEK_DC_4COM0x00a5) && | |||
331 | !(id->bInterfaceClass == UICLASS_VENDOR0xff && | |||
332 | ((id->bInterfaceSubClass == 0x02 && | |||
333 | id->bInterfaceProtocol == 0x01) || | |||
334 | (id->bInterfaceSubClass == 0x00 && | |||
335 | id->bInterfaceProtocol == 0x00)))) { | |||
336 | return UMATCH_NONE0; | |||
337 | } else | |||
338 | return UMATCH_VENDOR_IFACESUBCLASS6; | |||
339 | } | |||
340 | ||||
341 | return UMATCH_NONE0; | |||
342 | } | |||
343 | ||||
344 | void | |||
345 | umsm_attach(struct device *parent, struct device *self, void *aux) | |||
346 | { | |||
347 | struct umsm_softc *sc = (struct umsm_softc *)self; | |||
348 | struct usb_attach_arg *uaa = aux; | |||
349 | struct ucom_attach_args uca; | |||
350 | usb_interface_descriptor_t *id; | |||
351 | usb_endpoint_descriptor_t *ed; | |||
352 | int i; | |||
353 | ||||
354 | bzero(&uca, sizeof(uca))__builtin_bzero((&uca), (sizeof(uca))); | |||
355 | sc->sc_udev = uaa->device; | |||
356 | sc->sc_iface = uaa->iface; | |||
357 | sc->sc_flag = umsm_lookup(uaa->vendor, uaa->product)((const struct umsm_type *)usbd_match_device((const struct usb_devno *)(umsm_devs), sizeof (umsm_devs) / sizeof ((umsm_devs)[0]), sizeof ((umsm_devs)[0]), (uaa->vendor), (uaa->product) ))->umsm_flag; | |||
358 | ||||
359 | id = usbd_get_interface_descriptor(sc->sc_iface); | |||
360 | ||||
361 | /* | |||
362 | * Some 3G modems have multiple interfaces and some of them | |||
363 | * are umass class. Don't claim ownership in such case. | |||
364 | */ | |||
365 | if (id == NULL((void *)0) || id->bInterfaceClass == UICLASS_MASS0x08) { | |||
| ||||
366 | /* | |||
367 | * Some 3G modems require a special request to | |||
368 | * enable their modem function. | |||
369 | */ | |||
370 | if ((sc->sc_flag & DEV_HUAWEI0x0001) && uaa->ifaceno == 0) { | |||
371 | umsm_huawei_changemode(uaa->device); | |||
372 | printf("%s: umass only mode. need to reattach\n", | |||
373 | sc->sc_dev.dv_xname); | |||
374 | } else if (sc->sc_flag & DEV_TRUINSTALL0x0002) { | |||
375 | umsm_truinstall_changemode(uaa->device); | |||
376 | printf("%s: truinstall mode. need to reattach\n", | |||
377 | sc->sc_dev.dv_xname); | |||
378 | } else if ((sc->sc_flag & DEV_UMASS(0x0010 | 0x0020 | 0x0040 | 0x0080 | 0x0100 | 0x0200 | 0x0400 | 0x1000)) && uaa->ifaceno == 0) { | |||
379 | umsm_umass_changemode(sc); | |||
380 | } | |||
381 | ||||
382 | /* | |||
383 | * The device will reset its own bus from the device side | |||
384 | * when its mode was changed, so just return. | |||
385 | */ | |||
386 | return; | |||
387 | } | |||
388 | ||||
389 | sc->sc_iface_no = id->bInterfaceNumber; | |||
390 | uca.bulkin = uca.bulkout = -1; | |||
391 | sc->sc_intr_number = sc->sc_isize = -1; | |||
392 | for (i = 0; i < id->bNumEndpoints; i++) { | |||
393 | ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); | |||
394 | if (ed == NULL((void *)0)) { | |||
395 | printf("%s: no endpoint descriptor found for %d\n", | |||
396 | sc->sc_dev.dv_xname, i); | |||
397 | usbd_deactivate(sc->sc_udev); | |||
398 | return; | |||
399 | } | |||
400 | ||||
401 | if (UE_GET_DIR(ed->bEndpointAddress)((ed->bEndpointAddress) & 0x80) == UE_DIR_IN0x80 && | |||
402 | UE_GET_XFERTYPE(ed->bmAttributes)((ed->bmAttributes) & 0x03) == UE_INTERRUPT0x03) { | |||
403 | sc->sc_intr_number = ed->bEndpointAddress; | |||
404 | sc->sc_isize = UGETW(ed->wMaxPacketSize)(*(u_int16_t *)(ed->wMaxPacketSize)); | |||
405 | DPRINTF(("%s: find interrupt endpoint for %s\n", | |||
406 | __func__, sc->sc_dev.dv_xname)); | |||
407 | } else if (UE_GET_DIR(ed->bEndpointAddress)((ed->bEndpointAddress) & 0x80) == UE_DIR_IN0x80 && | |||
408 | UE_GET_XFERTYPE(ed->bmAttributes)((ed->bmAttributes) & 0x03) == UE_BULK0x02) | |||
409 | uca.bulkin = ed->bEndpointAddress; | |||
410 | else if (UE_GET_DIR(ed->bEndpointAddress)((ed->bEndpointAddress) & 0x80) == UE_DIR_OUT0x00 && | |||
411 | UE_GET_XFERTYPE(ed->bmAttributes)((ed->bmAttributes) & 0x03) == UE_BULK0x02) | |||
412 | uca.bulkout = ed->bEndpointAddress; | |||
413 | } | |||
414 | if (uca.bulkin == -1 || uca.bulkout == -1) { | |||
415 | printf("%s: missing endpoint\n", sc->sc_dev.dv_xname); | |||
416 | usbd_deactivate(sc->sc_udev); | |||
417 | return; | |||
418 | } | |||
419 | ||||
420 | sc->sc_dtr = sc->sc_rts = -1; | |||
421 | ||||
422 | /* We need to force size as some devices lie */ | |||
423 | uca.ibufsize = UMSMBUFSZ4096; | |||
424 | uca.obufsize = UMSMBUFSZ4096; | |||
425 | uca.ibufsizepad = UMSMBUFSZ4096; | |||
426 | uca.opkthdrlen = 0; | |||
427 | uca.device = sc->sc_udev; | |||
428 | uca.iface = sc->sc_iface; | |||
429 | uca.methods = &umsm_methods; | |||
430 | uca.arg = sc; | |||
431 | uca.info = NULL((void *)0); | |||
432 | uca.portno = UCOM_UNK_PORTNO-1; | |||
433 | ||||
434 | sc->sc_subdev = config_found_sm(self, &uca, ucomprint, ucomsubmatch); | |||
435 | } | |||
436 | ||||
437 | int | |||
438 | umsm_detach(struct device *self, int flags) | |||
439 | { | |||
440 | struct umsm_softc *sc = (struct umsm_softc *)self; | |||
441 | int rv = 0; | |||
442 | ||||
443 | /* close the interrupt endpoint if that is opened */ | |||
444 | if (sc->sc_intr_pipe != NULL((void *)0)) { | |||
445 | usbd_close_pipe(sc->sc_intr_pipe); | |||
446 | free(sc->sc_intr_buf, M_USBDEV102, sc->sc_isize); | |||
447 | sc->sc_intr_pipe = NULL((void *)0); | |||
448 | } | |||
449 | ||||
450 | usbd_deactivate(sc->sc_udev); | |||
451 | if (sc->sc_subdev != NULL((void *)0)) { | |||
452 | rv = config_detach(sc->sc_subdev, flags); | |||
453 | sc->sc_subdev = NULL((void *)0); | |||
454 | } | |||
455 | ||||
456 | return (rv); | |||
457 | } | |||
458 | ||||
459 | int | |||
460 | umsm_open(void *addr, int portno) | |||
461 | { | |||
462 | struct umsm_softc *sc = addr; | |||
463 | int err; | |||
464 | ||||
465 | if (usbd_is_dying(sc->sc_udev)) | |||
466 | return (ENXIO6); | |||
467 | ||||
468 | if (sc->sc_intr_number != -1 && sc->sc_intr_pipe == NULL((void *)0)) { | |||
469 | sc->sc_intr_buf = malloc(sc->sc_isize, M_USBDEV102, M_WAITOK0x0001); | |||
470 | err = usbd_open_pipe_intr(sc->sc_iface, | |||
471 | sc->sc_intr_number, | |||
472 | USBD_SHORT_XFER_OK0x04, | |||
473 | &sc->sc_intr_pipe, | |||
474 | sc, | |||
475 | sc->sc_intr_buf, | |||
476 | sc->sc_isize, | |||
477 | umsm_intr, | |||
478 | UMSM_INTR_INTERVAL100); | |||
479 | if (err) { | |||
480 | printf("%s: cannot open interrupt pipe (addr %d)\n", | |||
481 | sc->sc_dev.dv_xname, | |||
482 | sc->sc_intr_number); | |||
483 | return (EIO5); | |||
484 | } | |||
485 | } | |||
486 | ||||
487 | return (0); | |||
488 | } | |||
489 | ||||
490 | void | |||
491 | umsm_close(void *addr, int portno) | |||
492 | { | |||
493 | struct umsm_softc *sc = addr; | |||
494 | int err; | |||
495 | ||||
496 | if (usbd_is_dying(sc->sc_udev)) | |||
497 | return; | |||
498 | ||||
499 | if (sc->sc_intr_pipe != NULL((void *)0)) { | |||
500 | err = usbd_close_pipe(sc->sc_intr_pipe); | |||
501 | if (err) | |||
502 | printf("%s: close interrupt pipe failed: %s\n", | |||
503 | sc->sc_dev.dv_xname, | |||
504 | usbd_errstr(err)); | |||
505 | free(sc->sc_intr_buf, M_USBDEV102, sc->sc_isize); | |||
506 | sc->sc_intr_pipe = NULL((void *)0); | |||
507 | } | |||
508 | } | |||
509 | ||||
510 | void | |||
511 | umsm_intr(struct usbd_xfer *xfer, void *priv, | |||
512 | usbd_status status) | |||
513 | { | |||
514 | struct umsm_softc *sc = priv; | |||
515 | struct usb_cdc_notification *buf; | |||
516 | u_char mstatus; | |||
517 | ||||
518 | buf = (struct usb_cdc_notification *)sc->sc_intr_buf; | |||
519 | if (usbd_is_dying(sc->sc_udev)) | |||
520 | return; | |||
521 | ||||
522 | if (status != USBD_NORMAL_COMPLETION) { | |||
523 | if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) | |||
524 | return; | |||
525 | ||||
526 | DPRINTF(("%s: umsm_intr: abnormal status: %s\n", | |||
527 | sc->sc_dev.dv_xname, usbd_errstr(status))); | |||
528 | usbd_clear_endpoint_stall_async(sc->sc_intr_pipe); | |||
529 | return; | |||
530 | } | |||
531 | ||||
532 | if (buf->bmRequestType != UCDC_NOTIFICATION0xa1) { | |||
533 | #if 1 /* test */ | |||
534 | printf("%s: this device is not using CDC notify message in intr pipe.\n" | |||
535 | "Please send your dmesg to <bugs@openbsd.org>, thanks.\n", | |||
536 | sc->sc_dev.dv_xname); | |||
537 | printf("%s: intr buffer 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", | |||
538 | sc->sc_dev.dv_xname, | |||
539 | sc->sc_intr_buf[0], sc->sc_intr_buf[1], | |||
540 | sc->sc_intr_buf[2], sc->sc_intr_buf[3], | |||
541 | sc->sc_intr_buf[4], sc->sc_intr_buf[5], | |||
542 | sc->sc_intr_buf[6]); | |||
543 | #else | |||
544 | DPRINTF(("%s: umsm_intr: unknown message type(0x%02x)\n", | |||
545 | sc->sc_dev.dv_xname, buf->bmRequestType)); | |||
546 | #endif | |||
547 | return; | |||
548 | } | |||
549 | ||||
550 | if (buf->bNotification == UCDC_N_SERIAL_STATE0x20) { | |||
551 | /* invalid message length, discard it */ | |||
552 | if (UGETW(buf->wLength)(*(u_int16_t *)(buf->wLength)) != 2) | |||
553 | return; | |||
554 | /* XXX: sc_lsr is always 0 */ | |||
555 | sc->sc_lsr = sc->sc_msr = 0; | |||
556 | mstatus = buf->data[0]; | |||
557 | if (ISSET(mstatus, UCDC_N_SERIAL_RI)((mstatus) & (0x08))) | |||
558 | sc->sc_msr |= UMSR_RI0x40; | |||
559 | if (ISSET(mstatus, UCDC_N_SERIAL_DSR)((mstatus) & (0x02))) | |||
560 | sc->sc_msr |= UMSR_DSR0x20; | |||
561 | if (ISSET(mstatus, UCDC_N_SERIAL_DCD)((mstatus) & (0x01))) | |||
562 | sc->sc_msr |= UMSR_DCD0x80; | |||
563 | } else if (buf->bNotification != UCDC_N_CONNECTION_SPEED_CHANGE0x2a) { | |||
564 | DPRINTF(("%s: umsm_intr: unknown notify message (0x%02x)\n", | |||
565 | sc->sc_dev.dv_xname, buf->bNotification)); | |||
566 | return; | |||
567 | } | |||
568 | ||||
569 | ucom_status_change((struct ucom_softc *)sc->sc_subdev); | |||
570 | } | |||
571 | ||||
572 | void | |||
573 | umsm_get_status(void *addr, int portno, u_char *lsr, u_char *msr) | |||
574 | { | |||
575 | struct umsm_softc *sc = addr; | |||
576 | ||||
577 | if (lsr != NULL((void *)0)) | |||
578 | *lsr = sc->sc_lsr; | |||
579 | if (msr != NULL((void *)0)) | |||
580 | *msr = sc->sc_msr; | |||
581 | } | |||
582 | ||||
583 | void | |||
584 | umsm_set(void *addr, int portno, int reg, int onoff) | |||
585 | { | |||
586 | struct umsm_softc *sc = addr; | |||
587 | usb_device_request_t req; | |||
588 | int ls; | |||
589 | ||||
590 | switch (reg) { | |||
591 | case UCOM_SET_DTR1: | |||
592 | if (sc->sc_dtr == onoff) | |||
593 | return; | |||
594 | sc->sc_dtr = onoff; | |||
595 | break; | |||
596 | case UCOM_SET_RTS2: | |||
597 | if (sc->sc_rts == onoff) | |||
598 | return; | |||
599 | sc->sc_rts = onoff; | |||
600 | break; | |||
601 | default: | |||
602 | return; | |||
603 | } | |||
604 | ||||
605 | /* build a usb request */ | |||
606 | ls = (sc->sc_dtr ? UCDC_LINE_DTR0x0001 : 0) | | |||
607 | (sc->sc_rts ? UCDC_LINE_RTS0x0002 : 0); | |||
608 | req.bmRequestType = UT_WRITE_CLASS_INTERFACE(0x00 | 0x20 | 0x01); | |||
609 | req.bRequest = UCDC_SET_CONTROL_LINE_STATE0x22; | |||
610 | USETW(req.wValue, ls)(*(u_int16_t *)(req.wValue) = (ls)); | |||
611 | USETW(req.wIndex, sc->sc_iface_no)(*(u_int16_t *)(req.wIndex) = (sc->sc_iface_no)); | |||
612 | USETW(req.wLength, 0)(*(u_int16_t *)(req.wLength) = (0)); | |||
613 | ||||
614 | (void)usbd_do_request(sc->sc_udev, &req, 0); | |||
615 | } | |||
616 | ||||
617 | usbd_status | |||
618 | umsm_huawei_changemode(struct usbd_device *dev) | |||
619 | { | |||
620 | usb_device_request_t req; | |||
621 | usbd_status err; | |||
622 | ||||
623 | req.bmRequestType = UT_WRITE_DEVICE(0x00 | 0x00 | 0x00); | |||
624 | req.bRequest = UR_SET_FEATURE0x03; | |||
625 | USETW(req.wValue, UF_DEVICE_REMOTE_WAKEUP)(*(u_int16_t *)(req.wValue) = (1)); | |||
626 | USETW(req.wIndex, E220_MODE_CHANGE_REQUEST)(*(u_int16_t *)(req.wIndex) = (0x2)); | |||
627 | USETW(req.wLength, 0)(*(u_int16_t *)(req.wLength) = (0)); | |||
628 | ||||
629 | err = usbd_do_request(dev, &req, 0); | |||
630 | if (err) | |||
631 | return (EIO5); | |||
632 | ||||
633 | return (0); | |||
634 | } | |||
635 | ||||
636 | usbd_status | |||
637 | umsm_truinstall_changemode(struct usbd_device *dev) | |||
638 | { | |||
639 | usb_device_request_t req; | |||
640 | usbd_status err; | |||
641 | req.bmRequestType = UT_WRITE_VENDOR_DEVICE(0x00 | 0x40 | 0x00); | |||
642 | req.bRequest = TRUINSTALL_CHANGEMODE_REQUEST0x0b; | |||
643 | USETW(req.wValue, 0x1)(*(u_int16_t *)(req.wValue) = (0x1)); | |||
644 | USETW(req.wIndex, 0)(*(u_int16_t *)(req.wIndex) = (0)); | |||
645 | USETW(req.wLength, 0)(*(u_int16_t *)(req.wLength) = (0)); | |||
646 | ||||
647 | err = usbd_do_request(dev, &req, 0); | |||
648 | if (err) | |||
649 | return (EIO5); | |||
650 | ||||
651 | return (0); | |||
652 | } | |||
653 | ||||
654 | usbd_status | |||
655 | umsm_umass_changemode(struct umsm_softc *sc) | |||
656 | { | |||
657 | #define UMASS_CMD_REZERO_UNIT0x01 0x01 | |||
658 | #define UMASS_CMD_START_STOP0x1b 0x1b | |||
659 | #define UMASS_CMDPARAM_EJECT0x02 0x02 | |||
660 | #define UMASS_SERVICE_ACTION_OUT0x9f 0x9f | |||
661 | usb_interface_descriptor_t *id; | |||
662 | usb_endpoint_descriptor_t *ed; | |||
663 | struct usbd_xfer *xfer; | |||
664 | struct usbd_pipe *cmdpipe; | |||
665 | usbd_status err; | |||
666 | u_int32_t n; | |||
667 | void *bufp; | |||
668 | int target_ep, i; | |||
669 | ||||
670 | struct umass_bbb_cbw cbw; | |||
671 | static int dCBWTag = 0x12345678; | |||
672 | ||||
673 | USETDW(cbw.dCBWSignature, CBWSIGNATURE)(*(u_int32_t *)(cbw.dCBWSignature) = (0x43425355)); | |||
674 | USETDW(cbw.dCBWTag, dCBWTag)(*(u_int32_t *)(cbw.dCBWTag) = (dCBWTag)); | |||
675 | cbw.bCBWLUN = 0; | |||
676 | cbw.bCDBLength= 6; | |||
677 | bzero(cbw.CBWCDB, sizeof(cbw.CBWCDB))__builtin_bzero((cbw.CBWCDB), (sizeof(cbw.CBWCDB))); | |||
678 | ||||
679 | switch (sc->sc_flag) { | |||
680 | case DEV_UMASS10x0010: | |||
681 | USETDW(cbw.dCBWDataTransferLength, 0x0)(*(u_int32_t *)(cbw.dCBWDataTransferLength) = (0x0)); | |||
682 | cbw.bCBWFlags = CBWFLAGS_OUT0x00; | |||
683 | cbw.CBWCDB[0] = UMASS_CMD_REZERO_UNIT0x01; | |||
684 | cbw.CBWCDB[1] = 0x0; /* target LUN: 0 */ | |||
685 | break; | |||
686 | case DEV_UMASS20x0020: | |||
687 | USETDW(cbw.dCBWDataTransferLength, 0x1)(*(u_int32_t *)(cbw.dCBWDataTransferLength) = (0x1)); | |||
688 | cbw.bCBWFlags = CBWFLAGS_IN0x80; | |||
689 | cbw.CBWCDB[0] = UMASS_CMD_REZERO_UNIT0x01; | |||
690 | cbw.CBWCDB[1] = 0x0; /* target LUN: 0 */ | |||
691 | break; | |||
692 | case DEV_UMASS30x0040: /* longcheer */ | |||
693 | USETDW(cbw.dCBWDataTransferLength, 0x80)(*(u_int32_t *)(cbw.dCBWDataTransferLength) = (0x80)); | |||
694 | cbw.bCBWFlags = CBWFLAGS_IN0x80; | |||
695 | cbw.CBWCDB[0] = 0x06; | |||
696 | cbw.CBWCDB[1] = 0xf5; | |||
697 | cbw.CBWCDB[2] = 0x04; | |||
698 | cbw.CBWCDB[3] = 0x02; | |||
699 | cbw.CBWCDB[4] = 0x52; | |||
700 | cbw.CBWCDB[5] = 0x70; | |||
701 | break; | |||
702 | case DEV_UMASS40x0080: | |||
703 | USETDW(cbw.dCBWDataTransferLength, 0x0)(*(u_int32_t *)(cbw.dCBWDataTransferLength) = (0x0)); | |||
704 | cbw.bCBWFlags = CBWFLAGS_OUT0x00; | |||
705 | cbw.CBWCDB[0] = UMASS_CMD_START_STOP0x1b; | |||
706 | cbw.CBWCDB[1] = 0x00; /* target LUN: 0 */ | |||
707 | cbw.CBWCDB[4] = UMASS_CMDPARAM_EJECT0x02; | |||
708 | break; | |||
709 | case DEV_UMASS50x0100: | |||
710 | cbw.bCBWFlags = CBWFLAGS_OUT0x00; | |||
711 | cbw.CBWCDB[0] = 0x11; | |||
712 | cbw.CBWCDB[1] = 0x06; | |||
713 | break; | |||
714 | case DEV_UMASS60x0200: /* ZTE */ | |||
715 | USETDW(cbw.dCBWDataTransferLength, 0x20)(*(u_int32_t *)(cbw.dCBWDataTransferLength) = (0x20)); | |||
716 | cbw.bCBWFlags = CBWFLAGS_IN0x80; | |||
717 | cbw.bCDBLength= 12; | |||
718 | cbw.CBWCDB[0] = 0x85; | |||
719 | cbw.CBWCDB[1] = 0x01; | |||
720 | cbw.CBWCDB[2] = 0x01; | |||
721 | cbw.CBWCDB[3] = 0x01; | |||
722 | cbw.CBWCDB[4] = 0x18; | |||
723 | cbw.CBWCDB[5] = 0x01; | |||
724 | cbw.CBWCDB[6] = 0x01; | |||
725 | cbw.CBWCDB[7] = 0x01; | |||
726 | cbw.CBWCDB[8] = 0x01; | |||
727 | cbw.CBWCDB[9] = 0x01; | |||
728 | break; | |||
729 | case DEV_UMASS70x0400: /* ZTE */ | |||
730 | USETDW(cbw.dCBWDataTransferLength, 0xc0)(*(u_int32_t *)(cbw.dCBWDataTransferLength) = (0xc0)); | |||
731 | cbw.bCBWFlags = CBWFLAGS_IN0x80; | |||
732 | cbw.CBWCDB[0] = UMASS_SERVICE_ACTION_OUT0x9f; | |||
733 | cbw.CBWCDB[1] = 0x03; | |||
734 | break; | |||
735 | case DEV_UMASS80x1000: | |||
736 | USETDW(cbw.dCBWDataTransferLength, 0x0)(*(u_int32_t *)(cbw.dCBWDataTransferLength) = (0x0)); | |||
737 | cbw.bCBWFlags = CBWFLAGS_OUT0x00; | |||
738 | cbw.CBWCDB[0] = 0xf0; | |||
739 | cbw.CBWCDB[1] = 0x01; | |||
740 | cbw.CBWCDB[2] = 0x03; | |||
741 | break; | |||
742 | default: | |||
743 | DPRINTF(("%s: unknown device type.\n", sc->sc_dev.dv_xname)); | |||
744 | break; | |||
745 | } | |||
746 | ||||
747 | /* get command endpoint address */ | |||
748 | id = usbd_get_interface_descriptor(sc->sc_iface); | |||
749 | for (i = 0; i < id->bNumEndpoints; i++) { | |||
750 | ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); | |||
751 | if (ed == NULL((void *)0)) { | |||
752 | return (USBD_IOERROR); | |||
753 | } | |||
754 | ||||
755 | if (UE_GET_DIR(ed->bEndpointAddress)((ed->bEndpointAddress) & 0x80) == UE_DIR_OUT0x00 && | |||
756 | UE_GET_XFERTYPE(ed->bmAttributes)((ed->bmAttributes) & 0x03) == UE_BULK0x02) | |||
757 | target_ep = ed->bEndpointAddress; | |||
758 | } | |||
759 | ||||
760 | /* open command endpoint */ | |||
761 | err = usbd_open_pipe(sc->sc_iface, target_ep, | |||
| ||||
762 | USBD_EXCLUSIVE_USE0x01, &cmdpipe); | |||
763 | if (err) { | |||
764 | DPRINTF(("%s: open pipe for modem change cmd failed: %s\n", | |||
765 | sc->sc_dev.dv_xname, usbd_errstr(err))); | |||
766 | return (err); | |||
767 | } | |||
768 | ||||
769 | xfer = usbd_alloc_xfer(sc->sc_udev); | |||
770 | if (xfer == NULL((void *)0)) { | |||
771 | usbd_close_pipe(cmdpipe); | |||
772 | return (USBD_NOMEM); | |||
773 | } else { | |||
774 | bufp = usbd_alloc_buffer(xfer, UMASS_BBB_CBW_SIZE31); | |||
775 | if (bufp == NULL((void *)0)) | |||
776 | err = USBD_NOMEM; | |||
777 | else { | |||
778 | n = UMASS_BBB_CBW_SIZE31; | |||
779 | memcpy(bufp, &cbw, UMASS_BBB_CBW_SIZE)__builtin_memcpy((bufp), (&cbw), (31)); | |||
780 | usbd_setup_xfer(xfer, cmdpipe, 0, bufp, n, | |||
781 | USBD_NO_COPY0x01 | USBD_SYNCHRONOUS0x02, 0, NULL((void *)0)); | |||
782 | err = usbd_transfer(xfer); | |||
783 | if (err) { | |||
784 | usbd_clear_endpoint_stall(cmdpipe); | |||
785 | DPRINTF(("%s: send error:%s", __func__, | |||
786 | usbd_errstr(err))); | |||
787 | } | |||
788 | } | |||
789 | usbd_close_pipe(cmdpipe); | |||
790 | usbd_free_buffer(xfer); | |||
791 | usbd_free_xfer(xfer); | |||
792 | } | |||
793 | ||||
794 | return (err); | |||
795 | } |