24 * Use is subject to license terms. 25 */ 26 27#pragma ident "%Z%%M% %I% %E% SMI" 28 29/* 30 * Descriptor parsing functions 31 */ 32#define USBA_FRAMEWORK 33#include <sys/usb/usba/usba_impl.h> 34 35#define INCREMENT_BUF(buf) \ 36 if ((buf)[0] == 0) { \ 37 break; \ 38 } else { \ 39 (buf) += (buf)[0]; \ 40 } 41#define isdigit(ch) ((ch >= '0') && (ch <= '9')) 42 43extern usba_cfg_pwr_descr_t default_cfg_power; 44extern usba_if_pwr_descr_t default_if_power; 45 46size_t 47usb_parse_data(char *format, 48 uchar_t *data, 49 size_t datalen, 50 void *structure, 51 size_t structlen) 52{ 53 int fmt; 54 int counter = 1; 55 int multiplier = 0; 56 uchar_t *dataend = data + datalen; 57 char *structstart = (char *)structure; 58 void *structend = (void *)((intptr_t)structstart + structlen); 59 60 if ((format == NULL) || (data == NULL) || (structure == NULL)) { 61 62 return (USB_PARSE_ERROR); 63 } 64 65 while ((fmt = *format) != '\0') { 66 67 /* 68 * Could some one pass a "format" that is greater than 69 * the structlen? Conversely, one could pass a ret_buf_len 70 * that is less than the "format" length. 71 * If so, we need to protect against writing over memory. 72 */ 73 if (counter++ > structlen) { 74 break; 75 } 76 77 if (fmt == 'c') { 78 uint8_t *cp = (uint8_t *)structure; 79 80 cp = (uint8_t *)(((uintptr_t)cp + _CHAR_ALIGNMENT - 1) & 81 ~(_CHAR_ALIGNMENT - 1)); 82 if (((data + 1) > dataend) || 83 ((cp + 1) > (uint8_t *)structend)) 84 break; 85 86 *cp++ = *data++; 87 structure = (void *)cp; 88 if (multiplier) { 89 multiplier--; 90 } 91 if (multiplier == 0) { 92 format++; 93 } 94 } else if (fmt == 's') { 95 uint16_t *sp = (uint16_t *)structure; 96 97 sp = (uint16_t *) 98 (((uintptr_t)sp + _SHORT_ALIGNMENT - 1) & 99 ~(_SHORT_ALIGNMENT - 1)); 100 if (((data + 2) > dataend) || 101 ((sp + 1) > (uint16_t *)structend)) 102 break; 103 104 *sp++ = (data[1] << 8) + data[0]; 105 data += 2; 106 structure = (void *)sp; 107 if (multiplier) { 108 multiplier--; 109 } 110 if (multiplier == 0) { 111 format++; 112 } 113 } else if (fmt == 'l') { 114 uint32_t *lp = (uint32_t *)structure; 115 116 lp = (uint32_t *) 117 (((uintptr_t)lp + _INT_ALIGNMENT - 1) & 118 ~(_INT_ALIGNMENT - 1)); 119 if (((data + 4) > dataend) || 120 ((lp + 1) > (uint32_t *)structend)) 121 break; 122 123 *lp++ = ((((( 124 (uint32_t)data[3] << 8) | data[2]) << 8) | 125 data[1]) << 8) | data[0]; 126 data += 4; 127 structure = (void *)lp; 128 if (multiplier) { 129 multiplier--; 130 } 131 if (multiplier == 0) { 132 format++; 133 } 134 } else if (fmt == 'L') { 135 uint64_t *llp = (uint64_t *)structure; 136 137 llp = (uint64_t *) 138 (((uintptr_t)llp + _LONG_LONG_ALIGNMENT - 1) & 139 ~(_LONG_LONG_ALIGNMENT - 1)); 140 if (((data + 8) > dataend) || 141 ((llp + 1) >= (uint64_t *)structend)) 142 break; 143 144 *llp++ = (((((((((((((data[7] << 8) | 145 data[6]) << 8) | data[5]) << 8) | 146 data[4]) << 8) | data[3]) << 8) | 147 data[2]) << 8) | data[1]) << 8) | 148 data[0]; 149 data += 8; 150 structure = (void *)llp; 151 if (multiplier) { 152 multiplier--; 153 } 154 if (multiplier == 0) { 155 format++; 156 } 157 } else if (isdigit(fmt)) { 158 multiplier = (multiplier * 10) + (fmt - '0'); 159 format++; 160 counter--; 161 } else { 162 multiplier = 0; 163 break; 164 } 165 } 166 167 return ((intptr_t)structure - (intptr_t)structstart); 168} 169 170 171size_t 172usb_parse_CV_descr(char *format, 173 uchar_t *data, 174 size_t datalen, 175 void *structure, 176 size_t structlen) 177{ 178 return (usb_parse_data(format, data, datalen, structure, 179 structlen)); 180} 181 182 183/* 184 * Helper function: returns pointer to n-th descriptor of 185 * type descr_type, unless the end of the buffer or a descriptor 186 * of type stop_descr_type1 or stop_descr_type2 is encountered first. 187 */ 188static uchar_t * 189usb_nth_descr(uchar_t *buf, 190 size_t buflen, 191 int descr_type, 192 uint_t n, 193 int stop_descr_type1, 194 int stop_descr_type2) 195{ 196 uchar_t *bufstart = buf; 197 uchar_t *bufend = buf + buflen; 198 199 if (buf == NULL) { 200 201 return (NULL); 202 } 203 204 while (buf + 2 <= bufend) { 205 if ((buf != bufstart) && ((buf[1] == stop_descr_type1) || 206 (buf[1] == stop_descr_type2))) { 207 208 return (NULL); 209 } 210 211 if ((descr_type == USB_DESCR_TYPE_ANY) || 212 (buf[1] == descr_type)) { 213 if (n-- == 0) { 214 215 return (buf); 216 } 217 } 218 219 /* 220 * Check for a bad buffer. 221 * If buf[0] is 0, then this will be an infite loop 222 */ 223 INCREMENT_BUF(buf); 224 } 225 226 return (NULL); 227} 228 229 230size_t 231usb_parse_dev_descr(uchar_t *buf, /* from GET_DESCRIPTOR(DEVICE) */ 232 size_t buflen, 233 usb_dev_descr_t *ret_descr, 234 size_t ret_buf_len) 235{ 236 if ((buf == NULL) || (ret_descr == NULL) || 237 (buflen < 2) || (buf[1] != USB_DESCR_TYPE_DEV)) { 238 239 return (USB_PARSE_ERROR); 240 } 241 242 return (usb_parse_data("ccsccccssscccc", 243 buf, buflen, ret_descr, ret_buf_len)); 244} 245 246 247size_t 248usb_parse_cfg_descr(uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ 249 size_t buflen, 250 usb_cfg_descr_t *ret_descr, 251 size_t ret_buf_len) 252{ 253 if ((buf == NULL) || (ret_descr == NULL) || 254 (buflen < 2) || (buf[1] != USB_DESCR_TYPE_CFG)) { 255 256 return (USB_PARSE_ERROR); 257 } 258 259 return (usb_parse_data("ccsccccc", 260 buf, buflen, ret_descr, ret_buf_len)); 261} 262 263 264size_t 265usba_parse_cfg_pwr_descr( 266 uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ 267 size_t buflen, 268 usba_cfg_pwr_descr_t *ret_descr, 269 size_t ret_buf_len) 270{ 271 uchar_t *bufend = buf + buflen; 272 273 if ((buf == NULL) || (ret_descr == NULL)) { 274 275 return (USB_PARSE_ERROR); 276 } 277 while (buf + 2 <= bufend) { 278 279 if (buf[1] == USBA_DESCR_TYPE_CFG_PWR_1_1) { 280 return (usb_parse_data("ccsccccccccsss", 281 buf, buflen, ret_descr, ret_buf_len)); 282 } 283 284 /* 285 * Check for a bad buffer. 286 * If buf[0] is 0, then this will be an infinite loop 287 */ 288 INCREMENT_BUF(buf); 289 } 290 291 /* return the default configuration power descriptor */ 292 bcopy(&default_cfg_power, ret_descr, USBA_CFG_PWR_DESCR_SIZE); 293 294 return (ret_descr->bLength); 295 296} 297 298 299size_t
| 23 * Use is subject to license terms. 24 */ 25 26#pragma ident "%Z%%M% %I% %E% SMI" 27 28/* 29 * Descriptor parsing functions 30 */ 31#define USBA_FRAMEWORK 32#include <sys/usb/usba/usba_impl.h> 33 34#define INCREMENT_BUF(buf) \ 35 if ((buf)[0] == 0) { \ 36 break; \ 37 } else { \ 38 (buf) += (buf)[0]; \ 39 } 40#define isdigit(ch) ((ch >= '0') && (ch <= '9')) 41 42extern usba_cfg_pwr_descr_t default_cfg_power; 43extern usba_if_pwr_descr_t default_if_power; 44 45size_t 46usb_parse_data(char *format, 47 uchar_t *data, 48 size_t datalen, 49 void *structure, 50 size_t structlen) 51{ 52 int fmt; 53 int counter = 1; 54 int multiplier = 0; 55 uchar_t *dataend = data + datalen; 56 char *structstart = (char *)structure; 57 void *structend = (void *)((intptr_t)structstart + structlen); 58 59 if ((format == NULL) || (data == NULL) || (structure == NULL)) { 60 61 return (USB_PARSE_ERROR); 62 } 63 64 while ((fmt = *format) != '\0') { 65 66 /* 67 * Could some one pass a "format" that is greater than 68 * the structlen? Conversely, one could pass a ret_buf_len 69 * that is less than the "format" length. 70 * If so, we need to protect against writing over memory. 71 */ 72 if (counter++ > structlen) { 73 break; 74 } 75 76 if (fmt == 'c') { 77 uint8_t *cp = (uint8_t *)structure; 78 79 cp = (uint8_t *)(((uintptr_t)cp + _CHAR_ALIGNMENT - 1) & 80 ~(_CHAR_ALIGNMENT - 1)); 81 if (((data + 1) > dataend) || 82 ((cp + 1) > (uint8_t *)structend)) 83 break; 84 85 *cp++ = *data++; 86 structure = (void *)cp; 87 if (multiplier) { 88 multiplier--; 89 } 90 if (multiplier == 0) { 91 format++; 92 } 93 } else if (fmt == 's') { 94 uint16_t *sp = (uint16_t *)structure; 95 96 sp = (uint16_t *) 97 (((uintptr_t)sp + _SHORT_ALIGNMENT - 1) & 98 ~(_SHORT_ALIGNMENT - 1)); 99 if (((data + 2) > dataend) || 100 ((sp + 1) > (uint16_t *)structend)) 101 break; 102 103 *sp++ = (data[1] << 8) + data[0]; 104 data += 2; 105 structure = (void *)sp; 106 if (multiplier) { 107 multiplier--; 108 } 109 if (multiplier == 0) { 110 format++; 111 } 112 } else if (fmt == 'l') { 113 uint32_t *lp = (uint32_t *)structure; 114 115 lp = (uint32_t *) 116 (((uintptr_t)lp + _INT_ALIGNMENT - 1) & 117 ~(_INT_ALIGNMENT - 1)); 118 if (((data + 4) > dataend) || 119 ((lp + 1) > (uint32_t *)structend)) 120 break; 121 122 *lp++ = ((((( 123 (uint32_t)data[3] << 8) | data[2]) << 8) | 124 data[1]) << 8) | data[0]; 125 data += 4; 126 structure = (void *)lp; 127 if (multiplier) { 128 multiplier--; 129 } 130 if (multiplier == 0) { 131 format++; 132 } 133 } else if (fmt == 'L') { 134 uint64_t *llp = (uint64_t *)structure; 135 136 llp = (uint64_t *) 137 (((uintptr_t)llp + _LONG_LONG_ALIGNMENT - 1) & 138 ~(_LONG_LONG_ALIGNMENT - 1)); 139 if (((data + 8) > dataend) || 140 ((llp + 1) >= (uint64_t *)structend)) 141 break; 142 143 *llp++ = (((((((((((((data[7] << 8) | 144 data[6]) << 8) | data[5]) << 8) | 145 data[4]) << 8) | data[3]) << 8) | 146 data[2]) << 8) | data[1]) << 8) | 147 data[0]; 148 data += 8; 149 structure = (void *)llp; 150 if (multiplier) { 151 multiplier--; 152 } 153 if (multiplier == 0) { 154 format++; 155 } 156 } else if (isdigit(fmt)) { 157 multiplier = (multiplier * 10) + (fmt - '0'); 158 format++; 159 counter--; 160 } else { 161 multiplier = 0; 162 break; 163 } 164 } 165 166 return ((intptr_t)structure - (intptr_t)structstart); 167} 168 169 170size_t 171usb_parse_CV_descr(char *format, 172 uchar_t *data, 173 size_t datalen, 174 void *structure, 175 size_t structlen) 176{ 177 return (usb_parse_data(format, data, datalen, structure, 178 structlen)); 179} 180 181 182/* 183 * Helper function: returns pointer to n-th descriptor of 184 * type descr_type, unless the end of the buffer or a descriptor 185 * of type stop_descr_type1 or stop_descr_type2 is encountered first. 186 */ 187static uchar_t * 188usb_nth_descr(uchar_t *buf, 189 size_t buflen, 190 int descr_type, 191 uint_t n, 192 int stop_descr_type1, 193 int stop_descr_type2) 194{ 195 uchar_t *bufstart = buf; 196 uchar_t *bufend = buf + buflen; 197 198 if (buf == NULL) { 199 200 return (NULL); 201 } 202 203 while (buf + 2 <= bufend) { 204 if ((buf != bufstart) && ((buf[1] == stop_descr_type1) || 205 (buf[1] == stop_descr_type2))) { 206 207 return (NULL); 208 } 209 210 if ((descr_type == USB_DESCR_TYPE_ANY) || 211 (buf[1] == descr_type)) { 212 if (n-- == 0) { 213 214 return (buf); 215 } 216 } 217 218 /* 219 * Check for a bad buffer. 220 * If buf[0] is 0, then this will be an infite loop 221 */ 222 INCREMENT_BUF(buf); 223 } 224 225 return (NULL); 226} 227 228 229size_t 230usb_parse_dev_descr(uchar_t *buf, /* from GET_DESCRIPTOR(DEVICE) */ 231 size_t buflen, 232 usb_dev_descr_t *ret_descr, 233 size_t ret_buf_len) 234{ 235 if ((buf == NULL) || (ret_descr == NULL) || 236 (buflen < 2) || (buf[1] != USB_DESCR_TYPE_DEV)) { 237 238 return (USB_PARSE_ERROR); 239 } 240 241 return (usb_parse_data("ccsccccssscccc", 242 buf, buflen, ret_descr, ret_buf_len)); 243} 244 245 246size_t 247usb_parse_cfg_descr(uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ 248 size_t buflen, 249 usb_cfg_descr_t *ret_descr, 250 size_t ret_buf_len) 251{ 252 if ((buf == NULL) || (ret_descr == NULL) || 253 (buflen < 2) || (buf[1] != USB_DESCR_TYPE_CFG)) { 254 255 return (USB_PARSE_ERROR); 256 } 257 258 return (usb_parse_data("ccsccccc", 259 buf, buflen, ret_descr, ret_buf_len)); 260} 261 262 263size_t 264usba_parse_cfg_pwr_descr( 265 uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ 266 size_t buflen, 267 usba_cfg_pwr_descr_t *ret_descr, 268 size_t ret_buf_len) 269{ 270 uchar_t *bufend = buf + buflen; 271 272 if ((buf == NULL) || (ret_descr == NULL)) { 273 274 return (USB_PARSE_ERROR); 275 } 276 while (buf + 2 <= bufend) { 277 278 if (buf[1] == USBA_DESCR_TYPE_CFG_PWR_1_1) { 279 return (usb_parse_data("ccsccccccccsss", 280 buf, buflen, ret_descr, ret_buf_len)); 281 } 282 283 /* 284 * Check for a bad buffer. 285 * If buf[0] is 0, then this will be an infinite loop 286 */ 287 INCREMENT_BUF(buf); 288 } 289 290 /* return the default configuration power descriptor */ 291 bcopy(&default_cfg_power, ret_descr, USBA_CFG_PWR_DESCR_SIZE); 292 293 return (ret_descr->bLength); 294 295} 296 297 298size_t
|
300usb_parse_if_descr(uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ 301 size_t buflen, 302 uint_t if_number, 303 uint_t alt_if_setting, 304 usb_if_descr_t *ret_descr, 305 size_t ret_buf_len) 306{ 307 uchar_t *bufend = buf + buflen; 308 309 if ((buf == NULL) || (ret_descr == NULL)) { 310 311 return (USB_PARSE_ERROR); 312 } 313 314 while (buf + 4 <= bufend) { 315 if ((buf[1] == USB_DESCR_TYPE_IF) && 316 (buf[2] == if_number) && 317 (buf[3] == alt_if_setting)) { 318 319 return (usb_parse_data("ccccccccc", 320 buf, bufend - buf, ret_descr, ret_buf_len)); 321 } 322 323 /* 324 * Check for a bad buffer. 325 * If buf[0] is 0, then this will be an infinite loop 326 */ 327 INCREMENT_BUF(buf); 328 } 329 330 return (USB_PARSE_ERROR); 331} 332 333size_t 334usba_parse_if_pwr_descr(uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ 335 size_t buflen, 336 uint_t if_number, 337 uint_t alt_if_setting, 338 usba_if_pwr_descr_t *ret_descr, 339 size_t ret_buf_len) 340{ 341 uchar_t *bufend = buf + buflen; 342 343 if ((buf == NULL) || (ret_descr == NULL)) { 344 345 return (USB_PARSE_ERROR); 346 } 347 348 while (buf + 4 <= bufend) { 349 if ((buf[1] == USB_DESCR_TYPE_IF) && 350 (buf[2] == if_number) && 351 (buf[3] == alt_if_setting)) { 352 353 buf += buf[0]; 354 355 if (buf + 2 <= bufend) { 356 if (buf[1] == USBA_DESCR_TYPE_IF_PWR_1_1) { 357 358 return ( 359 usb_parse_data("cccccccccsss", 360 buf, bufend - buf, ret_descr, 361 ret_buf_len)); 362 } else { 363 break; 364 } 365 } else { 366 break; 367 } 368 } 369 370 /* 371 * Check for a bad buffer. 372 * If buf[0] is 0, then this will be an infinite loop 373 */ 374 INCREMENT_BUF(buf); 375 } 376 377 /* return the default interface power descriptor */ 378 bcopy(&default_if_power, ret_descr, USBA_IF_PWR_DESCR_SIZE); 379 380 return (ret_descr->bLength); 381} 382 383 384/* 385 * the endpoint index is relative to the interface. index 0 is 386 * the first endpoint 387 */ 388size_t 389usb_parse_ep_descr(uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ 390 size_t buflen, 391 uint_t if_number, 392 uint_t alt_if_setting, 393 uint_t ep_index, 394 usb_ep_descr_t *ret_descr, 395 size_t ret_buf_len) 396{ 397 uchar_t *bufend = buf + buflen; 398 399 if ((buf == NULL) || (ret_descr == NULL)) { 400 401 return (USB_PARSE_ERROR); 402 } 403 404 while ((buf + 4) <= bufend) { 405 if (buf[1] == USB_DESCR_TYPE_IF && 406 buf[2] == if_number && 407 buf[3] == alt_if_setting) { 408 if ((buf = usb_nth_descr(buf, bufend - buf, 409 USB_DESCR_TYPE_EP, ep_index, 410 USB_DESCR_TYPE_IF, -1)) == NULL) { 411 412 break; 413 } 414 415 return (usb_parse_data("ccccsc", 416 buf, bufend - buf, 417 ret_descr, ret_buf_len)); 418 } 419 420 /* 421 * Check for a bad buffer. 422 * If buf[0] is 0, then this will be an infinite loop 423 */ 424 INCREMENT_BUF(buf); 425 } 426 427 return (USB_PARSE_ERROR); 428} 429 430 431/* 432 * Returns (at ret_descr) a null-terminated string. Null termination is 433 * guaranteed, even if the string is longer than the buffer. Thus, a 434 * maximum of (ret_buf_len - 1) characters are returned. 435 * Stops silently on first character not in UNICODE format. 436 */ 437/*ARGSUSED*/ 438size_t 439usba_ascii_string_descr(uchar_t *buf, /* from GET_DESCRIPTOR(STRING) */ 440 size_t buflen, 441 char *ret_descr, 442 size_t ret_buf_len) 443{ 444 int i = 1; 445 char *retstart = ret_descr; 446 uchar_t *bufend = buf + buflen; 447 448 if ((buf == NULL) || (ret_descr == NULL) || 449 (ret_buf_len == 0) || (buflen < 2) || 450 (buf[0] < 2) || (buf[1] != USB_DESCR_TYPE_STRING)) { 451 452 return (USB_PARSE_ERROR); 453 } 454 455 for (buf = buf + 2; buf+1 < bufend && ret_buf_len > 1 && 456 buf[0] != 0 && buf[1] == 0 && (i < ret_buf_len); buf += 2, i++) { 457 *ret_descr++ = buf[0]; 458 } 459 460 *ret_descr++ = 0; 461 462 return (ret_descr - retstart); 463} 464 465 466size_t 467usb_parse_CV_cfg_descr(uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ 468 size_t buflen, 469 char *fmt, 470 uint_t descr_type, 471 uint_t descr_index, 472 void *ret_descr, 473 size_t ret_buf_len) 474{ 475 uchar_t *bufend = buf + buflen; 476 477 if ((buf == NULL) || (ret_descr == NULL) || (fmt == NULL) || 478 (buflen < 2) || ((buf = usb_nth_descr(buf, buflen, descr_type, 479 descr_index, -1, -1)) == NULL)) { 480 481 return (USB_PARSE_ERROR); 482 } 483 484 return (usb_parse_data(fmt, buf, bufend - buf, ret_descr, 485 ret_buf_len)); 486} 487 488 489size_t 490usb_parse_CV_if_descr(uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ 491 size_t buflen, 492 char *fmt, 493 uint_t if_number, 494 uint_t alt_if_setting, 495 uint_t descr_type, 496 uint_t descr_index, 497 void *ret_descr, 498 size_t ret_buf_len) 499{ 500 uchar_t *bufend = buf + buflen; 501 502 if ((buf == NULL) || (ret_descr == NULL) || (fmt == NULL)) { 503 504 return (USB_PARSE_ERROR); 505 } 506 507 while (buf + 4 <= bufend) { 508 if ((buf[1] == USB_DESCR_TYPE_IF) && 509 (buf[2] == if_number) && 510 (buf[3] == alt_if_setting)) { 511 if ((buf = usb_nth_descr(buf, bufend - buf, descr_type, 512 descr_index, USB_DESCR_TYPE_IF, -1)) == 513 NULL) { 514 break; 515 } 516 517 return (usb_parse_data(fmt, 518 buf, bufend - buf, ret_descr, ret_buf_len)); 519 } 520 521 /* 522 * Check for a bad buffer. 523 * If buf[0] is 0, then this will be an infinite loop 524 */ 525 INCREMENT_BUF(buf); 526 } 527 528 return (USB_PARSE_ERROR); 529} 530 531 532size_t 533usb_parse_CV_ep_descr(uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ 534 size_t buflen, 535 char *fmt, 536 uint_t if_number, 537 uint_t alt_if_setting, 538 uint_t ep_index, 539 uint_t descr_type, 540 uint_t descr_index, 541 void *ret_descr, 542 size_t ret_buf_len) 543{ 544 uchar_t *bufend = buf + buflen; 545 546 if ((buf == NULL) || (ret_descr == NULL) || (fmt == NULL)) { 547 548 return (USB_PARSE_ERROR); 549 } 550 551 while (buf + 4 <= bufend) { 552 if ((buf[1] == USB_DESCR_TYPE_IF) && 553 (buf[2] == if_number) && 554 (buf[3] == alt_if_setting)) { 555 if ((buf = usb_nth_descr(buf, bufend - buf, 556 USB_DESCR_TYPE_EP, ep_index, 557 USB_DESCR_TYPE_IF, -1)) == NULL) { 558 559 break; 560 } 561 562 if ((buf = usb_nth_descr(buf, bufend - buf, 563 descr_type, descr_index, 564 USB_DESCR_TYPE_EP, 565 USB_DESCR_TYPE_IF)) == NULL) { 566 567 break; 568 } 569 570 return (usb_parse_data(fmt, buf, bufend - buf, 571 ret_descr, ret_buf_len)); 572 } 573 574 /* 575 * Check for a bad buffer. 576 * If buf[0] is 0, then this will be an infite loop 577 */ 578 INCREMENT_BUF(buf); 579 } 580 581 return (USB_PARSE_ERROR); 582}
| 332usb_parse_if_descr(uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ 333 size_t buflen, 334 uint_t if_number, 335 uint_t alt_if_setting, 336 usb_if_descr_t *ret_descr, 337 size_t ret_buf_len) 338{ 339 uchar_t *bufend = buf + buflen; 340 341 if ((buf == NULL) || (ret_descr == NULL)) { 342 343 return (USB_PARSE_ERROR); 344 } 345 346 while (buf + 4 <= bufend) { 347 if ((buf[1] == USB_DESCR_TYPE_IF) && 348 (buf[2] == if_number) && 349 (buf[3] == alt_if_setting)) { 350 351 return (usb_parse_data("ccccccccc", 352 buf, bufend - buf, ret_descr, ret_buf_len)); 353 } 354 355 /* 356 * Check for a bad buffer. 357 * If buf[0] is 0, then this will be an infinite loop 358 */ 359 INCREMENT_BUF(buf); 360 } 361 362 return (USB_PARSE_ERROR); 363} 364 365size_t 366usba_parse_if_pwr_descr(uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ 367 size_t buflen, 368 uint_t if_number, 369 uint_t alt_if_setting, 370 usba_if_pwr_descr_t *ret_descr, 371 size_t ret_buf_len) 372{ 373 uchar_t *bufend = buf + buflen; 374 375 if ((buf == NULL) || (ret_descr == NULL)) { 376 377 return (USB_PARSE_ERROR); 378 } 379 380 while (buf + 4 <= bufend) { 381 if ((buf[1] == USB_DESCR_TYPE_IF) && 382 (buf[2] == if_number) && 383 (buf[3] == alt_if_setting)) { 384 385 buf += buf[0]; 386 387 if (buf + 2 <= bufend) { 388 if (buf[1] == USBA_DESCR_TYPE_IF_PWR_1_1) { 389 390 return ( 391 usb_parse_data("cccccccccsss", 392 buf, bufend - buf, ret_descr, 393 ret_buf_len)); 394 } else { 395 break; 396 } 397 } else { 398 break; 399 } 400 } 401 402 /* 403 * Check for a bad buffer. 404 * If buf[0] is 0, then this will be an infinite loop 405 */ 406 INCREMENT_BUF(buf); 407 } 408 409 /* return the default interface power descriptor */ 410 bcopy(&default_if_power, ret_descr, USBA_IF_PWR_DESCR_SIZE); 411 412 return (ret_descr->bLength); 413} 414 415 416/* 417 * the endpoint index is relative to the interface. index 0 is 418 * the first endpoint 419 */ 420size_t 421usb_parse_ep_descr(uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ 422 size_t buflen, 423 uint_t if_number, 424 uint_t alt_if_setting, 425 uint_t ep_index, 426 usb_ep_descr_t *ret_descr, 427 size_t ret_buf_len) 428{ 429 uchar_t *bufend = buf + buflen; 430 431 if ((buf == NULL) || (ret_descr == NULL)) { 432 433 return (USB_PARSE_ERROR); 434 } 435 436 while ((buf + 4) <= bufend) { 437 if (buf[1] == USB_DESCR_TYPE_IF && 438 buf[2] == if_number && 439 buf[3] == alt_if_setting) { 440 if ((buf = usb_nth_descr(buf, bufend - buf, 441 USB_DESCR_TYPE_EP, ep_index, 442 USB_DESCR_TYPE_IF, -1)) == NULL) { 443 444 break; 445 } 446 447 return (usb_parse_data("ccccsc", 448 buf, bufend - buf, 449 ret_descr, ret_buf_len)); 450 } 451 452 /* 453 * Check for a bad buffer. 454 * If buf[0] is 0, then this will be an infinite loop 455 */ 456 INCREMENT_BUF(buf); 457 } 458 459 return (USB_PARSE_ERROR); 460} 461 462 463/* 464 * Returns (at ret_descr) a null-terminated string. Null termination is 465 * guaranteed, even if the string is longer than the buffer. Thus, a 466 * maximum of (ret_buf_len - 1) characters are returned. 467 * Stops silently on first character not in UNICODE format. 468 */ 469/*ARGSUSED*/ 470size_t 471usba_ascii_string_descr(uchar_t *buf, /* from GET_DESCRIPTOR(STRING) */ 472 size_t buflen, 473 char *ret_descr, 474 size_t ret_buf_len) 475{ 476 int i = 1; 477 char *retstart = ret_descr; 478 uchar_t *bufend = buf + buflen; 479 480 if ((buf == NULL) || (ret_descr == NULL) || 481 (ret_buf_len == 0) || (buflen < 2) || 482 (buf[0] < 2) || (buf[1] != USB_DESCR_TYPE_STRING)) { 483 484 return (USB_PARSE_ERROR); 485 } 486 487 for (buf = buf + 2; buf+1 < bufend && ret_buf_len > 1 && 488 buf[0] != 0 && buf[1] == 0 && (i < ret_buf_len); buf += 2, i++) { 489 *ret_descr++ = buf[0]; 490 } 491 492 *ret_descr++ = 0; 493 494 return (ret_descr - retstart); 495} 496 497 498size_t 499usb_parse_CV_cfg_descr(uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ 500 size_t buflen, 501 char *fmt, 502 uint_t descr_type, 503 uint_t descr_index, 504 void *ret_descr, 505 size_t ret_buf_len) 506{ 507 uchar_t *bufend = buf + buflen; 508 509 if ((buf == NULL) || (ret_descr == NULL) || (fmt == NULL) || 510 (buflen < 2) || ((buf = usb_nth_descr(buf, buflen, descr_type, 511 descr_index, -1, -1)) == NULL)) { 512 513 return (USB_PARSE_ERROR); 514 } 515 516 return (usb_parse_data(fmt, buf, bufend - buf, ret_descr, 517 ret_buf_len)); 518} 519 520 521size_t 522usb_parse_CV_if_descr(uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ 523 size_t buflen, 524 char *fmt, 525 uint_t if_number, 526 uint_t alt_if_setting, 527 uint_t descr_type, 528 uint_t descr_index, 529 void *ret_descr, 530 size_t ret_buf_len) 531{ 532 uchar_t *bufend = buf + buflen; 533 534 if ((buf == NULL) || (ret_descr == NULL) || (fmt == NULL)) { 535 536 return (USB_PARSE_ERROR); 537 } 538 539 while (buf + 4 <= bufend) { 540 if ((buf[1] == USB_DESCR_TYPE_IF) && 541 (buf[2] == if_number) && 542 (buf[3] == alt_if_setting)) { 543 if ((buf = usb_nth_descr(buf, bufend - buf, descr_type, 544 descr_index, USB_DESCR_TYPE_IF, -1)) == 545 NULL) { 546 break; 547 } 548 549 return (usb_parse_data(fmt, 550 buf, bufend - buf, ret_descr, ret_buf_len)); 551 } 552 553 /* 554 * Check for a bad buffer. 555 * If buf[0] is 0, then this will be an infinite loop 556 */ 557 INCREMENT_BUF(buf); 558 } 559 560 return (USB_PARSE_ERROR); 561} 562 563 564size_t 565usb_parse_CV_ep_descr(uchar_t *buf, /* from GET_DESCRIPTOR(CONFIGURATION) */ 566 size_t buflen, 567 char *fmt, 568 uint_t if_number, 569 uint_t alt_if_setting, 570 uint_t ep_index, 571 uint_t descr_type, 572 uint_t descr_index, 573 void *ret_descr, 574 size_t ret_buf_len) 575{ 576 uchar_t *bufend = buf + buflen; 577 578 if ((buf == NULL) || (ret_descr == NULL) || (fmt == NULL)) { 579 580 return (USB_PARSE_ERROR); 581 } 582 583 while (buf + 4 <= bufend) { 584 if ((buf[1] == USB_DESCR_TYPE_IF) && 585 (buf[2] == if_number) && 586 (buf[3] == alt_if_setting)) { 587 if ((buf = usb_nth_descr(buf, bufend - buf, 588 USB_DESCR_TYPE_EP, ep_index, 589 USB_DESCR_TYPE_IF, -1)) == NULL) { 590 591 break; 592 } 593 594 if ((buf = usb_nth_descr(buf, bufend - buf, 595 descr_type, descr_index, 596 USB_DESCR_TYPE_EP, 597 USB_DESCR_TYPE_IF)) == NULL) { 598 599 break; 600 } 601 602 return (usb_parse_data(fmt, buf, bufend - buf, 603 ret_descr, ret_buf_len)); 604 } 605 606 /* 607 * Check for a bad buffer. 608 * If buf[0] is 0, then this will be an infite loop 609 */ 610 INCREMENT_BUF(buf); 611 } 612 613 return (USB_PARSE_ERROR); 614}
|