Bug Summary

File:src/add-ons/kernel/drivers/common/usb_modeswitch.cpp
Warning:line 538, column 10
Use of memory after it is freed

Annotated Source Code

1/*
2 * Copyright 2010, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Jérôme Duval, korli@users.berlios.de
7 */
8
9/*
10 Devices and messages reference: usb-modeswitch-data-20100826
11 Huawei devices updated to usb-modeswitch-data-20150115
12*/
13
14#include <ByteOrder.h>
15#include <Drivers.h>
16#include <KernelExport.h>
17#include <lock.h>
18#include <USB3.h>
19
20#include <malloc.h>
21#include <stdio.h>
22#include <string.h>
23
24#define DRIVER_NAME"usb_modeswitch" "usb_modeswitch"
25
26#define TRACE_USB_MODESWITCH1 1
27#ifdef TRACE_USB_MODESWITCH1
28#define TRACE(x...)dprintf("usb_modeswitch" ": " x...) dprintf(DRIVER_NAME"usb_modeswitch" ": " x)
29#else
30#define TRACE(x...)dprintf("usb_modeswitch" ": " x...) /* nothing */
31#endif
32#define TRACE_ALWAYS(x...)dprintf("usb_modeswitch" ": " x...) dprintf(DRIVER_NAME"usb_modeswitch" ": " x)
33#define ENTER()dprintf("usb_modeswitch" ": " "%s", __FUNCTION__) TRACE("%s", __FUNCTION__)dprintf("usb_modeswitch" ": " "%s", __FUNCTION__)
34
35
36enum msgType {
37 MSG_HUAWEI_1 = 0,
38 MSG_HUAWEI_2,
39 MSG_HUAWEI_3,
40 MSG_NOKIA_1,
41 MSG_OLIVETTI_1,
42 MSG_OLIVETTI_2,
43 MSG_OPTION_1,
44 MSG_ATHEROS_1,
45 MSG_ZTE_1,
46 MSG_ZTE_2,
47 MSG_ZTE_3,
48 MSG_NONE
49};
50
51
52unsigned char kDevicesMsg[][31] = {
53 { /* MSG_HUAWEI_1 */
54 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78,
55 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
56 0x06, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
58 },
59 { /* MSG_HUAWEI_2 */
60 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78,
61 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x0a, 0x11,
62 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
64 },
65 { /* MSG_HUAWEI_3 */
66 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78,
67 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
68 0x06, 0x20, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01,
69 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
70 },
71 { /* MSG_NOKIA_1 */
72 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78,
73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x1b,
74 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
76 },
77 { /* MSG_OLIVETTI_1 */
78 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78,
79 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x1b,
80 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
81 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
82 },
83 { /* MSG_OLIVETTI_2 */
84 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78,
85 0xc0, 0x00, 0x00, 0x00, 0x80, 0x01, 0x06, 0x06,
86 0xf5, 0x04, 0x02, 0x52, 0x70, 0x00, 0x00, 0x00,
87 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
88 },
89 { /* MSG_OPTION_1 */
90 0x55, 0x53, 0x42, 0x43, 0x78, 0x56, 0x34, 0x12,
91 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x06, 0x10,
92 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
93 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
94 },
95 { /* MSG_ATHEROS_1 */
96 0x55, 0x53, 0x42, 0x43, 0x29, 0x00, 0x00, 0x00,
97 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x1b,
98 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
99 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
100 },
101 { /* MSG_ZTE_1 */
102 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78,
103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x1e,
104 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
105 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
106 },
107 { /* MSG_ZTE_2 */
108 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x79,
109 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x1b,
110 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
111 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
112 },
113 { /* MSG_ZTE_3 */
114 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x70,
115 0x20, 0x00, 0x00, 0x00, 0x80, 0x00, 0x0c, 0x85,
116 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
117 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
118 }
119};
120
121
122#define HUAWEI_VENDOR0x12d1 0x12d1
123#define NOKIA_VENDOR0x0421 0x0421
124#define NOVATEL_VENDOR0x1410 0x1410
125#define ZYDAS_VENDOR0x0ace 0x0ace
126#define ZTE_VENDOR0x19d2 0x19d2
127#define OLIVETTI_VENDOR0x0b3c 0x0b3c
128#define OPTION_VENDOR0x0af0 0x0af0
129#define ATHEROS_VENDOR0x0cf3 0x0cf3
130
131
132static const struct {
133 usb_support_descriptor desc;
134 msgType type, type2, type3;
135} kDevices[] = {
136 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x101e}, MSG_HUAWEI_1},
137 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x1030}, MSG_HUAWEI_2},
138 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x1031}, MSG_HUAWEI_2},
139 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x1446}, MSG_HUAWEI_3},
140 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x1449}, MSG_HUAWEI_3},
141 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x14ad}, MSG_HUAWEI_3},
142 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x14b5}, MSG_HUAWEI_3},
143 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x14b7}, MSG_HUAWEI_3},
144 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x14ba}, MSG_HUAWEI_3},
145 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x14c1}, MSG_HUAWEI_3},
146 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x14c3}, MSG_HUAWEI_3},
147 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x14c4}, MSG_HUAWEI_3},
148 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x14c5}, MSG_HUAWEI_3},
149 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x14d1}, MSG_HUAWEI_3},
150 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x14fe}, MSG_HUAWEI_3},
151 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x1505}, MSG_HUAWEI_3},
152 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x151a}, MSG_HUAWEI_3},
153 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x1520}, MSG_HUAWEI_3},
154 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x1521}, MSG_HUAWEI_3},
155 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x1523}, MSG_HUAWEI_3},
156 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x1526}, MSG_HUAWEI_3},
157 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x1553}, MSG_HUAWEI_3},
158 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x1557}, MSG_HUAWEI_3},
159 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x155b}, MSG_HUAWEI_3},
160 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x156a}, MSG_HUAWEI_3},
161 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x1576}, MSG_HUAWEI_3},
162 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x157d}, MSG_HUAWEI_3},
163 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x1583}, MSG_HUAWEI_3},
164 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x15ca}, MSG_HUAWEI_3},
165 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x15e7}, MSG_HUAWEI_3},
166 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x1c0b}, MSG_HUAWEI_3},
167 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x1c1b}, MSG_HUAWEI_3},
168 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x1c24}, MSG_HUAWEI_3},
169 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x1da1}, MSG_HUAWEI_3},
170 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x1f01}, MSG_HUAWEI_3},
171 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x1f02}, MSG_HUAWEI_3},
172 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x1f03}, MSG_HUAWEI_3},
173 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x1f11}, MSG_HUAWEI_3},
174 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x1f15}, MSG_HUAWEI_3},
175 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x1f16}, MSG_HUAWEI_3},
176 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x1f17}, MSG_HUAWEI_3},
177 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x1f18}, MSG_HUAWEI_3},
178 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x1f19}, MSG_HUAWEI_3},
179 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x1f1b}, MSG_HUAWEI_3},
180 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x1f1c}, MSG_HUAWEI_3},
181 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x1f1d}, MSG_HUAWEI_3},
182 {{ 0, 0, 0, HUAWEI_VENDOR0x12d1, 0x1f1e}, MSG_HUAWEI_3},
183 {{ 0, 0, 0, NOKIA_VENDOR0x0421, 0x060c}, MSG_NOKIA_1},
184 {{ 0, 0, 0, NOKIA_VENDOR0x0421, 0x0610}, MSG_NOKIA_1},
185 {{ 0, 0, 0, NOKIA_VENDOR0x0421, 0x061d}, MSG_NOKIA_1},
186 {{ 0, 0, 0, NOKIA_VENDOR0x0421, 0x0622}, MSG_NOKIA_1},
187 {{ 0, 0, 0, NOKIA_VENDOR0x0421, 0x0627}, MSG_NOKIA_1},
188 {{ 0, 0, 0, NOKIA_VENDOR0x0421, 0x062c}, MSG_NOKIA_1},
189 {{ 0, 0, 0, NOKIA_VENDOR0x0421, 0x0632}, MSG_NOKIA_1},
190 {{ 0, 0, 0, NOKIA_VENDOR0x0421, 0x0637}, MSG_NOKIA_1},
191 {{ 0, 0, 0, NOVATEL_VENDOR0x1410, 0x5010}, MSG_NOKIA_1},
192 {{ 0, 0, 0, NOVATEL_VENDOR0x1410, 0x5020}, MSG_NOKIA_1},
193 {{ 0, 0, 0, NOVATEL_VENDOR0x1410, 0x5030}, MSG_NOKIA_1},
194 {{ 0, 0, 0, NOVATEL_VENDOR0x1410, 0x5031}, MSG_NOKIA_1},
195 {{ 0, 0, 0, NOVATEL_VENDOR0x1410, 0x5041}, MSG_NOKIA_1},
196 {{ 0, 0, 0, NOVATEL_VENDOR0x1410, 0x5059}, MSG_NOKIA_1},
197 {{ 0, 0, 0, NOVATEL_VENDOR0x1410, 0x7001}, MSG_NOKIA_1},
198 {{ 0, 0, 0, ZYDAS_VENDOR0x0ace, 0x2011}, MSG_NOKIA_1},
199 {{ 0, 0, 0, ZYDAS_VENDOR0x0ace, 0x20ff}, MSG_NOKIA_1},
200 {{ 0, 0, 0, ZTE_VENDOR0x19d2, 0x0013}, MSG_NOKIA_1},
201 {{ 0, 0, 0, ZTE_VENDOR0x19d2, 0x0026}, MSG_NOKIA_1},
202 {{ 0, 0, 0, ZTE_VENDOR0x19d2, 0x0031}, MSG_NOKIA_1},
203 {{ 0, 0, 0, ZTE_VENDOR0x19d2, 0x0083}, MSG_NOKIA_1},
204 {{ 0, 0, 0, ZTE_VENDOR0x19d2, 0x0101}, MSG_NOKIA_1},
205 {{ 0, 0, 0, ZTE_VENDOR0x19d2, 0x0115}, MSG_NOKIA_1},
206 {{ 0, 0, 0, ZTE_VENDOR0x19d2, 0x0120}, MSG_NOKIA_1},
207 {{ 0, 0, 0, ZTE_VENDOR0x19d2, 0x0169}, MSG_NOKIA_1},
208 {{ 0, 0, 0, ZTE_VENDOR0x19d2, 0x0325}, MSG_NOKIA_1},
209 {{ 0, 0, 0, ZTE_VENDOR0x19d2, 0x1001}, MSG_NOKIA_1},
210 {{ 0, 0, 0, ZTE_VENDOR0x19d2, 0x1007}, MSG_NOKIA_1},
211 {{ 0, 0, 0, ZTE_VENDOR0x19d2, 0x1009}, MSG_NOKIA_1},
212 {{ 0, 0, 0, ZTE_VENDOR0x19d2, 0x1013}, MSG_NOKIA_1},
213 {{ 0, 0, 0, ZTE_VENDOR0x19d2, 0x1017}, MSG_NOKIA_1},
214 {{ 0, 0, 0, ZTE_VENDOR0x19d2, 0x1171}, MSG_NOKIA_1},
215 {{ 0, 0, 0, ZTE_VENDOR0x19d2, 0x1175}, MSG_NOKIA_1},
216 {{ 0, 0, 0, ZTE_VENDOR0x19d2, 0x1179}, MSG_NOKIA_1},
217 {{ 0, 0, 0, ZTE_VENDOR0x19d2, 0x1201}, MSG_NOKIA_1},
218 {{ 0, 0, 0, ZTE_VENDOR0x19d2, 0x1523}, MSG_NOKIA_1},
219 {{ 0, 0, 0, ZTE_VENDOR0x19d2, 0xffde}, MSG_NOKIA_1},
220 {{ 0, 0, 0, ZTE_VENDOR0x19d2, 0x0003}, MSG_ZTE_1, MSG_ZTE_2},
221 {{ 0, 0, 0, ZTE_VENDOR0x19d2, 0x0053}, MSG_ZTE_1, MSG_ZTE_2},
222 {{ 0, 0, 0, ZTE_VENDOR0x19d2, 0x0103}, MSG_ZTE_1, MSG_ZTE_2},
223 {{ 0, 0, 0, ZTE_VENDOR0x19d2, 0x0154}, MSG_ZTE_1, MSG_ZTE_2},
224 {{ 0, 0, 0, ZTE_VENDOR0x19d2, 0x1224}, MSG_ZTE_1, MSG_ZTE_2},
225 {{ 0, 0, 0, ZTE_VENDOR0x19d2, 0x1517}, MSG_ZTE_1, MSG_ZTE_2},
226 {{ 0, 0, 0, ZTE_VENDOR0x19d2, 0x1542}, MSG_ZTE_1, MSG_ZTE_2},
227 {{ 0, 0, 0, ZTE_VENDOR0x19d2, 0x0149}, MSG_ZTE_1, MSG_ZTE_2, MSG_ZTE_3},
228 {{ 0, 0, 0, ZTE_VENDOR0x19d2, 0x2000}, MSG_ZTE_1, MSG_ZTE_2, MSG_ZTE_3},
229 {{ 0, 0, 0, OLIVETTI_VENDOR0x0b3c, 0xc700}, MSG_OLIVETTI_1},
230 {{ 0, 0, 0, OLIVETTI_VENDOR0x0b3c, 0xf000}, MSG_OLIVETTI_2},
231 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x6711}, MSG_OPTION_1},
232 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x6731}, MSG_OPTION_1},
233 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x6751}, MSG_OPTION_1},
234 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x6771}, MSG_OPTION_1},
235 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x6791}, MSG_OPTION_1},
236 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x6811}, MSG_OPTION_1},
237 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x6911}, MSG_OPTION_1},
238 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x6951}, MSG_OPTION_1},
239 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x6971}, MSG_OPTION_1},
240 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x7011}, MSG_OPTION_1},
241 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x7031}, MSG_OPTION_1},
242 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x7051}, MSG_OPTION_1},
243 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x7071}, MSG_OPTION_1},
244 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x7111}, MSG_OPTION_1},
245 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x7211}, MSG_OPTION_1},
246 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x7251}, MSG_OPTION_1},
247 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x7271}, MSG_OPTION_1},
248 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x7301}, MSG_OPTION_1},
249 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x7311}, MSG_OPTION_1},
250 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x7361}, MSG_OPTION_1},
251 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x7381}, MSG_OPTION_1},
252 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x7401}, MSG_OPTION_1},
253 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x7501}, MSG_OPTION_1},
254 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x7601}, MSG_OPTION_1},
255 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x7701}, MSG_OPTION_1},
256 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x7706}, MSG_OPTION_1},
257 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x7801}, MSG_OPTION_1},
258 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x7901}, MSG_OPTION_1},
259 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x8006}, MSG_OPTION_1},
260 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x8200}, MSG_OPTION_1},
261 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x8201}, MSG_OPTION_1},
262 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x8300}, MSG_OPTION_1},
263 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x8302}, MSG_OPTION_1},
264 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x8304}, MSG_OPTION_1},
265 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x8400}, MSG_OPTION_1},
266 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x8600}, MSG_OPTION_1},
267 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x8800}, MSG_OPTION_1},
268 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x8900}, MSG_OPTION_1},
269 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0x9000}, MSG_OPTION_1},
270 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0xc031}, MSG_OPTION_1},
271 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0xc100}, MSG_OPTION_1},
272 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0xc031}, MSG_OPTION_1},
273 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0xd013}, MSG_OPTION_1},
274 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0xd031}, MSG_OPTION_1},
275 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0xd033}, MSG_OPTION_1},
276 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0xd035}, MSG_OPTION_1},
277 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0xd055}, MSG_OPTION_1},
278 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0xd057}, MSG_OPTION_1},
279 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0xd058}, MSG_OPTION_1},
280 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0xd155}, MSG_OPTION_1},
281 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0xd157}, MSG_OPTION_1},
282 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0xd255}, MSG_OPTION_1},
283 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0xd257}, MSG_OPTION_1},
284 {{ 0, 0, 0, OPTION_VENDOR0x0af0, 0xd357}, MSG_OPTION_1},
285 {{ 0, 0, 0, ATHEROS_VENDOR0x0cf3, 0x20ff}, MSG_ATHEROS_1},
286};
287static uint32 kDevicesCount = sizeof(kDevices) / sizeof(kDevices[0]);
288
289
290typedef struct _my_device {
291 usb_device device;
292 bool removed;
293 mutex lock;
294 struct _my_device *link;
295
296 // device state
297 usb_pipe bulk_in;
298 usb_pipe bulk_out;
299 uint8 interface;
300 uint8 alternate_setting;
301
302 // used to store callback information
303 sem_id notify;
304 status_t status;
305 size_t actual_length;
306
307 msgType type[3];
308} my_device;
309
310
311int32 api_version = B_CUR_DRIVER_API_VERSION2;
312static usb_module_info *gUSBModule = NULL__null;
313static my_device *gDeviceList = NULL__null;
314static uint32 gDeviceCount = 0;
315static mutex gDeviceListLock;
316
317
318//
319//#pragma mark - Device Allocation Helper Functions
320//
321
322
323static void
324my_free_device(my_device *device)
325{
326 mutex_lock(&device->lock);
327 mutex_destroy(&device->lock);
328 delete_sem(device->notify);
329 free(device);
330}
331
332
333//
334//#pragma mark - Bulk-only Functions
335//
336
337
338static void
339my_callback(void *cookie, status_t status, void *data,
340 size_t actualLength)
341{
342 my_device *device = (my_device *)cookie;
343 device->status = status;
344 device->actual_length = actualLength;
345 release_sem(device->notify);
346}
347
348
349static status_t
350my_transfer_data(my_device *device, bool directionIn, void *data,
351 size_t dataLength)
352{
353 status_t result = gUSBModule->queue_bulk(directionIn ? device->bulk_in
354 : device->bulk_out, data, dataLength, my_callback, device);
355 if (result != B_OK((int)0)) {
356 TRACE_ALWAYS("failed to queue data transfer\n")dprintf("usb_modeswitch" ": " "failed to queue data transfer\n"
)
;
357 return result;
358 }
359
360 do {
361 bigtime_t timeout = directionIn ? 500000 : 500000;
362 result = acquire_sem_etc(device->notify, 1, B_RELATIVE_TIMEOUT,
363 timeout);
364 if (result == B_TIMED_OUT((-2147483647 - 1) + 9)) {
365 // Cancel the transfer and collect the sem that should now be
366 // released through the callback on cancel. Handling of device
367 // reset is done in usb_printer_operation() when it detects that
368 // the transfer failed.
369 gUSBModule->cancel_queued_transfers(directionIn ? device->bulk_in
370 : device->bulk_out);
371 acquire_sem_etc(device->notify, 1, B_RELATIVE_TIMEOUT, 0);
372 }
373 } while (result == B_INTERRUPTED((-2147483647 - 1) + 10));
374
375 if (result != B_OK((int)0)) {
376 TRACE_ALWAYS("acquire_sem failed while waiting for data transfer\n")dprintf("usb_modeswitch" ": " "acquire_sem failed while waiting for data transfer\n"
)
;
377 return result;
378 }
379
380 return B_OK((int)0);
381}
382
383
384enum msgType
385my_get_msg_type(const usb_device_descriptor *desc, int index)
386{
387 for (uint32 i = 0; i < kDevicesCount; i++) {
388 if (kDevices[i].desc.dev_class != 0x0
389 && kDevices[i].desc.dev_class != desc->device_class)
390 continue;
391 if (kDevices[i].desc.dev_subclass != 0x0
392 && kDevices[i].desc.dev_subclass != desc->device_subclass)
393 continue;
394 if (kDevices[i].desc.dev_protocol != 0x0
395 && kDevices[i].desc.dev_protocol != desc->device_protocol)
396 continue;
397 if (kDevices[i].desc.vendor != 0x0
398 && kDevices[i].desc.vendor != desc->vendor_id)
399 continue;
400 if (kDevices[i].desc.product != 0x0
401 && kDevices[i].desc.product != desc->product_id)
402 continue;
403 switch (index) {
404 case 0:
405 return kDevices[i].type;
406 case 1:
407 return kDevices[i].type2;
408 case 2:
409 return kDevices[i].type3;
410 }
411
412 }
413
414 return MSG_NONE;
415}
416
417
418
419status_t
420my_modeswitch(my_device* device)
421{
422 status_t err = B_OK((int)0);
423 if (device->type[0] == MSG_NONE)
424 return B_OK((int)0);
425 for (int i = 0; i < 3; i++) {
426 if (device->type[i] == MSG_NONE)
427 break;
428
429 err = my_transfer_data(device, false, kDevicesMsg[device->type[i]],
430 sizeof(kDevicesMsg[device->type[i]]));
431 if (err != B_OK((int)0)) {
432 TRACE_ALWAYS("send message %d failed\n", i + 1)dprintf("usb_modeswitch" ": " "send message %d failed\n", i +
1)
;
433 return err;
434 }
435
436 TRACE("device switched: %p\n", device)dprintf("usb_modeswitch" ": " "device switched: %p\n", device
)
;
437
438 char data[36];
439 err = my_transfer_data(device, true, data, sizeof(data));
440 if (err != B_OK((int)0)) {
441 TRACE_ALWAYS("receive response %d failed 0x%" B_PRIx32 "\n",dprintf("usb_modeswitch" ": " "receive response %d failed 0x%"
"" "x" "\n", i + 1, device->status)
442 i + 1, device->status)dprintf("usb_modeswitch" ": " "receive response %d failed 0x%"
"" "x" "\n", i + 1, device->status)
;
443 return err;
444 }
445 TRACE("device switched (response length %ld)\n", device->actual_length)dprintf("usb_modeswitch" ": " "device switched (response length %ld)\n"
, device->actual_length)
;
446 }
447
448 TRACE("device switched: %p\n", device)dprintf("usb_modeswitch" ": " "device switched: %p\n", device
)
;
449
450 return B_OK((int)0);
451}
452
453
454//
455//#pragma mark - Device Attach/Detach Notifications and Callback
456//
457
458
459static status_t
460my_device_added(usb_device newDevice, void **cookie)
461{
462 TRACE("device_added(0x%08" B_PRIx32 ")\n", newDevice)dprintf("usb_modeswitch" ": " "device_added(0x%08" "" "x" ")\n"
, newDevice)
;
463 my_device *device = (my_device *)malloc(sizeof(my_device));
1
Memory is allocated
464 device->device = newDevice;
465 device->removed = false;
466 device->interface = 0xff;
467 device->alternate_setting = 0;
468
469 // scan through the interfaces to find our bulk-only data interface
470 const usb_configuration_info *configuration =
471 gUSBModule->get_configuration(newDevice);
472 if (configuration == NULL__null) {
2
Assuming 'configuration' is not equal to NULL
3
Taking false branch
473 free(device);
474 return B_ERROR(-1);
475 }
476
477 for (size_t i = 0; i < configuration->interface_count; i++) {
4
Assuming the condition is true
5
Loop condition is true. Entering loop body
13
Assuming the condition is true
14
Loop condition is true. Entering loop body
22
Assuming the condition is true
23
Loop condition is true. Entering loop body
478 usb_interface_info *interface = configuration->interface[i].active;
479 if (interface == NULL__null)
6
Assuming 'interface' is not equal to NULL
7
Taking false branch
15
Assuming 'interface' is not equal to NULL
16
Taking false branch
24
Assuming 'interface' is not equal to NULL
25
Taking false branch
480 continue;
481
482 if (true) {
8
Taking true branch
17
Taking true branch
26
Taking true branch
483
484 bool hasIn = false;
485 bool hasOut = false;
486 for (size_t j = 0; j < interface->endpoint_count; j++) {
9
Assuming the condition is false
10
Loop condition is false. Execution continues on line 506
18
Assuming the condition is false
19
Loop condition is false. Execution continues on line 506
27
Assuming the condition is true
28
Loop condition is true. Entering loop body
35
Assuming the condition is true
36
Loop condition is true. Entering loop body
487 usb_endpoint_info *endpoint = &interface->endpoint[j];
488 if (endpoint == NULL__null
29
Assuming 'endpoint' is not equal to NULL
31
Taking false branch
38
Taking false branch
489 || endpoint->descr->attributes != USB_ENDPOINT_ATTR_BULK0x02)
30
Assuming the condition is false
37
Assuming the condition is false
490 continue;
491
492 if (!hasIn && (endpoint->descr->endpoint_address
32
Assuming the condition is false
33
Taking false branch
39
Assuming the condition is true
40
Taking true branch
493 & USB_ENDPOINT_ADDR_DIR_IN0x80)) {
494 device->bulk_in = endpoint->handle;
495 hasIn = true;
496 } else if (!hasOut && (endpoint->descr->endpoint_address
34
Taking true branch
497 & USB_ENDPOINT_ADDR_DIR_IN0x80) == 0) {
498 device->bulk_out = endpoint->handle;
499 hasOut = true;
500 }
501
502 if (hasIn && hasOut)
41
Taking true branch
503 break;
42
Execution continues on line 506
504 }
505
506 if (!(hasIn && hasOut))
11
Taking true branch
20
Taking true branch
43
Taking false branch
507 continue;
12
Execution continues on line 477
21
Execution continues on line 477
508
509 device->interface = interface->descr->interface_number;
510 device->alternate_setting = interface->descr->alternate_setting;
511
512 break;
44
Execution continues on line 516
513 }
514 }
515
516 if (device->interface == 0xff) {
45
Assuming the condition is false
46
Taking false branch
517 TRACE_ALWAYS("no valid interface found\n")dprintf("usb_modeswitch" ": " "no valid interface found\n");
518 free(device);
519 return B_ERROR(-1);
520 }
521
522 const usb_device_descriptor *descriptor
523 = gUSBModule->get_device_descriptor(newDevice);
524 if (descriptor == NULL__null) {
47
Assuming 'descriptor' is not equal to NULL
48
Taking false branch
525 free(device);
526 return B_ERROR(-1);
527 }
528 for (int i = 0; i < 3; i++) {
49
Loop condition is true. Entering loop body
50
Loop condition is true. Entering loop body
51
Loop condition is true. Entering loop body
52
Loop condition is false. Execution continues on line 532
529 device->type[i] = my_get_msg_type(descriptor, i);
530 }
531
532 mutex_init(&device->lock, DRIVER_NAME"usb_modeswitch" " device lock");
533
534 device->notify = create_sem(0, DRIVER_NAME"usb_modeswitch" " callback notify");
535 if (device->notify < B_OK((int)0)) {
53
Assuming the condition is true
54
Taking true branch
536 mutex_destroy(&device->lock);
537 free(device);
55
Memory is released
538 return device->notify;
56
Use of memory after it is freed
539 }
540
541 mutex_lock(&gDeviceListLock);
542 device->link = gDeviceList;
543 gDeviceList = device;
544 mutex_unlock(&gDeviceListLock);
545
546 *cookie = device;
547
548 return my_modeswitch(device);
549}
550
551
552static status_t
553my_device_removed(void *cookie)
554{
555 TRACE("device_removed(%p)\n", cookie)dprintf("usb_modeswitch" ": " "device_removed(%p)\n", cookie);
556 my_device *device = (my_device *)cookie;
557
558 mutex_lock(&gDeviceListLock);
559 if (gDeviceList == device) {
560 gDeviceList = device->link;
561 } else {
562 my_device *element = gDeviceList;
563 while (element) {
564 if (element->link == device) {
565 element->link = device->link;
566 break;
567 }
568
569 element = element->link;
570 }
571 }
572 gDeviceCount--;
573
574 device->removed = true;
575 gUSBModule->cancel_queued_transfers(device->bulk_in);
576 gUSBModule->cancel_queued_transfers(device->bulk_out);
577 my_free_device(device);
578
579 mutex_unlock(&gDeviceListLock);
580 return B_OK((int)0);
581}
582
583
584//
585//#pragma mark - Driver Entry Points
586//
587
588
589status_t
590init_hardware()
591{
592 TRACE("init_hardware()\n")dprintf("usb_modeswitch" ": " "init_hardware()\n");
593 return B_OK((int)0);
594}
595
596
597status_t
598init_driver()
599{
600 TRACE("init_driver()\n")dprintf("usb_modeswitch" ": " "init_driver()\n");
601 static usb_notify_hooks notifyHooks = {
602 &my_device_added,
603 &my_device_removed
604 };
605
606 gDeviceList = NULL__null;
607 gDeviceCount = 0;
608 mutex_init(&gDeviceListLock, DRIVER_NAME"usb_modeswitch" " device list lock");
609
610 TRACE("trying module %s\n", B_USB_MODULE_NAME)dprintf("usb_modeswitch" ": " "trying module %s\n", "bus_managers/usb/v3"
)
;
611 status_t result = get_module(B_USB_MODULE_NAME"bus_managers/usb/v3",
612 (module_info **)&gUSBModule);
613 if (result < B_OK((int)0)) {
614 TRACE_ALWAYS("getting module failed 0x%08" B_PRIx32 "\n", result)dprintf("usb_modeswitch" ": " "getting module failed 0x%08" ""
"x" "\n", result)
;
615 mutex_destroy(&gDeviceListLock);
616 return result;
617 }
618
619 size_t descriptorsSize = kDevicesCount * sizeof(usb_support_descriptor);
620 usb_support_descriptor *supportedDevices =
621 (usb_support_descriptor *)malloc(descriptorsSize);
622 if (supportedDevices == NULL__null) {
623 TRACE_ALWAYS("descriptor allocation failed\n")dprintf("usb_modeswitch" ": " "descriptor allocation failed\n"
)
;
624 put_module(B_USB_MODULE_NAME"bus_managers/usb/v3");
625 mutex_destroy(&gDeviceListLock);
626 return result;
627 }
628
629 for (uint32 i = 0; i < kDevicesCount; i++)
630 supportedDevices[i] = kDevices[i].desc;
631
632 gUSBModule->register_driver(DRIVER_NAME"usb_modeswitch", supportedDevices, kDevicesCount,
633 NULL__null);
634 gUSBModule->install_notify(DRIVER_NAME"usb_modeswitch", &notifyHooks);
635 free(supportedDevices);
636 return B_OK((int)0);
637}
638
639
640void
641uninit_driver()
642{
643 TRACE("uninit_driver()\n")dprintf("usb_modeswitch" ": " "uninit_driver()\n");
644 gUSBModule->uninstall_notify(DRIVER_NAME"usb_modeswitch");
645 mutex_lock(&gDeviceListLock);
646 mutex_destroy(&gDeviceListLock);
647 put_module(B_USB_MODULE_NAME"bus_managers/usb/v3");
648}
649
650
651const char **
652publish_devices()
653{
654 TRACE("publish_devices()\n")dprintf("usb_modeswitch" ": " "publish_devices()\n");
655 return NULL__null;
656}
657
658
659device_hooks *
660find_device(const char *name)
661{
662 TRACE("find_device()\n")dprintf("usb_modeswitch" ": " "find_device()\n");
663 return NULL__null;
664}