Print this page
7974 Some USB3 drives don't attach
Reviewed by: Dan McDonald <danmcd@omniti.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/io/usb/usba/usbai_register.c
+++ new/usr/src/uts/common/io/usb/usba/usbai_register.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
|
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 *
25 25 * Copyright 2014 Garrett D'Amore <garrett@damore.org>
26 - * Copyright 2016 Joyent, Inc.
26 + * Copyright 2017 Joyent, Inc.
27 27 */
28 28
29 29 /*
30 30 * USBA: Solaris USB Architecture support
31 31 *
32 32 * This module builds a tree of parsed USB standard descriptors and unparsed
33 33 * Class/Vendor specific (C/V) descriptors. Routines are grouped into three
34 34 * groups: those which build the tree, those which take it down, and those which
35 35 * dump it.
36 36 *
37 37 * The tree built hangs off of the dev_cfg field of the usb_client_dev_data_t
38 38 * structure returned by usb_get_dev_data(). The tree consists of different
39 39 * kinds of tree nodes (usb_xxx_data_t) each containing a standard USB
40 40 * descriptor (usb_xxx_descr_t) and pointers to arrays of other nodes.
41 41 *
42 42 * Arrays are dynamically sized, as the descriptors coming from the device may
43 43 * lie, but the number of descriptors from the device is a more reliable
44 44 * indicator of configuration. This makes the code more robust. After the raw
45 45 * descriptor data has been parsed into a non-sparse tree, the tree is ordered
46 46 * and made sparse with a bin-sort style algorithm.
47 47 *
48 48 * dev_cfg is an array of configuration tree nodes. Each contains space for one
49 49 * parsed standard USB configuration descriptor, a pointer to an array of c/v
50 50 * tree nodes and a pointer to an array of interface tree nodes.
51 51 *
52 52 * Each interface tree node represents a group of interface descriptors, called
53 53 * alternates, with the same interface number. Thus, each interface tree node
54 54 * has a pointer to an array of alternate-interface tree nodes each containing a
55 55 * standard USB interface descriptor. Alternate-interface tree nodes also
56 56 * contain a pointer to an array of c/v tree nodes and a pointer to an array of
57 57 * endpoint tree nodes.
58 58 *
59 59 * Endpoint tree nodes contain a standard endpoint descriptor, plus a pointer to
60 60 * an array of c/v tree nodes.
61 61 *
62 62 * Each array in the tree contains elements ranging from 0 to the largest key
63 63 * value of it's elements. Endpoints are a special case. The direction bit is
64 64 * right shifted over three unused bits before the index is determined, leaving
65 65 * a range of 0..31 instead of a sparsely-populated range of 0..255.
66 66 *
67 67 * The indices of tree elements coincide with their USB key values. For
68 68 * example, standard USB devices have no configuration 0; if they have one
69 69 * configuration it is #1. dev_cfg[0] is zeroed out; dev_cfg[1] is the root
70 70 * of configuration #1.
71 71 *
72 72 * The idea here is for a driver to be able to parse the tree to easily find a
73 73 * desired descriptor. For example, the interval of endpoint 2, alternate 3,
74 74 * interface 1, configuration 1 would be:
75 75 * dv->dev_cfg[1].cfg_if[1].if_alt[3].altif_ep[2].ep_descr.bInterval
76 76 *
77 77 * How the tree is built:
78 78 *
79 79 * usb_build_descr_tree() is responsible for the whole process.
80 80 *
81 81 * Next, usba_build_descr_tree() coordinates parsing this byte stream,
82 82 * descriptor by descriptor. usba_build_descr_tree() calls the appropriate
83 83 * usba_process_xx_descr() function to interpret and install each descriptor in
84 84 * the tree, based on the descriptor's type. When done with this phase, a
85 85 * non-sparse tree exists containing tree nodes with descriptors in the order
86 86 * they were found in the raw data.
87 87 *
88 88 * All levels of the tree, except alternates, remain non-sparse. Alternates are
89 89 * moved, possibly, within their array, so that descriptors are indexed by their
90 90 * alternate ID.
91 91 *
92 92 * The usba_reg_state_t structure maintains state of the tree-building process,
93 93 * helping coordinate all routines involved.
94 94 */
95 95 #define USBA_FRAMEWORK
96 96 #include <sys/usb/usba.h>
97 97 #include <sys/usb/usba/usba_impl.h>
98 98 #include <sys/usb/usba/usba_private.h>
99 99 #include <sys/usb/usba/hcdi_impl.h>
100 100 #include <sys/usb/hubd/hub.h>
101 101
102 102 #include <sys/usb/usba/usbai_register_impl.h>
103 103
104 104 /*
105 105 * Header needed for use by this module only.
106 106 * However, function may be used in V0.8 drivers so needs to be global.
107 107 */
108 108 int usb_log_descr_tree(usb_client_dev_data_t *, usb_log_handle_t,
109 109 uint_t, uint_t);
110 110
111 111 /* Debug stuff */
112 112 usb_log_handle_t usbai_reg_log_handle;
113 113 uint_t usbai_register_errlevel = USB_LOG_L2;
114 114 uint_t usbai_register_dump_errlevel = USB_LOG_L2;
115 115 uint_t usbai_register_errmask = (uint_t)-1;
116 116
117 117 /* Function prototypes */
118 118 static int usba_build_descr_tree(dev_info_t *, usba_device_t *,
119 119 usb_client_dev_data_t *);
120 120 static void usba_process_cfg_descr(usba_reg_state_t *);
121 121 static int usba_process_if_descr(usba_reg_state_t *, boolean_t *);
122 122 static int usba_process_ep_descr(usba_reg_state_t *);
123 123 static int usba_process_ss_ep_comp_descr(usba_reg_state_t *);
124 124 static int usba_process_cv_descr(usba_reg_state_t *);
125 125 static int usba_set_parse_values(dev_info_t *dip, usba_device_t *usba_device,
126 126 usba_reg_state_t *state);
127 127 static void* usba_kmem_realloc(void *, int, int);
128 128 static void usba_augment_array(void **, uint_t, uint_t);
129 129 static void usba_make_alts_sparse(usb_alt_if_data_t **, uint_t *);
130 130
131 131 static void usba_order_tree(usba_reg_state_t *);
132 132
133 133 static void usba_free_if_array(usb_if_data_t *, uint_t);
134 134 static void usba_free_ep_array(usb_ep_data_t *, uint_t);
135 135 static void usba_free_cv_array(usb_cvs_data_t *, uint_t);
136 136
137 137 static int usba_dump_descr_tree(dev_info_t *, usb_client_dev_data_t *,
138 138 usb_log_handle_t, uint_t, uint_t);
139 139 static void usba_dump_if(usb_if_data_t *, usb_log_handle_t,
140 140 uint_t, uint_t, char *);
141 141 static void usba_dump_ep(uint_t, usb_ep_data_t *, usb_log_handle_t, uint_t,
142 142 uint_t, char *);
143 143 static void usba_dump_cv(usb_cvs_data_t *, usb_log_handle_t, uint_t, uint_t,
144 144 char *, int);
145 145 static void usba_dump_bin(uint8_t *, int, int, usb_log_handle_t,
146 146 uint_t, uint_t, char *, int);
147 147
148 148 /* Framework initialization. */
149 149 void
150 150 usba_usbai_register_initialization()
151 151 {
152 152 usbai_reg_log_handle = usb_alloc_log_hdl(NULL, "usbreg",
153 153 &usbai_register_errlevel,
154 154 &usbai_register_errmask, NULL,
155 155 0);
156 156
157 157 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
158 158 "usba_usbai_register_initialization");
159 159 }
160 160
161 161
162 162 /* Framework destruction. */
163 163 void
164 164 usba_usbai_register_destroy()
165 165 {
166 166 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
167 167 "usba_usbai_register destroy");
168 168
169 169 usb_free_log_hdl(usbai_reg_log_handle);
170 170 }
171 171
172 172
173 173 /*
174 174 * usb_client_attach:
175 175 *
176 176 * Arguments:
177 177 * dip - pointer to devinfo node of the client
178 178 * version - USBA registration version number
179 179 * flags - None used
180 180 *
181 181 * Return Values:
182 182 * USB_SUCCESS - attach succeeded
183 183 * USB_INVALID_ARGS - received null dip
184 184 * USB_INVALID_VERSION - version argument is incorrect.
185 185 * USB_FAILURE - other internal failure
186 186 */
187 187 /*ARGSUSED*/
188 188 int
189 189 usb_client_attach(dev_info_t *dip, uint_t version, usb_flags_t flags)
190 190 {
191 191 int rval;
192 192 usba_device_t *usba_device;
193 193
194 194 if (dip == NULL) {
195 195
196 196 return (USB_INVALID_ARGS);
197 197 }
198 198
199 199 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
200 200 "usb_client attach:");
201 201
202 202 usba_device = usba_get_usba_device(dip);
203 203
204 204 /*
205 205 * Allow exact match for legacy (DDK 0.8/9) drivers, or same major
206 206 * VERSion and smaller or same minor version for non-legacy drivers.
207 207 */
208 208 if ((version !=
209 209 USBA_MAKE_VER(USBA_LEG_MAJOR_VER, USBA_LEG_MINOR_VER)) &&
210 210 ((USBA_GET_MAJOR(version) != USBA_MAJOR_VER) ||
211 211 (USBA_GET_MINOR(version) > USBA_MINOR_VER))) {
212 212 USB_DPRINTF_L1(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
213 213 "Incorrect USB driver version for %s%d: found: %d.%d, "
214 214 "expecting %d.%d",
215 215 ddi_driver_name(dip), ddi_get_instance(dip),
216 216 USBA_GET_MAJOR(version), USBA_GET_MINOR(version),
217 217 USBA_MAJOR_VER, USBA_MINOR_VER);
218 218
219 219 return (USB_INVALID_VERSION);
220 220 }
221 221
222 222 if (version == USBA_MAKE_VER(USBA_LEG_MAJOR_VER, USBA_LEG_MINOR_VER)) {
223 223 USB_DPRINTF_L2(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
224 224 "Accepting legacy USB driver version %d.%d for %s%d",
225 225 USBA_LEG_MAJOR_VER, USBA_LEG_MINOR_VER,
226 226 ddi_driver_name(dip), ddi_get_instance(dip));
227 227 }
228 228
229 229 rval = ndi_prop_update_int(DDI_DEV_T_NONE, dip, "driver-major",
230 230 USBA_GET_MAJOR(version));
231 231 if (rval != DDI_PROP_SUCCESS) {
232 232
233 233 return (USB_FAILURE);
234 234 }
235 235 rval = ndi_prop_update_int(DDI_DEV_T_NONE, dip, "driver-minor",
236 236 USBA_GET_MINOR(version));
237 237 if (rval != DDI_PROP_SUCCESS) {
238 238
239 239 return (USB_FAILURE);
240 240 }
241 241
242 242 mutex_enter(&usba_device->usb_mutex);
243 243 if (strcmp(ddi_driver_name(dip), "usb_mid") != 0) {
244 244 usba_device->usb_client_flags[usba_get_ifno(dip)] |=
245 245 USBA_CLIENT_FLAG_ATTACH;
246 246 usba_device->usb_client_attach_list->dip = dip;
247 247 }
248 248 mutex_exit(&usba_device->usb_mutex);
249 249
250 250 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
251 251 "usb_client attach: done");
252 252
253 253 return (USB_SUCCESS);
254 254 }
255 255
256 256
257 257 /*
258 258 * usb_client_detach:
259 259 * free dev_data is reg != NULL, not much else to do
260 260 *
261 261 * Arguments:
262 262 * dip - pointer to devinfo node of the client
263 263 * reg - return registration data at this address
264 264 */
265 265 void
266 266 usb_client_detach(dev_info_t *dip, usb_client_dev_data_t *reg)
267 267 {
268 268 usba_device_t *usba_device = usba_get_usba_device(dip);
269 269
270 270 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
271 271 "usb_client_detach:");
272 272
273 273 if (dip) {
274 274 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
275 275 "Unregistering usb client %s%d: reg=0x%p",
276 276 ddi_driver_name(dip), ddi_get_instance(dip), (void *)reg);
277 277
278 278 usb_free_dev_data(dip, reg);
279 279
280 280 mutex_enter(&usba_device->usb_mutex);
281 281 if (strcmp(ddi_driver_name(dip), "usb_mid") != 0) {
282 282 usba_device->usb_client_flags[usba_get_ifno(dip)] &=
283 283 ~USBA_CLIENT_FLAG_ATTACH;
284 284 }
285 285 mutex_exit(&usba_device->usb_mutex);
286 286 }
287 287
288 288 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
289 289 "usb_client_detach done");
290 290 }
291 291
292 292
293 293 /*
294 294 * usb_register_client (deprecated):
295 295 * The client registers with USBA during attach.
296 296 */
297 297 /*ARGSUSED*/
298 298 int
299 299 usb_register_client(dev_info_t *dip, uint_t version,
300 300 usb_client_dev_data_t **reg, usb_reg_parse_lvl_t parse_level,
301 301 usb_flags_t flags)
302 302 {
303 303 int rval = usb_client_attach(dip, version, flags);
304 304
305 305 if (rval == USB_SUCCESS) {
306 306 rval = usb_get_dev_data(dip, reg, parse_level, flags);
307 307
308 308 if (rval != USB_SUCCESS) {
309 309 usb_client_detach(dip, NULL);
310 310 }
311 311 }
312 312
313 313 return (rval);
314 314 }
315 315
316 316
317 317 /*
318 318 * usb_unregister_client (deprecated):
319 319 * Undo the makings of usb_get_dev_data(). Free memory if allocated.
320 320 *
321 321 * Arguments:
322 322 * dip - pointer to devinfo node of the client
323 323 * reg - pointer to registration data to be freed
324 324 */
325 325 void
326 326 usb_unregister_client(dev_info_t *dip, usb_client_dev_data_t *reg)
327 327 {
328 328 usb_client_detach(dip, reg);
329 329 }
330 330
331 331
332 332 /*
333 333 * usb_get_dev_data:
334 334 * On completion, the registration data has been initialized.
335 335 * Most data items are straightforward.
336 336 * Among the items returned in the data is the tree of
337 337 * parsed descriptors, in dev_cfg; the number of configurations parsed,
338 338 * in dev_n_cfg; a pointer to the current configuration in the tree,
339 339 * in dev_curr_cfg; the index of the first valid interface in the
340 340 * tree, in dev_curr_if, and a parse level that accurately reflects what
341 341 * is in the tree, in dev_parse_level.
342 342 *
343 343 * This routine sets up directly-initialized fields, and calls
344 344 * usb_build_descr_tree() to parse the raw descriptors and initialize the
345 345 * tree.
346 346 *
347 347 * Parse_level determines the extent to which the tree is built. It has
348 348 * the following values:
349 349 *
350 350 * USB_PARSE_LVL_NONE - Build no tree. dev_n_cfg will return 0, dev_cfg
351 351 * and dev_curr_cfg will return NULL.
352 352 * USB_PARSE_LVL_IF - Parse configured interface only, if configuration#
353 353 * and interface properties are set (as when different
354 354 * interfaces are viewed by the OS as different device
355 355 * instances). If an OS device instance is set up to
356 356 * represent an entire physical device, this works
357 357 * like USB_PARSE_LVL_ALL.
358 358 * USB_PARSE_LVL_CFG - Parse entire configuration of configured interface
359 359 * only. This is like USB_PARSE_LVL_IF except entire
360 360 * configuration is returned.
361 361 * USB_PARSE_LVL_ALL - Parse entire device (all configurations), even
362 362 * when driver is bound to a single interface of a
363 363 * single configuration.
364 364 *
365 365 * No tree is built for root hubs, regardless of parse_level.
366 366 *
367 367 * Arguments:
368 368 * dip - pointer to devinfo node of the client
369 369 * version - USBA registration version number
370 370 * reg - return registration data at this address
371 371 * parse_level - See above
372 372 * flags - None used
373 373 *
374 374 * Return Values:
375 375 * USB_SUCCESS - usb_get_dev_data succeeded
376 376 * USB_INVALID_ARGS - received null dip or reg argument
377 377 * USB_INVALID_CONTEXT - called from callback context
378 378 * USB_FAILURE - bad descriptor info or other internal failure
379 379 *
380 380 * Note: The non-standard USB descriptors are returned in RAW format.
381 381 * returns initialized registration data. Most data items are clear.
382 382 * Among the items returned is the tree of parsed descriptors in dev_cfg;
383 383 * and the number of configurations parsed in dev_n_cfg.
384 384 *
385 385 * The registration data is not shared. each client receives its own
386 386 * copy.
387 387 */
388 388 /*ARGSUSED*/
389 389 int
390 390 usb_get_dev_data(dev_info_t *dip,
391 391 usb_client_dev_data_t **reg, usb_reg_parse_lvl_t parse_level,
392 392 usb_flags_t flags)
393 393 {
394 394 usb_client_dev_data_t *usb_reg = NULL;
395 395 char *tmpbuf = NULL;
396 396 usba_device_t *usba_device;
397 397 int rval = USB_SUCCESS;
398 398
399 399 if ((dip == NULL) || (reg == NULL)) {
400 400
401 401 return (USB_INVALID_ARGS);
402 402 }
403 403
404 404 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
405 405 "usb_get_dev_data: %s%d",
406 406 ddi_driver_name(dip), ddi_get_instance(dip));
407 407
408 408 *reg = NULL;
409 409
410 410 /* did the client attach first? */
411 411 if (ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
412 412 "driver-major", -1) == -1) {
413 413
414 414 return (USB_INVALID_VERSION);
415 415 }
416 416 if (ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
417 417 "driver-minor", -1) == -1) {
418 418
419 419 return (USB_INVALID_VERSION);
420 420 }
421 421
422 422 usb_reg = kmem_zalloc(sizeof (usb_client_dev_data_t), KM_SLEEP);
423 423 usba_device = usba_get_usba_device(dip);
424 424 usb_reg->dev_descr = usba_device->usb_dev_descr;
425 425 usb_reg->dev_default_ph = usba_get_dflt_pipe_handle(dip);
426 426 if (usb_reg->dev_default_ph == NULL) {
427 427 kmem_free(usb_reg, sizeof (usb_client_dev_data_t));
428 428
429 429 return (USB_FAILURE);
430 430 }
431 431
432 432 usb_reg->dev_iblock_cookie = usba_hcdi_get_hcdi(
433 433 usba_device->usb_root_hub_dip)->hcdi_soft_iblock_cookie;
434 434
435 435 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
436 436 "cookie = 0x%p", (void *)usb_reg->dev_iblock_cookie);
437 437
438 438 tmpbuf = (char *)kmem_zalloc(USB_MAXSTRINGLEN, KM_SLEEP);
439 439
440 440 if (usba_device->usb_mfg_str != NULL) {
441 441 usb_reg->dev_mfg = kmem_zalloc(
442 442 strlen(usba_device->usb_mfg_str) + 1, KM_SLEEP);
443 443 (void) strcpy(usb_reg->dev_mfg, usba_device->usb_mfg_str);
444 444 }
445 445
446 446 if (usba_device->usb_product_str != NULL) {
447 447 usb_reg->dev_product = kmem_zalloc(
448 448 strlen(usba_device->usb_product_str) + 1,
449 449 KM_SLEEP);
450 450 (void) strcpy(usb_reg->dev_product,
451 451 usba_device->usb_product_str);
452 452 }
453 453
454 454 if (usba_device->usb_serialno_str != NULL) {
455 455 usb_reg->dev_serial = kmem_zalloc(
456 456 strlen(usba_device->usb_serialno_str) + 1,
457 457 KM_SLEEP);
458 458 (void) strcpy(usb_reg->dev_serial,
459 459 usba_device->usb_serialno_str);
460 460 }
461 461
462 462 if ((usb_reg->dev_parse_level = parse_level) == USB_PARSE_LVL_NONE) {
463 463 rval = USB_SUCCESS;
464 464
465 465 } else if ((rval = usba_build_descr_tree(dip, usba_device, usb_reg)) !=
466 466 USB_SUCCESS) {
467 467 usb_unregister_client(dip, usb_reg);
468 468 usb_reg = NULL;
469 469 } else {
470 470
471 471 /* Current tree cfg is always zero if only one cfg in tree. */
472 472 if (usb_reg->dev_n_cfg == 1) {
473 473 usb_reg->dev_curr_cfg = &usb_reg->dev_cfg[0];
474 474 } else {
475 475 mutex_enter(&usba_device->usb_mutex);
476 476 usb_reg->dev_curr_cfg =
477 477 &usb_reg->dev_cfg[usba_device->usb_active_cfg_ndx];
478 478 mutex_exit(&usba_device->usb_mutex);
479 479 ASSERT(usb_reg->dev_curr_cfg != NULL);
480 480 ASSERT(usb_reg->dev_curr_cfg->cfg_descr.bLength ==
481 481 USB_CFG_DESCR_SIZE);
482 482 }
483 483
484 484 /*
485 485 * Keep dev_curr_if at device's single interface only if that
486 486 * particular interface has been explicitly defined by the
487 487 * device.
488 488 */
489 489 usb_reg->dev_curr_if = usba_get_ifno(dip);
490 490 #ifdef DEBUG
491 491 (void) usb_log_descr_tree(usb_reg, usbai_reg_log_handle,
492 492 usbai_register_dump_errlevel, (uint_t)-1);
493 493 #endif
494 494 /*
495 495 * Fail if interface and configuration of dev_curr_if and
496 496 * dev_curr_cfg don't exist or are invalid. (Shouldn't happen.)
497 497 * These indices must be reliable for tree traversal.
498 498 */
499 499 if ((usb_reg->dev_curr_cfg->cfg_n_if <= usb_reg->dev_curr_if) ||
500 500 (usb_reg->dev_curr_cfg->cfg_descr.bLength == 0) ||
501 501 (usb_reg->dev_curr_cfg->cfg_if[usb_reg->dev_curr_if].
502 502 if_n_alt == 0)) {
503 503 USB_DPRINTF_L2(DPRINT_MASK_ALL, usbai_reg_log_handle,
504 504 "usb_get_dev_data: dev_curr_cfg or "
505 505 "dev_curr_if have no descriptors");
506 506 usb_unregister_client(dip, usb_reg);
507 507 usb_reg = NULL;
508 508 rval = USB_FAILURE;
509 509 }
510 510 }
511 511
512 512 *reg = usb_reg;
513 513 kmem_free(tmpbuf, USB_MAXSTRINGLEN);
514 514
515 515 if (rval == USB_SUCCESS) {
516 516 usb_client_dev_data_list_t *entry = kmem_zalloc(
517 517 sizeof (*entry), KM_SLEEP);
518 518 mutex_enter(&usba_device->usb_mutex);
519 519
520 520 usba_device->usb_client_flags[usba_get_ifno(dip)] |=
521 521 USBA_CLIENT_FLAG_DEV_DATA;
522 522
523 523 entry->cddl_dip = dip;
524 524 entry->cddl_dev_data = usb_reg;
525 525 entry->cddl_ifno = usba_get_ifno(dip);
526 526
527 527 entry->cddl_next =
528 528 usba_device->usb_client_dev_data_list.cddl_next;
529 529 if (entry->cddl_next) {
530 530 entry->cddl_next->cddl_prev = entry;
531 531 }
532 532 entry->cddl_prev = &usba_device->usb_client_dev_data_list;
533 533 usba_device->usb_client_dev_data_list.cddl_next = entry;
534 534
535 535 mutex_exit(&usba_device->usb_mutex);
536 536 }
537 537
538 538 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
539 539 "usb_get_dev_data rval=%d", rval);
540 540
541 541 return (rval);
542 542 }
543 543
544 544
545 545 /*
546 546 * usb_free_dev_data
547 547 * undoes what usb_get_dev_data does
548 548 *
549 549 * Arguments:
550 550 * dip - pointer to devinfo node of the client
551 551 * reg - return registration data at this address
552 552 */
553 553 void
554 554 usb_free_dev_data(dev_info_t *dip, usb_client_dev_data_t *reg)
555 555 {
556 556 if (dip == NULL) {
557 557
558 558 return;
559 559 }
560 560
561 561 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
562 562 "usb_free_dev_data %s%d: reg=0x%p",
563 563 ddi_driver_name(dip), ddi_get_instance(dip), (void *)reg);
564 564
565 565 if (reg != NULL) {
566 566 usba_device_t *usba_device = usba_get_usba_device(dip);
567 567 usb_client_dev_data_list_t *next, *prev, *entry;
568 568 int matches = 0;
569 569
570 570 if (reg->dev_serial != NULL) {
571 571 kmem_free((char *)reg->dev_serial,
572 572 strlen((char *)reg->dev_serial) + 1);
573 573 }
574 574
575 575 if (reg->dev_product != NULL) {
576 576 kmem_free((char *)reg->dev_product,
577 577 strlen((char *)reg->dev_product) + 1);
578 578 }
579 579
580 580 if (reg->dev_mfg != NULL) {
581 581 kmem_free((char *)reg->dev_mfg,
582 582 strlen((char *)reg->dev_mfg) + 1);
583 583 }
584 584
585 585 /* Free config tree under reg->dev_cfg. */
586 586 if (reg->dev_cfg != NULL) {
587 587 usb_free_descr_tree(dip, reg);
588 588 }
589 589
590 590 mutex_enter(&usba_device->usb_mutex);
591 591 prev = &usba_device->usb_client_dev_data_list;
592 592 entry = usba_device->usb_client_dev_data_list.cddl_next;
593 593
594 594 /* free the entries in usb_client_data_list */
595 595 while (entry) {
596 596 next = entry->cddl_next;
597 597 if ((dip == entry->cddl_dip) &&
598 598 (reg == entry->cddl_dev_data)) {
599 599 prev->cddl_next = entry->cddl_next;
600 600 if (entry->cddl_next) {
601 601 entry->cddl_next->cddl_prev = prev;
602 602 }
603 603 kmem_free(entry, sizeof (*entry));
604 604 } else {
605 605 /*
606 606 * any other entries for this interface?
607 607 */
608 608 if (usba_get_ifno(dip) == entry->cddl_ifno) {
609 609 matches++;
610 610 }
611 611 prev = entry;
612 612 }
613 613 entry = next;
614 614 }
615 615
616 616 USB_DPRINTF_L3(DPRINT_MASK_REGISTER,
617 617 usbai_reg_log_handle,
618 618 "usb_free_dev_data: next=0x%p flags[%d]=0x%x",
619 619 (void *)usba_device->usb_client_dev_data_list.cddl_next,
620 620 usba_get_ifno(dip),
621 621 usba_device->usb_client_flags[usba_get_ifno(dip)]);
622 622
623 623 if (matches == 0) {
624 624 usba_device->
625 625 usb_client_flags[usba_get_ifno(dip)] &=
626 626 ~USBA_CLIENT_FLAG_DEV_DATA;
627 627 }
628 628 mutex_exit(&usba_device->usb_mutex);
629 629
630 630 kmem_free(reg, sizeof (usb_client_dev_data_t));
631 631 }
632 632
633 633 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
634 634 "usb_free_dev_data done");
635 635 }
636 636
637 637 /*
638 638 * usba_build_descr_tree:
639 639 * This builds the descriptor tree. See module header comment for tree
640 640 * description.
641 641 *
642 642 * Arguments:
643 643 * dip - devinfo pointer - cannot be NULL.
644 644 * usba_device - pointer to usba_device structure.
645 645 * usb_reg - pointer to area returned to client describing device.
646 646 * number of configuration (dev_n_cfg) and array of
647 647 * configurations (dev_cfg) are initialized here -
648 648 * dev_parse_level used and may be modified to fit
649 649 * current configuration.
650 650 * Return values:
651 651 * USB_SUCCESS - Tree build succeeded
652 652 * USB_INVALID_ARGS - dev_parse_level in usb_reg is invalid.
653 653 * USB_FAILURE - Bad descriptor info or other internal failure
654 654 */
655 655 static int
656 656 usba_build_descr_tree(dev_info_t *dip, usba_device_t *usba_device,
657 657 usb_client_dev_data_t *usb_reg)
658 658 {
659 659 usba_reg_state_t state; /* State of tree construction */
660 660 int cfg_len_so_far = 0; /* Bytes found, this config. */
661 661 uint8_t *last_byte; /* Ptr to the end of the cfg cloud. */
662 662 uint_t this_cfg_ndx; /* Configuration counter. */
663 663 uint_t high_cfg_bound; /* High config index + 1. */
664 664 uint_t low_cfg_bound; /* Low config index. */
665 665 boolean_t process_this_if_tree = B_FALSE; /* Save alts, eps, */
666 666 /* of this interface. */
667 667
668 668 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
669 669 "usba_build_descr_tree starting");
670 670
671 671 bzero(&state, sizeof (usba_reg_state_t));
672 672 state.dip = dip;
673 673
674 674 /*
675 675 * Set config(s) and interface(s) to parse based on parse level.
676 676 * Adjust parse_level according to which configs and interfaces are
677 677 * made available by the device.
678 678 */
679 679 state.st_dev_parse_level = usb_reg->dev_parse_level;
680 680 if (usba_set_parse_values(dip, usba_device, &state) != USB_SUCCESS) {
681 681
682 682 return (USB_INVALID_ARGS);
683 683 }
684 684 usb_reg->dev_parse_level = state.st_dev_parse_level;
685 685
686 686 /* Preallocate configurations based on parse level. */
687 687 if (usb_reg->dev_parse_level == USB_PARSE_LVL_ALL) {
688 688 usb_reg->dev_n_cfg = usba_device->usb_n_cfgs;
689 689 low_cfg_bound = 0;
690 690 high_cfg_bound = usba_device->usb_n_cfgs;
691 691 } else {
692 692 usb_reg->dev_n_cfg = 1;
693 693 mutex_enter(&usba_device->usb_mutex);
694 694 low_cfg_bound = usba_device->usb_active_cfg_ndx;
695 695 high_cfg_bound = usba_device->usb_active_cfg_ndx + 1;
696 696 mutex_exit(&usba_device->usb_mutex);
697 697 }
698 698 usb_reg->dev_cfg = state.st_dev_cfg = kmem_zalloc(
699 699 (usb_reg->dev_n_cfg * sizeof (usb_cfg_data_t)),
700 700 KM_SLEEP);
701 701 /*
702 702 * this_cfg_ndx loops through all configurations presented;
703 703 * state.st_dev_n_cfg limits the cfgs checked to the number desired.
704 704 */
705 705 state.st_dev_n_cfg = 0;
706 706 for (this_cfg_ndx = low_cfg_bound; this_cfg_ndx < high_cfg_bound;
707 707 this_cfg_ndx++) {
708 708
709 709 state.st_curr_raw_descr =
710 710 usba_device->usb_cfg_array[this_cfg_ndx];
711 711 ASSERT(state.st_curr_raw_descr != NULL);
712 712
713 713 /* Clear the following for config cloud sanity checking. */
714 714 last_byte = NULL;
715 715 state.st_curr_cfg = NULL;
716 716 state.st_curr_if = NULL;
717 717 state.st_curr_alt = NULL;
718 718 state.st_curr_ep = NULL;
719 719
720 720 do {
721 721 /* All descr have length and type at offset 0 and 1 */
722 722 state.st_curr_raw_descr_len =
723 723 state.st_curr_raw_descr[0];
724 724 state.st_curr_raw_descr_type =
725 725 state.st_curr_raw_descr[1];
726 726
727 727 /* First descr in cloud must be a config descr. */
728 728 if ((last_byte == NULL) &&
729 729 (state.st_curr_raw_descr_type !=
730 730 USB_DESCR_TYPE_CFG)) {
731 731
732 732 return (USB_FAILURE);
733 733 }
734 734
735 735 /*
736 736 * Bomb if we don't find a new cfg descr when expected.
737 737 * cfg_len_so_far = total_cfg_length = 0 1st time thru.
738 738 */
739 739 if (cfg_len_so_far > state.st_total_cfg_length) {
740 740 USB_DPRINTF_L2(DPRINT_MASK_ALL,
741 741 usbai_reg_log_handle,
742 742 "usba_build_descr_tree: Configuration (%d) "
743 743 "larger than wTotalLength (%d).",
744 744 cfg_len_so_far, state.st_total_cfg_length);
745 745
746 746 return (USB_FAILURE);
747 747 }
748 748
749 749 USB_DPRINTF_L3(DPRINT_MASK_REGISTER,
750 750 usbai_reg_log_handle,
751 751 "usba_build_descr_tree: Process type %d descr "
752 752 "(addr=0x%p)", state.st_curr_raw_descr_type,
753 753 (void *)state.st_curr_raw_descr);
754 754
755 755 switch (state.st_curr_raw_descr_type) {
756 756 case USB_DESCR_TYPE_CFG:
757 757 cfg_len_so_far = 0;
758 758 process_this_if_tree = B_FALSE;
759 759
760 760 state.st_curr_cfg_str = usba_device->
761 761 usb_cfg_str_descr[this_cfg_ndx];
762 762 usba_process_cfg_descr(&state);
763 763 state.st_last_processed_descr_type =
764 764 USB_DESCR_TYPE_CFG;
765 765 last_byte = state.st_curr_raw_descr +
766 766 (state.st_total_cfg_length *
767 767 sizeof (uchar_t));
768 768
769 769 break;
770 770
771 771 case USB_DESCR_TYPE_IF:
772 772 /*
773 773 * process_this_if_tree == TRUE means this
774 774 * interface, plus all eps and c/vs in it are
775 775 * to be processed.
776 776 */
777 777 if (usba_process_if_descr(&state,
778 778 &process_this_if_tree) != USB_SUCCESS) {
779 779
780 780 return (USB_FAILURE);
781 781 }
782 782 state.st_last_processed_descr_type =
783 783 USB_DESCR_TYPE_IF;
784 784
785 785 break;
786 786
787 787 case USB_DESCR_TYPE_EP:
788 788 /*
789 789 * Skip if endpoints of a specific interface are
790 790 * desired and this endpoint is associated with
791 791 * a different interface.
792 792 */
793 793 if (process_this_if_tree) {
794 794 if (usba_process_ep_descr(&state) !=
795 795 USB_SUCCESS) {
796 796
797 797 return (USB_FAILURE);
798 798 }
799 799 state.st_last_processed_descr_type =
800 800 USB_DESCR_TYPE_EP;
801 801 }
802 802
803 803 break;
804 804
805 805 case USB_DESCR_TYPE_SS_EP_COMP:
806 806
807 807 /*
808 808 * These entries should always follow an
809 809 * endpoint description. If an endpoint
810 810 * description wasn't the last
811 811 * thing that we found, then we shouldn't
812 812 * process this descriptor.
813 813 */
814 814 if (state.st_last_processed_descr_type ==
815 815 USB_DESCR_TYPE_EP) {
816 816 if (usba_process_ss_ep_comp_descr(
817 817 &state) != USB_SUCCESS) {
818 818
819 819 return (USB_FAILURE);
820 820 }
821 821
822 822 state.st_last_processed_descr_type =
823 823 USB_DESCR_TYPE_SS_EP_COMP;
824 824
825 825 break;
826 826 }
827 827 break;
828 828
829 829 case USB_DESCR_TYPE_STRING:
830 830 USB_DPRINTF_L2(DPRINT_MASK_ALL,
831 831 usbai_reg_log_handle,
832 832 "usb_get_dev_data: "
833 833 "Found unexpected str descr at addr 0x%p",
834 834 (void *)state.st_curr_raw_descr);
835 835
836 836 break; /* Shouldn't be any here. Skip. */
837 837
838 838 default:
839 839 /*
840 840 * Treat all other descr as class/vendor
841 841 * specific. Skip if c/vs of a specific
842 842 * interface are desired and this c/v is
843 843 * associated with a different one.
844 844 * Device level c/vs should always be
845 845 * processed, e.g., the security descrs
846 846 * for the Host Wire Adapter.
847 847 */
848 848 if ((state.st_last_processed_descr_type ==
849 849 USB_DESCR_TYPE_CFG) ||
850 850 (process_this_if_tree == B_TRUE)) {
851 851 if (usba_process_cv_descr(&state) !=
852 852 USB_SUCCESS) {
853 853
854 854 return (USB_FAILURE);
855 855 }
856 856 }
857 857 }
858 858
859 859 state.st_curr_raw_descr += state.st_curr_raw_descr_len;
860 860 cfg_len_so_far += state.st_curr_raw_descr_len;
861 861
862 862 } while (state.st_curr_raw_descr < last_byte);
863 863 }
864 864
865 865 /* Make tree sparse, and put elements in order. */
866 866 usba_order_tree(&state);
867 867
868 868 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
869 869 "usba_build_descr_tree done");
870 870
871 871 return (USB_SUCCESS);
872 872 }
873 873
874 874
875 875 /*
876 876 * usba_process_cfg_descr:
877 877 * Set up a configuration tree node based on a raw config descriptor.
878 878 *
879 879 * Arguments:
880 880 * state - Pointer to this module's state structure.
881 881 *
882 882 * Returns:
883 883 * B_TRUE: the descr processed corresponds to a requested configuration.
884 884 * B_FALSE: the descr processed does not correspond to a requested config.
885 885 */
886 886 static void
887 887 usba_process_cfg_descr(usba_reg_state_t *state)
888 888 {
889 889 usb_cfg_data_t *curr_cfg;
890 890
891 891 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
892 892 "usba_process_cfg_descr starting");
893 893
894 894 curr_cfg = state->st_curr_cfg =
895 895 &state->st_dev_cfg[state->st_dev_n_cfg++];
896 896
897 897 /* Parse and store config descriptor proper in the tree. */
898 898 (void) usb_parse_data("2cs5c",
899 899 state->st_curr_raw_descr, state->st_curr_raw_descr_len,
900 900 &curr_cfg->cfg_descr,
901 901 sizeof (usb_cfg_descr_t));
902 902
903 903 state->st_total_cfg_length = curr_cfg->cfg_descr.wTotalLength;
904 904
905 905 if (state->st_curr_cfg_str != NULL) {
906 906 curr_cfg->cfg_strsize = strlen(state->st_curr_cfg_str) + 1;
907 907 curr_cfg->cfg_str = kmem_zalloc(curr_cfg->cfg_strsize,
908 908 KM_SLEEP);
909 909 (void) strcpy(curr_cfg->cfg_str, state->st_curr_cfg_str);
910 910 }
911 911
912 912 curr_cfg->cfg_n_if = curr_cfg->cfg_descr.bNumInterfaces;
913 913 curr_cfg->cfg_if = kmem_zalloc((curr_cfg->cfg_n_if *
914 914 sizeof (usb_if_data_t)), KM_SLEEP);
915 915
916 916 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
917 917 "usba_process_cfg_descr done");
918 918 }
919 919
920 920
921 921 /*
922 922 * usba_process_if_descr:
923 923 * This processes a raw interface descriptor, and sets up an analogous
924 924 * interface node and child "alternate" nodes (each containing an
925 925 * interface descriptor) in the descriptor tree.
926 926 *
927 927 * It groups all descriptors with the same bInterfaceNumber (alternates)
928 928 * into an array. It makes entries in an interface array, each of which
929 929 * points to an array of alternates.
930 930 *
931 931 * Arguments:
932 932 * state - Pointer to this module's state structure.
933 933 * requested_if - Address into which the following is returned:
934 934 * B_TRUE - the processed descr is of a requested interface.
935 935 * B_FALSE - the processed descr if of a non-requested interface.
936 936 *
937 937 * Returns:
938 938 * USB_SUCCESS: Descriptor is successfully parsed.
939 939 * USB_FAILURE: Descriptor is inappropriately placed in config cloud.
940 940 */
941 941 static int
942 942 usba_process_if_descr(usba_reg_state_t *state, boolean_t *requested_if)
943 943 {
944 944 char *string;
945 945 usb_if_descr_t *new_if_descr;
946 946 usba_device_t *usba_device = usba_get_usba_device(state->dip);
947 947 int is_root_hub = (usba_device->usb_addr == ROOT_HUB_ADDR);
948 948
949 949 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
950 950 "usba_process_if_descr starting");
951 951
952 952 /* No config preceeds this interface. */
953 953 if (state->st_curr_cfg == NULL) {
954 954 USB_DPRINTF_L2(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
955 955 "usba_process_if_descr found interface after no config.");
956 956
957 957 return (USB_FAILURE);
958 958 }
959 959
960 960 new_if_descr = kmem_zalloc(sizeof (usb_if_descr_t), KM_SLEEP);
961 961
962 962 /* Strictly speaking, unpacking is not necessary. Could use bcopy. */
963 963 (void) usb_parse_data("9c", state->st_curr_raw_descr,
964 964 state->st_curr_raw_descr_len,
965 965 new_if_descr, sizeof (usb_if_descr_t));
966 966
967 967 /* Check the interface number in case of a malfunction device */
968 968 if (new_if_descr->bInterfaceNumber >= state->st_curr_cfg->cfg_n_if) {
969 969 USB_DPRINTF_L2(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
970 970 "usba_process_if_descr: bInterfaceNumber=%d is not "
971 971 "a valid one", new_if_descr->bInterfaceNumber);
972 972 kmem_free(new_if_descr, sizeof (usb_if_descr_t));
973 973
974 974 *requested_if = B_FALSE;
975 975
976 976 return (USB_SUCCESS);
977 977 }
978 978 *requested_if = B_TRUE;
979 979
980 980 /* Not a requested interface. */
981 981 if ((state->st_if_to_build != new_if_descr->bInterfaceNumber) &&
982 982 (state->st_if_to_build != USBA_ALL)) {
983 983 *requested_if = B_FALSE;
984 984
985 985 } else {
986 986 usb_alt_if_data_t *alt_array;
987 987 uint_t alt_index;
988 988
989 989 /* Point to proper interface node, based on num in descr. */
990 990 state->st_curr_if =
991 991 &state->st_curr_cfg->cfg_if[new_if_descr->bInterfaceNumber];
992 992
993 993 /* Make room for new alternate. */
994 994 alt_index = state->st_curr_if->if_n_alt;
995 995 alt_array = state->st_curr_if->if_alt;
996 996 usba_augment_array((void **)(&alt_array), alt_index,
997 997 sizeof (usb_alt_if_data_t));
998 998
999 999 /* Ptr to the current alt, may be used to attach a c/v to it. */
1000 1000 state->st_curr_alt = &alt_array[alt_index];
1001 1001
1002 1002 bcopy(new_if_descr, &(alt_array[alt_index++].altif_descr),
1003 1003 sizeof (usb_if_descr_t));
1004 1004 state->st_curr_if->if_alt = alt_array;
1005 1005 state->st_curr_if->if_n_alt = alt_index;
1006 1006
1007 1007 string = kmem_zalloc(USB_MAXSTRINGLEN, KM_SLEEP);
1008 1008 if (!is_root_hub) {
1009 1009 (void) usb_get_string_descr(state->dip, USB_LANG_ID,
1010 1010 state->st_curr_alt->altif_descr.iInterface,
1011 1011 string, USB_MAXSTRINGLEN);
1012 1012 }
1013 1013 if (string[0] == '\0') {
1014 1014 (void) strcpy(string, "<none>");
1015 1015 }
1016 1016 state->st_curr_alt->altif_strsize = strlen(string) + 1;
1017 1017 state->st_curr_alt->altif_str = kmem_zalloc(
1018 1018 state->st_curr_alt->altif_strsize, KM_SLEEP);
1019 1019 (void) strcpy(state->st_curr_alt->altif_str, string);
1020 1020 kmem_free(string, USB_MAXSTRINGLEN);
1021 1021 }
1022 1022
1023 1023 kmem_free(new_if_descr, sizeof (usb_if_descr_t));
1024 1024
1025 1025 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1026 1026 "usba_process_if_descr done");
1027 1027
1028 1028 return (USB_SUCCESS);
1029 1029 }
1030 1030
1031 1031
1032 1032 /*
1033 1033 * usba_process_ep_descr:
1034 1034 * This processes a raw endpoint descriptor, and sets up an analogous
1035 1035 * endpoint descriptor node in the descriptor tree.
1036 1036 *
1037 1037 * Arguments:
1038 1038 * state - Pointer to this module's state structure.
1039 1039 *
1040 1040 * Returns:
1041 1041 * USB_SUCCESS: Descriptor is successfully parsed.
1042 1042 * USB_FAILURE: Descriptor is inappropriately placed in config cloud.
1043 1043 */
1044 1044 static int
1045 1045 usba_process_ep_descr(usba_reg_state_t *state)
1046 1046 {
1047 1047 usb_alt_if_data_t *curr_alt = state->st_curr_alt;
1048 1048
1049 1049 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1050 1050 "usba_process_ep_descr starting");
1051 1051
1052 1052 /* No interface preceeds this endpoint. */
1053 1053 if (state->st_curr_alt == NULL) {
1054 1054 USB_DPRINTF_L2(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1055 1055 "usba_process_ep_descr: no requested alt before endpt.");
1056 1056
1057 1057 return (USB_FAILURE);
1058 1058 }
1059 1059
1060 1060 usba_augment_array((void **)(&curr_alt->altif_ep),
1061 1061 curr_alt->altif_n_ep, sizeof (usb_ep_data_t));
1062 1062
1063 1063 /* Ptr to the current endpt, may be used to attach a c/v to it. */
1064 1064 state->st_curr_ep = &curr_alt->altif_ep[curr_alt->altif_n_ep++];
1065 1065
1066 1066 (void) usb_parse_data("4csc", state->st_curr_raw_descr,
1067 1067 state->st_curr_raw_descr_len,
1068 1068 &state->st_curr_ep->ep_descr, sizeof (usb_ep_descr_t));
1069 1069
1070 1070 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1071 1071 "usba_process_ep_descr done");
1072 1072
1073 1073 return (USB_SUCCESS);
1074 1074 }
1075 1075
1076 1076 /*
1077 1077 * usba_process_ss_ep_comp_descr:
1078 1078 * This processes a raw endpoint companion descriptor and associates it
1079 1079 * inside of an existing endpoint's entry.
1080 1080 *
1081 1081 * Arguments:
1082 1082 * state - Pointer to this module's state structure.
1083 1083 *
1084 1084 * Returns:
1085 1085 * USB_SUCCESS: Descriptor is successfully parsed.
1086 1086 * USB_FAILURE: Descriptor is inappropriately placed in config cloud.
1087 1087 */
1088 1088 static int
1089 1089 usba_process_ss_ep_comp_descr(usba_reg_state_t *state)
1090 1090 {
1091 1091 if (state->st_curr_ep == NULL)
1092 1092 return (USB_FAILURE);
1093 1093
1094 1094 (void) usb_parse_data("4cs", state->st_curr_raw_descr,
1095 1095 state->st_curr_raw_descr_len,
1096 1096 &state->st_curr_ep->ep_ss_comp,
1097 1097 sizeof (usb_ep_ss_comp_descr_t));
1098 1098 state->st_curr_ep->ep_ss_valid = B_TRUE;
1099 1099
1100 1100 return (USB_SUCCESS);
1101 1101 }
1102 1102
1103 1103
1104 1104 /*
1105 1105 * usba_process_cv_descr:
1106 1106 * This processes a raw endpoint descriptor, and sets up an analogous
1107 1107 * endpoint descriptor in the descriptor tree. C/Vs are associated with
1108 1108 * other descriptors they follow in the raw data.
1109 1109 * last_processed_descr_type indicates the type of descr this c/v follows.
1110 1110 *
1111 1111 * Arguments:
1112 1112 * state - Pointer to this module's state structure.
1113 1113 *
1114 1114 * Returns:
1115 1115 * USB_SUCCESS: Descriptor is successfully parsed.
1116 1116 * USB_FAILURE: Descriptor is inappropriately placed in config cloud.
1117 1117 */
1118 1118 static int
1119 1119 usba_process_cv_descr(usba_reg_state_t *state)
1120 1120 {
1121 1121 usb_cvs_data_t *curr_cv_descr;
1122 1122 usb_cvs_data_t **cvs_ptr = NULL;
1123 1123 uint_t *n_cvs_ptr;
1124 1124
1125 1125 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1126 1126 "usba_process_cv_descr starting. Processing c/v for descr type %d",
1127 1127 state->st_last_processed_descr_type);
1128 1128
1129 1129 /*
1130 1130 * Attach the c/v to a node based on the last descr type processed.
1131 1131 * Save handles to appropriate c/v node array and count to update.
1132 1132 */
1133 1133 switch (state->st_last_processed_descr_type) {
1134 1134 case USB_DESCR_TYPE_CFG:
|
↓ open down ↓ |
1098 lines elided |
↑ open up ↑ |
1135 1135 n_cvs_ptr = &state->st_curr_cfg->cfg_n_cvs;
1136 1136 cvs_ptr = &state->st_curr_cfg->cfg_cvs;
1137 1137 break;
1138 1138
1139 1139 case USB_DESCR_TYPE_IF:
1140 1140 n_cvs_ptr = &state->st_curr_alt->altif_n_cvs;
1141 1141 cvs_ptr = &state->st_curr_alt->altif_cvs;
1142 1142 break;
1143 1143
1144 1144 case USB_DESCR_TYPE_EP:
1145 + case USB_DESCR_TYPE_SS_EP_COMP:
1145 1146 n_cvs_ptr = &state->st_curr_ep->ep_n_cvs;
1146 1147 cvs_ptr = &state->st_curr_ep->ep_cvs;
1147 1148 break;
1148 1149
1149 1150 default:
1150 1151 USB_DPRINTF_L2(DPRINT_MASK_ALL, usbai_reg_log_handle,
1151 1152 "usba_process_cv_descr: Type of last descriptor unknown. ");
1152 1153
1153 1154 return (USB_FAILURE);
1154 1155 }
1155 1156
1156 1157 usba_augment_array((void **)cvs_ptr, *n_cvs_ptr,
1157 1158 sizeof (usb_cvs_data_t));
1158 1159 curr_cv_descr = &(*cvs_ptr)[(*n_cvs_ptr)++];
1159 1160
1160 1161 curr_cv_descr->cvs_buf =
1161 1162 kmem_zalloc(state->st_curr_raw_descr_len, KM_SLEEP);
1162 1163 curr_cv_descr->cvs_buf_len = state->st_curr_raw_descr_len;
1163 1164 bcopy(state->st_curr_raw_descr, curr_cv_descr->cvs_buf,
1164 1165 state->st_curr_raw_descr_len);
1165 1166
1166 1167 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1167 1168 "usba_process_cv_descr done");
1168 1169
1169 1170 return (USB_SUCCESS);
1170 1171 }
1171 1172
1172 1173
1173 1174 /*
1174 1175 * usba_set_parse_values:
1175 1176 * Based on parse level, set the configuration(s) and interface(s) to build
1176 1177 *
1177 1178 * Returned configuration value can be USBA_ALL indicating to build all
1178 1179 * configurations. Likewise for the returned interface value.
1179 1180 *
1180 1181 * Arguments:
1181 1182 * dip - pointer to devinfo of the device
1182 1183 * usba_device - pointer to usba_device structure of the device
1183 1184 * state - Pointer to this module's state structure.
1184 1185 * if no specific config specified, default to all config
1185 1186 * if no specific interface specified, default to all.
1186 1187 * if_to_build and config_to_build are modified.
1187 1188 * dev_parse_level may be modified.
1188 1189 *
1189 1190 * Returns:
1190 1191 * USB_SUCCESS - success
1191 1192 * USB_INVALID_ARGS - state->st_dev_parse_level is invalid.
1192 1193 */
1193 1194 static int
1194 1195 usba_set_parse_values(dev_info_t *dip, usba_device_t *usba_device,
1195 1196 usba_reg_state_t *state)
1196 1197 {
1197 1198 /* Default to *all* in case configuration# prop not set. */
1198 1199 mutex_enter(&usba_device->usb_mutex);
1199 1200 state->st_cfg_to_build = usba_device->usb_active_cfg_ndx;
1200 1201 mutex_exit(&usba_device->usb_mutex);
1201 1202 if (state->st_cfg_to_build == USBA_DEV_CONFIG_INDEX_UNDEFINED) {
1202 1203 state->st_cfg_to_build = USBA_ALL;
1203 1204 }
1204 1205 state->st_if_to_build = usb_get_if_number(dip);
1205 1206
1206 1207 switch (state->st_dev_parse_level) {
1207 1208 case USB_PARSE_LVL_ALL: /* Parse all configurations */
1208 1209 state->st_cfg_to_build = USBA_ALL;
1209 1210 state->st_if_to_build = USBA_ALL;
1210 1211 break;
1211 1212
1212 1213 case USB_PARSE_LVL_CFG: /* Parse all interfaces of a */
1213 1214 /* specific configuration. */
1214 1215 state->st_if_to_build = USBA_ALL;
1215 1216 break;
1216 1217
1217 1218 case USB_PARSE_LVL_IF: /* Parse configured interface only */
1218 1219 if (state->st_if_to_build < 0) {
1219 1220 state->st_if_to_build = USBA_ALL;
1220 1221 }
1221 1222 break;
1222 1223
1223 1224 default:
1224 1225
1225 1226 return (USB_INVALID_ARGS);
1226 1227 }
1227 1228
1228 1229 /*
1229 1230 * Set parse level to identify this tree properly, regardless of what
1230 1231 * the caller thought the tree would have.
1231 1232 */
1232 1233 if ((state->st_if_to_build == USBA_ALL) &&
1233 1234 (state->st_dev_parse_level == USB_PARSE_LVL_IF)) {
1234 1235 state->st_dev_parse_level = USB_PARSE_LVL_CFG;
1235 1236 }
1236 1237 if ((state->st_cfg_to_build == USBA_ALL) &&
1237 1238 (state->st_dev_parse_level == USB_PARSE_LVL_CFG)) {
1238 1239 state->st_dev_parse_level = USB_PARSE_LVL_ALL;
1239 1240 }
1240 1241
1241 1242 return (USB_SUCCESS);
1242 1243 }
1243 1244
1244 1245
1245 1246 /*
1246 1247 * usba_kmem_realloc:
1247 1248 * Resize dynamic memory. Copy contents of old area to
1248 1249 * beginning of new area.
1249 1250 *
1250 1251 * Arguments:
1251 1252 * old_mem - pointer to old memory area.
1252 1253 * old_size - size of old memory area. 0 is OK.
1253 1254 * new_size - size desired.
1254 1255 *
1255 1256 * Returns:
1256 1257 * pointer to new memory area.
1257 1258 */
1258 1259 static void*
1259 1260 usba_kmem_realloc(void* old_mem, int old_size, int new_size)
1260 1261 {
1261 1262 void *new_mem = NULL;
1262 1263
1263 1264 if (new_size > 0) {
1264 1265 new_mem = kmem_zalloc(new_size, KM_SLEEP);
1265 1266 if (old_size > 0) {
1266 1267 bcopy(old_mem, new_mem,
1267 1268 min(old_size, new_size));
1268 1269 }
1269 1270 }
1270 1271
1271 1272 if (old_size > 0) {
1272 1273 kmem_free(old_mem, old_size);
1273 1274 }
1274 1275
1275 1276 return (new_mem);
1276 1277 }
1277 1278
1278 1279
1279 1280 /*
1280 1281 * usba_augment_array:
1281 1282 * Add a new element on the end of an array.
1282 1283 *
1283 1284 * Arguments:
1284 1285 * addr - ptr to the array address. Array addr will change.
1285 1286 * n_elements - array element count.
1286 1287 * element_size - size of an array element
1287 1288 */
1288 1289 static void
1289 1290 usba_augment_array(void **addr, uint_t n_elements, uint_t element_size)
1290 1291 {
1291 1292 *addr = usba_kmem_realloc(*addr, (n_elements * element_size),
1292 1293 ((n_elements + 1) * element_size));
1293 1294 }
1294 1295
1295 1296
1296 1297 /*
1297 1298 * usba_make_alts_sparse:
1298 1299 * Disburse alternate array elements such that they are at the proper array
1299 1300 * indices for which alt they represent. It is assumed that all key values
1300 1301 * used for ordering the elements are positive. Original array space may
1301 1302 * be freed and new space allocated.
1302 1303 *
1303 1304 * Arguments:
1304 1305 * array - pointer to alternates array; may be modified
1305 1306 * n_elements - number of elements in the array; may be modified
1306 1307 */
1307 1308 static void
1308 1309 usba_make_alts_sparse(usb_alt_if_data_t **array, uint_t *n_elements)
1309 1310 {
1310 1311 uint_t n_orig_elements = *n_elements;
1311 1312 uint8_t smallest_value;
1312 1313 uint8_t largest_value;
1313 1314 uint8_t curr_value;
1314 1315 uint_t in_order = 0;
1315 1316 usb_alt_if_data_t *orig_addr = *array; /* Non-sparse array base ptr */
1316 1317 usb_alt_if_data_t *repl_array; /* Base ptr to sparse array */
1317 1318 uint_t n_repl_elements; /* Number elements in the new array */
1318 1319 uint_t i;
1319 1320
1320 1321 /* Check for a null array. */
1321 1322 if ((array == NULL) || (n_orig_elements == 0)) {
1322 1323
1323 1324 return;
1324 1325 }
1325 1326
1326 1327 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1327 1328 "make_sparse: array=0x%p, n_orig_elements=%d",
1328 1329 (void *)array, n_orig_elements);
1329 1330
1330 1331 curr_value = orig_addr[0].altif_descr.bAlternateSetting;
1331 1332 smallest_value = largest_value = curr_value;
1332 1333
1333 1334 /* Figure the low-high range of the array. */
1334 1335 for (i = 1; i < n_orig_elements; i++) {
1335 1336 curr_value = orig_addr[i].altif_descr.bAlternateSetting;
1336 1337 if (curr_value < smallest_value) {
1337 1338 smallest_value = curr_value;
1338 1339 } else if (curr_value > largest_value) {
1339 1340 in_order++;
1340 1341 largest_value = curr_value;
1341 1342 }
1342 1343 }
1343 1344 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1344 1345 "make_sparse: largest=%d, smallest=%d, "
1345 1346 "order=%d",
1346 1347 largest_value, smallest_value, in_order);
1347 1348
1348 1349 n_repl_elements = largest_value + 1;
1349 1350
1350 1351 /*
1351 1352 * No holes to leave, array starts at zero, and everything is already
1352 1353 * in order. Just return original array.
1353 1354 */
1354 1355 if ((n_repl_elements == n_orig_elements) &&
1355 1356 ((in_order + 1) == n_orig_elements)) {
1356 1357 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1357 1358 "No holes");
1358 1359
1359 1360 return;
1360 1361 }
1361 1362
1362 1363 /* Allocate zeroed space for the array. */
1363 1364 repl_array = kmem_zalloc(
1364 1365 (n_repl_elements * sizeof (usb_alt_if_data_t)), KM_SLEEP);
1365 1366
1366 1367 /* Now fill in the array. */
1367 1368 for (i = 0; i < n_orig_elements; i++) {
1368 1369 curr_value = orig_addr[i].altif_descr.bAlternateSetting;
1369 1370
1370 1371 /* Place in sparse array based on key. */
1371 1372 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1372 1373 "move %lu bytes (key %d) from 0x%p to 0x%p",
1373 1374 (unsigned long)sizeof (usb_alt_if_data_t), curr_value,
1374 1375 (void *)&orig_addr[i], (void *)&repl_array[curr_value]);
1375 1376
1376 1377 bcopy((char *)&orig_addr[i], (char *)&repl_array[curr_value],
1377 1378 sizeof (usb_alt_if_data_t));
1378 1379 }
1379 1380
1380 1381 kmem_free(*array, sizeof (usb_alt_if_data_t) * n_orig_elements);
1381 1382 *array = repl_array;
1382 1383 *n_elements = n_repl_elements;
1383 1384 }
1384 1385
1385 1386
1386 1387 /*
1387 1388 * usba_order_tree:
1388 1389 * Take a tree as built by usba_build_descr_tree and make sure the key
1389 1390 * values of all elements match their indeces. Proper order is implied.
1390 1391 *
1391 1392 * Arguments:
1392 1393 * state - Pointer to this module's state structure.
1393 1394 */
1394 1395 static void
1395 1396 usba_order_tree(usba_reg_state_t *state)
1396 1397 {
1397 1398 usb_cfg_data_t *this_cfg;
1398 1399 usb_if_data_t *this_if;
1399 1400 uint_t n_cfgs = state->st_dev_n_cfg;
1400 1401 uint_t cfg;
1401 1402 uint_t which_if;
1402 1403
1403 1404 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1404 1405 "usba_order_tree:");
1405 1406
1406 1407 for (cfg = 0; cfg < n_cfgs; cfg++) {
1407 1408 this_cfg = &state->st_dev_cfg[cfg];
1408 1409
1409 1410 for (which_if = 0; which_if < this_cfg->cfg_n_if; which_if++) {
1410 1411 this_if = this_cfg->cfg_if;
1411 1412 usba_make_alts_sparse(&this_if->if_alt,
1412 1413 &this_if->if_n_alt);
1413 1414 }
1414 1415 }
1415 1416 }
1416 1417
1417 1418
1418 1419 /*
1419 1420 * usb_free_descr_tree:
1420 1421 * Take down the configuration tree. Called internally and can be called
1421 1422 * from a driver standalone to take the tree down while leaving the rest
1422 1423 * of the registration intact.
1423 1424 *
1424 1425 * Arguments:
1425 1426 * dip - pointer to devinfo of the device
1426 1427 * dev_data - pointer to registration data containing the tree.
1427 1428 */
1428 1429 void
1429 1430 usb_free_descr_tree(dev_info_t *dip, usb_client_dev_data_t *dev_data)
1430 1431 {
1431 1432 usb_cfg_data_t *cfg_array;
1432 1433 int n_cfgs;
1433 1434 int cfg;
1434 1435
1435 1436 if ((dip == NULL) || (dev_data == NULL)) {
1436 1437
1437 1438 return;
1438 1439 }
1439 1440 cfg_array = dev_data->dev_cfg;
1440 1441 n_cfgs = dev_data->dev_n_cfg;
1441 1442
1442 1443 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1443 1444 "usb_free_descr_tree starting for %s%d",
1444 1445 ddi_driver_name(dip), ddi_get_instance(dip));
1445 1446
1446 1447 for (cfg = 0; cfg < n_cfgs; cfg++) {
1447 1448 if (cfg_array[cfg].cfg_if) {
1448 1449 usba_free_if_array(cfg_array[cfg].cfg_if,
1449 1450 cfg_array[cfg].cfg_n_if);
1450 1451 }
1451 1452 if (cfg_array[cfg].cfg_cvs) {
1452 1453 usba_free_cv_array(cfg_array[cfg].cfg_cvs,
1453 1454 cfg_array[cfg].cfg_n_cvs);
1454 1455 }
1455 1456 if (cfg_array[cfg].cfg_str) {
1456 1457 kmem_free(cfg_array[cfg].cfg_str,
1457 1458 cfg_array[cfg].cfg_strsize);
1458 1459 }
1459 1460 }
1460 1461
1461 1462 if (cfg_array) {
1462 1463 kmem_free(cfg_array, (sizeof (usb_cfg_data_t) * n_cfgs));
1463 1464 }
1464 1465
1465 1466 dev_data->dev_parse_level = USB_PARSE_LVL_NONE;
1466 1467 dev_data->dev_n_cfg = 0;
1467 1468 dev_data->dev_cfg = NULL;
1468 1469 dev_data->dev_curr_cfg = NULL;
1469 1470
1470 1471 USB_DPRINTF_L4(DPRINT_MASK_REGISTER, usbai_reg_log_handle,
1471 1472 "usb_free_descr_tree done");
1472 1473 }
1473 1474
1474 1475
1475 1476 /*
1476 1477 * usba_free_if_array:
1477 1478 * Free a configuration's array of interface nodes and their subtrees of
1478 1479 * interface alternate, endpoint and c/v descriptors.
1479 1480 *
1480 1481 * Arguments:
1481 1482 * if_array - pointer to array of interfaces to remove.
1482 1483 * n_ifs - number of elements in the array to remove.
1483 1484 */
1484 1485 static void
1485 1486 usba_free_if_array(usb_if_data_t *if_array, uint_t n_ifs)
1486 1487 {
1487 1488 uint_t which_if;
1488 1489 uint_t which_alt;
1489 1490 uint_t n_alts;
1490 1491 usb_alt_if_data_t *altif;
1491 1492
1492 1493 for (which_if = 0; which_if < n_ifs; which_if++) {
1493 1494 n_alts = if_array[which_if].if_n_alt;
1494 1495
1495 1496 /* Every interface has at least one alternate. */
1496 1497 for (which_alt = 0; which_alt < n_alts; which_alt++) {
1497 1498 altif = &if_array[which_if].if_alt[which_alt];
1498 1499 usba_free_ep_array(altif->altif_ep, altif->altif_n_ep);
1499 1500 usba_free_cv_array(altif->altif_cvs,
1500 1501 altif->altif_n_cvs);
1501 1502 kmem_free(altif->altif_str, altif->altif_strsize);
1502 1503 }
1503 1504
1504 1505 kmem_free(if_array[which_if].if_alt,
1505 1506 (sizeof (usb_alt_if_data_t) * n_alts));
1506 1507 }
1507 1508
1508 1509 /* Free the interface array itself. */
1509 1510 kmem_free(if_array, (sizeof (usb_if_data_t) * n_ifs));
1510 1511 }
1511 1512
1512 1513
1513 1514 /*
1514 1515 * usba_free_ep_array:
1515 1516 * Free an array of endpoint nodes and their subtrees of c/v descriptors.
1516 1517 *
1517 1518 * Arguments:
1518 1519 * ep_array - pointer to array of endpoints to remove.
1519 1520 * n_eps - number of elements in the array to remove.
1520 1521 */
1521 1522 static void
1522 1523 usba_free_ep_array(usb_ep_data_t *ep_array, uint_t n_eps)
1523 1524 {
1524 1525 uint_t ep;
1525 1526
1526 1527 for (ep = 0; ep < n_eps; ep++) {
1527 1528 usba_free_cv_array(ep_array[ep].ep_cvs, ep_array[ep].ep_n_cvs);
1528 1529 }
1529 1530
1530 1531 kmem_free(ep_array, (sizeof (usb_ep_data_t) * n_eps));
1531 1532 }
1532 1533
1533 1534
1534 1535 /*
1535 1536 * usba_free_cv_array:
1536 1537 * Free an array of class/vendor (c/v) descriptor nodes.
1537 1538 *
1538 1539 * Arguments:
1539 1540 * cv_array - pointer to array of c/v nodes to remove.
1540 1541 * n_cvs - number of elements in the array to remove.
1541 1542 */
1542 1543 static void
1543 1544 usba_free_cv_array(usb_cvs_data_t *cv_array, uint_t n_cvs)
1544 1545 {
1545 1546 uint_t cv_node;
1546 1547
1547 1548 /* Free data areas hanging off of each c/v descriptor. */
1548 1549 for (cv_node = 0; cv_node < n_cvs; cv_node++) {
1549 1550 kmem_free(cv_array[cv_node].cvs_buf,
1550 1551 cv_array[cv_node].cvs_buf_len);
1551 1552 }
1552 1553
1553 1554 /* Free the array of cv descriptors. */
1554 1555 kmem_free(cv_array, (sizeof (usb_cvs_data_t) * n_cvs));
1555 1556 }
1556 1557
1557 1558
1558 1559 /*
1559 1560 * usb_log_descr_tree:
1560 1561 * Log to the usba_debug_buf a descriptor tree as returned by
1561 1562 * usbai_register_client.
1562 1563 *
1563 1564 * Arguments:
1564 1565 * dev_data - pointer to registration area containing the tree
1565 1566 * log_handle - pointer to log handle to use for dumping.
1566 1567 * level - print level, one of USB_LOG_L0 ... USB_LOG_L4
1567 1568 * Please see usb_log(9F) for details.
1568 1569 * mask - print mask. Please see usb_log(9F) for details.
1569 1570 *
1570 1571 * Returns:
1571 1572 * USB_SUCCESS - tree successfully dumped
1572 1573 * USB_INVALID_CONTEXT - called from callback context
1573 1574 * USB_INVALID_ARGS - bad arguments given
1574 1575 */
1575 1576 int
1576 1577 usb_log_descr_tree(usb_client_dev_data_t *dev_data,
1577 1578 usb_log_handle_t log_handle, uint_t level, uint_t mask)
1578 1579 {
1579 1580 return (usba_dump_descr_tree(NULL, dev_data, log_handle, level, mask));
1580 1581 }
1581 1582
1582 1583
1583 1584 /*
1584 1585 * usb_print_descr_tree:
1585 1586 * Print to the screen a descriptor tree as returned by
1586 1587 * usbai_register_client.
1587 1588 *
1588 1589 * Arguments:
1589 1590 * dip - pointer to devinfo of the client
1590 1591 * dev_data - pointer to registration area containing the tree
1591 1592 *
1592 1593 * Returns:
1593 1594 * USB_SUCCESS - tree successfully dumped
1594 1595 * USB_INVALID_CONTEXT - called from callback context
1595 1596 * USB_INVALID_ARGS - bad arguments given
1596 1597 */
1597 1598 int
1598 1599 usb_print_descr_tree(dev_info_t *dip, usb_client_dev_data_t *dev_data)
1599 1600 {
1600 1601 return (usba_dump_descr_tree(dip, dev_data, NULL, 0, 0));
1601 1602 }
1602 1603
1603 1604
1604 1605 /*
1605 1606 * usba_dump_descr_tree:
1606 1607 * Dump a descriptor tree.
1607 1608 *
1608 1609 * Arguments:
1609 1610 * dip - pointer to devinfo of the client. Used when no
1610 1611 * log_handle argument given.
1611 1612 * usb_reg - pointer to registration area containing the tree
1612 1613 * log_handle - pointer to log handle to use for dumping. If NULL,
1613 1614 * use internal log handle, which dumps to screen.
1614 1615 * level - print level, one of USB_LOG_L0 ... USB_LOG_L4
1615 1616 * Used only when log_handle provided.
1616 1617 * mask - print mask, used when log_handle argument provided.
1617 1618 *
1618 1619 * Returns:
1619 1620 * USB_SUCCESS - tree successfully dumped
1620 1621 * USB_INVALID_CONTEXT - called from callback context
1621 1622 * USB_INVALID_ARGS - bad arguments given
1622 1623 */
1623 1624 static int
1624 1625 usba_dump_descr_tree(dev_info_t *dip, usb_client_dev_data_t *usb_reg,
1625 1626 usb_log_handle_t log_handle, uint_t level, uint_t mask)
1626 1627 {
1627 1628 usb_log_handle_t dump_handle;
1628 1629 uint_t dump_level;
1629 1630 uint_t dump_mask;
1630 1631 int which_config; /* Counters. */
1631 1632 int which_if;
1632 1633 int which_cv;
1633 1634 usb_cfg_data_t *config; /* ptr to current configuration tree node */
1634 1635 usb_cfg_descr_t *config_descr; /* and its USB descriptor. */
1635 1636 char *string;
1636 1637 char *name_string = NULL;
1637 1638 int name_string_size;
1638 1639
1639 1640 if ((usb_reg == NULL) || ((log_handle == NULL) && (dip == NULL))) {
1640 1641
1641 1642 return (USB_INVALID_ARGS);
1642 1643 }
1643 1644
1644 1645 /*
1645 1646 * To keep calling this simple, kmem_zalloc with the sleep flag always.
1646 1647 * This means no interrupt context is allowed.
1647 1648 */
1648 1649 if (servicing_interrupt()) {
1649 1650
1650 1651 return (USB_INVALID_CONTEXT);
1651 1652 }
1652 1653
1653 1654 string = kmem_zalloc(USB_MAXSTRINGLEN, KM_SLEEP);
1654 1655
1655 1656 if (log_handle != NULL) {
1656 1657 dump_level = level;
1657 1658 dump_mask = mask;
1658 1659 dump_handle = log_handle;
1659 1660 } else {
1660 1661 dump_level = USB_LOG_L1;
1661 1662 dump_mask = DPRINT_MASK_ALL;
1662 1663
1663 1664 /* Build device name string. */
1664 1665 (void) snprintf(string, USB_MAXSTRINGLEN,
1665 1666 "Port%d", usb_get_addr(dip));
1666 1667 name_string_size = strlen(string) + 1;
1667 1668 name_string = kmem_zalloc(name_string_size, KM_SLEEP);
1668 1669 (void) strcpy(name_string, string);
1669 1670
1670 1671 /* Allocate a log handle specifying the name string. */
1671 1672 dump_handle = usb_alloc_log_hdl(NULL, name_string,
1672 1673 &dump_level, &dump_mask, NULL,
1673 1674 USB_FLAGS_SLEEP);
1674 1675 }
1675 1676
1676 1677 (void) usb_log(dump_handle, dump_level, dump_mask,
1677 1678 "USB descriptor tree for %s %s",
1678 1679 (usb_reg->dev_mfg != NULL ? usb_reg->dev_mfg : ""),
1679 1680 (usb_reg->dev_product != NULL ? usb_reg->dev_product : ""));
1680 1681 if (usb_reg->dev_n_cfg == 0) {
1681 1682 (void) usb_log(dump_handle, dump_level, dump_mask,
1682 1683 "No descriptor tree present");
1683 1684 } else {
1684 1685 (void) usb_log(dump_handle, dump_level, dump_mask,
1685 1686 "highest configuration found=%d", usb_reg->dev_n_cfg - 1);
1686 1687 }
1687 1688
1688 1689 for (which_config = 0; which_config < usb_reg->dev_n_cfg;
1689 1690 which_config++) {
1690 1691 config = &usb_reg->dev_cfg[which_config];
1691 1692 config_descr = &config->cfg_descr;
1692 1693 if (config_descr->bLength == 0) {
1693 1694
1694 1695 continue;
1695 1696 }
1696 1697 if (dump_level == USB_LOG_L0) {
1697 1698 (void) usb_log(dump_handle, dump_level, dump_mask, " ");
1698 1699 }
1699 1700 (void) usb_log(dump_handle, dump_level, dump_mask,
1700 1701 "Configuration #%d (Addr= 0x%p)", which_config,
1701 1702 (void *)config);
1702 1703 (void) usb_log(dump_handle, dump_level, dump_mask,
1703 1704 "String descr=%s", config->cfg_str);
1704 1705 (void) usb_log(dump_handle, dump_level, dump_mask,
1705 1706 "config descr: len=%d tp=%d totLen=%d numIf=%d "
1706 1707 "cfgVal=%d att=0x%x pwr=%d",
1707 1708 config_descr->bLength, config_descr->bDescriptorType,
1708 1709 config_descr->wTotalLength, config_descr->bNumInterfaces,
1709 1710 config_descr->bConfigurationValue,
1710 1711 config_descr->bmAttributes, config_descr->bMaxPower);
1711 1712 if ((config->cfg_n_if > 0) || (config->cfg_n_cvs > 0)) {
1712 1713 (void) usb_log(dump_handle, dump_level, dump_mask,
1713 1714 "usb_cfg_data_t shows max if=%d "
1714 1715 "and %d cv descr(s).",
1715 1716 config->cfg_n_if - 1, config->cfg_n_cvs);
1716 1717 }
1717 1718
1718 1719 for (which_if = 0; which_if < config->cfg_n_if;
1719 1720 which_if++) {
1720 1721
1721 1722 if (dump_level == USB_LOG_L0) {
1722 1723 (void) usb_log(dump_handle, dump_level,
1723 1724 dump_mask, " ");
1724 1725 }
1725 1726 (void) usb_log(dump_handle, dump_level, dump_mask,
1726 1727 " interface #%d (0x%p)",
1727 1728 which_if, (void *)&config->cfg_if[which_if]);
1728 1729 usba_dump_if(&config->cfg_if[which_if],
1729 1730 dump_handle, dump_level, dump_mask, string);
1730 1731 }
1731 1732
1732 1733 for (which_cv = 0; which_cv < config->cfg_n_cvs; which_cv++) {
1733 1734 (void) usb_log(dump_handle, dump_level, dump_mask,
1734 1735 " config cv descriptor %d (Address=0x%p)",
1735 1736 which_cv, (void *)&config->cfg_cvs[which_cv]);
1736 1737 usba_dump_cv(&config->cfg_cvs[which_cv],
1737 1738 dump_handle, dump_level, dump_mask, string, 4);
1738 1739 }
1739 1740 }
1740 1741
1741 1742 (void) usb_log(dump_handle, dump_level, dump_mask,
1742 1743 "Returning dev_curr_cfg:0x%p, dev_curr_if:%d",
1743 1744 (void *)usb_reg->dev_curr_cfg, usb_reg->dev_curr_if);
1744 1745
1745 1746 if (log_handle == NULL) {
1746 1747 usb_free_log_hdl(dump_handle);
1747 1748 }
1748 1749 if (name_string != NULL) {
1749 1750 kmem_free(name_string, name_string_size);
1750 1751 }
1751 1752 kmem_free(string, USB_MAXSTRINGLEN);
1752 1753
1753 1754 return (USB_SUCCESS);
1754 1755 }
1755 1756
1756 1757
1757 1758 /*
1758 1759 * usba_dump_if:
1759 1760 * Dump an interface node and its branches.
1760 1761 *
1761 1762 * Arguments:
1762 1763 * which_if - interface node to dump
1763 1764 * dump_handle - write data through this log handle
1764 1765 * dump_level - level passed to usb_log
1765 1766 * dump_mask - mask passed to usb_log
1766 1767 * string - temporary area used for processing
1767 1768 *
1768 1769 */
1769 1770 static void
1770 1771 usba_dump_if(usb_if_data_t *which_if, usb_log_handle_t dump_handle,
1771 1772 uint_t dump_level, uint_t dump_mask, char *string)
1772 1773 {
1773 1774 int which_alt; /* Number of alt being dumped */
1774 1775 usb_alt_if_data_t *alt; /* Pointer to it. */
1775 1776 usb_if_descr_t *if_descr; /* Pointer to its USB descr. */
1776 1777 int which_ep; /* Endpoint counter. */
1777 1778 int which_cv; /* C/V descr counter. */
1778 1779
1779 1780 for (which_alt = 0; which_alt < which_if->if_n_alt; which_alt++) {
1780 1781 alt = &which_if->if_alt[which_alt];
1781 1782 if_descr = &alt->altif_descr;
1782 1783
1783 1784 if (if_descr->bLength == 0) {
1784 1785
1785 1786 continue;
1786 1787 }
1787 1788 if (dump_level == USB_LOG_L0) {
1788 1789 (void) usb_log(dump_handle, dump_level, dump_mask, " ");
1789 1790 }
1790 1791 (void) usb_log(dump_handle, dump_level, dump_mask,
1791 1792 "\tAlt #%d (0x%p)", which_alt, (void *)alt);
1792 1793 (void) usb_log(dump_handle, dump_level, dump_mask,
1793 1794 "\tString descr=%s", alt->altif_str);
1794 1795 (void) usb_log(dump_handle, dump_level, dump_mask,
1795 1796 "\tif descr: len=%d type=%d if=%d alt=%d n_ept=%d "
1796 1797 "cls=%d sub=%d proto=%d",
1797 1798 if_descr->bLength,
1798 1799 if_descr->bDescriptorType, if_descr->bInterfaceNumber,
1799 1800 if_descr->bAlternateSetting, if_descr->bNumEndpoints,
1800 1801 if_descr->bInterfaceClass, if_descr->bInterfaceSubClass,
1801 1802 if_descr->bInterfaceProtocol);
1802 1803
1803 1804 if ((alt->altif_n_ep > 0) || (alt->altif_n_cvs > 0)) {
1804 1805 (void) usb_log(dump_handle, dump_level, dump_mask,
1805 1806 "\tusb_alt_if_data_t shows max ep=%d "
1806 1807 "and %d cv descr(s).",
1807 1808 alt->altif_n_ep - 1, alt->altif_n_cvs);
1808 1809 }
1809 1810
1810 1811 for (which_ep = 0; which_ep < alt->altif_n_ep;
1811 1812 which_ep++) {
1812 1813 if (alt->altif_ep[which_ep].ep_descr.bLength == 0) {
1813 1814
1814 1815 continue;
1815 1816 }
1816 1817 if (dump_level == USB_LOG_L0) {
1817 1818 (void) usb_log(dump_handle, dump_level,
1818 1819 dump_mask, " ");
1819 1820 }
1820 1821 usba_dump_ep(which_ep, &alt->altif_ep[which_ep],
1821 1822 dump_handle, dump_level, dump_mask, string);
1822 1823 }
1823 1824
1824 1825 for (which_cv = 0; which_cv < alt->altif_n_cvs; which_cv++) {
1825 1826 if (dump_level == USB_LOG_L0) {
1826 1827 (void) usb_log(dump_handle, dump_level,
1827 1828 dump_mask, " ");
1828 1829 }
1829 1830 (void) usb_log(dump_handle, dump_level, dump_mask,
1830 1831 "\talt cv descriptor #%d (0x%p), size=%d",
1831 1832 which_cv, (void *)&alt->altif_cvs[which_cv],
1832 1833 alt->altif_cvs[which_cv].cvs_buf_len);
1833 1834 usba_dump_cv(&alt->altif_cvs[which_cv],
1834 1835 dump_handle, dump_level, dump_mask, string, 2);
1835 1836 }
1836 1837 }
1837 1838 }
1838 1839
1839 1840
1840 1841 /*
1841 1842 * usba_dump_ep:
1842 1843 * Dump an endpoint node and its branches.
1843 1844 *
1844 1845 * Arguments:
1845 1846 * which_ep - index to display
1846 1847 * ep - endpoint node to dump
1847 1848 * dump_handle - write data through this log handle
1848 1849 * dump_level - level passed to usb_log
1849 1850 * dump_mask - mask passed to usb_log
1850 1851 * string - temporary area used for processing
1851 1852 *
1852 1853 */
1853 1854 static void
1854 1855 usba_dump_ep(uint_t which_ep, usb_ep_data_t *ep, usb_log_handle_t dump_handle,
1855 1856 uint_t dump_level, uint_t dump_mask, char *string)
1856 1857 {
1857 1858 int which_cv;
1858 1859 usb_ep_descr_t *ep_descr = &ep->ep_descr;
1859 1860
1860 1861 (void) usb_log(dump_handle, dump_level, dump_mask,
1861 1862 "\t endpoint[%d], epaddr=0x%x (0x%p)", which_ep,
1862 1863 ep_descr->bEndpointAddress, (void *)ep);
1863 1864 (void) usb_log(dump_handle, dump_level, dump_mask,
1864 1865 "\t len=%d type=%d attr=0x%x pktsize=%d interval=%d",
1865 1866 ep_descr->bLength, ep_descr->bDescriptorType,
1866 1867 ep_descr->bmAttributes, ep_descr->wMaxPacketSize,
1867 1868 ep_descr->bInterval);
1868 1869 if (ep->ep_n_cvs > 0) {
1869 1870 (void) usb_log(dump_handle, dump_level, dump_mask,
1870 1871 "\t usb_ep_data_t shows %d cv descr(s)", ep->ep_n_cvs);
1871 1872 }
1872 1873
1873 1874 for (which_cv = 0; which_cv < ep->ep_n_cvs; which_cv++) {
1874 1875 if (dump_level == USB_LOG_L0) {
1875 1876 (void) usb_log(dump_handle, dump_level,
1876 1877 dump_mask, " ");
1877 1878 }
1878 1879 (void) usb_log(dump_handle, dump_level, dump_mask,
1879 1880 "\t endpoint cv descriptor %d (0x%p), size=%d",
1880 1881 which_cv, (void *)&ep->ep_cvs[which_cv],
1881 1882 ep->ep_cvs[which_cv].cvs_buf_len);
1882 1883 usba_dump_cv(&ep->ep_cvs[which_cv],
1883 1884 dump_handle, dump_level, dump_mask, string, 3);
1884 1885 }
1885 1886 }
1886 1887
1887 1888
1888 1889 /*
1889 1890 * usba_dump_cv:
1890 1891 * Dump a raw class or vendor specific descriptor.
1891 1892 *
1892 1893 * Arguments:
1893 1894 * cv_node - pointer to the descriptor to dump
1894 1895 * dump_handle - write data through this log handle
1895 1896 * dump_level - level passed to usb_log
1896 1897 * dump_mask - mask passed to usb_log
1897 1898 * string - temporary area used for processing
1898 1899 * indent - number of tabs to indent output
1899 1900 *
1900 1901 */
1901 1902 static void
1902 1903 usba_dump_cv(usb_cvs_data_t *cv_node, usb_log_handle_t dump_handle,
1903 1904 uint_t dump_level, uint_t dump_mask, char *string, int indent)
1904 1905 {
1905 1906 if (cv_node) {
1906 1907 usba_dump_bin(cv_node->cvs_buf, cv_node->cvs_buf_len, indent,
1907 1908 dump_handle, dump_level, dump_mask, string,
1908 1909 USB_MAXSTRINGLEN);
1909 1910 }
1910 1911 }
1911 1912
1912 1913
1913 1914 /*
1914 1915 * usba_dump_bin:
1915 1916 * Generic byte dump function.
1916 1917 *
1917 1918 * Arguments:
1918 1919 * data - pointer to the data to dump
1919 1920 * max_bytes - amount of data to dump
1920 1921 * indent - number of indentation levels
1921 1922 * dump_handle - write data through this log handle
1922 1923 * dump_level - level passed to usb_log
1923 1924 * dump_mask - mask passed to usb_log
1924 1925 * buffer - temporary area used for processing
1925 1926 * bufferlen - size of the temporary string area
1926 1927 *
1927 1928 */
1928 1929 static void
1929 1930 usba_dump_bin(uint8_t *data, int max_bytes, int indent,
1930 1931 usb_log_handle_t dump_handle, uint_t dump_level, uint_t dump_mask,
1931 1932 char *buffer, int bufferlen)
1932 1933 {
1933 1934 int i;
1934 1935 int bufoffset = 0;
1935 1936 int nexthere;
1936 1937
1937 1938 if ((indent * SPACES_PER_INDENT) >
1938 1939 (bufferlen - (BINDUMP_BYTES_PER_LINE * 3))) {
1939 1940 (void) usb_log(dump_handle, dump_level, dump_mask,
1940 1941 "Offset to usb_dump_bin must be %d or less. "
1941 1942 "Setting to 0.\n",
1942 1943 (bufferlen - (BINDUMP_BYTES_PER_LINE * 3)));
1943 1944 indent = 0;
1944 1945 }
1945 1946
1946 1947 /* Assume a tab is 2 four-space units. */
1947 1948 for (i = 0; i < indent/2; i++) {
1948 1949 buffer[bufoffset] = '\t';
1949 1950 bufoffset++;
1950 1951 }
1951 1952
1952 1953 if (indent % 2) {
1953 1954 (void) strcpy(&buffer[bufoffset], INDENT_SPACE_STR);
1954 1955 bufoffset += SPACES_PER_INDENT;
1955 1956 }
1956 1957
1957 1958 i = 0; /* Num dumped bytes put on this line. */
1958 1959 nexthere = bufoffset;
1959 1960 while (i < max_bytes) {
1960 1961 (void) sprintf(&buffer[nexthere], "%2x ", *data++);
1961 1962 nexthere += 3;
1962 1963 i++;
1963 1964 if (!(i % BINDUMP_BYTES_PER_LINE)) {
1964 1965 buffer[nexthere] = '\0';
1965 1966 (void) usb_log(dump_handle, dump_level, dump_mask,
1966 1967 buffer);
1967 1968 nexthere = bufoffset;
1968 1969 }
1969 1970 }
1970 1971
1971 1972 if (nexthere > bufoffset) {
1972 1973 buffer[nexthere] = '\0';
1973 1974 (void) usb_log(dump_handle, dump_level, dump_mask, buffer);
1974 1975 }
1975 1976 }
1976 1977
1977 1978 /*
1978 1979 * usb_ep_xdescr_fill:
1979 1980 *
1980 1981 * Fills in the extended endpoint descriptor based on data from the
1981 1982 * configuration tree.
1982 1983 *
1983 1984 * Arguments:
1984 1985 * version - Should be USB_EP_XDESCR_CURRENT_VERSION
1985 1986 * dip - devinfo pointer
1986 1987 * ep_data - endpoint data pointer
1987 1988 * ep_xdesc - An extended descriptor structure, filled upon
1988 1989 * successful completion.
1989 1990 *
1990 1991 * Return values:
1991 1992 * USB_SUCCESS - filling data succeeded
1992 1993 * USB_INVALID_ARGS - invalid arguments
1993 1994 */
1994 1995 int
1995 1996 usb_ep_xdescr_fill(uint_t version, dev_info_t *dip, usb_ep_data_t *ep_data,
1996 1997 usb_ep_xdescr_t *ep_xdescr)
1997 1998 {
1998 1999 if (version != USB_EP_XDESCR_VERSION_ONE) {
1999 2000
2000 2001 return (USB_INVALID_ARGS);
2001 2002 }
2002 2003
2003 2004 if (dip == NULL || ep_data == NULL || ep_xdescr == NULL) {
2004 2005
2005 2006 return (USB_INVALID_ARGS);
2006 2007 }
2007 2008
2008 2009 bzero(ep_xdescr, sizeof (usb_ep_xdescr_t));
2009 2010 ep_xdescr->uex_version = version;
2010 2011 ep_xdescr->uex_ep = ep_data->ep_descr;
2011 2012 if (ep_data->ep_ss_valid == B_TRUE) {
2012 2013 ep_xdescr->uex_flags |= USB_EP_XFLAGS_SS_COMP;
2013 2014 ep_xdescr->uex_ep_ss = ep_data->ep_ss_comp;
2014 2015 }
2015 2016
2016 2017 return (USB_SUCCESS);
2017 2018 }
|
↓ open down ↓ |
863 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX