xref: /haiku/src/add-ons/kernel/drivers/common/usb_modeswitch.cpp (revision 1ae464b9cfbe9520ebd54d66fef6f36814f5d3d7)
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"
25 
26 #define TRACE_USB_MODESWITCH 1
27 #ifdef TRACE_USB_MODESWITCH
28 #define TRACE(x...)			dprintf(DRIVER_NAME ": " x)
29 #else
30 #define TRACE(x...)			/* nothing */
31 #endif
32 #define TRACE_ALWAYS(x...)	dprintf(DRIVER_NAME ": " x)
33 #define ENTER()	TRACE("%s", __FUNCTION__)
34 
35 
36 enum 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 
52 unsigned 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_VENDOR	0x12d1
123 #define NOKIA_VENDOR	0x0421
124 #define NOVATEL_VENDOR	0x1410
125 #define ZYDAS_VENDOR	0x0ace
126 #define ZTE_VENDOR		0x19d2
127 #define OLIVETTI_VENDOR	0x0b3c
128 #define OPTION_VENDOR	0x0af0
129 #define ATHEROS_VENDOR	0x0cf3
130 
131 
132 static const struct {
133 	usb_support_descriptor desc;
134 	msgType type, type2, type3;
135 } kDevices[] = {
136 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x101e}, MSG_HUAWEI_1},
137 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x1030}, MSG_HUAWEI_2},
138 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x1031}, MSG_HUAWEI_2},
139 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x1446}, MSG_HUAWEI_3},
140 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x1449}, MSG_HUAWEI_3},
141 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x14ad}, MSG_HUAWEI_3},
142 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x14b5}, MSG_HUAWEI_3},
143 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x14b7}, MSG_HUAWEI_3},
144 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x14ba}, MSG_HUAWEI_3},
145 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x14c1}, MSG_HUAWEI_3},
146 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x14c3}, MSG_HUAWEI_3},
147 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x14c4}, MSG_HUAWEI_3},
148 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x14c5}, MSG_HUAWEI_3},
149 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x14d1}, MSG_HUAWEI_3},
150 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x14fe}, MSG_HUAWEI_3},
151 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x1505}, MSG_HUAWEI_3},
152 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x151a}, MSG_HUAWEI_3},
153 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x1520}, MSG_HUAWEI_3},
154 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x1521}, MSG_HUAWEI_3},
155 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x1523}, MSG_HUAWEI_3},
156 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x1526}, MSG_HUAWEI_3},
157 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x1553}, MSG_HUAWEI_3},
158 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x1557}, MSG_HUAWEI_3},
159 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x155b}, MSG_HUAWEI_3},
160 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x156a}, MSG_HUAWEI_3},
161 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x1576}, MSG_HUAWEI_3},
162 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x157d}, MSG_HUAWEI_3},
163 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x1583}, MSG_HUAWEI_3},
164 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x15ca}, MSG_HUAWEI_3},
165 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x15e7}, MSG_HUAWEI_3},
166 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x1c0b}, MSG_HUAWEI_3},
167 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x1c1b}, MSG_HUAWEI_3},
168 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x1c24}, MSG_HUAWEI_3},
169 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x1da1}, MSG_HUAWEI_3},
170 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x1f01}, MSG_HUAWEI_3},
171 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x1f02}, MSG_HUAWEI_3},
172 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x1f03}, MSG_HUAWEI_3},
173 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x1f11}, MSG_HUAWEI_3},
174 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x1f15}, MSG_HUAWEI_3},
175 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x1f16}, MSG_HUAWEI_3},
176 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x1f17}, MSG_HUAWEI_3},
177 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x1f18}, MSG_HUAWEI_3},
178 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x1f19}, MSG_HUAWEI_3},
179 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x1f1b}, MSG_HUAWEI_3},
180 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x1f1c}, MSG_HUAWEI_3},
181 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x1f1d}, MSG_HUAWEI_3},
182 	{{ 0, 0, 0, HUAWEI_VENDOR, 0x1f1e}, MSG_HUAWEI_3},
183 	{{ 0, 0, 0, NOKIA_VENDOR, 0x060c}, MSG_NOKIA_1},
184 	{{ 0, 0, 0, NOKIA_VENDOR, 0x0610}, MSG_NOKIA_1},
185 	{{ 0, 0, 0, NOKIA_VENDOR, 0x061d}, MSG_NOKIA_1},
186 	{{ 0, 0, 0, NOKIA_VENDOR, 0x0622}, MSG_NOKIA_1},
187 	{{ 0, 0, 0, NOKIA_VENDOR, 0x0627}, MSG_NOKIA_1},
188 	{{ 0, 0, 0, NOKIA_VENDOR, 0x062c}, MSG_NOKIA_1},
189 	{{ 0, 0, 0, NOKIA_VENDOR, 0x0632}, MSG_NOKIA_1},
190 	{{ 0, 0, 0, NOKIA_VENDOR, 0x0637}, MSG_NOKIA_1},
191 	{{ 0, 0, 0, NOVATEL_VENDOR, 0x5010}, MSG_NOKIA_1},
192 	{{ 0, 0, 0, NOVATEL_VENDOR, 0x5020}, MSG_NOKIA_1},
193 	{{ 0, 0, 0, NOVATEL_VENDOR, 0x5030}, MSG_NOKIA_1},
194 	{{ 0, 0, 0, NOVATEL_VENDOR, 0x5031}, MSG_NOKIA_1},
195 	{{ 0, 0, 0, NOVATEL_VENDOR, 0x5041}, MSG_NOKIA_1},
196 	{{ 0, 0, 0, NOVATEL_VENDOR, 0x5059}, MSG_NOKIA_1},
197 	{{ 0, 0, 0, NOVATEL_VENDOR, 0x7001}, MSG_NOKIA_1},
198 	{{ 0, 0, 0, ZYDAS_VENDOR, 0x2011}, MSG_NOKIA_1},
199 	{{ 0, 0, 0, ZYDAS_VENDOR, 0x20ff}, MSG_NOKIA_1},
200 	{{ 0, 0, 0, ZTE_VENDOR, 0x0013}, MSG_NOKIA_1},
201 	{{ 0, 0, 0, ZTE_VENDOR, 0x0026}, MSG_NOKIA_1},
202 	{{ 0, 0, 0, ZTE_VENDOR, 0x0031}, MSG_NOKIA_1},
203 	{{ 0, 0, 0, ZTE_VENDOR, 0x0083}, MSG_NOKIA_1},
204 	{{ 0, 0, 0, ZTE_VENDOR, 0x0101}, MSG_NOKIA_1},
205 	{{ 0, 0, 0, ZTE_VENDOR, 0x0115}, MSG_NOKIA_1},
206 	{{ 0, 0, 0, ZTE_VENDOR, 0x0120}, MSG_NOKIA_1},
207 	{{ 0, 0, 0, ZTE_VENDOR, 0x0169}, MSG_NOKIA_1},
208 	{{ 0, 0, 0, ZTE_VENDOR, 0x0325}, MSG_NOKIA_1},
209 	{{ 0, 0, 0, ZTE_VENDOR, 0x1001}, MSG_NOKIA_1},
210 	{{ 0, 0, 0, ZTE_VENDOR, 0x1007}, MSG_NOKIA_1},
211 	{{ 0, 0, 0, ZTE_VENDOR, 0x1009}, MSG_NOKIA_1},
212 	{{ 0, 0, 0, ZTE_VENDOR, 0x1013}, MSG_NOKIA_1},
213 	{{ 0, 0, 0, ZTE_VENDOR, 0x1017}, MSG_NOKIA_1},
214 	{{ 0, 0, 0, ZTE_VENDOR, 0x1171}, MSG_NOKIA_1},
215 	{{ 0, 0, 0, ZTE_VENDOR, 0x1175}, MSG_NOKIA_1},
216 	{{ 0, 0, 0, ZTE_VENDOR, 0x1179}, MSG_NOKIA_1},
217 	{{ 0, 0, 0, ZTE_VENDOR, 0x1201}, MSG_NOKIA_1},
218 	{{ 0, 0, 0, ZTE_VENDOR, 0x1523}, MSG_NOKIA_1},
219 	{{ 0, 0, 0, ZTE_VENDOR, 0xffde}, MSG_NOKIA_1},
220 	{{ 0, 0, 0, ZTE_VENDOR, 0x0003}, MSG_ZTE_1, MSG_ZTE_2},
221 	{{ 0, 0, 0, ZTE_VENDOR, 0x0053}, MSG_ZTE_1, MSG_ZTE_2},
222 	{{ 0, 0, 0, ZTE_VENDOR, 0x0103}, MSG_ZTE_1, MSG_ZTE_2},
223 	{{ 0, 0, 0, ZTE_VENDOR, 0x0154}, MSG_ZTE_1, MSG_ZTE_2},
224 	{{ 0, 0, 0, ZTE_VENDOR, 0x1224}, MSG_ZTE_1, MSG_ZTE_2},
225 	{{ 0, 0, 0, ZTE_VENDOR, 0x1517}, MSG_ZTE_1, MSG_ZTE_2},
226 	{{ 0, 0, 0, ZTE_VENDOR, 0x1542}, MSG_ZTE_1, MSG_ZTE_2},
227 	{{ 0, 0, 0, ZTE_VENDOR, 0x0149}, MSG_ZTE_1, MSG_ZTE_2, MSG_ZTE_3},
228 	{{ 0, 0, 0, ZTE_VENDOR, 0x2000}, MSG_ZTE_1, MSG_ZTE_2, MSG_ZTE_3},
229 	{{ 0, 0, 0, OLIVETTI_VENDOR, 0xc700}, MSG_OLIVETTI_1},
230 	{{ 0, 0, 0, OLIVETTI_VENDOR, 0xf000}, MSG_OLIVETTI_2},
231 	{{ 0, 0, 0, OPTION_VENDOR, 0x6711}, MSG_OPTION_1},
232 	{{ 0, 0, 0, OPTION_VENDOR, 0x6731}, MSG_OPTION_1},
233 	{{ 0, 0, 0, OPTION_VENDOR, 0x6751}, MSG_OPTION_1},
234 	{{ 0, 0, 0, OPTION_VENDOR, 0x6771}, MSG_OPTION_1},
235 	{{ 0, 0, 0, OPTION_VENDOR, 0x6791}, MSG_OPTION_1},
236 	{{ 0, 0, 0, OPTION_VENDOR, 0x6811}, MSG_OPTION_1},
237 	{{ 0, 0, 0, OPTION_VENDOR, 0x6911}, MSG_OPTION_1},
238 	{{ 0, 0, 0, OPTION_VENDOR, 0x6951}, MSG_OPTION_1},
239 	{{ 0, 0, 0, OPTION_VENDOR, 0x6971}, MSG_OPTION_1},
240 	{{ 0, 0, 0, OPTION_VENDOR, 0x7011}, MSG_OPTION_1},
241 	{{ 0, 0, 0, OPTION_VENDOR, 0x7031}, MSG_OPTION_1},
242 	{{ 0, 0, 0, OPTION_VENDOR, 0x7051}, MSG_OPTION_1},
243 	{{ 0, 0, 0, OPTION_VENDOR, 0x7071}, MSG_OPTION_1},
244 	{{ 0, 0, 0, OPTION_VENDOR, 0x7111}, MSG_OPTION_1},
245 	{{ 0, 0, 0, OPTION_VENDOR, 0x7211}, MSG_OPTION_1},
246 	{{ 0, 0, 0, OPTION_VENDOR, 0x7251}, MSG_OPTION_1},
247 	{{ 0, 0, 0, OPTION_VENDOR, 0x7271}, MSG_OPTION_1},
248 	{{ 0, 0, 0, OPTION_VENDOR, 0x7301}, MSG_OPTION_1},
249 	{{ 0, 0, 0, OPTION_VENDOR, 0x7311}, MSG_OPTION_1},
250 	{{ 0, 0, 0, OPTION_VENDOR, 0x7361}, MSG_OPTION_1},
251 	{{ 0, 0, 0, OPTION_VENDOR, 0x7381}, MSG_OPTION_1},
252 	{{ 0, 0, 0, OPTION_VENDOR, 0x7401}, MSG_OPTION_1},
253 	{{ 0, 0, 0, OPTION_VENDOR, 0x7501}, MSG_OPTION_1},
254 	{{ 0, 0, 0, OPTION_VENDOR, 0x7601}, MSG_OPTION_1},
255 	{{ 0, 0, 0, OPTION_VENDOR, 0x7701}, MSG_OPTION_1},
256 	{{ 0, 0, 0, OPTION_VENDOR, 0x7706}, MSG_OPTION_1},
257 	{{ 0, 0, 0, OPTION_VENDOR, 0x7801}, MSG_OPTION_1},
258 	{{ 0, 0, 0, OPTION_VENDOR, 0x7901}, MSG_OPTION_1},
259 	{{ 0, 0, 0, OPTION_VENDOR, 0x8006}, MSG_OPTION_1},
260 	{{ 0, 0, 0, OPTION_VENDOR, 0x8200}, MSG_OPTION_1},
261 	{{ 0, 0, 0, OPTION_VENDOR, 0x8201}, MSG_OPTION_1},
262 	{{ 0, 0, 0, OPTION_VENDOR, 0x8300}, MSG_OPTION_1},
263 	{{ 0, 0, 0, OPTION_VENDOR, 0x8302}, MSG_OPTION_1},
264 	{{ 0, 0, 0, OPTION_VENDOR, 0x8304}, MSG_OPTION_1},
265 	{{ 0, 0, 0, OPTION_VENDOR, 0x8400}, MSG_OPTION_1},
266 	{{ 0, 0, 0, OPTION_VENDOR, 0x8600}, MSG_OPTION_1},
267 	{{ 0, 0, 0, OPTION_VENDOR, 0x8800}, MSG_OPTION_1},
268 	{{ 0, 0, 0, OPTION_VENDOR, 0x8900}, MSG_OPTION_1},
269 	{{ 0, 0, 0, OPTION_VENDOR, 0x9000}, MSG_OPTION_1},
270 	{{ 0, 0, 0, OPTION_VENDOR, 0xc031}, MSG_OPTION_1},
271 	{{ 0, 0, 0, OPTION_VENDOR, 0xc100}, MSG_OPTION_1},
272 	{{ 0, 0, 0, OPTION_VENDOR, 0xc031}, MSG_OPTION_1},
273 	{{ 0, 0, 0, OPTION_VENDOR, 0xd013}, MSG_OPTION_1},
274 	{{ 0, 0, 0, OPTION_VENDOR, 0xd031}, MSG_OPTION_1},
275 	{{ 0, 0, 0, OPTION_VENDOR, 0xd033}, MSG_OPTION_1},
276 	{{ 0, 0, 0, OPTION_VENDOR, 0xd035}, MSG_OPTION_1},
277 	{{ 0, 0, 0, OPTION_VENDOR, 0xd055}, MSG_OPTION_1},
278 	{{ 0, 0, 0, OPTION_VENDOR, 0xd057}, MSG_OPTION_1},
279 	{{ 0, 0, 0, OPTION_VENDOR, 0xd058}, MSG_OPTION_1},
280 	{{ 0, 0, 0, OPTION_VENDOR, 0xd155}, MSG_OPTION_1},
281 	{{ 0, 0, 0, OPTION_VENDOR, 0xd157}, MSG_OPTION_1},
282 	{{ 0, 0, 0, OPTION_VENDOR, 0xd255}, MSG_OPTION_1},
283 	{{ 0, 0, 0, OPTION_VENDOR, 0xd257}, MSG_OPTION_1},
284 	{{ 0, 0, 0, OPTION_VENDOR, 0xd357}, MSG_OPTION_1},
285 	{{ 0, 0, 0, ATHEROS_VENDOR, 0x20ff}, MSG_ATHEROS_1},
286 };
287 static uint32 kDevicesCount = sizeof(kDevices) / sizeof(kDevices[0]);
288 
289 
290 typedef 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 
311 int32 api_version = B_CUR_DRIVER_API_VERSION;
312 static usb_module_info *gUSBModule = NULL;
313 static my_device *gDeviceList = NULL;
314 static uint32 gDeviceCount = 0;
315 static mutex gDeviceListLock;
316 
317 
318 //
319 //#pragma mark - Device Allocation Helper Functions
320 //
321 
322 
323 static void
my_free_device(my_device * device)324 my_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 
338 static void
my_callback(void * cookie,status_t status,void * data,size_t actualLength)339 my_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 
349 static status_t
my_transfer_data(my_device * device,bool directionIn,void * data,size_t dataLength)350 my_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) {
356 		TRACE_ALWAYS("failed to queue data transfer\n");
357 		return result;
358 	}
359 
360 	do {
361 		bigtime_t timeout = 500000;
362 		result = acquire_sem_etc(device->notify, 1, B_RELATIVE_TIMEOUT,
363 			timeout);
364 		if (result == B_TIMED_OUT) {
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);
374 
375 	if (result != B_OK) {
376 		TRACE_ALWAYS("acquire_sem failed while waiting for data transfer\n");
377 		return result;
378 	}
379 
380 	return B_OK;
381 }
382 
383 
384 enum msgType
my_get_msg_type(const usb_device_descriptor * desc,int index)385 my_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 
419 status_t
my_modeswitch(my_device * device)420 my_modeswitch(my_device* device)
421 {
422 	status_t err = B_OK;
423 	if (device->type[0] == MSG_NONE)
424 			return B_OK;
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) {
432 			TRACE_ALWAYS("send message %d failed\n", i + 1);
433 			return err;
434 		}
435 
436 		TRACE("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) {
441 			TRACE_ALWAYS("receive response %d failed 0x%" B_PRIx32 "\n",
442 				i + 1, device->status);
443 			return err;
444 		}
445 		TRACE("device switched (response length %ld)\n", device->actual_length);
446 	}
447 
448 	TRACE("device switched: %p\n", device);
449 
450 	return B_OK;
451 }
452 
453 
454 //
455 //#pragma mark - Device Attach/Detach Notifications and Callback
456 //
457 
458 
459 static status_t
my_device_added(usb_device newDevice,void ** cookie)460 my_device_added(usb_device newDevice, void **cookie)
461 {
462 	TRACE("device_added(0x%08" B_PRIx32 ")\n", newDevice);
463 	my_device *device = (my_device *)malloc(sizeof(my_device));
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) {
473 		free(device);
474 		return B_ERROR;
475 	}
476 
477 	for (size_t i = 0; i < configuration->interface_count; i++) {
478 		usb_interface_info *interface = configuration->interface[i].active;
479 		if (interface == NULL)
480 			continue;
481 
482 		if (true) {
483 
484 			bool hasIn = false;
485 			bool hasOut = false;
486 			for (size_t j = 0; j < interface->endpoint_count; j++) {
487 				usb_endpoint_info *endpoint = &interface->endpoint[j];
488 				if (endpoint == NULL
489 					|| endpoint->descr->attributes != USB_ENDPOINT_ATTR_BULK)
490 					continue;
491 
492 				if (!hasIn && (endpoint->descr->endpoint_address
493 					& USB_ENDPOINT_ADDR_DIR_IN)) {
494 					device->bulk_in = endpoint->handle;
495 					hasIn = true;
496 				} else if (!hasOut && (endpoint->descr->endpoint_address
497 					& USB_ENDPOINT_ADDR_DIR_IN) == 0) {
498 					device->bulk_out = endpoint->handle;
499 					hasOut = true;
500 				}
501 
502 				if (hasIn && hasOut)
503 					break;
504 			}
505 
506 			if (!(hasIn && hasOut))
507 				continue;
508 
509 			device->interface = interface->descr->interface_number;
510 			device->alternate_setting = interface->descr->alternate_setting;
511 
512 			break;
513 		}
514 	}
515 
516 	if (device->interface == 0xff) {
517 		TRACE_ALWAYS("no valid interface found\n");
518 		free(device);
519 		return B_ERROR;
520 	}
521 
522 	const usb_device_descriptor *descriptor
523 		= gUSBModule->get_device_descriptor(newDevice);
524 	if (descriptor == NULL) {
525 		free(device);
526 		return B_ERROR;
527 	}
528 	for (int i = 0; i < 3; i++) {
529 		device->type[i] = my_get_msg_type(descriptor, i);
530 	}
531 
532 	mutex_init(&device->lock, DRIVER_NAME " device lock");
533 
534 	sem_id callbackSem = create_sem(0, DRIVER_NAME " callback notify");
535 	if (callbackSem < B_OK) {
536 		mutex_destroy(&device->lock);
537 		free(device);
538 		return callbackSem;
539 	}
540 	device->notify = callbackSem;
541 
542 	mutex_lock(&gDeviceListLock);
543 	device->link = gDeviceList;
544 	gDeviceList = device;
545 	mutex_unlock(&gDeviceListLock);
546 
547 	*cookie = device;
548 
549 	return my_modeswitch(device);
550 }
551 
552 
553 static status_t
my_device_removed(void * cookie)554 my_device_removed(void *cookie)
555 {
556 	TRACE("device_removed(%p)\n", cookie);
557 	my_device *device = (my_device *)cookie;
558 
559 	mutex_lock(&gDeviceListLock);
560 	if (gDeviceList == device) {
561 		gDeviceList = device->link;
562 	} else {
563 		my_device *element = gDeviceList;
564 		while (element) {
565 			if (element->link == device) {
566 				element->link = device->link;
567 				break;
568 			}
569 
570 			element = element->link;
571 		}
572 	}
573 	gDeviceCount--;
574 
575 	device->removed = true;
576 	gUSBModule->cancel_queued_transfers(device->bulk_in);
577 	gUSBModule->cancel_queued_transfers(device->bulk_out);
578 	my_free_device(device);
579 
580 	mutex_unlock(&gDeviceListLock);
581 	return B_OK;
582 }
583 
584 
585 //
586 //#pragma mark - Driver Entry Points
587 //
588 
589 
590 status_t
init_hardware()591 init_hardware()
592 {
593 	TRACE("init_hardware()\n");
594 	return B_OK;
595 }
596 
597 
598 status_t
init_driver()599 init_driver()
600 {
601 	TRACE("init_driver()\n");
602 	static usb_notify_hooks notifyHooks = {
603 		&my_device_added,
604 		&my_device_removed
605 	};
606 
607 	gDeviceList = NULL;
608 	gDeviceCount = 0;
609 	mutex_init(&gDeviceListLock, DRIVER_NAME " device list lock");
610 
611 	TRACE("trying module %s\n", B_USB_MODULE_NAME);
612 	status_t result = get_module(B_USB_MODULE_NAME,
613 		(module_info **)&gUSBModule);
614 	if (result < B_OK) {
615 		TRACE_ALWAYS("getting module failed 0x%08" B_PRIx32 "\n", result);
616 		mutex_destroy(&gDeviceListLock);
617 		return result;
618 	}
619 
620 	size_t descriptorsSize = kDevicesCount * sizeof(usb_support_descriptor);
621 	usb_support_descriptor *supportedDevices =
622 		(usb_support_descriptor *)malloc(descriptorsSize);
623 	if (supportedDevices == NULL) {
624 		TRACE_ALWAYS("descriptor allocation failed\n");
625 		put_module(B_USB_MODULE_NAME);
626 		mutex_destroy(&gDeviceListLock);
627 		return result;
628 	}
629 
630 	for (uint32 i = 0; i < kDevicesCount; i++)
631 		supportedDevices[i] = kDevices[i].desc;
632 
633 	gUSBModule->register_driver(DRIVER_NAME, supportedDevices, kDevicesCount,
634 		NULL);
635 	gUSBModule->install_notify(DRIVER_NAME, &notifyHooks);
636 	free(supportedDevices);
637 	return B_OK;
638 }
639 
640 
641 void
uninit_driver()642 uninit_driver()
643 {
644 	TRACE("uninit_driver()\n");
645 	gUSBModule->uninstall_notify(DRIVER_NAME);
646 	mutex_lock(&gDeviceListLock);
647 	mutex_destroy(&gDeviceListLock);
648 	put_module(B_USB_MODULE_NAME);
649 }
650 
651 
652 const char **
publish_devices()653 publish_devices()
654 {
655 	TRACE("publish_devices()\n");
656 	return NULL;
657 }
658 
659 
660 device_hooks *
find_device(const char * name)661 find_device(const char *name)
662 {
663 	TRACE("find_device()\n");
664 	return NULL;
665 }
666